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

Version Description

= v120213 = Optimization and a few bug fixes. Upgrade immediately.

Download this release

Release Info

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

Code changes from version 111220 to 120213

includes/classes/admin-css-js-in.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Admin_CSS_JS
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_admin_css_js_in"))
21
  {
22
  /**
23
  * Administrative CSS/JS for menu pages ( inner processing routines ).
@@ -37,39 +37,39 @@ if (!class_exists ("c_ws_plugin__s2member_admin_css_js_in"))
37
  *
38
  * @return null Or exits script execution after loading CSS.
39
  */
40
- public static function menu_pages_css ()
41
  {
42
- do_action ("ws_plugin__s2member_before_menu_pages_css", get_defined_vars ());
43
  /**/
44
- if (!empty ($_GET["ws_plugin__s2member_menu_pages_css"]) && is_user_logged_in () && current_user_can ("create_users"))
45
  {
46
- status_header (200); /* 200 OK status header. */
47
  /**/
48
- header ("Content-Type: text/css; charset=utf-8");
49
- header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
50
- header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
51
- header ("Cache-Control: no-cache, must-revalidate, max-age=0");
52
- header ("Pragma: no-cache");
53
  /**/
54
- eval ('while (@ob_end_clean ());'); /* Clean buffers. */
55
  /**/
56
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
57
- $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
58
  /**/
59
- ob_start ("c_ws_plugin__s2member_utils_css::compress_css");
60
  /**/
61
- include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.css";
62
  /**/
63
  echo "\n"; /* Add a line break before inclusion of this file. */
64
  /**/
65
- @include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages-s.css";
66
  /**/
67
- do_action ("ws_plugin__s2member_during_menu_pages_css", get_defined_vars ());
68
  /**/
69
- exit (); /* Clean exit. */
70
  }
71
  /**/
72
- do_action ("ws_plugin__s2member_after_menu_pages_css", get_defined_vars ());
73
  }
74
  /**
75
  * Outputs the JS for administrative menu pages.
@@ -81,41 +81,41 @@ if (!class_exists ("c_ws_plugin__s2member_admin_css_js_in"))
81
  *
82
  * @return null Or exits script execution after loading JS.
83
  */
84
- public static function menu_pages_js ()
85
  {
86
- do_action ("ws_plugin__s2member_before_menu_pages_js", get_defined_vars ());
87
  /**/
88
- if (!empty ($_GET["ws_plugin__s2member_menu_pages_js"]) && is_user_logged_in () && current_user_can ("create_users"))
89
  {
90
- status_header (200); /* 200 OK status header. */
91
  /**/
92
- header ("Content-Type: text/javascript; charset=utf-8");
93
- header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
94
- header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
95
- header ("Cache-Control: no-cache, must-revalidate, max-age=0");
96
- header ("Pragma: no-cache");
97
  /**/
98
- eval ('while (@ob_end_clean ());'); /* Clean buffers. */
99
  /**/
100
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
101
- $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
102
  /**/
103
- for ($n = 0, $labels = ""; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
104
- $labels .= "labels['level" . $n . "'] = '" . ((!empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"])) ? str_replace ('"', "", c_ws_plugin__s2member_utils_strings::esc_js_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_label"], 3)) : "") . "';";
105
- unset ($n);
106
  /**/
107
- include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages-min.js";
108
  /**/
109
  echo "\n"; /* Add a line break before inclusion of this file. */
110
  /**/
111
- @include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages-s-min.js";
112
  /**/
113
- do_action ("ws_plugin__s2member_during_menu_pages_js", get_defined_vars ());
114
  /**/
115
- exit (); /* Clean exit. */
116
  }
117
  /**/
118
- do_action ("ws_plugin__s2member_after_menu_pages_js", get_defined_vars ());
119
  }
120
  }
121
  }
14
  * @package s2Member\Admin_CSS_JS
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_admin_css_js_in"))
21
  {
22
  /**
23
  * Administrative CSS/JS for menu pages ( inner processing routines ).
37
  *
38
  * @return null Or exits script execution after loading CSS.
39
  */
40
+ public static function menu_pages_css()
41
  {
42
+ do_action("ws_plugin__s2member_before_menu_pages_css", get_defined_vars());
43
  /**/
44
+ if(!empty($_GET["ws_plugin__s2member_menu_pages_css"]) && is_user_logged_in() && current_user_can("create_users"))
45
  {
46
+ status_header(200); /* 200 OK status header. */
47
  /**/
48
+ header("Content-Type: text/css; charset=utf-8");
49
+ header("Expires: ".gmdate("D, d M Y H:i:s", strtotime("-1 week"))." GMT");
50
+ header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
51
+ header("Cache-Control: no-cache, must-revalidate, max-age=0");
52
+ header("Pragma: no-cache");
53
  /**/
54
+ eval('while (@ob_end_clean ());'); /* Clean buffers. */
55
  /**/
56
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
57
+ $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images";
58
  /**/
59
+ ob_start("c_ws_plugin__s2member_utils_css::compress_css");
60
  /**/
61
+ include_once dirname(dirname(__FILE__))."/menu-pages/menu-pages.css";
62
  /**/
63
  echo "\n"; /* Add a line break before inclusion of this file. */
64
  /**/
65
+ @include_once dirname(dirname(__FILE__))."/menu-pages/menu-pages-s.css";
66
  /**/
67
+ do_action("ws_plugin__s2member_during_menu_pages_css", get_defined_vars());
68
  /**/
69
+ exit(); /* Clean exit. */
70
  }
71
  /**/
72
+ do_action("ws_plugin__s2member_after_menu_pages_css", get_defined_vars());
73
  }
74
  /**
75
  * Outputs the JS for administrative menu pages.
81
  *
82
  * @return null Or exits script execution after loading JS.
83
  */
84
+ public static function menu_pages_js()
85
  {
86
+ do_action("ws_plugin__s2member_before_menu_pages_js", get_defined_vars());
87
  /**/
88
+ if(!empty($_GET["ws_plugin__s2member_menu_pages_js"]) && is_user_logged_in() && current_user_can("create_users"))
89
  {
90
+ status_header(200); /* 200 OK status header. */
91
  /**/
92
+ header("Content-Type: application/x-javascript; charset=utf-8");
93
+ header("Expires: ".gmdate("D, d M Y H:i:s", strtotime("-1 week"))." GMT");
94
+ header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
95
+ header("Cache-Control: no-cache, must-revalidate, max-age=0");
96
+ header("Pragma: no-cache");
97
  /**/
98
+ eval('while (@ob_end_clean ());'); /* Clean buffers. */
99
  /**/
100
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
101
+ $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images";
102
  /**/
103
+ for($n = 0, $labels = ""; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
104
+ $labels .= "labels['level".$n."'] = '".((!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_label"])) ? str_replace('"', "", c_ws_plugin__s2member_utils_strings::esc_js_sq($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_label"], 3)) : "")."';";
105
+ unset($n);
106
  /**/
107
+ include_once dirname(dirname(__FILE__))."/menu-pages/menu-pages-min.js";
108
  /**/
109
  echo "\n"; /* Add a line break before inclusion of this file. */
110
  /**/
111
+ @include_once dirname(dirname(__FILE__))."/menu-pages/menu-pages-s-min.js";
112
  /**/
113
+ do_action("ws_plugin__s2member_during_menu_pages_js", get_defined_vars());
114
  /**/
115
+ exit(); /* Clean exit. */
116
  }
117
  /**/
118
+ do_action("ws_plugin__s2member_after_menu_pages_js", get_defined_vars());
119
  }
120
  }
121
  }
includes/classes/css-js-in.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\CSS_JS
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_css_js_in"))
21
  {
22
  /**
23
  * CSS/JS loading handlers for s2Member ( inner processing routines ).
@@ -37,35 +37,35 @@ if (!class_exists ("c_ws_plugin__s2member_css_js_in"))
37
  *
38
  * @return null Or exits script execution after loading CSS.
39
  */
40
- public static function css ()
41
  {
42
- do_action ("ws_plugin__s2member_before_css", get_defined_vars ());
43
  /**/
44
- if (!empty ($_GET["ws_plugin__s2member_css"]))
45
  {
46
  status_header(200); /* 200 OK status. */
47
  /**/
48
  header("Content-Type: text/css; charset=utf-8");
49
- header("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("+1 week")) . " GMT");
50
- header("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
51
  header("Cache-Control: max-age=604800");
52
  header("Pragma: public");
53
  /**/
54
  eval('while (@ob_end_clean ());');
55
  /**/
56
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
57
- $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
58
  /**/
59
  ob_start("c_ws_plugin__s2member_utils_css::compress_css");
60
  /**/
61
- include_once dirname (dirname (__FILE__)) . "/s2member.css";
62
  /**/
63
- do_action ("ws_plugin__s2member_during_css", get_defined_vars ());
64
  /**/
65
- exit (); /* Clean exit. */
66
  }
67
  /**/
68
- do_action ("ws_plugin__s2member_after_css", get_defined_vars ());
69
  }
70
  /**
71
  * Outputs JS for theme integration.
@@ -79,127 +79,127 @@ if (!class_exists ("c_ws_plugin__s2member_css_js_in"))
79
  *
80
  * @return null Or exits script execution after loading JS w/Globals.
81
  */
82
- public static function js_w_globals ()
83
  {
84
- do_action ("ws_plugin__s2member_before_js_w_globals", get_defined_vars ());
85
  /**/
86
- if (!empty ($_GET["ws_plugin__s2member_js_w_globals"]))
87
  {
88
  status_header(200); /* 200 OK status header. */
89
  /**/
90
- header("Content-Type: text/javascript; charset=utf-8");
91
- header("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("+1 week")) . " GMT");
92
- header("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
93
  header("Cache-Control: max-age=604800");
94
  header("Pragma: public");
95
  /**/
96
  eval('while (@ob_end_clean ());');
97
  /**/
98
- include_once dirname (dirname (__FILE__)) . "/jquery/jquery.sprintf/jquery.sprintf-min.js";
99
  /**/
100
  echo "\n"; /* Add a line break before writing JavaScript Globals to file. */
101
  /**/
102
- echo "var S2MEMBER_VERSION = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_VERSION) . "',";
103
  /**/
104
- echo "S2MEMBER_CURRENT_USER_LOGIN_COUNTER = " . S2MEMBER_CURRENT_USER_LOGIN_COUNTER . ",";
105
  /**/
106
- echo "S2MEMBER_CURRENT_USER_IS_LOGGED_IN = " . ((S2MEMBER_CURRENT_USER_IS_LOGGED_IN) ? "true" : "false") . ",";
107
- echo "S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER = " . ((S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER) ? "true" : "false") . ",";
108
  /**/
109
- echo "S2MEMBER_CURRENT_USER_ACCESS_LEVEL = " . S2MEMBER_CURRENT_USER_ACCESS_LEVEL . ",";
110
- echo "S2MEMBER_CURRENT_USER_ACCESS_LABEL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_ACCESS_LABEL) . "',";
111
  /**/
112
- echo "S2MEMBER_CURRENT_USER_SUBSCR_ID = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_SUBSCR_ID) . "',";
113
- echo "S2MEMBER_CURRENT_USER_SUBSCR_OR_WP_ID = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_SUBSCR_OR_WP_ID) . "',";
114
- echo "S2MEMBER_CURRENT_USER_SUBSCR_GATEWAY = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_SUBSCR_GATEWAY) . "',";
115
- echo "S2MEMBER_CURRENT_USER_CUSTOM = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_CUSTOM) . "',";
116
  /**/
117
- echo "S2MEMBER_CURRENT_USER_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_REGISTRATION_TIME . ",";
118
- echo "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME . ",";
119
  /**/
120
- echo "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS . ",";
121
- echo "S2MEMBER_CURRENT_USER_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_REGISTRATION_DAYS . ",";
122
  /**/
123
- echo "S2MEMBER_CURRENT_USER_DISPLAY_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_DISPLAY_NAME) . "',";
124
- echo "S2MEMBER_CURRENT_USER_FIRST_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_FIRST_NAME) . "',";
125
- echo "S2MEMBER_CURRENT_USER_LAST_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_LAST_NAME) . "',";
126
  /**/
127
- echo "S2MEMBER_CURRENT_USER_LOGIN = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_LOGIN) . "',";
128
- echo "S2MEMBER_CURRENT_USER_EMAIL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_EMAIL) . "',";
129
- echo "S2MEMBER_CURRENT_USER_IP = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_IP) . "',";
130
- echo "S2MEMBER_CURRENT_USER_REGISTRATION_IP = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_REGISTRATION_IP) . "',";
131
  /**/
132
- echo "S2MEMBER_CURRENT_USER_ID = " . S2MEMBER_CURRENT_USER_ID . ",";
133
- echo "S2MEMBER_CURRENT_USER_FIELDS = " . S2MEMBER_CURRENT_USER_FIELDS . ",";
134
  /**/
135
- echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED = " . S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED . ",";
136
- echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED = " . ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? "true" : "false") . ",";
137
- echo "S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY = " . S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY . ",";
138
- echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS . ",";
139
  /**/
140
- echo "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID = " . S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID . ",";
141
- echo "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID = " . S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID . ",";
142
- echo "S2MEMBER_LOGIN_WELCOME_PAGE_ID = " . S2MEMBER_LOGIN_WELCOME_PAGE_ID . ",";
143
  /**/
144
- echo "S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL) . "',";
145
- echo "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL) . "',";
146
- echo "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL) . "',";
147
- echo "S2MEMBER_LOGIN_WELCOME_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_LOGIN_WELCOME_PAGE_URL) . "',";
148
- echo "S2MEMBER_LOGOUT_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_LOGOUT_PAGE_URL) . "',";
149
- echo "S2MEMBER_LOGIN_PAGE_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_LOGIN_PAGE_URL) . "',";
150
  /**/
151
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
152
  {
153
- if (defined (($S2MEMBER_LEVELn_LABEL = "S2MEMBER_LEVEL" . $n . "_LABEL")))
154
- echo $S2MEMBER_LEVELn_LABEL . " = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (constant ($S2MEMBER_LEVELn_LABEL)) . "',";
155
  }
156
  /**/
157
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
158
  {
159
- if (defined (($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED = "S2MEMBER_LEVEL" . $n . "_FILE_DOWNLOADS_ALLOWED")))
160
- echo $S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED . " = " . constant ($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED) . ",";
161
  }
162
  /**/
163
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
164
  {
165
- if (defined (($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS = "S2MEMBER_LEVEL" . $n . "_FILE_DOWNLOADS_ALLOWED_DAYS")))
166
- echo $S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS . " = " . constant ($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS) . ",";
167
  }
168
  /**/
169
- echo "S2MEMBER_FILE_DOWNLOAD_INLINE_EXTENSIONS = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_FILE_DOWNLOAD_INLINE_EXTENSIONS) . "',";
170
  /**/
171
- echo "S2MEMBER_REG_EMAIL_FROM_NAME = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_REG_EMAIL_FROM_NAME) . "',";
172
- echo "S2MEMBER_REG_EMAIL_FROM_EMAIL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_REG_EMAIL_FROM_EMAIL) . "',";
173
  /**/
174
- echo "S2MEMBER_PAYPAL_NOTIFY_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_PAYPAL_NOTIFY_URL) . "',";
175
- echo "S2MEMBER_PAYPAL_RETURN_URL = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_PAYPAL_RETURN_URL) . "',";
176
  /**/
177
- echo "S2MEMBER_PAYPAL_BUSINESS = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_PAYPAL_BUSINESS) . "',";
178
- echo "S2MEMBER_PAYPAL_ENDPOINT = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_PAYPAL_ENDPOINT) . "',";
179
- echo "S2MEMBER_PAYPAL_API_ENDPOINT = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_PAYPAL_API_ENDPOINT) . "',";
180
  /**/
181
- echo "S2MEMBER_VALUE_FOR_PP_INV = Math.round (new Date ().getTime ()) + '~" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_IP) . "',";
182
  echo "S2MEMBER_VALUE_FOR_PP_INV_GEN = s2member_value_for_pp_inv_gen = function(){ var invoice = '', formatSeed = function(seed, reqWidth) { seed = parseInt(seed, 10).toString (16); if (reqWidth < seed.length) return seed.slice (seed.length - reqWidth); else if (reqWidth > seed.length) return Array(1 + (reqWidth - seed.length)).join ('0') + seed; return seed; }; if (typeof S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED === 'undefined') S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED = Math.floor (Math.random () * 0x75bcd15); S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED++; invoice = formatSeed(parseInt(new Date ().getTime () / 1000, 10), 8); invoice += formatSeed(S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED, 5); invoice += '~' + S2MEMBER_CURRENT_USER_IP; return invoice; },";
183
  /**/
184
- echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0) . "',";
185
- echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0) . "',";
186
  /**/
187
- echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON1 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON1) . "',";
188
- echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS1 = '" . c_ws_plugin__s2member_utils_strings::esc_js_sq (S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS1) . "';";
189
  /**/
190
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
191
- $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
192
  /**/
193
  echo "\n"; /* Add a line break before inclusion. */
194
  /**/
195
- include_once dirname (dirname (__FILE__)) . "/s2member-min.js";
196
  /**/
197
- do_action ("ws_plugin__s2member_during_js_w_globals", get_defined_vars ());
198
  /**/
199
- exit (); /* Clean exit. */
200
  }
201
  /**/
202
- do_action ("ws_plugin__s2member_after_js_w_globals", get_defined_vars ());
203
  }
204
  }
205
  }
14
  * @package s2Member\CSS_JS
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_css_js_in"))
21
  {
22
  /**
23
  * CSS/JS loading handlers for s2Member ( inner processing routines ).
37
  *
38
  * @return null Or exits script execution after loading CSS.
39
  */
40
+ public static function css()
41
  {
42
+ do_action("ws_plugin__s2member_before_css", get_defined_vars());
43
  /**/
44
+ if(!empty($_GET["ws_plugin__s2member_css"]))
45
  {
46
  status_header(200); /* 200 OK status. */
47
  /**/
48
  header("Content-Type: text/css; charset=utf-8");
49
+ header("Expires: ".gmdate("D, d M Y H:i:s", strtotime("+1 week"))." GMT");
50
+ header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
51
  header("Cache-Control: max-age=604800");
52
  header("Pragma: public");
53
  /**/
54
  eval('while (@ob_end_clean ());');
55
  /**/
56
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
57
+ $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images";
58
  /**/
59
  ob_start("c_ws_plugin__s2member_utils_css::compress_css");
60
  /**/
61
+ include_once dirname(dirname(__FILE__))."/s2member.css";
62
  /**/
63
+ do_action("ws_plugin__s2member_during_css", get_defined_vars());
64
  /**/
65
+ exit(); /* Clean exit. */
66
  }
67
  /**/
68
+ do_action("ws_plugin__s2member_after_css", get_defined_vars());
69
  }
70
  /**
71
  * Outputs JS for theme integration.
79
  *
80
  * @return null Or exits script execution after loading JS w/Globals.
81
  */
82
+ public static function js_w_globals()
83
  {
84
+ do_action("ws_plugin__s2member_before_js_w_globals", get_defined_vars());
85
  /**/
86
+ if(!empty($_GET["ws_plugin__s2member_js_w_globals"]))
87
  {
88
  status_header(200); /* 200 OK status header. */
89
  /**/
90
+ header("Content-Type: application/x-javascript; charset=utf-8");
91
+ header("Expires: ".gmdate("D, d M Y H:i:s", strtotime("+1 week"))." GMT");
92
+ header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
93
  header("Cache-Control: max-age=604800");
94
  header("Pragma: public");
95
  /**/
96
  eval('while (@ob_end_clean ());');
97
  /**/
98
+ include_once dirname(dirname(__FILE__))."/jquery/jquery.sprintf/jquery.sprintf-min.js";
99
  /**/
100
  echo "\n"; /* Add a line break before writing JavaScript Globals to file. */
101
  /**/
102
+ echo "var S2MEMBER_VERSION = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_VERSION)."',";
103
  /**/
104
+ echo "S2MEMBER_CURRENT_USER_LOGIN_COUNTER = ".S2MEMBER_CURRENT_USER_LOGIN_COUNTER.",";
105
  /**/
106
+ echo "S2MEMBER_CURRENT_USER_IS_LOGGED_IN = ".((S2MEMBER_CURRENT_USER_IS_LOGGED_IN) ? "true" : "false").",";
107
+ echo "S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER = ".((S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER) ? "true" : "false").",";
108
  /**/
109
+ echo "S2MEMBER_CURRENT_USER_ACCESS_LEVEL = ".S2MEMBER_CURRENT_USER_ACCESS_LEVEL.",";
110
+ echo "S2MEMBER_CURRENT_USER_ACCESS_LABEL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_ACCESS_LABEL)."',";
111
  /**/
112
+ echo "S2MEMBER_CURRENT_USER_SUBSCR_ID = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_SUBSCR_ID)."',";
113
+ echo "S2MEMBER_CURRENT_USER_SUBSCR_OR_WP_ID = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_SUBSCR_OR_WP_ID)."',";
114
+ echo "S2MEMBER_CURRENT_USER_SUBSCR_GATEWAY = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_SUBSCR_GATEWAY)."',";
115
+ echo "S2MEMBER_CURRENT_USER_CUSTOM = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_CUSTOM)."',";
116
  /**/
117
+ echo "S2MEMBER_CURRENT_USER_REGISTRATION_TIME = ".S2MEMBER_CURRENT_USER_REGISTRATION_TIME.",";
118
+ echo "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME = ".S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME.",";
119
  /**/
120
+ echo "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS = ".S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS.",";
121
+ echo "S2MEMBER_CURRENT_USER_REGISTRATION_DAYS = ".S2MEMBER_CURRENT_USER_REGISTRATION_DAYS.",";
122
  /**/
123
+ echo "S2MEMBER_CURRENT_USER_DISPLAY_NAME = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_DISPLAY_NAME)."',";
124
+ echo "S2MEMBER_CURRENT_USER_FIRST_NAME = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_FIRST_NAME)."',";
125
+ echo "S2MEMBER_CURRENT_USER_LAST_NAME = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_LAST_NAME)."',";
126
  /**/
127
+ echo "S2MEMBER_CURRENT_USER_LOGIN = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_LOGIN)."',";
128
+ echo "S2MEMBER_CURRENT_USER_EMAIL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_EMAIL)."',";
129
+ echo "S2MEMBER_CURRENT_USER_IP = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_IP)."',";
130
+ echo "S2MEMBER_CURRENT_USER_REGISTRATION_IP = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_REGISTRATION_IP)."',";
131
  /**/
132
+ echo "S2MEMBER_CURRENT_USER_ID = ".S2MEMBER_CURRENT_USER_ID.",";
133
+ echo "S2MEMBER_CURRENT_USER_FIELDS = ".S2MEMBER_CURRENT_USER_FIELDS.",";
134
  /**/
135
+ echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED = ".S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED.",";
136
+ echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED = ".((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? "true" : "false").",";
137
+ echo "S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY = ".S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY.",";
138
+ echo "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS = ".S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS.",";
139
  /**/
140
+ echo "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID = ".S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID.",";
141
+ echo "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID = ".S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID.",";
142
+ echo "S2MEMBER_LOGIN_WELCOME_PAGE_ID = ".S2MEMBER_LOGIN_WELCOME_PAGE_ID.",";
143
  /**/
144
+ echo "S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL)."',";
145
+ echo "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL)."',";
146
+ echo "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL)."',";
147
+ echo "S2MEMBER_LOGIN_WELCOME_PAGE_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_LOGIN_WELCOME_PAGE_URL)."',";
148
+ echo "S2MEMBER_LOGOUT_PAGE_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_LOGOUT_PAGE_URL)."',";
149
+ echo "S2MEMBER_LOGIN_PAGE_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_LOGIN_PAGE_URL)."',";
150
  /**/
151
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
152
  {
153
+ if(defined(($S2MEMBER_LEVELn_LABEL = "S2MEMBER_LEVEL".$n."_LABEL")))
154
+ echo $S2MEMBER_LEVELn_LABEL." = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(constant($S2MEMBER_LEVELn_LABEL))."',";
155
  }
156
  /**/
157
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
158
  {
159
+ if(defined(($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED = "S2MEMBER_LEVEL".$n."_FILE_DOWNLOADS_ALLOWED")))
160
+ echo $S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED." = ".constant($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED).",";
161
  }
162
  /**/
163
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
164
  {
165
+ if(defined(($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS = "S2MEMBER_LEVEL".$n."_FILE_DOWNLOADS_ALLOWED_DAYS")))
166
+ echo $S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS." = ".constant($S2MEMBER_LEVELn_FILE_DOWNLOADS_ALLOWED_DAYS).",";
167
  }
168
  /**/
169
+ echo "S2MEMBER_FILE_DOWNLOAD_INLINE_EXTENSIONS = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_FILE_DOWNLOAD_INLINE_EXTENSIONS)."',";
170
  /**/
171
+ echo "S2MEMBER_REG_EMAIL_FROM_NAME = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_REG_EMAIL_FROM_NAME)."',";
172
+ echo "S2MEMBER_REG_EMAIL_FROM_EMAIL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_REG_EMAIL_FROM_EMAIL)."',";
173
  /**/
174
+ echo "S2MEMBER_PAYPAL_NOTIFY_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_NOTIFY_URL)."',";
175
+ echo "S2MEMBER_PAYPAL_RETURN_URL = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_RETURN_URL)."',";
176
  /**/
177
+ echo "S2MEMBER_PAYPAL_BUSINESS = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_BUSINESS)."',";
178
+ echo "S2MEMBER_PAYPAL_ENDPOINT = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_ENDPOINT)."',";
179
+ echo "S2MEMBER_PAYPAL_API_ENDPOINT = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_PAYPAL_API_ENDPOINT)."',";
180
  /**/
181
+ echo "S2MEMBER_VALUE_FOR_PP_INV = Math.round (new Date ().getTime ()) + '~".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_IP)."',";
182
  echo "S2MEMBER_VALUE_FOR_PP_INV_GEN = s2member_value_for_pp_inv_gen = function(){ var invoice = '', formatSeed = function(seed, reqWidth) { seed = parseInt(seed, 10).toString (16); if (reqWidth < seed.length) return seed.slice (seed.length - reqWidth); else if (reqWidth > seed.length) return Array(1 + (reqWidth - seed.length)).join ('0') + seed; return seed; }; if (typeof S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED === 'undefined') S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED = Math.floor (Math.random () * 0x75bcd15); S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED++; invoice = formatSeed(parseInt(new Date ().getTime () / 1000, 10), 8); invoice += formatSeed(S2MEMBER_VALUE_FOR_PP_INV_GEN_UNIQUE_SEED, 5); invoice += '~' + S2MEMBER_CURRENT_USER_IP; return invoice; },";
183
  /**/
184
+ echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0 = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0)."',";
185
+ echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0 = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0)."',";
186
  /**/
187
+ echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON1 = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON1)."',";
188
+ echo "S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS1 = '".c_ws_plugin__s2member_utils_strings::esc_js_sq(S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS1)."';";
189
  /**/
190
  $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
191
+ $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images";
192
  /**/
193
  echo "\n"; /* Add a line break before inclusion. */
194
  /**/
195
+ include_once dirname(dirname(__FILE__))."/s2member-min.js";
196
  /**/
197
+ do_action("ws_plugin__s2member_during_js_w_globals", get_defined_vars());
198
  /**/
199
+ exit(); /* Clean exit. */
200
  }
201
  /**/
202
+ do_action("ws_plugin__s2member_after_js_w_globals", get_defined_vars());
203
  }
204
  }
205
  }
includes/classes/custom-reg-fields.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Custom_Reg_Fields
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_custom_reg_fields"))
21
  {
22
  /**
23
  * Custom Registration/Profile Fields for s2Member.
@@ -46,224 +46,225 @@ if (!class_exists ("c_ws_plugin__s2member_custom_reg_fields"))
46
  * @param str $_editable_context Optional. One of `profile|profile-view|registration`.
47
  * @return str The resulting Custom Field, in HTML format.
48
  */
49
- public static function custom_field_gen ($_function = FALSE, $_field = FALSE, $_name_prefix = FALSE, $_id_prefix = FALSE, $_classes = FALSE, $_styles = FALSE, $_tabindex = FALSE, $_attrs = FALSE, $_submission = FALSE, $_value = FALSE, $_editable_context = FALSE)
50
  {
51
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
52
- do_action ("ws_plugin__s2member_before_custom_field_gen", get_defined_vars ());
53
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
54
  /**/
55
- if (!($gen = "") && $_function && is_array ($field = $_field) && !empty ($field["type"]) && !empty ($field["id"]) && $_name_prefix && $_id_prefix)
56
  {
57
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
58
- do_action ("ws_plugin__s2member_during_custom_field_gen_before", get_defined_vars ());
59
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
60
- /**/
61
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
62
- $field_id_class = preg_replace ("/_/", "-", $field_var);
63
- /**/
64
- $name_suffix = (preg_match ("/\[$/", $_name_prefix)) ? ']' : '';
65
- $field_name = trim ($_name_prefix . $field_var . $name_suffix);
66
- /**/
67
- $common = ''; /* Common attribute configuration. */
68
- $common .= ' name="' . esc_attr ($field_name) . '"';
69
- $common .= ' id="' . esc_attr ($_id_prefix . $field_id_class) . '"';
70
- $common .= ((!empty ($field["required"]) && $field["required"] === "yes") ? ' aria-required="true"' : '');
71
- $common .= ((strlen ($_tabindex)) ? ' tabindex="' . esc_attr ($_tabindex) . '"' : ''); /* No tabindex if empty. */
72
- $common .= ((!empty ($field["expected"])) ? ' data-expected="' . esc_attr ($field["expected"]) . '"' : ''); /* Certain data expected? */
73
- $common .= (($_editable_context === "profile-view" || (!empty ($field["editable"]) && strpos ($field["editable"], "no") === 0 && $_editable_context === "profile")) ? ' disabled="disabled"' : '');
74
- $common .= (($_classes || !empty ($field["classes"])) ? ' class="' . esc_attr (trim ($_classes . ((!empty ($field["classes"])) ? ' ' . $field["classes"] : ''))) . '"' : '');
75
- $common .= (($_styles || !empty ($field["styles"])) ? ' style="' . esc_attr (trim ($_styles . ((!empty ($field["styles"])) ? ' ' . $field["styles"] : ''))) . '"' : '');
76
- $common .= (($_attrs || !empty ($field["attrs"])) ? ' ' . trim ($_attrs . ((!empty ($field["attrs"])) ? ' ' . $field["attrs"] : '')) : '');
77
- /**/
78
- if ($field["type"] === "text")
79
  {
80
- if ($_editable_context === "profile-view")
81
- $gen = esc_html ((string)$_value);
82
  /**/
83
- else /* Else handle this Field normally. */
84
  {
85
  $gen = '<input type="text" maxlength="100" autocomplete="off"';
86
- $gen .= ' value="' . format_to_edit ((isset ($field["deflt"]) && strlen ($field["deflt"]) && !$_submission) ? (string)$field["deflt"] : (string)$_value) . '"';
87
- $gen .= $common . ' />';
88
  }
89
  }
90
  /**/
91
- else if ($field["type"] === "textarea")
92
  {
93
- if ($_editable_context === "profile-view")
94
- $gen = nl2br (esc_html ((string)$_value));
95
  /**/
96
- else /* Else handle this Field normally. */
97
  {
98
- $gen = '<textarea rows="3"' . $common . '>';
99
- $gen .= format_to_edit ((isset ($field["deflt"]) && strlen ($field["deflt"]) && !$_submission) ? (string)$field["deflt"] : (string)$_value);
100
  $gen .= '</textarea>';
101
  }
102
  }
103
  /**/
104
- else if ($field["type"] === "select" && !empty ($field["options"]))
105
  {
106
- if ($_editable_context === "profile-view")
107
  {
108
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $option_line)
109
  {
110
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
111
- if ($option_value === (string)$_value)
112
  {
113
  $gen = $option_label;
114
  break;
115
  }
116
  }
117
  }
118
- else /* Else handle this Field normally. */
119
  {
120
- $gen = '<select' . $common . '>';
121
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $option_line)
 
122
  {
123
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
124
- $gen .= '<option value="' . esc_attr ($option_value) . '"' . ((($option_default && !$_submission) || $option_value === (string)$_value) ? ' selected="selected"' : '') . '>' . $option_label . '</option>';
125
  }
126
  $gen .= '</select>';
127
  }
128
  }
129
  /**/
130
- else if ($field["type"] === "selects" && !empty ($field["options"]))
131
  {
132
- if ($_editable_context === "profile-view")
133
  {
134
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $option_line)
135
  {
136
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
137
- if (in_array ($option_value, (array)$_value))
138
- $gen .= $option_label . ", ";
139
  }
140
- $gen = trim ($gen, ", \r\n\t\0\x0B");
141
  }
142
- else /* Else handle this Field normally. */
143
  {
144
- $common = preg_replace ('/ name\="(.+?)"/', ' name="$1[]"', $common);
145
- $common = preg_replace ('/ style\="(.+?)"/', ' style="height:auto; $1"', $common);
146
  /**/
147
- $gen = '<select multiple="multiple" size="3"' . $common . '>';
148
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $option_line)
149
  {
150
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
151
- $gen .= '<option value="' . esc_attr ($option_value) . '"' . ((($option_default && !$_submission) || in_array ($option_value, (array)$_value)) ? ' selected="selected"' : '') . '>' . $option_label . '</option>';
152
  }
153
  $gen .= '</select>';
154
  }
155
  }
156
  /**/
157
- else if ($field["type"] === "checkbox" && !empty ($field["label"]))
158
  {
159
- if ($_editable_context === "profile-view")
160
  $gen = ((string)$_value) ? "yes" : "no";
161
  /**/
162
- else /* Else handle this Field normally. */
163
  {
164
  $gen = '<input type="checkbox" value="1"';
165
  $gen .= (((string)$_value) ? ' checked="checked"' : '');
166
- $gen .= $common . ' /><label for="' . esc_attr ($_id_prefix . $field_id_class) . '" style="display:inline !important; margin:0 !important;">' . $field["label"] . '</label>';
167
  }
168
  }
169
  /**/
170
- else if ($field["type"] === "pre_checkbox" && !empty ($field["label"]))
171
  {
172
- if ($_editable_context === "profile-view")
173
  $gen = ((string)$_value) ? "yes" : "no";
174
  /**/
175
- else /* Else handle this Field normally. */
176
  {
177
  $gen = '<input type="checkbox" value="1"';
178
  $gen .= ((!$_submission || (string)$_value) ? ' checked="checked"' : '');
179
- $gen .= $common . ' /><label for="' . esc_attr ($_id_prefix . $field_id_class) . '" style="display:inline !important; margin:0 !important;">' . $field["label"] . '</label>';
180
  }
181
  }
182
  /**/
183
- else if ($field["type"] === "checkboxes" && !empty ($field["options"]))
184
  {
185
- if ($_editable_context === "profile-view")
186
  {
187
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
188
  {
189
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
190
- if (in_array ($option_value, (array)$_value))
191
- $gen .= $option_label . ", ";
192
  }
193
- $gen = trim ($gen, ", \r\n\t\0\x0B");
194
  }
195
- else /* Else handle this Field normally. */
196
  {
197
- $common = preg_replace ('/ name\="(.+?)"/', ' name="$1[]"', $common);
198
  /**/
199
- $sep = apply_filters ("ws_plugin__s2member_custom_field_gen_checkboxes_sep", "&nbsp;&nbsp;", get_defined_vars ());
200
- $opl = apply_filters ("ws_plugin__s2member_custom_field_gen_checkboxes_opl", "ws-plugin--s2member-custom-reg-field-op-l", get_defined_vars ());
201
  /**/
202
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
203
  {
204
- $common_i = preg_replace ('/ id\="(.+?)"/', ' id="$1-' . ($i) . '"', $common);
205
  /**/
206
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
207
  /**/
208
  $gen .= ($i > 0) ? $sep : ''; /* Separators can be filtered above. */
209
- $gen .= '<input type="checkbox" value="' . esc_attr ($option_value) . '"';
210
- $gen .= ((($option_default && !$_submission) || in_array ($option_value, (array)$_value)) ? ' checked="checked"' : '');
211
- $gen .= $common_i . ' /><label for="' . esc_attr ($_id_prefix . $field_id_class . "-" . $i) . '" class="' . esc_attr ($opl) . '" style="display:inline !important; margin:0 !important;">' . $option_label . '</label>';
212
  }
213
  }
214
  }
215
  /**/
216
- else if ($field["type"] === "radios" && !empty ($field["options"]))
217
  {
218
- if ($_editable_context === "profile-view")
219
  {
220
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
221
  {
222
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
223
- if ($option_value === (string)$_value)
224
  {
225
  $gen = $option_label;
226
  break;
227
  }
228
  }
229
  }
230
- else /* Else handle this Field normally. */
231
  {
232
- $sep = apply_filters ("ws_plugin__s2member_custom_field_gen_radios_sep", "&nbsp;&nbsp;", get_defined_vars ());
233
- $opl = apply_filters ("ws_plugin__s2member_custom_field_gen_radios_opl", "ws-plugin--s2member-custom-reg-field-op-l", get_defined_vars ());
234
  /**/
235
- foreach (preg_split ("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
236
  {
237
- $common_i = preg_replace ('/ id\="(.+?)"/', ' id="$1-' . ($i) . '"', $common);
238
  /**/
239
- list ($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/\|/", trim ($option_line)));
240
  /**/
241
  $gen .= ($i > 0) ? $sep : ''; /* Separators can be filtered above. */
242
- $gen .= '<input type="radio" value="' . esc_attr ($option_value) . '"';
243
  $gen .= ((($option_default && !$_submission) || $option_value === (string)$_value) ? ' checked="checked"' : '');
244
- $gen .= $common_i . ' /><label for="' . esc_attr ($_id_prefix . $field_id_class . "-" . $i) . '" class="' . esc_attr ($opl) . '" style="display:inline !important; margin:0 !important;">' . $option_label . '</label>';
245
  }
246
  }
247
  }
248
- else /* Default to using a text field. */
249
  {
250
- if ($_editable_context === "profile-view")
251
- $gen = esc_html ((string)$_value);
252
  /**/
253
- else /* Else handle this Field normally. */
254
  {
255
  $gen = '<input type="text" maxlength="100" autocomplete="off"';
256
- $gen .= ' value="' . format_to_edit ((isset ($field["deflt"]) && strlen ($field["deflt"]) && !$_submission) ? (string)$field["deflt"] : (string)$_value) . '"';
257
- $gen .= $common . ' />';
258
  }
259
  }
260
  /**/
261
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
262
- do_action ("ws_plugin__s2member_during_custom_field_gen_after", get_defined_vars ());
263
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
264
  }
265
  /**/
266
- return apply_filters ("ws_plugin__s2member_custom_field_gen", $gen, get_defined_vars ());
267
  }
268
  /**
269
  * Determines which Custom Fields apply to a specific Level.
@@ -276,27 +277,27 @@ if (!class_exists ("c_ws_plugin__s2member_custom_reg_fields"))
276
  * @param str $_editable_context Optional. One of `profile|profile-view|registration`.
277
  * @return array Array of Custom Field IDs applicable.
278
  */
279
- public static function custom_fields_configured_at_level ($_level = "auto-detection", $_editable_context = FALSE)
280
  {
281
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
282
- do_action ("ws_plugin__s2member_before_custom_fields_configured_at_level", get_defined_vars ());
283
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
284
  /**/
285
- $level = ($_level === "auto-detection") ? c_ws_plugin__s2member_user_access::user_access_level () : $_level;
286
- if ($_level === "auto-detection" && $level < 0 && ($reg_cookies = c_ws_plugin__s2member_register_access::reg_cookies_ok ()) && extract ($reg_cookies) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $item_number, $m) && !empty ($m[1]) && is_numeric ($m[1]))
287
- $level = $m[1]; /* A numeric Membership Level # . */
288
  /**/
289
- $level = ($level !== "any" && (!is_numeric ($level) || $level < 0)) ? 0 : $level; /* Default. */
290
  /**/
291
- if (($level === "any" || (is_numeric ($level) && $level >= 0)) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
292
  {
293
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
294
- if ($level === "any" || $field["levels"] === "all" || in_array ($level, preg_split ("/[;,]+/", preg_replace ("/[^0-9;,]/", "", $field["levels"]))))
295
- if (empty ($_editable_context) || $_editable_context === "administrative" || ($_editable_context === "registration" && $field["editable"] !== "yes-invisible") || (($_editable_context === "profile" || $_editable_context === "profile-view") && $field["editable"] !== "no-invisible"))
296
  $configured[] = $field["id"]; /* Add this to the array. */
297
  }
298
  /**/
299
- return apply_filters ("ws_plugin__s2member_custom_fields_configured_at_level", ((!empty ($configured)) ? $configured : array ()), get_defined_vars ());
300
  }
301
  /**
302
  * Adds Custom Fields to: `/wp-signup.php`.
@@ -312,105 +313,105 @@ if (!class_exists ("c_ws_plugin__s2member_custom_reg_fields"))
312
  *
313
  * @todo Optimize with ``empty()``.
314
  */
315
- public static function ms_custom_registration_fields ()
316
  {
317
- do_action ("ws_plugin__s2member_before_ms_custom_registration_fields", get_defined_vars ());
318
  /**/
319
- if (is_multisite () && is_main_site ()) /* Must be Main Site of a Network. */
320
  {
321
- $_p = (!empty ($_POST)) ? c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep ($_POST)) : array ();
322
  /**/
323
- echo '<input type="hidden" name="ws_plugin__s2member_registration" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-registration")) . '" />' . "\n";
324
  /**/
325
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
326
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_before", get_defined_vars ());
327
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
328
  /**/
329
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_names"])
330
  {
331
- echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section"></div>' . "\n";
332
  /**/
333
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
334
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_before_first_name", get_defined_vars ());
335
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
336
  /**/
337
- echo '<label for="ws-plugin--s2member-custom-reg-field-first-name">' . _x ("First Name", "s2member-front", "s2member") . ' *</label>' . "\n";
338
- echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="' . esc_attr ($_p["ws_plugin__s2member_custom_reg_field_first_name"]) . '" />' . "\n";
339
- echo '<br />' . "\n";
340
  /**/
341
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
342
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_after_first_name", get_defined_vars ());
343
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
344
  /**/
345
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
346
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_before_last_name", get_defined_vars ());
347
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
348
  /**/
349
- echo '<label for="ws-plugin--s2member-custom-reg-field-last-name">' . _x ("Last Name", "s2member-front", "s2member") . ' *</label>' . "\n";
350
- echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="' . esc_attr ($_p["ws_plugin__s2member_custom_reg_field_last_name"]) . '" />' . "\n";
351
- echo '<br />' . "\n";
352
  /**/
353
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
354
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_after_last_name", get_defined_vars ());
355
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
356
  }
357
  /**/
358
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
359
- if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level ("auto-detection", "registration"))
360
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
361
  {
362
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
363
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_before_custom_fields", get_defined_vars ());
364
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
365
  /**/
366
- if (in_array ($field["id"], $fields_applicable)) /* Field applicable? */
367
  {
368
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
369
- $field_id_class = preg_replace ("/_/", "-", $field_var);
370
  /**/
371
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
372
- if (apply_filters ("ws_plugin__s2member_during_ms_custom_registration_fields_during_custom_fields_display", true, get_defined_vars ()))
373
  {
374
- if (!empty ($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
375
- echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section' . ((!empty ($field["sectitle"])) ? '-title' : '') . '">' . ((!empty ($field["sectitle"])) ? $field["sectitle"] : '') . '</div>';
376
  /**/
377
- echo '<label for="ws-plugin--s2member-custom-reg-field-' . esc_attr ($field_id_class) . '"' . ((preg_match ("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ' style="display:none;"' : '') . '>' . $field["label"] . (($field["required"] === "yes") ? ' *' : '') . '</label>' . ((preg_match ("/^(checkbox|pre_checkbox)$/", $field["type"])) ? '<br />' : '') . "\n";
378
- echo c_ws_plugin__s2member_custom_reg_fields::custom_field_gen (__FUNCTION__, $field, "ws_plugin__s2member_custom_reg_field_", "ws-plugin--s2member-custom-reg-field-", "ws-plugin--s2member-custom-reg-field", "", "", "", $_p, $_p["ws_plugin__s2member_custom_reg_field_" . $field_var], "registration");
379
- echo '<br />' . "\n";
380
  }
381
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
382
  }
383
  /**/
384
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
385
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_after_custom_fields", get_defined_vars ());
386
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
387
  }
388
  /**/
389
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] && c_ws_plugin__s2member_list_servers::list_servers_integrated ())
390
  {
391
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
392
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_before_opt_in", get_defined_vars ());
393
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
394
  /**/
395
- echo '<label for="ws-plugin--s2member-custom-reg-field-opt-in">' . "\n";
396
- echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_field_opt_in" id="ws-plugin--s2member-custom-reg-field-opt-in" class="ws-plugin--s2member-custom-reg-field" value="1"' . (((empty ($_p) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) || $_p["ws_plugin__s2member_custom_reg_field_opt_in"]) ? ' checked="checked"' : '') . ' />' . "\n";
397
- echo $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"] . "\n";
398
- echo '</label>' . "\n";
399
- echo '<br />' . "\n";
400
  /**/
401
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
402
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_after_opt_in", get_defined_vars ());
403
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
404
  }
405
  /**/
406
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
407
- do_action ("ws_plugin__s2member_during_ms_custom_registration_fields_after", get_defined_vars ());
408
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
409
  }
410
  /**/
411
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
412
- do_action ("ws_plugin__s2member_after_ms_custom_registration_fields", get_defined_vars ());
413
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
414
  /**/
415
  return; /* Return for uniformity. */
416
  }
@@ -426,143 +427,143 @@ if (!class_exists ("c_ws_plugin__s2member_custom_reg_fields"))
426
  *
427
  * @todo Optimize with ``empty()``.
428
  */
429
- public static function custom_registration_fields ()
430
  {
431
- do_action ("ws_plugin__s2member_before_custom_registration_fields", get_defined_vars ());
432
  /**/
433
- $_p = (!empty ($_POST)) ? c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep ($_POST)) : array ();
434
  /**/
435
- echo '<input type="hidden" name="ws_plugin__s2member_registration" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-registration")) . '" />' . "\n";
436
  /**/
437
  $tabindex = 20; /* Incremented tabindex starting with 20. */
438
  /**/
439
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
440
- do_action ("ws_plugin__s2member_during_custom_registration_fields_before", get_defined_vars ());
441
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
442
  /**/
443
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
444
  {
445
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
446
- do_action ("ws_plugin__s2member_during_custom_registration_fields_before_user_pass", get_defined_vars ());
447
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
448
  /**/
449
- echo '<p>' . "\n";
450
  /**/
451
- echo '<label for="ws-plugin--s2member-custom-reg-field-user-pass1" title="' . esc_attr (_x ("Please type your Password twice to confirm.", "s2member-front", "s2member")) . '">' . "\n";
452
- echo '<span>' . _x ("Password ( please type it twice )", "s2member-front", "s2member") . ' *</span><br />' . "\n";
453
- echo '<input type="password" aria-required="true" maxlength="100" autocomplete="off" name="ws_plugin__s2member_custom_reg_field_user_pass1" id="ws-plugin--s2member-custom-reg-field-user-pass1" class="ws-plugin--s2member-custom-reg-field" value="' . format_to_edit ($_p["ws_plugin__s2member_custom_reg_field_user_pass1"]) . '" tabindex="' . esc_attr (($tabindex = $tabindex + 10)) . '" />' . "\n";
454
- echo '</label>' . "\n";
455
  /**/
456
- echo '<label for="ws-plugin--s2member-custom-reg-field-user-pass2" title="' . esc_attr (_x ("Please type your Password twice to confirm.", "s2member-front", "s2member")) . '">' . "\n";
457
- echo '<input type="password" maxlength="100" autocomplete="off" name="ws_plugin__s2member_custom_reg_field_user_pass2" id="ws-plugin--s2member-custom-reg-field-user-pass2" class="ws-plugin--s2member-custom-reg-field" value="' . format_to_edit ($_p["ws_plugin__s2member_custom_reg_field_user_pass2"]) . '" tabindex="' . esc_attr (($tabindex = $tabindex + 10)) . '" />' . "\n";
458
- echo '</label>' . "\n";
459
  /**/
460
- echo '<div id="ws-plugin--s2member-custom-reg-field-user-pass-strength" class="ws-plugin--s2member-password-strength"><em>' . _x ("password strength indicator", "s2member-front", "s2member") . '</em></div>' . "\n";
461
  /**/
462
- echo '</p>' . "\n";
463
  /**/
464
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
465
- do_action ("ws_plugin__s2member_during_custom_registration_fields_after_user_pass", get_defined_vars ());
466
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
467
  }
468
  /**/
469
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_names"])
470
  {
471
- echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section"></div>' . "\n";
472
- /**/
473
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
474
- do_action ("ws_plugin__s2member_during_custom_registration_fields_before_first_name", get_defined_vars ());
475
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
476
- /**/
477
- echo '<p>' . "\n";
478
- echo '<label for="ws-plugin--s2member-custom-reg-field-first-name">' . "\n";
479
- echo '<span>' . _x ("First Name", "s2member-front", "s2member") . ' *</span><br />' . "\n";
480
- echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="' . esc_attr ($_p["ws_plugin__s2member_custom_reg_field_first_name"]) . '" tabindex="' . esc_attr (($tabindex = $tabindex + 10)) . '" />' . "\n";
481
- echo '</label>' . "\n";
482
- echo '</p>' . "\n";
483
- /**/
484
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
485
- do_action ("ws_plugin__s2member_during_custom_registration_fields_after_first_name", get_defined_vars ());
486
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
487
- /**/
488
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
489
- do_action ("ws_plugin__s2member_during_custom_registration_fields_before_last_name", get_defined_vars ());
490
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
491
- /**/
492
- echo '<p>' . "\n";
493
- echo '<label for="ws-plugin--s2member-custom-reg-field-last-name">' . "\n";
494
- echo '<span>' . _x ("Last Name", "s2member-front", "s2member") . ' *</span><br />' . "\n";
495
- echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="' . esc_attr ($_p["ws_plugin__s2member_custom_reg_field_last_name"]) . '" tabindex="' . esc_attr (($tabindex = $tabindex + 10)) . '" />' . "\n";
496
- echo '</label>' . "\n";
497
- echo '</p>' . "\n";
498
- /**/
499
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
500
- do_action ("ws_plugin__s2member_during_custom_registration_fields_after_last_name", get_defined_vars ());
501
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
502
  }
503
  /**/
504
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
505
- if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level ("auto-detection", "registration"))
506
  {
507
  $tabindex = $tabindex + 9; /* Start tabindex at +9 ( +1 below ). */
508
  /**/
509
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
510
  {
511
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
512
- do_action ("ws_plugin__s2member_during_custom_registration_fields_before_custom_fields", get_defined_vars ());
513
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
514
  /**/
515
- if (in_array ($field["id"], $fields_applicable)) /* Field applicable? */
516
  {
517
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
518
- $field_id_class = preg_replace ("/_/", "-", $field_var);
519
  /**/
520
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
521
- if (apply_filters ("ws_plugin__s2member_during_custom_registration_fields_during_custom_fields_display", true, get_defined_vars ()))
522
  {
523
- if (!empty ($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
524
- echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section' . ((!empty ($field["sectitle"])) ? '-title' : '') . '">' . ((!empty ($field["sectitle"])) ? $field["sectitle"] : '') . '</div>';
525
  /**/
526
- echo '<p>' . "\n";
527
- echo '<label for="ws-plugin--s2member-custom-reg-field-' . esc_attr ($field_id_class) . '">' . "\n";
528
- echo '<span' . ((preg_match ("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ' style="display:none;"' : '') . '>' . $field["label"] . (($field["required"] === "yes") ? ' *' : '') . '</span></label>' . ((preg_match ("/^(checkbox|pre_checkbox)$/", $field["type"])) ? '' : '<br />') . "\n";
529
- echo c_ws_plugin__s2member_custom_reg_fields::custom_field_gen (__FUNCTION__, $field, "ws_plugin__s2member_custom_reg_field_", "ws-plugin--s2member-custom-reg-field-", "ws-plugin--s2member-custom-reg-field", "", ($tabindex = $tabindex + 1), "", $_p, $_p["ws_plugin__s2member_custom_reg_field_" . $field_var], "registration");
530
- echo '</p>' . "\n";
531
  }
532
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
533
  }
534
  /**/
535
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
536
- do_action ("ws_plugin__s2member_during_custom_registration_fields_after_custom_fields", get_defined_vars ());
537
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
538
  }
539
  }
540
  /**/
541
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] && c_ws_plugin__s2member_list_servers::list_servers_integrated ())
542
  {
543
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
544
- do_action ("ws_plugin__s2member_during_custom_registration_fields_before_opt_in", get_defined_vars ());
545
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
546
- /**/
547
- echo '<p>' . "\n";
548
- echo '<label for="ws-plugin--s2member-custom-reg-field-opt-in">' . "\n";
549
- echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_field_opt_in" id="ws-plugin--s2member-custom-reg-field-opt-in" class="ws-plugin--s2member-custom-reg-field" value="1"' . (((empty ($_p) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) || $_p["ws_plugin__s2member_custom_reg_field_opt_in"]) ? ' checked="checked"' : '') . ' tabindex="' . esc_attr (($tabindex = $tabindex + 10)) . '" />' . "\n";
550
- echo $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"] . "\n";
551
- echo '</label>' . "\n";
552
- echo '</p>' . "\n";
553
- /**/
554
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
555
- do_action ("ws_plugin__s2member_during_custom_registration_fields_after_opt_in", get_defined_vars ());
556
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
557
  }
558
  /**/
559
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
560
- do_action ("ws_plugin__s2member_during_custom_registration_fields_after", get_defined_vars ());
561
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
562
  /**/
563
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
564
- do_action ("ws_plugin__s2member_after_custom_registration_fields", get_defined_vars ());
565
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
566
  /**/
567
  return; /* Return for uniformity. */
568
  }
14
  * @package s2Member\Custom_Reg_Fields
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_custom_reg_fields"))
21
  {
22
  /**
23
  * Custom Registration/Profile Fields for s2Member.
46
  * @param str $_editable_context Optional. One of `profile|profile-view|registration`.
47
  * @return str The resulting Custom Field, in HTML format.
48
  */
49
+ public static function custom_field_gen($_function = FALSE, $_field = FALSE, $_name_prefix = FALSE, $_id_prefix = FALSE, $_classes = FALSE, $_styles = FALSE, $_tabindex = FALSE, $_attrs = FALSE, $_submission = FALSE, $_value = FALSE, $_editable_context = FALSE)
50
  {
51
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
52
+ do_action("ws_plugin__s2member_before_custom_field_gen", get_defined_vars());
53
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
54
  /**/
55
+ if(!($gen = "") && $_function && is_array($field = $_field) && !empty($field["type"]) && !empty($field["id"]) && $_name_prefix && $_id_prefix)
56
  {
57
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
58
+ do_action("ws_plugin__s2member_during_custom_field_gen_before", get_defined_vars());
59
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
60
+ /**/
61
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
62
+ $field_id_class = preg_replace("/_/", "-", $field_var);
63
+ /**/
64
+ $name_suffix = (preg_match("/\[$/", $_name_prefix)) ? ']' : '';
65
+ $field_name = trim($_name_prefix.$field_var.$name_suffix);
66
+ /**/
67
+ $common = ''; /* Common attributes. */
68
+ $common .= ' name="'.esc_attr($field_name).'"';
69
+ $common .= ' id="'.esc_attr($_id_prefix.$field_id_class).'"';
70
+ $common .= ((!empty($field["required"]) && $field["required"] === "yes") ? ' aria-required="true"' : '');
71
+ $common .= ((strlen($_tabindex)) ? ' tabindex="'.esc_attr($_tabindex).'"' : /* No tabindex if empty. */ '');
72
+ $common .= (( /* Certain data expected? */!empty($field["expected"])) ? ' data-expected="'.esc_attr($field["expected"]).'"' : '');
73
+ $common .= (($_editable_context === "profile-view" || (!empty($field["editable"]) && strpos($field["editable"], "no") === 0 && $_editable_context === "profile")) ? ' disabled="disabled"' : '');
74
+ $common .= (($_classes || !empty($field["classes"])) ? ' class="'.esc_attr(trim($_classes.((!empty($field["classes"])) ? ' '.$field["classes"] : ''))).'"' : '');
75
+ $common .= (($_styles || !empty($field["styles"])) ? ' style="'.esc_attr(trim($_styles.((!empty($field["styles"])) ? ' '.$field["styles"] : ''))).'"' : '');
76
+ $common .= (($_attrs || !empty($field["attrs"])) ? ' '.trim($_attrs.((!empty($field["attrs"])) ? ' '.$field["attrs"] : '')) : '');
77
+ /**/
78
+ if($field["type"] === "text")
79
  {
80
+ if($_editable_context === "profile-view")
81
+ $gen = esc_html((string)$_value);
82
  /**/
83
+ else /* Else handle normally. */
84
  {
85
  $gen = '<input type="text" maxlength="100" autocomplete="off"';
86
+ $gen .= ' value="'.format_to_edit((!$_submission && isset($field["deflt"]) && strlen((string)$field["deflt"])) ? (string)$field["deflt"] : (string)$_value).'"';
87
+ $gen .= $common.' />';
88
  }
89
  }
90
  /**/
91
+ else if($field["type"] === "textarea")
92
  {
93
+ if($_editable_context === "profile-view")
94
+ $gen = nl2br(esc_html((string)$_value));
95
  /**/
96
+ else /* Else handle normally. */
97
  {
98
+ $gen = '<textarea rows="3"'.$common.'>';
99
+ $gen .= format_to_edit((!$_submission && isset($field["deflt"]) && strlen((string)$field["deflt"])) ? (string)$field["deflt"] : (string)$_value);
100
  $gen .= '</textarea>';
101
  }
102
  }
103
  /**/
104
+ else if($field["type"] === "select" && !empty($field["options"]))
105
  {
106
+ if($_editable_context === "profile-view")
107
  {
108
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $option_line)
109
  {
110
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
111
+ if($option_value === (string)$_value)
112
  {
113
  $gen = $option_label;
114
  break;
115
  }
116
  }
117
  }
118
+ else /* Else handle normally. */
119
  {
120
+ $gen = '<select'.$common.'>';
121
+ $selected_default_option = false;
122
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $option_line)
123
  {
124
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
125
+ $gen .= '<option value="'.esc_attr($option_value).'"'.(((($option_default && !$_submission) || ($option_value === (string)$_value && !$selected_default_option)) && ($selected_default_option = true)) ? ' selected="selected"' : '').'>'.$option_label.'</option>';
126
  }
127
  $gen .= '</select>';
128
  }
129
  }
130
  /**/
131
+ else if($field["type"] === "selects" && !empty($field["options"]))
132
  {
133
+ if($_editable_context === "profile-view")
134
  {
135
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $option_line)
136
  {
137
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
138
+ if(in_array($option_value, (array)$_value))
139
+ $gen .= $option_label.", ";
140
  }
141
+ $gen = c_ws_plugin__s2member_utils_strings::trim($gen, 0, ",");
142
  }
143
+ else /* Else handle normally. */
144
  {
145
+ $common = preg_replace('/ name\="(.+?)"/', ' name="$1[]"', $common);
146
+ $common = preg_replace('/ style\="(.+?)"/', ' style="height:auto; $1"', $common);
147
  /**/
148
+ $gen = '<select multiple="multiple" size="3"'.$common.'>';
149
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $option_line)
150
  {
151
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
152
+ $gen .= '<option value="'.esc_attr($option_value).'"'.((($option_default && !$_submission) || in_array($option_value, (array)$_value)) ? ' selected="selected"' : '').'>'.$option_label.'</option>';
153
  }
154
  $gen .= '</select>';
155
  }
156
  }
157
  /**/
158
+ else if($field["type"] === "checkbox" && !empty($field["label"]))
159
  {
160
+ if($_editable_context === "profile-view")
161
  $gen = ((string)$_value) ? "yes" : "no";
162
  /**/
163
+ else /* Else handle normally. */
164
  {
165
  $gen = '<input type="checkbox" value="1"';
166
  $gen .= (((string)$_value) ? ' checked="checked"' : '');
167
+ $gen .= $common.' /><label for="'.esc_attr($_id_prefix.$field_id_class).'" style="display:inline !important; margin:0 !important;">'.$field["label"].'</label>';
168
  }
169
  }
170
  /**/
171
+ else if($field["type"] === "pre_checkbox" && !empty($field["label"]))
172
  {
173
+ if($_editable_context === "profile-view")
174
  $gen = ((string)$_value) ? "yes" : "no";
175
  /**/
176
+ else /* Else handle normally. */
177
  {
178
  $gen = '<input type="checkbox" value="1"';
179
  $gen .= ((!$_submission || (string)$_value) ? ' checked="checked"' : '');
180
+ $gen .= $common.' /><label for="'.esc_attr($_id_prefix.$field_id_class).'" style="display:inline !important; margin:0 !important;">'.$field["label"].'</label>';
181
  }
182
  }
183
  /**/
184
+ else if($field["type"] === "checkboxes" && !empty($field["options"]))
185
  {
186
+ if($_editable_context === "profile-view")
187
  {
188
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
189
  {
190
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
191
+ if(in_array($option_value, (array)$_value))
192
+ $gen .= $option_label.", ";
193
  }
194
+ $gen = c_ws_plugin__s2member_utils_strings::trim($gen, 0, ",");
195
  }
196
+ else /* Else handle normally. */
197
  {
198
+ $common = preg_replace('/ name\="(.+?)"/', ' name="$1[]"', $common);
199
  /**/
200
+ $sep = apply_filters("ws_plugin__s2member_custom_field_gen_checkboxes_sep", "&nbsp;&nbsp;", get_defined_vars());
201
+ $opl = apply_filters("ws_plugin__s2member_custom_field_gen_checkboxes_opl", "ws-plugin--s2member-custom-reg-field-op-l", get_defined_vars());
202
  /**/
203
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
204
  {
205
+ $common_i = preg_replace('/ id\="(.+?)"/', ' id="$1-'.($i).'"', $common);
206
  /**/
207
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
208
  /**/
209
  $gen .= ($i > 0) ? $sep : ''; /* Separators can be filtered above. */
210
+ $gen .= '<input type="checkbox" value="'.esc_attr($option_value).'"';
211
+ $gen .= ((($option_default && !$_submission) || in_array($option_value, (array)$_value)) ? ' checked="checked"' : '');
212
+ $gen .= $common_i.' /><label for="'.esc_attr($_id_prefix.$field_id_class."-".$i).'" class="'.esc_attr($opl).'" style="display:inline !important; margin:0 !important;">'.$option_label.'</label>';
213
  }
214
  }
215
  }
216
  /**/
217
+ else if($field["type"] === "radios" && !empty($field["options"]))
218
  {
219
+ if($_editable_context === "profile-view")
220
  {
221
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
222
  {
223
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
224
+ if($option_value === (string)$_value)
225
  {
226
  $gen = $option_label;
227
  break;
228
  }
229
  }
230
  }
231
+ else /* Else handle normally. */
232
  {
233
+ $sep = apply_filters("ws_plugin__s2member_custom_field_gen_radios_sep", "&nbsp;&nbsp;", get_defined_vars());
234
+ $opl = apply_filters("ws_plugin__s2member_custom_field_gen_radios_opl", "ws-plugin--s2member-custom-reg-field-op-l", get_defined_vars());
235
  /**/
236
+ foreach(preg_split("/[\r\n\t]+/", $field["options"]) as $i => $option_line)
237
  {
238
+ $common_i = preg_replace('/ id\="(.+?)"/', ' id="$1-'.($i).'"', $common);
239
  /**/
240
+ list($option_value, $option_label, $option_default) = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/\|/", trim($option_line)));
241
  /**/
242
  $gen .= ($i > 0) ? $sep : ''; /* Separators can be filtered above. */
243
+ $gen .= '<input type="radio" value="'.esc_attr($option_value).'"';
244
  $gen .= ((($option_default && !$_submission) || $option_value === (string)$_value) ? ' checked="checked"' : '');
245
+ $gen .= $common_i.' /><label for="'.esc_attr($_id_prefix.$field_id_class."-".$i).'" class="'.esc_attr($opl).'" style="display:inline !important; margin:0 !important;">'.$option_label.'</label>';
246
  }
247
  }
248
  }
249
+ else /* Default to a text field input type when nothing matches. */
250
  {
251
+ if($_editable_context === "profile-view")
252
+ $gen = esc_html((string)$_value);
253
  /**/
254
+ else /* Else handle normally. */
255
  {
256
  $gen = '<input type="text" maxlength="100" autocomplete="off"';
257
+ $gen .= ' value="'.format_to_edit((!$_submission && isset($field["deflt"]) && strlen((string)$field["deflt"])) ? (string)$field["deflt"] : (string)$_value).'"';
258
+ $gen .= $common.' />';
259
  }
260
  }
261
  /**/
262
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
263
+ do_action("ws_plugin__s2member_during_custom_field_gen_after", get_defined_vars());
264
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
265
  }
266
  /**/
267
+ return apply_filters("ws_plugin__s2member_custom_field_gen", $gen, get_defined_vars());
268
  }
269
  /**
270
  * Determines which Custom Fields apply to a specific Level.
277
  * @param str $_editable_context Optional. One of `profile|profile-view|registration`.
278
  * @return array Array of Custom Field IDs applicable.
279
  */
280
+ public static function custom_fields_configured_at_level($_level = "auto-detection", $_editable_context = FALSE)
281
  {
282
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
283
+ do_action("ws_plugin__s2member_before_custom_fields_configured_at_level", get_defined_vars());
284
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
285
  /**/
286
+ $level = ($_level === "auto-detection") ? c_ws_plugin__s2member_user_access::user_access_level() : $_level;
287
+ if($_level === "auto-detection" && $level < 0 && ($reg_cookies = c_ws_plugin__s2member_register_access::reg_cookies_ok()) && extract($reg_cookies) && preg_match($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $item_number, $m) && !empty($m[1]) && is_numeric($m[1]))
288
+ $level = /* A numeric Membership Level # . */ $m[1];
289
  /**/
290
+ $level = ($level !== "any" && (!is_numeric($level) || $level < 0)) ? 0 : /* Default. */ $level;
291
  /**/
292
+ if(($level === "any" || (is_numeric($level) && $level >= 0)) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
293
  {
294
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
295
+ if($level === "any" || $field["levels"] === "all" || in_array($level, preg_split("/[;,]+/", preg_replace("/[^0-9;,]/", "", $field["levels"]))))
296
+ if(empty($_editable_context) || $_editable_context === "administrative" || ($_editable_context === "registration" && $field["editable"] !== "yes-invisible") || (($_editable_context === "profile" || $_editable_context === "profile-view") && $field["editable"] !== "no-invisible"))
297
  $configured[] = $field["id"]; /* Add this to the array. */
298
  }
299
  /**/
300
+ return apply_filters("ws_plugin__s2member_custom_fields_configured_at_level", ((!empty($configured)) ? $configured : array()), get_defined_vars());
301
  }
302
  /**
303
  * Adds Custom Fields to: `/wp-signup.php`.
313
  *
314
  * @todo Optimize with ``empty()``.
315
  */
316
+ public static function ms_custom_registration_fields()
317
  {
318
+ do_action("ws_plugin__s2member_before_ms_custom_registration_fields", get_defined_vars());
319
  /**/
320
+ if(is_multisite() && is_main_site()) /* Must be Main Site of a Network. */
321
  {
322
+ $_p = (!empty($_POST)) ? c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST)) : array();
323
  /**/
324
+ echo '<input type="hidden" name="ws_plugin__s2member_registration" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-registration")).'" />'."\n";
325
  /**/
326
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
327
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_before", get_defined_vars());
328
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
329
  /**/
330
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_names"])
331
  {
332
+ echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section"></div>'."\n";
333
  /**/
334
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
335
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_before_first_name", get_defined_vars());
336
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
337
  /**/
338
+ echo '<label for="ws-plugin--s2member-custom-reg-field-first-name">'._x("First Name", "s2member-front", "s2member").' *</label>'."\n";
339
+ echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="'.esc_attr($_p["ws_plugin__s2member_custom_reg_field_first_name"]).'" />'."\n";
340
+ echo '<br />'."\n";
341
  /**/
342
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
343
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_after_first_name", get_defined_vars());
344
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
345
  /**/
346
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
347
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_before_last_name", get_defined_vars());
348
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
349
  /**/
350
+ echo '<label for="ws-plugin--s2member-custom-reg-field-last-name">'._x("Last Name", "s2member-front", "s2member").' *</label>'."\n";
351
+ echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="'.esc_attr($_p["ws_plugin__s2member_custom_reg_field_last_name"]).'" />'."\n";
352
+ echo '<br />'."\n";
353
  /**/
354
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
355
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_after_last_name", get_defined_vars());
356
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
357
  }
358
  /**/
359
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
360
+ if($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level("auto-detection", "registration"))
361
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
362
  {
363
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
364
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_before_custom_fields", get_defined_vars());
365
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
366
  /**/
367
+ if(in_array($field["id"], $fields_applicable)) /* Field applicable? */
368
  {
369
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
370
+ $field_id_class = preg_replace("/_/", "-", $field_var);
371
  /**/
372
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
373
+ if(apply_filters("ws_plugin__s2member_during_ms_custom_registration_fields_during_custom_fields_display", true, get_defined_vars()))
374
  {
375
+ if(!empty($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
376
+ echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section'.((!empty($field["sectitle"])) ? '-title' : '').'">'.((!empty($field["sectitle"])) ? $field["sectitle"] : '').'</div>';
377
  /**/
378
+ echo '<label for="ws-plugin--s2member-custom-reg-field-'.esc_attr($field_id_class).'"'.((preg_match("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ' style="display:none;"' : '').'>'.$field["label"].(($field["required"] === "yes") ? ' *' : '').'</label>'.((preg_match("/^(checkbox|pre_checkbox)$/", $field["type"])) ? '<br />' : '')."\n";
379
+ echo c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_custom_reg_field_", "ws-plugin--s2member-custom-reg-field-", "ws-plugin--s2member-custom-reg-field", "", "", "", $_p, $_p["ws_plugin__s2member_custom_reg_field_".$field_var], "registration");
380
+ echo '<br />'."\n";
381
  }
382
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
383
  }
384
  /**/
385
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
386
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_after_custom_fields", get_defined_vars());
387
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
388
  }
389
  /**/
390
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] && c_ws_plugin__s2member_list_servers::list_servers_integrated())
391
  {
392
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
393
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_before_opt_in", get_defined_vars());
394
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
395
  /**/
396
+ echo '<label for="ws-plugin--s2member-custom-reg-field-opt-in">'."\n";
397
+ echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_field_opt_in" id="ws-plugin--s2member-custom-reg-field-opt-in" class="ws-plugin--s2member-custom-reg-field" value="1"'.(((empty($_p) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) || $_p["ws_plugin__s2member_custom_reg_field_opt_in"]) ? ' checked="checked"' : '').' />'."\n";
398
+ echo $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"]."\n";
399
+ echo '</label>'."\n";
400
+ echo '<br />'."\n";
401
  /**/
402
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
403
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_after_opt_in", get_defined_vars());
404
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
405
  }
406
  /**/
407
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
408
+ do_action("ws_plugin__s2member_during_ms_custom_registration_fields_after", get_defined_vars());
409
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
410
  }
411
  /**/
412
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
413
+ do_action("ws_plugin__s2member_after_ms_custom_registration_fields", get_defined_vars());
414
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
415
  /**/
416
  return; /* Return for uniformity. */
417
  }
427
  *
428
  * @todo Optimize with ``empty()``.
429
  */
430
+ public static function custom_registration_fields()
431
  {
432
+ do_action("ws_plugin__s2member_before_custom_registration_fields", get_defined_vars());
433
  /**/
434
+ $_p = (!empty($_POST)) ? c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST)) : array();
435
  /**/
436
+ echo '<input type="hidden" name="ws_plugin__s2member_registration" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-registration")).'" />'."\n";
437
  /**/
438
  $tabindex = 20; /* Incremented tabindex starting with 20. */
439
  /**/
440
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
441
+ do_action("ws_plugin__s2member_during_custom_registration_fields_before", get_defined_vars());
442
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
443
  /**/
444
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
445
  {
446
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
447
+ do_action("ws_plugin__s2member_during_custom_registration_fields_before_user_pass", get_defined_vars());
448
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
449
  /**/
450
+ echo '<p>'."\n";
451
  /**/
452
+ echo '<label for="ws-plugin--s2member-custom-reg-field-user-pass1" title="'.esc_attr(_x("Please type your Password twice to confirm.", "s2member-front", "s2member")).'">'."\n";
453
+ echo '<span>'._x("Password ( please type it twice )", "s2member-front", "s2member").' *</span><br />'."\n";
454
+ echo '<input type="password" aria-required="true" maxlength="100" autocomplete="off" name="ws_plugin__s2member_custom_reg_field_user_pass1" id="ws-plugin--s2member-custom-reg-field-user-pass1" class="ws-plugin--s2member-custom-reg-field" value="'.format_to_edit($_p["ws_plugin__s2member_custom_reg_field_user_pass1"]).'" tabindex="'.esc_attr(($tabindex = $tabindex + 10)).'" />'."\n";
455
+ echo '</label>'."\n";
456
  /**/
457
+ echo '<label for="ws-plugin--s2member-custom-reg-field-user-pass2" title="'.esc_attr(_x("Please type your Password twice to confirm.", "s2member-front", "s2member")).'">'."\n";
458
+ echo '<input type="password" maxlength="100" autocomplete="off" name="ws_plugin__s2member_custom_reg_field_user_pass2" id="ws-plugin--s2member-custom-reg-field-user-pass2" class="ws-plugin--s2member-custom-reg-field" value="'.format_to_edit($_p["ws_plugin__s2member_custom_reg_field_user_pass2"]).'" tabindex="'.esc_attr(($tabindex = $tabindex + 10)).'" />'."\n";
459
+ echo '</label>'."\n";
460
  /**/
461
+ echo '<div id="ws-plugin--s2member-custom-reg-field-user-pass-strength" class="ws-plugin--s2member-password-strength"><em>'._x("password strength indicator", "s2member-front", "s2member").'</em></div>'."\n";
462
  /**/
463
+ echo '</p>'."\n";
464
  /**/
465
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
466
+ do_action("ws_plugin__s2member_during_custom_registration_fields_after_user_pass", get_defined_vars());
467
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
468
  }
469
  /**/
470
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_names"])
471
  {
472
+ echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section"></div>'."\n";
473
+ /**/
474
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
475
+ do_action("ws_plugin__s2member_during_custom_registration_fields_before_first_name", get_defined_vars());
476
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
477
+ /**/
478
+ echo '<p>'."\n";
479
+ echo '<label for="ws-plugin--s2member-custom-reg-field-first-name">'."\n";
480
+ echo '<span>'._x("First Name", "s2member-front", "s2member").' *</span><br />'."\n";
481
+ echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="'.esc_attr($_p["ws_plugin__s2member_custom_reg_field_first_name"]).'" tabindex="'.esc_attr(($tabindex = $tabindex + 10)).'" />'."\n";
482
+ echo '</label>'."\n";
483
+ echo '</p>'."\n";
484
+ /**/
485
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
486
+ do_action("ws_plugin__s2member_during_custom_registration_fields_after_first_name", get_defined_vars());
487
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
488
+ /**/
489
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
490
+ do_action("ws_plugin__s2member_during_custom_registration_fields_before_last_name", get_defined_vars());
491
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
492
+ /**/
493
+ echo '<p>'."\n";
494
+ echo '<label for="ws-plugin--s2member-custom-reg-field-last-name">'."\n";
495
+ echo '<span>'._x("Last Name", "s2member-front", "s2member").' *</span><br />'."\n";
496
+ echo '<input type="text" aria-required="true" maxlength="100" autocomplete="off" 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" value="'.esc_attr($_p["ws_plugin__s2member_custom_reg_field_last_name"]).'" tabindex="'.esc_attr(($tabindex = $tabindex + 10)).'" />'."\n";
497
+ echo '</label>'."\n";
498
+ echo '</p>'."\n";
499
+ /**/
500
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
501
+ do_action("ws_plugin__s2member_during_custom_registration_fields_after_last_name", get_defined_vars());
502
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
503
  }
504
  /**/
505
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
506
+ if($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level("auto-detection", "registration"))
507
  {
508
  $tabindex = $tabindex + 9; /* Start tabindex at +9 ( +1 below ). */
509
  /**/
510
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
511
  {
512
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
513
+ do_action("ws_plugin__s2member_during_custom_registration_fields_before_custom_fields", get_defined_vars());
514
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
515
  /**/
516
+ if(in_array($field["id"], $fields_applicable)) /* Field applicable? */
517
  {
518
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
519
+ $field_id_class = preg_replace("/_/", "-", $field_var);
520
  /**/
521
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
522
+ if(apply_filters("ws_plugin__s2member_during_custom_registration_fields_during_custom_fields_display", true, get_defined_vars()))
523
  {
524
+ if(!empty($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
525
+ echo '<div class="ws-plugin--s2member-custom-reg-field-divider-section'.((!empty($field["sectitle"])) ? '-title' : '').'">'.((!empty($field["sectitle"])) ? $field["sectitle"] : '').'</div>';
526
  /**/
527
+ echo '<p>'."\n";
528
+ echo '<label for="ws-plugin--s2member-custom-reg-field-'.esc_attr($field_id_class).'">'."\n";
529
+ echo '<span'.((preg_match("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ' style="display:none;"' : '').'>'.$field["label"].(($field["required"] === "yes") ? ' *' : '').'</span></label>'.((preg_match("/^(checkbox|pre_checkbox)$/", $field["type"])) ? '' : '<br />')."\n";
530
+ echo c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_custom_reg_field_", "ws-plugin--s2member-custom-reg-field-", "ws-plugin--s2member-custom-reg-field", "", ($tabindex = $tabindex + 1), "", $_p, $_p["ws_plugin__s2member_custom_reg_field_".$field_var], "registration");
531
+ echo '</p>'."\n";
532
  }
533
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
534
  }
535
  /**/
536
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
537
+ do_action("ws_plugin__s2member_during_custom_registration_fields_after_custom_fields", get_defined_vars());
538
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
539
  }
540
  }
541
  /**/
542
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] && c_ws_plugin__s2member_list_servers::list_servers_integrated())
543
  {
544
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
545
+ do_action("ws_plugin__s2member_during_custom_registration_fields_before_opt_in", get_defined_vars());
546
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
547
+ /**/
548
+ echo '<p>'."\n";
549
+ echo '<label for="ws-plugin--s2member-custom-reg-field-opt-in">'."\n";
550
+ echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_field_opt_in" id="ws-plugin--s2member-custom-reg-field-opt-in" class="ws-plugin--s2member-custom-reg-field" value="1"'.(((empty($_p) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) || $_p["ws_plugin__s2member_custom_reg_field_opt_in"]) ? ' checked="checked"' : '').' tabindex="'.esc_attr(($tabindex = $tabindex + 10)).'" />'."\n";
551
+ echo $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"]."\n";
552
+ echo '</label>'."\n";
553
+ echo '</p>'."\n";
554
+ /**/
555
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
556
+ do_action("ws_plugin__s2member_during_custom_registration_fields_after_opt_in", get_defined_vars());
557
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
558
  }
559
  /**/
560
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
561
+ do_action("ws_plugin__s2member_during_custom_registration_fields_after", get_defined_vars());
562
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
563
  /**/
564
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
565
+ do_action("ws_plugin__s2member_after_custom_registration_fields", get_defined_vars());
566
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
567
  /**/
568
  return; /* Return for uniformity. */
569
  }
includes/classes/files-in.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Files
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_files_in"))
21
  {
22
  /**
23
  * File Download routines for s2Member ( inner processing routines ).
@@ -41,16 +41,16 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
41
  * @return null|str If called directly with ``$create_file_download_url``, returns a string with the URL, based on configuration.
42
  * Else, this function may exit script execution after serving a File Download.
43
  */
44
- public static function check_file_download_access ($create_file_download_url = FALSE)
45
  {
46
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
47
- do_action ("ws_plugin__s2member_before_file_download_access", get_defined_vars ());
48
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
49
  /**/
50
- $_g = !empty ($_GET) ? $_GET : array ();
51
- $_g = c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep ($_g));
52
  /**/
53
- $creating = /* Creating URL? */ (is_array ($create = $create_file_download_url)) ? true : false;
54
  $serving = /* If NOT creating a File Download URL, we're serving one. */ (!$creating) ? true : false;
55
  /**/
56
  $req["file_download"] = ($creating) ? @$create["file_download"] : @$_g["s2member_file_download"];
@@ -70,143 +70,144 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
70
  $req["count_against_user"] = ($creating) ? @$create["count_against_user"] : /* N/A. */ null;
71
  $req["check_user"] = ($creating) ? @$create["check_user"] : /* N/A. */ null;
72
  /**/
73
- if ($req["file_download"] && is_string ($req["file_download"]) && ($req["file_download"] = trim ($req["file_download"], "/")))
74
- if (strpos ($req["file_download"], "..") === false && strpos (basename ($req["file_download"]), ".") !== 0)
75
  {
76
- $using_amazon_s3_storage = ((!$req["file_storage"] || strcasecmp ((string)$req["file_storage"], "s3") === 0) && c_ws_plugin__s2member_utils_conds::using_amazon_s3_storage ()) ? true : false;
77
- $using_amazon_cf_storage = ((!$req["file_storage"] || strcasecmp ((string)$req["file_storage"], "cf") === 0) && c_ws_plugin__s2member_utils_conds::using_amazon_cf_storage ()) ? true : false;
78
  $using_amazon_storage = /* Either/or? */ ($using_amazon_s3_storage || $using_amazon_cf_storage) ? true : false;
79
  /**/
80
- $excluded = apply_filters ("ws_plugin__s2member_check_file_download_access_excluded", false, get_defined_vars ());
81
- $valid_file_download_key = ($req["file_download_key"] && is_string ($req["file_download_key"])) ? c_ws_plugin__s2member_files_in::check_file_download_key ($req["file_download"], $req["file_download_key"]) : false;
82
- $checking_user = ($excluded || $valid_file_download_key || ($creating && (!isset ($req["check_user"]) || !filter_var ($req["check_user"], FILTER_VALIDATE_BOOLEAN)) && (!isset ($req["count_against_user"]) || !filter_var ($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true;
83
- $updating_user_counter = (!$checking_user || ($creating && (!isset ($req["count_against_user"]) || !filter_var ($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true;
 
84
  /**/
85
- if ( /* In either case, the following routines apply whenever we ARE ``$checking_user``. */($serving || $creating) && $checking_user)
86
  {
87
- if (!$using_amazon_storage && !file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $req["file_download"]))
88
  {
89
- if /* We only need this section when/if we're actually serving. */ ($serving)
90
- status_header (404) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') #
91
- . exit (_x ('<strong>404: Sorry, file not found.</strong> Please contact Support for assistance.', "s2member-front", "s2member"));
92
  /**/
93
  else /* Else return false. */
94
  return false;
95
  }
96
  /**/
97
- else if ($req["file_download_key"] && is_string ($req["file_download_key"]) && !$valid_file_download_key)
98
  {
99
- if /* We only need this section when/if we're actually serving. */ ($serving)
100
- status_header (503) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') #
101
- . exit (_x ('<strong>503 ( Invalid Key ):</strong> Sorry, your access to this file has expired. Please contact Support for assistance.', "s2member-front", "s2member"));
102
  /**/
103
  else /* Else return false. */
104
  return false;
105
  }
106
  /**/
107
- else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] || ($file_downloads_enabled_by_site_owner = $min_level_4_downloads = c_ws_plugin__s2member_files::min_level_4_downloads ()) === false)
108
  {
109
- if /* We only need remote functionality when/if we're actually serving. */ ($serving)
110
- if (!has_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization"))
111
- add_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization", 10, 2);
112
  /**/
113
- if /* We only need remote functionality when/if we're actually serving. */ ($creating)
114
- if (has_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization"))
115
- remove_filter ("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization", 10, 2);
116
  /**/
117
- if ((isset ($file_downloads_enabled_by_site_owner, $min_level_4_downloads) && $file_downloads_enabled_by_site_owner === false) || ($file_downloads_enabled_by_site_owner = $min_level_4_downloads = c_ws_plugin__s2member_files::min_level_4_downloads ()) === false)
118
  {
119
- if /* We only need this section when/if we're actually serving. */ ($serving)
120
- status_header (503) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') #
121
- . exit (_x ('<strong>503: Basic File Downloads are NOT enabled yet.</strong> Please contact Support for assistance. If you are the site owner, please configure: <code>s2Member -> Download Options -> Basic Download Restrictions</code>.', "s2member-front", "s2member"));
122
  /**/
123
  else /* Else return false. */
124
  return false;
125
  }
126
  /**/
127
- else if (!is_object ($user = apply_filters ("ws_plugin__s2member_check_file_download_access_user", ((is_user_logged_in ()) ? wp_get_current_user () : false), get_defined_vars ())) || empty ($user->ID) || !($user_id = $user->ID) || !is_array ($user_file_downloads = c_ws_plugin__s2member_files::user_downloads ($user)) || (!$user->has_cap ("administrator") && (!$user_file_downloads["allowed"] || !$user_file_downloads["allowed_days"])))
128
  {
129
- if (preg_match ("/^access[_\-]s2member[_\-]level([0-9]+)\//", $req["file_download"], $m) && strlen ($req_level = $m[1]) && (!is_object ($user) || empty ($user->ID) || !$user->has_cap ("access_s2member_level" . $req_level)))
130
  {
131
- if /* We only need this section when/if we're actually serving. */ ($serving)
132
- c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */ ("file", $req["file_download"], "level", $req_level, $_SERVER["REQUEST_URI"]) . exit ();
133
  /**/
134
  else /* Else return false. */
135
  return false;
136
  }
137
  /**/
138
- else if (preg_match ("/^access[_\-]s2member[_\-]ccap[_\-](.+?)\//", $req["file_download"], $m) && strlen ($req_ccap = preg_replace ("/-/", "_", $m[1])) && (!is_object ($user) || empty ($user->ID) || !$user->has_cap ("access_s2member_ccap_" . $req_ccap)))
139
  {
140
- if /* We only need this section when/if we're actually serving. */ ($serving)
141
- c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */ ("file", $req["file_download"], "ccap", $req_ccap, $_SERVER["REQUEST_URI"]) . exit ();
142
  /**/
143
  else /* Else return false. */
144
  return false;
145
  }
146
  /**/
147
- else if /* We only need this section when/if we're actually serving. */ ($serving)
148
- c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */ ("file", $req["file_download"], "level", $min_level_4_downloads, $_SERVER["REQUEST_URI"]) . exit ();
149
  /**/
150
  else /* Else return false. */
151
  return false;
152
  }
153
  /**/
154
- else if (preg_match ("/^access[_\-]s2member[_\-]level([0-9]+)\//", $req["file_download"], $m) && strlen ($req_level = $m[1]) && !$user->has_cap ("access_s2member_level" . $req_level))
155
  {
156
- if /* We only need this section when/if we're actually serving. */ ($serving)
157
- c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */ ("file", $req["file_download"], "level", $req_level, $_SERVER["REQUEST_URI"]) . exit ();
158
  /**/
159
  else /* Else return false. */
160
  return false;
161
  }
162
  /**/
163
- else if (preg_match ("/^access[_\-]s2member[_\-]ccap[_\-](.+?)\//", $req["file_download"], $m) && strlen ($req_ccap = preg_replace ("/-/", "_", $m[1])) && !$user->has_cap ("access_s2member_ccap_" . $req_ccap))
164
  {
165
- if /* We only need this section when/if we're actually serving. */ ($serving)
166
- c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */ ("file", $req["file_download"], "ccap", $req_ccap, $_SERVER["REQUEST_URI"]) . exit ();
167
  /**/
168
  else /* Else return false. */
169
  return false;
170
  }
171
  /**/
172
- else if /* In either case, the following routines apply. */ ($serving || $creating)
173
  {
174
  $user_previous_file_downloads = /* Downloads the User has already; in current period/cycle. */ 0;
175
  $user_already_downloaded_this_file = $user_already_downloaded_a_streaming_variation_of_this_file = false;
176
  /**/
177
- $user_file_download_access_log = (is_array ($user_file_download_access_log = get_user_option ("s2member_file_download_access_log", $user_id))) ? $user_file_download_access_log : array ();
178
- $user_file_download_access_arc = (is_array ($user_file_download_access_arc = get_user_option ("s2member_file_download_access_arc", $user_id))) ? $user_file_download_access_arc : array ();
179
  /**/
180
- $streaming_file_extns = c_ws_plugin__s2member_utils_strings::preg_quote_deep ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"], "/");
181
- $streaming_variations = /* Only count one streaming media file variation. */ "/\.(" . implode ("|", $streaming_file_extns) . ")$/i";
182
  /**/
183
- foreach ($user_file_download_access_log as $user_file_download_access_log_entry_key => $user_file_download_access_log_entry)
184
  {
185
- if ( /* Weed out corrupt/empty log entries. */isset ($user_file_download_access_log_entry["date"], $user_file_download_access_log_entry["file"]))
186
  {
187
- if (strtotime ($user_file_download_access_log_entry["date"]) < strtotime ("-" . $user_file_downloads["allowed_days"] . " days"))
188
  {
189
- unset /* Remove it from the `log`. */ ($user_file_download_access_log[$user_file_download_access_log_entry_key]);
190
  $user_file_download_access_arc[] = /* Move `log` entry to the `archive` now. */ $user_file_download_access_log_entry;
191
  }
192
- else if (strtotime ($user_file_download_access_log_entry["date"]) >= strtotime ("-" . $user_file_downloads["allowed_days"] . " days"))
193
  {
194
  $user_previous_file_downloads++; /* Previous files always count against this User/Member. */
195
  /**/
196
  $_user_file_download_access_log_entry = &$user_file_download_access_log[$user_file_download_access_log_entry_key];
197
  $_user_already_downloaded_this_file = $_user_already_downloaded_a_streaming_variation_of_this_file = false;
198
  /**/
199
- if /* Already downloaded this file? If yes, mark this flag as true. */ ($user_file_download_access_log_entry["file"] === $req["file_download"])
200
  $user_already_downloaded_this_file = $_user_already_downloaded_this_file = /* Already downloaded this file? If yes, mark as true. */ true;
201
  /**/
202
- else if (preg_replace ($streaming_variations, "", $user_file_download_access_log_entry["file"]) === preg_replace ($streaming_variations, "", $req["file_download"]))
203
  $user_already_downloaded_this_file = $_user_already_downloaded_this_file = $user_already_downloaded_a_streaming_variation_of_this_file = $_user_already_downloaded_a_streaming_variation_of_this_file = true;
204
  /**/
205
- if ( /* Updating counter? */$updating_user_counter && ($_user_already_downloaded_this_file || $_user_already_downloaded_a_streaming_variation_of_this_file))
206
  {
207
- $_user_file_download_access_log_entry /* First, we update the last download time for this file. */["ltime"] = time ();
208
  /**/
209
- if ( /* Backward compatiility here. Is this even set? */!empty ($user_file_download_access_log_entry["counter"]))
210
  $_user_file_download_access_log_entry["counter"] = (int)$user_file_download_access_log_entry["counter"] + 1;
211
  else /* Backward compatiility here. Default value to `1`, if this is NOT even set yet. */
212
  $_user_file_download_access_log_entry["counter"] = 1 + 1;
@@ -214,185 +215,198 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
214
  }
215
  }
216
  else /* Weed out empty log entries. Some older versions of s2Member may have corrupt/empty log entries. */
217
- unset ($user_file_download_access_log[$user_file_download_access_log_entry_key]); /* Remove. */
218
  }
219
- if ( /* Updating counter? */$updating_user_counter && /* Do we need a new log entry for this file? */ !$user_already_downloaded_this_file && !$user_already_downloaded_a_streaming_variation_of_this_file)
220
- $user_file_download_access_log[] = array ("date" => date ("Y-m-d"), "time" => time (), "ltime" => time (), "file" => $req["file_download"], "counter" => 1);
221
  /**/
222
- if ($user_previous_file_downloads >= $user_file_downloads["allowed"] && !$user_already_downloaded_this_file && !$user_already_downloaded_a_streaming_variation_of_this_file && !$user->has_cap ("administrator"))
223
  {
224
- if /* We only need this section when/if we're actually serving. */ ($serving)
225
- wp_redirect (add_query_arg (urlencode_deep (array ("_s2member_seeking" => array ("type" => "file", "file" => $req["file_download"], "_uri" => base64_encode ($_SERVER["REQUEST_URI"])), "s2member_seeking" => "file-" . $req["file_download"])), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"])), apply_filters ("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars ())) . exit ();
226
  /**/
227
  else /* Else return false. */
228
  return false;
229
  }
230
- else if /* Save/update counter? By default, we do NOT update the counter when a URL is simply being created for access. */ ($updating_user_counter)
231
- update_user_option ($user_id, "s2member_file_download_access_log", c_ws_plugin__s2member_utils_arrays::array_unique ($user_file_download_access_log)) . update_user_option ($user_id, "s2member_file_download_access_arc", c_ws_plugin__s2member_utils_arrays::array_unique ($user_file_download_access_arc));
232
  }
233
  }
234
  }
235
  else /* Otherwise, we're either NOT ``$checking_user``; or permission was granted with a valid File Download Key. */
236
  {
237
- if (!$using_amazon_storage && !file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $req["file_download"]))
238
  {
239
- if /* We only need this section when/if we're actually serving. */ ($serving)
240
- status_header (404) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') #
241
- . exit (_x ('<strong>404: Sorry, file not found.</strong> Please contact Support for assistance.', "s2member-front", "s2member"));
242
  /**/
243
  else /* Else return false. */
244
  return false;
245
  }
246
  }
247
  /**/
248
- if /* In either case, the following routines apply. */ ($serving || $creating)
249
  {
250
- $basename = basename ($req["file_download"]);
251
- $mimetypes = parse_ini_file (dirname (dirname (dirname (__FILE__))) . "/includes/mime-types.ini");
252
- $extension = strtolower (substr ($req["file_download"], strrpos ($req["file_download"], ".") + 1));
253
  /**/
254
- $key = ($req["file_download_key"] && is_string ($req["file_download_key"])) ? $req["file_download_key"] : false;
255
  /**/
256
- $stream = (isset ($req["file_stream"])) ? filter_var ($req["file_stream"], FILTER_VALIDATE_BOOLEAN) : ((in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_stream_extensions"]))) ? true : false);
257
- $inline = (!$stream && isset ($req["file_inline"])) ? filter_var ($req["file_inline"], FILTER_VALIDATE_BOOLEAN) : (($stream || in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]))) ? true : false);
258
- $ssl = (isset ($req["file_ssl"])) ? filter_var ($req["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl ()) ? true : false);
259
- $storage = ($req["file_storage"] && is_string ($req["file_storage"])) ? strtolower ($req["file_storage"]) : false;
260
- $remote = (isset ($req["file_remote"])) ? filter_var ($req["file_remote"], FILTER_VALIDATE_BOOLEAN) : false;
261
  /**/
262
- $rewrite_base_guess = dirname ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . "/" . c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]);
263
- $rewrite_base = ($req["file_rewrite_base"] && is_string ($req["file_rewrite_base"])) ? $req["file_rewrite_base"] : false;
264
- $rewrite = $rewriting = (!$rewrite_base && isset ($req["file_rewrite"])) ? filter_var ($req["file_rewrite"], FILTER_VALIDATE_BOOLEAN) : (($rewrite_base) ? true : false);
 
 
265
  /**/
266
- $skip_confirmation = (isset ($req["skip_confirmation"])) ? filter_var ($req["skip_confirmation"], FILTER_VALIDATE_BOOLEAN) : false;
267
- $url_to_storage_source = (isset ($req["url_to_storage_source"])) ? filter_var ($req["url_to_storage_source"], FILTER_VALIDATE_BOOLEAN) : false;
268
  /**/
269
- $pathinfo = (!$using_amazon_storage) ? pathinfo (($file = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $req["file_download"])) : array ();
270
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream";
271
- $length = (!$using_amazon_storage && $file) ? filesize ($file) : -1;
272
  /**/
273
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
274
- do_action ("ws_plugin__s2member_during_file_download_access", get_defined_vars ());
275
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
276
  /**/
277
- if ($using_amazon_s3_storage && ($serving || ($creating && $url_to_storage_source)))
278
  {
279
- if /* We only need this section when/if we're actually serving. */ ($serving)
280
- wp_redirect (c_ws_plugin__s2member_files_in::amazon_s3_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype)) . exit ();
281
  /**/
282
  else /* Else return File Download URL. */
283
- return apply_filters ("ws_plugin__s2member_file_download_access_url", c_ws_plugin__s2member_files_in::amazon_s3_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype), get_defined_vars ());
284
  }
285
  /**/
286
- else if ($using_amazon_cf_storage && ($serving || ($creating && $url_to_storage_source)))
287
  {
288
- if /* We only need this section when/if we're actually serving. */ ($serving)
289
- wp_redirect (c_ws_plugin__s2member_files_in::amazon_cf_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype)) . exit ();
290
  /**/
291
  else /* Else return File Download URL. */
292
- return apply_filters ("ws_plugin__s2member_file_download_access_url", c_ws_plugin__s2member_files_in::amazon_cf_url ($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype), get_defined_vars ());
293
  }
294
  /**/
295
- else if /* Creating a rewrite URL, pointing to local storage. */ ($creating && $rewriting)
296
  {
297
- $url = ($rewrite_base) ? rtrim ($rewrite_base, "/") : rtrim ($rewrite_base_guess, "/");
298
- $url .= (isset ($req["file_download_key"])) ? (($key) ? "/s2member-file-download-key-" . $key : "") : "";
299
- $url .= (isset ($req["file_stream"])) ? (($stream) ? "/s2member-file-stream" : "/s2member-file-stream-no") : "";
300
- $url .= (isset ($req["file_inline"])) ? (($inline) ? "/s2member-file-inline" : "/s2member-file-inline-no") : "";
301
- $url .= (isset ($req["file_storage"])) ? (($storage) ? "/s2member-file-storage-" . $storage : "") : "";
302
- $url .= (isset ($req["file_remote"])) ? (($remote) ? "/s2member-file-remote" : "/s2member-file-remote-no") : "";
303
- $url .= (isset ($req["skip_confirmation"])) ? (($skip_confirmation) ? "/s2member-skip-confirmation" : "/s2member-skip-confirmation-no") : "";
304
  /**/
305
- $url = /* File Download Access URL via `mod_rewrite` functionality. */ $url . "/" . $req["file_download"];
306
- $url = ($ssl) ? preg_replace ("/^https?/", "https", $url) : preg_replace ("/^https?/", "http", $url);
307
  /**/
308
- return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ());
309
  }
310
  /**/
311
- else if /* Else we're creating a URL w/ a query-string; w/ local storage. */ ($creating)
312
  { /* Note: we don't URL encode unreserved chars. Improves media player compatibility. */
313
- $_url_e_key = ($key) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($key)) : "";
314
- $_url_e_storage = ($storage) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($storage)) : "";
315
- $_url_e_file = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($req["file_download"]));
316
  /**/
317
- $url = (isset ($req["file_download_key"])) ? (($key && $_url_e_key) ? "&s2member_file_download_key=" . $_url_e_key : "") : "";
318
- $url .= (isset ($req["file_stream"])) ? (($stream) ? "&s2member_file_stream=yes" : "&s2member_file_stream=no") : "";
319
- $url .= (isset ($req["file_inline"])) ? (($inline) ? "&s2member_file_inline=yes" : "&s2member_file_inline=no") : "";
320
- $url .= (isset ($req["file_storage"])) ? (($storage && $_url_e_storage) ? "&s2member_file_storage=" . $_url_e_storage : "") : "";
321
- $url .= (isset ($req["file_remote"])) ? (($remote) ? "&s2member_file_remote=yes" : "&s2member_file_remote=no") : "";
322
- $url .= (isset ($req["skip_confirmation"])) ? (($skip_confirmation) ? "&s2member_skip_confirmation=yes" : "&s2member_skip_confirmation=no") : "";
323
  /**/
324
- $url = site_url ("/?" . ltrim ($url . "&s2member_file_download=/" . $_url_e_file, "&"));
325
- $url = ($ssl) ? preg_replace ("/^https?/", "https", $url) : preg_replace ("/^https?/", "http", $url);
326
  /**/
327
- return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ());
328
  }
329
  /**/
330
  else /* Else, ``if ($serving)``, use local storage option. */
331
  {
332
- @set_time_limit (0) . @ini_set ("zlib.output_compression", 0);
333
  /**/
334
- status_header /* 200 OK status header. */ (200);
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  /**/
336
- header ("Content-Encoding:");
337
- header ("Accept-Ranges: none");
338
- header ("Content-Type: " . $mimetype);
339
- header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
340
- header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
341
- header ("Cache-Control: no-cache, must-revalidate, max-age=0");
342
- header ("Cache-Control: post-check=0, pre-check=0", false);
343
- header ("Pragma: no-cache");
344
  /**/
345
- header ('Content-Disposition: ' . (($inline) ? "inline" : "attachment") . '; filename="' . $basename . '"');
346
  /**/
347
- eval /* End/clean any output buffers that may exist already. Prep for content delivery. */ ('while (@ob_end_clean ());');
348
  /**/
349
- $_chunk_file = ($_SERVER["SERVER_PROTOCOL"] === "HTTP/1.1" && preg_match ("/apache/i", $_SERVER["SERVER_SOFTWARE"])) ? true : false;
350
- /**/
351
- if ($length && apply_filters ("ws_plugin__s2member_chunk_file_downloads", $_chunk_file, get_defined_vars ()) && is_resource ($resource = fopen ($file, "rb")))
352
  {
353
- $_chunk_size = apply_filters ("ws_plugin__s2member_chunk_file_downloads_w_chunk_size", 2097152, get_defined_vars ());
354
  /**/
355
- if (apply_filters ("ws_plugin__s2member_chunk_file_downloads_w_content_length", true, get_defined_vars ()))
356
- header ("Content-Length: " . $length);
357
  /**/
358
- header /* `Transfer-Encoding: chunked` conserves memory. */ ("Transfer-Encoding: chunked");
359
  /**/
360
- while (!feof ($resource) && ($chunk_size = strlen ($data = fread ($resource, $_chunk_size))))
361
- eval ('echo dechex ($chunk_size) . "\r\n". $data . "\r\n"; @flush ();');
362
  /**/
363
- fclose ($resource) . exit ("0\r\n\r\n");
364
  }
365
- else if ($length && apply_filters ("ws_plugin__s2member_flush_file_downloads", true, get_defined_vars ()) && is_resource ($resource = fopen ($file, "rb")))
366
  {
367
- $_flush_size = apply_filters ("ws_plugin__s2member_flush_file_downloads_w_flush_size", 2097152, get_defined_vars ());
368
  /**/
369
- if (apply_filters ("ws_plugin__s2member_flush_file_downloads_w_content_length", true, get_defined_vars ()))
370
- header ("Content-Length: " . $length);
371
  /**/
372
- while (!feof ($resource) && ($flush_size = strlen ($data = fread ($resource, $_flush_size))))
373
- eval /* Conserves memory. */ ('echo $data; @flush ();');
374
  }
375
- else if /* Else, use: ``file_get_contents()``. */ ($length)
376
  {
377
- @ini_set /* RAM/memory. */ ("memory_limit", WP_MAX_MEMORY_LIMIT);
378
- header ("Content-Length: " . $length) . exit (file_get_contents ($file));
379
  }
380
  else /* Else, we have an empty file with no length. */
381
  {
382
- header ("Content-Length: 0") . exit ();
383
  }
384
  }
385
  }
386
  }
387
  /**/
388
- else if /* We only need this section when/if we're actually serving. */ ($serving && $req["file_download"])
389
- status_header (503) . header ("Content-Type: text/html; charset=utf-8") . eval ('while (@ob_end_clean ());') #
390
- . exit (_x ('<strong>503: Access denied.</strong> Invalid File Download specs.', "s2member-front", "s2member"));
391
  /**/
392
- else if /* We only need this section when/if we're creating a URL. */ ($creating)
393
  return false;
394
  /**/
395
- do_action ("ws_plugin__s2member_after_file_download_access", get_defined_vars ());
396
  /**/
397
  return ($creating) ? /* If creating, false. */ false : null;
398
  }
@@ -409,44 +423,44 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
409
  *
410
  * @see s2Member\API_Functions\s2member_file_download_url()
411
  */
412
- public static function create_file_download_url ($config = FALSE, $get_streamer_array = FALSE)
413
  {
414
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
415
- do_action ("ws_plugin__s2member_before_create_file_download_url", get_defined_vars ());
416
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
417
  /**/
418
- $config = (is_array ($config)) ? $config : /* This absolutely MUST be an array. */ array ();
419
  /**/
420
- $config["file_download"] = (isset ($config["file_download"]) && is_string ($config["file_download"])) ? trim ($config["file_download"], "/") : @$config["file_download"];
421
- $config["file_download_key"] = (isset ($config["file_download"]) && is_string ($config["file_download"]) && !empty ($config["file_download_key"])) ? c_ws_plugin__s2member_files::file_download_key ($config["file_download"], ((in_array ($config["file_download_key"], array ("ip-forever", "universal", "cache-compatible"))) ? $config["file_download_key"] : false)) : @$config["file_download_key"];
422
  /**/
423
  $config["url_to_storage_source"] = /* Force a streaming URL here via ``$get_streamer_array``? */ ($get_streamer_array) ? true : @$config["url_to_storage_source"];
424
  $config["file_stream"] = /* Force a streaming URL here via ``$get_streamer_array``? */ ($get_streamer_array) ? true : @$config["file_stream"];
425
  /**/
426
- if (($_url = c_ws_plugin__s2member_files_in::check_file_download_access /* Successfully created a URL to the file? */ (($create_file_download_url = $config))))
427
  {
428
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
429
- do_action ("ws_plugin__s2member_during_create_file_download_url", get_defined_vars ());
430
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
431
  /**/
432
- $extension = strtolower (substr ($config["file_download"], strrpos ($config["file_download"], ".") + 1));
433
- $streaming = (isset ($config["file_stream"])) ? filter_var ($config["file_stream"], FILTER_VALIDATE_BOOLEAN) : ((in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_stream_extensions"]))) ? true : false);
434
- $ssl = (isset ($config["file_ssl"])) ? filter_var ($config["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl ()) ? true : false);
435
  /**/
436
- if ($get_streamer_array && $streaming && ($cfx = "/cfx/st") && ($cfx_pos = strpos ($_url, $cfx)) !== false && ($streamer = substr ($_url, 0, $cfx_pos + strlen ($cfx))) && ($url = c_ws_plugin__s2member_files_in::check_file_download_access (array_merge ($config, array ("file_stream" => false, "check_user" => false, "count_against_user" => false)))))
437
- $return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
438
  /**/
439
- else if ($get_streamer_array && $streaming && is_array ($ups = c_ws_plugin__s2member_utils_urls::parse_url ($_url)) && isset ($ups["scheme"], $ups["host"]) && ($streamer = $ups["scheme"] . "://" . $ups["host"] . ((!empty ($ups["port"])) ? ":" . $ups["port"] : "")) && ($url = c_ws_plugin__s2member_files_in::check_file_download_access (array_merge ($config, array ("file_stream" => false, "check_user" => false, "count_against_user" => false)))))
440
- $return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
441
  /**/
442
- else if /* If streamer, we MUST return false here; unable to acquire streamer/file. */ ($get_streamer_array)
443
  $return = /* We MUST return false here, unable to acquire streamer/file. */ false;
444
  /**/
445
  else /* Else return URL string ( ``$get_streamer_array`` is false ). */
446
  $return = /* Else return URL string. */ $_url;
447
  }
448
  /**/
449
- return apply_filters ("ws_plugin__s2member_create_file_download_url", ((isset ($return)) ? $return : false), get_defined_vars ());
450
  }
451
  /**
452
  * Checks Header Authorization for Remote File Downloads.
@@ -459,34 +473,34 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
459
  * @param obj $user Expects a WP_User object passed in by the Filter.
460
  * @return obj A `WP_User` object, possibly obtained through Header Authorization.
461
  */
462
- public static function check_file_remote_authorization ($user = FALSE)
463
  {
464
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
465
- do_action ("ws_plugin__s2member_before_check_file_remote_authorization", get_defined_vars ());
466
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
467
  /**/
468
- $_g = c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep (((!empty ($_GET)) ? $_GET : array ())));
469
  /**/
470
- if (!is_object ($user) && isset ($_g["s2member_file_remote"]) && filter_var ($_g["s2member_file_remote"], FILTER_VALIDATE_BOOLEAN))
471
  {
472
- do_action ("ws_plugin__s2member_during_check_file_remote_authorization_before", get_defined_vars ());
473
  /**/
474
- if (empty ($_SERVER["PHP_AUTH_USER"]) || empty ($_SERVER["PHP_AUTH_PW"]) || !user_pass_ok ($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]))
475
  {
476
- header ('WWW-Authenticate: Basic realm="' . c_ws_plugin__s2member_utils_strings::esc_dq (strip_tags (_x ("Members Only", "s2member-front", "s2member"))) . '"');
477
  /**/
478
- status_header /* Send an unauthorized 401 status header now. */ (401);
479
- header /* Content-Type with UTF-8. */ ("Content-Type: text/html; charset=utf-8");
480
- eval /* End/clean any output buffers that may exist. */ ('while (@ob_end_clean ());');
481
  /**/
482
- exit (_x ('<strong>401:</strong> Sorry, access denied.', "s2member-front", "s2member"));
483
  }
484
- else if (is_object ($_user = new WP_User ($_SERVER["PHP_AUTH_USER"])) && !empty ($_user->ID))
485
  $user = /* Now assign ``$user``. */ $_user;
486
  /**/
487
- do_action ("ws_plugin__s2member_during_check_file_remote_authorization_after", get_defined_vars ());
488
  }
489
- return apply_filters ("ws_plugin__s2member_check_file_remote_authorization", $user, get_defined_vars ());
490
  }
491
  /**
492
  * Checks a File Download Key for validity.
@@ -498,22 +512,22 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
498
  * @param str $key Input File Download Key to validate.
499
  * @return bool True if valid, else false.
500
  */
501
- public static function check_file_download_key ($file = FALSE, $key = FALSE)
502
  {
503
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
504
- do_action ("_ws_plugin__s2member_before_check_file_download_key", get_defined_vars ());
505
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
506
  /**/
507
- if ($file && is_string ($file) && ($file = trim ($file, "/")) && $key && is_string ($key))
508
  {
509
- if ($key === c_ws_plugin__s2member_files::file_download_key ($file) || $key === c_ws_plugin__s2member_files::file_download_key ("/" . $file))
510
  $valid = /* File Download Key is valid. */ true;
511
- else if ($key === c_ws_plugin__s2member_files::file_download_key ($file, "ip-forever") || $key === c_ws_plugin__s2member_files::file_download_key ("/" . $file, "ip-forever"))
512
  $valid = /* File Download Key is valid. */ true;
513
- else if ($key === c_ws_plugin__s2member_files::file_download_key ($file, "universal") || $key === c_ws_plugin__s2member_files::file_download_key ("/" . $file, "universal"))
514
  $valid = /* File Download Key is valid. */ true;
515
  }
516
- return apply_filters ("ws_plugin__s2member_check_file_download_key", ((isset ($valid) && $valid) ? true : false), get_defined_vars ());
517
  }
518
  /**
519
  * Creates an Amazon® S3 HMAC-SHA1 signature.
@@ -524,11 +538,11 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
524
  * @param str $string Input string/data, to be signed by this routine.
525
  * @return str An HMAC-SHA1 signature for Amazon® S3.
526
  */
527
- public static function amazon_s3_sign ($string = FALSE)
528
  {
529
  $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
530
  /**/
531
- return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign ((string)$string, $s3c["secret_key"]);
532
  }
533
  /**
534
  * Creates an Amazon® S3 HMAC-SHA1 signature URL.
@@ -544,24 +558,24 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
544
  * @param str $mimetype The MIME content-type of the resource file.
545
  * @return str An HMAC-SHA1 signature URL for Amazon® S3.
546
  */
547
- public static function amazon_s3_url ($file = FALSE, $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = FALSE, $mimetype = FALSE)
548
  {
549
- $file = /* Trim / force string. */ trim ((string)$file, "/");
550
  /**/
551
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
552
- if (preg_match ("/^amazon_s3_files_/", $option) && ($option = preg_replace ("/^amazon_s3_files_/", "", $option)))
553
  $s3c[$option] = $option_value;
554
  /**/
555
- $s3c["expires"] = strtotime ("+" . apply_filters ("ws_plugin__s2member_amazon_s3_file_expires_time", "30 seconds", get_defined_vars ()));
556
  /**/
557
- $s3_file = add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode_deep (array ("response-cache-control" => ($s3_cache_control = "no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"), "response-content-disposition" => ($s3_content_disposition = (((bool)$inline) ? "inline" : "attachment") . '; filename="' . (string)$basename . '"'), "response-content-type" => ($s3_content_type = (string)$mimetype), "response-expires" => ($s3_expires = gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT")))), "/" . $file);
558
- $s3_raw_file = add_query_arg (array ("response-cache-control" => $s3_cache_control, "response-content-disposition" => $s3_content_disposition, "response-content-type" => $s3_content_type, "response-expires" => $s3_expires), "/" . $file);
559
- $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("GET\n\n\n" . $s3c["expires"] . "\n" . "/" . $s3c["bucket"] . $s3_raw_file));
560
  /**/
561
- $s3_url = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "http" . (($ssl) ? "s" : "") . "://s3.amazonaws.com/" . $s3c["bucket"] . $s3_file : "http" . (($ssl) ? "s" : "") . "://" . $s3c["bucket"] . ".s3.amazonaws.com" . $s3_file;
562
  /**/
563
- return add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */
564
- (urlencode_deep (array ("AWSAccessKeyId" => $s3c["access_key"], "Expires" => $s3c["expires"], "Signature" => $s3_signature))), $s3_url);
565
  }
566
  /**
567
  * Auto-configures an Amazon® S3 Bucket's ACLs.
@@ -572,82 +586,82 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
572
  * @return array Array containing a true `success` element on success, else a failure array.
573
  * Failure array will contain a failure `code`, and a failure `message`.
574
  */
575
- public static function amazon_s3_auto_configure_acls ()
576
  {
577
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
578
- if (preg_match ("/^amazon_s3_files_/", $option) && ($option = preg_replace ("/^amazon_s3_files_/", "", $option)))
579
  $s3c[$option] = $option_value;
580
  /**/
581
  $cfc["distros_s3_access_id"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_s3_access_id"];
582
  /**/
583
- if /* Must have Amazon® S3 Bucket/Keys. */ ($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"])
584
  {
585
- $s3_date = gmdate ("D, d M Y H:i:s") . " GMT";
586
- $s3_location = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "/" . $s3c["bucket"] . "/?acl" : "/?acl";
587
- $s3_domain = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "s3.amazonaws.com" : $s3c["bucket"] . ".s3.amazonaws.com";
588
- $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("GET\n\n\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?acl"));
589
- $s3_args = array ("method" => "GET", "headers" => array ("Host" => $s3_domain, "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature));
590
  /**/
591
- if (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && $s3_response["code"] === 200)
592
  {
593
- if (preg_match ("/\<Owner\>(.+?)\<\/Owner\>/is", $s3_response["body"], $s3_owner_tag) && preg_match ("/\<ID\>(.+?)\<\/ID\>/is", $s3_owner_tag[1], $s3_owner_id_tag) && (preg_match ("/\<DisplayName\>(.*?)\<\/DisplayName\>/is", $s3_owner_tag[1], $s3_owner_display_name_tag) || ($s3_owner_display_name_tag = array ("-", "Owner"))))
594
  {
595
- $s3_owner = array ("access_id" => trim ($s3_owner_id_tag[1]), "display_name" => trim ($s3_owner_display_name_tag[1]));
596
- $s3_acls_xml = '<AccessControlPolicy><Owner><ID>' . esc_html ($s3_owner["access_id"]) . '</ID><DisplayName>' . esc_html ($s3_owner["display_name"]) . '</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>' . esc_html ($s3_owner["access_id"]) . '</ID><DisplayName>' . esc_html ($s3_owner["display_name"]) . '</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant>' . (($cfc["distros_s3_access_id"]) ? '<Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>' . esc_html ($cfc["distros_s3_access_id"]) . '</ID><DisplayName>s2Member/CloudFront</DisplayName></Grantee><Permission>READ</Permission></Grant>' : '') . '</AccessControlList></AccessControlPolicy>';
597
- $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("PUT\n\napplication/xml\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?acl"));
598
- $s3_args = array ("method" => "PUT", "body" => $s3_acls_xml, "headers" => array ("Host" => $s3_domain, "Content-Type" => "application/xml", "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature));
599
  /**/
600
- if (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && $s3_response["code"] === 200)
601
  {
602
- $s3_location = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "/" . $s3c["bucket"] . "/?policy" : "/?policy";
603
- ($s3_policy_id = md5 (uniqid ("s2Member/CloudFront:", true))) . ($s3_policy_sid = md5 (uniqid ("s2Member/CloudFront:", true)));
604
- $s3_policy_json = '{"Version":"2008-10-17","Id":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($s3_policy_id) . '","Statement":[{"Sid":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($s3_policy_sid) . '","Effect":"Allow","Principal":{"CanonicalUser":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($cfc["distros_s3_access_id"]) . '"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::' . c_ws_plugin__s2member_utils_strings::esc_dq ($s3c["bucket"]) . '/*"}]}';
605
- $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("PUT\n\napplication/json\n" . $s3_date . "\n/" . $s3c["bucket"] . "/?policy"));
606
- $s3_args = array ("method" => "PUT", "body" => $s3_policy_json, "headers" => array ("Host" => $s3_domain, "Content-Type" => "application/json", "Date" => $s3_date, "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature));
607
  /**/
608
- if (!$cfc["distros_s3_access_id"] || (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && ($s3_response["code"] === 200 || $s3_response["code"] === 204 /* Also OK. */)))
609
  {
610
- $s3_location = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "/" . $s3c["bucket"] . "/crossdomain.xml" : "/crossdomain.xml";
611
- $s3_policy_xml = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/cfg-files/s2-cross-xml.php")));
612
- $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("PUT\n\ntext/xml\n" . $s3_date . "\nx-amz-acl:public-read\n/" . $s3c["bucket"] . "/crossdomain.xml"));
613
- $s3_args = array ("method" => "PUT", "body" => $s3_policy_xml, "headers" => array ("Host" => $s3_domain, "Content-Type" => "text/xml", "Date" => $s3_date, "X-Amz-Acl" => "public-read", "Authorization" => "AWS " . $s3c["access_key"] . ":" . $s3_signature));
614
  /**/
615
- if (($s3_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $s3_domain . $s3_location, false, array_merge ($s3_args, array ("timeout" => 20)), "array")) && $s3_response["code"] === 200)
616
- return /* Successfully configured Amazon® S3 Bucket ACLs and Policy. */ array ("success" => true, "code" => null, "message" => null);
617
  /**/
618
- else if (isset ($s3_response["code"], $s3_response["message"]))
619
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
620
- return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 Cross-Domain Policy. %s", "s2member-admin", "s2member"), $s3_response["message"]));
621
  /**/
622
  else /* Else, we use a default error code and message. */
623
- return array ("success" => false, "code" => -94, "message" => _x ("Unable to update existing Amazon® S3 Cross-Domain Policy. Connection failed.", "s2member-admin", "s2member"));
624
  }
625
- else if (isset ($s3_response["code"], $s3_response["message"]))
626
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
627
- return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 Bucket Policy. %s", "s2member-admin", "s2member"), $s3_response["message"]));
628
  /**/
629
  else /* Else, we use a default error code and message. */
630
- return array ("success" => false, "code" => -95, "message" => _x ("Unable to update existing Amazon® S3 Bucket Policy. Connection failed.", "s2member-admin", "s2member"));
631
  }
632
- else if (isset ($s3_response["code"], $s3_response["message"]))
633
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
634
- return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 Bucket ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"]));
635
  /**/
636
  else /* Else, we use a default error code and message. */
637
- return array ("success" => false, "code" => -96, "message" => _x ("Unable to update existing Amazon® S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member"));
638
  }
639
  else /* Else, we use a default error code and message. */
640
- return array ("success" => false, "code" => -97, "message" => _x ("Unable to acquire/read existing Amazon® S3 Bucket ACLs. Unexpected response.", "s2member-admin", "s2member"));
641
  }
642
- else if (isset ($s3_response["code"], $s3_response["message"]))
643
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
644
- return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® S3 Bucket ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"]));
645
  /**/
646
  else /* Else, we use a default error code and message. */
647
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to acquire existing Amazon® S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member"));
648
  }
649
  else /* Else, we use a default error code and message. */
650
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to auto-configure existing Amazon® S3 Bucket ACLs. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key.", "s2member-admin", "s2member"));
651
  }
652
  /**
653
  * Creates an Amazon® CloudFront HMAC-SHA1 signature.
@@ -658,11 +672,11 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
658
  * @param str $string Input string/data, to be signed by this routine.
659
  * @return str An HMAC-SHA1 signature for Amazon® CloudFront.
660
  */
661
- public static function amazon_cf_sign ($string = FALSE)
662
  {
663
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
664
  /**/
665
- return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign ((string)$string, ($cfc["secret_key"] = $s3c["secret_key"]));
666
  }
667
  /**
668
  * Creates an Amazon® CloudFront RSA-SHA1 signature.
@@ -676,11 +690,11 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
676
  * @todo Double underscores *( i.e. base64 padding chars )* in the signature seem to cause issues for Amazon® CloudFront?
677
  * See ticket: {@link https://forums.aws.amazon.com/thread.jspa?messageID=286182&#286182}
678
  */
679
- public static function amazon_cf_rsa_sign ($string = FALSE)
680
  {
681
  $cfc["private_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"];
682
  /**/
683
- return c_ws_plugin__s2member_utils_strings::rsa_sha1_sign ((string)$string, $cfc["private_key"]);
684
  }
685
  /**
686
  * Creates an Amazon® CloudFront RSA-SHA1 signature URL.
@@ -696,29 +710,29 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
696
  * @param str $mimetype The MIME content-type of the resource file.
697
  * @return str An RSA-SHA1 signature URL for Amazon® CloudFront.
698
  */
699
- public static function amazon_cf_url ($file = FALSE, $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = FALSE, $mimetype = FALSE)
700
  {
701
- $file = /* Trim / force string. */ trim ((string)$file, "/");
702
  /**/
703
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
704
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
705
  $cfc[$option] = $option_value;
706
  /**/
707
- $cfc["expires"] = strtotime ("+" . apply_filters ("ws_plugin__s2member_amazon_cf_file_expires_time", "24 hours", get_defined_vars ()));
708
  /**/
709
- $cf_extn = /* Parses the file extension out so we can scan it in some special scenarios. */ strtolower (substr ($file, strrpos ($file, ".") + 1));
710
- $cf_ip_res = /* Do NOT restrict access to a particular IP during `localhost` development. The IP may NOT be the same one Amazon® CloudFront sees. */ (c_ws_plugin__s2member_utils_conds::is_localhost ()) ? false : true;
711
- $cf_stream_extn_resource_exclusions = array_unique ((array)apply_filters ("ws_plugin__s2member_amazon_cf_file_streaming_extension_resource_exclusions", array ("mp3" /* MP3 files should NOT include an extension in their resource reference. */), get_defined_vars ()));
712
- $cf_resource = ($stream) ? ((in_array ($cf_extn, $cf_stream_extn_resource_exclusions)) ? substr ($file, 0, strrpos ($file, ".")) : $file) : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file;
713
- $cf_url = ($stream) ? "rtmp" . (($ssl) ? "e" : "") . "://" . (($cfc["distro_streaming_cname"]) ? $cfc["distro_streaming_cname"] : $cfc["distro_streaming_dname"]) . "/cfx/st/" . $file : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file;
714
- $cf_policy = '{"Statement":[{"Resource":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($cf_resource) . '","Condition":{' . (($cf_ip_res) ? '"IpAddress":{"AWS:SourceIp":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($_SERVER["REMOTE_ADDR"]) . '/32"},' : '') . '"DateLessThan":{"AWS:EpochTime":' . (int)$cfc["expires"] . '}}}]}';
715
  /**/
716
- $cf_signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_sign ($cf_policy);
717
- $cf_base64_url_safe_policy = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_policy, array ("+", "=", "/"), array ("-", "_", "~"), false);
718
- $cf_base64_url_safe_signature = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_signature, array ("+", "=", "/"), array ("-", "_", "~"), false);
719
  /**/
720
- return add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */
721
- (urlencode_deep (array ("Policy" => $cf_base64_url_safe_policy, "Signature" => $cf_base64_url_safe_signature, "Key-Pair-Id" => $cfc["private_key_id"]))), $cf_url);
722
  }
723
  /**
724
  * Auto-configures Amazon® S3/CloudFront distros.
@@ -729,170 +743,170 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
729
  * @return array Array containing a true `success` element on success, else a failure array.
730
  * Failure array will contain a failure `code`, and a failure `message`.
731
  */
732
- public static function amazon_cf_auto_configure_distros ()
733
  {
734
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
735
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
736
  $cfc[$option] = $option_value;
737
  /**/
738
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
739
  $cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"];
740
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
741
  /**/
742
- if /* We MUST have an Amazon® S3 Bucket and Keys. */ ($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"])
743
  {
744
- if /* We MUST have Amazon® CloudFront Keys in order to auto-configure. */ ($cfc["private_key"] && $cfc["private_key_id"])
745
  {
746
- if (!$cfc["distro_downloads_id"] || ($cfc["distro_downloads_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro ($cfc["distro_downloads_id"], "downloads")) && ($cf_get_response["success"] || $cf_get_response["code"] === 404)))
747
  {
748
- if (!$cfc["distro_downloads_id"] || ($cfc["distro_downloads_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404))
749
  $cf_distro_downloads_clear = /* Clear, ready for a new one. */ true;
750
  /**/
751
- else if ($cfc["distro_downloads_id"] && $cf_get_response && $cf_get_response["success"] && !$cf_get_response["deployed"])
752
- return array ("success" => false, "code" => -86, "message" => _x ("Unable to delete existing Amazon® CloudFront Downloads Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
753
  /**/
754
- else if ($cfc["distro_downloads_id"] && $cf_get_response && $cf_get_response["success"] && $cf_get_response["deployed"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_distro ($cfc["distro_downloads_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"])
755
  $cf_distro_downloads_clear = /* Clear, ready for a new one. */ true;
756
  /**/
757
- else if (isset ($cf_del_response["code"], $cf_del_response["message"]))
758
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
759
- return array ("success" => false, "code" => $cf_del_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_del_response["message"]));
760
  /**/
761
- if /* Successfully cleared? Ready for a new one? */ (isset ($cf_distro_downloads_clear) && $cf_distro_downloads_clear)
762
  {
763
- unset /* Unset these before processing additional routines. Prevents problems in error reporting. */ ($cf_get_response, $cf_del_response);
764
  /**/
765
- if (!$cfc["distro_streaming_id"] || ($cfc["distro_streaming_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro ($cfc["distro_streaming_id"], "streaming")) && ($cf_get_response["success"] || $cf_get_response["code"] === 404)))
766
  {
767
- if (!$cfc["distro_streaming_id"] || ($cfc["distro_streaming_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404))
768
  $cf_distro_streaming_clear = /* Clear, ready for a new one. */ true;
769
  /**/
770
- else if ($cfc["distro_streaming_id"] && $cf_get_response && $cf_get_response["success"] && !$cf_get_response["deployed"])
771
- return array ("success" => false, "code" => -87, "message" => _x ("Unable to delete existing Amazon® CloudFront Streaming Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
772
  /**/
773
- else if ($cfc["distro_streaming_id"] && $cf_get_response && $cf_get_response["success"] && $cf_get_response["deployed"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_distro ($cfc["distro_streaming_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"])
774
  $cf_distro_streaming_clear = /* Clear, ready for a new one. */ true;
775
  /**/
776
- else if (isset ($cf_del_response["code"], $cf_del_response["message"]))
777
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
778
- return array ("success" => false, "code" => $cf_del_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_del_response["message"]));
779
  /**/
780
- if /* Successfully cleared? Ready for a new one? */ (isset ($cf_distro_streaming_clear) && $cf_distro_streaming_clear)
781
  {
782
- unset /* Unset these before processing additional routines. Prevents problems in error reporting. */ ($cf_get_response, $cf_del_response);
783
  /**/
784
- if (!$cfc["distros_access_id"] || ($cfc["distros_access_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_access_origin_identity ($cfc["distros_access_id"])) && ($cf_get_response["success"] || $cf_get_response["code"] === 404)))
785
  {
786
- if (!$cfc["distros_access_id"] || ($cfc["distros_access_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404))
787
  $cf_distros_access_clear = /* Clear, ready for a new one. */ true;
788
  /**/
789
- else if ($cfc["distros_access_id"] && $cf_get_response && $cf_get_response["success"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_access_origin_identity ($cfc["distros_access_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"])
790
  $cf_distros_access_clear = /* Clear, ready for a new one. */ true;
791
  /**/
792
- else if (isset ($cf_del_response["code"], $cf_del_response["message"]))
793
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
794
- return array ("success" => false, "code" => $cf_del_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_del_response["message"]));
795
  /**/
796
- if /* Successfully cleared? Ready for a new one? */ (isset ($cf_distros_access_clear) && $cf_distros_access_clear)
797
  {
798
- unset /* Unset these before processing additional routines. Prevents problems in error reporting. */ ($cf_get_response, $cf_del_response);
799
  /**/
800
- $cfc = array_merge ($cfc, array ("distros_access_id" => "", "distros_s3_access_id" => "", "distro_downloads_id" => "", "distro_downloads_dname" => "", "distro_streaming_id" => "", "distro_streaming_dname" => "", "distros_auto_config_status" => ""));
801
- $cf_options = array ("ws_plugin__s2member_amazon_cf_files_distros_access_id" => "", "ws_plugin__s2member_amazon_cf_files_distros_s3_access_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_downloads_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_downloads_dname" => "", "ws_plugin__s2member_amazon_cf_files_distro_streaming_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_streaming_dname" => "", "ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" => "");
802
- c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false);
803
  /**/
804
- if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distros_access_origin_identity ()) && $cf_response["success"])
805
  {
806
- $cfc = array_merge ($cfc, array ("distros_access_id" => $cf_response["distros_access_id"], "distros_s3_access_id" => $cf_response["distros_s3_access_id"]));
807
- $cf_options = array ("ws_plugin__s2member_amazon_cf_files_distros_access_id" => $cf_response["distros_access_id"], "ws_plugin__s2member_amazon_cf_files_distros_s3_access_id" => $cf_response["distros_s3_access_id"]);
808
- c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false);
809
  /**/
810
- if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distro ("downloads")) && $cf_response["success"])
811
  {
812
- $cfc = array_merge ($cfc, array ("distro_downloads_id" => $cf_response["distro_downloads_id"], "distro_downloads_dname" => $cf_response["distro_downloads_dname"]));
813
- $cf_options = array ("ws_plugin__s2member_amazon_cf_files_distro_downloads_id" => $cf_response["distro_downloads_id"], "ws_plugin__s2member_amazon_cf_files_distro_downloads_dname" => $cf_response["distro_downloads_dname"]);
814
- c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false);
815
  /**/
816
- if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distro ("streaming")) && $cf_response["success"])
817
  {
818
- $cfc = array_merge ($cfc, array ("distro_streaming_id" => $cf_response["distro_streaming_id"], "distro_streaming_dname" => $cf_response["distro_streaming_dname"]));
819
- $cf_options = array ("ws_plugin__s2member_amazon_cf_files_distro_streaming_id" => $cf_response["distro_streaming_id"], "ws_plugin__s2member_amazon_cf_files_distro_streaming_dname" => $cf_response["distro_streaming_dname"]);
820
- c_ws_plugin__s2member_menu_pages::update_all_options ($cf_options, true, false, false, false, false);
821
  /**/
822
- for ($a = 1, $attempts = 4, $sleep = 2, sleep ($sleep); $a <= $attempts; $a++, (($a <= $attempts) ? sleep ($sleep) : null))
823
  /* Allow a generous propagation time here. Amazon's high-availability services do NOT guarantee real-time updates.
824
  Since we DO need a fully propagated Origin Access Identity now, we need to make several attempts at success.
825
  For further details, please see this thread: <https://forums.aws.amazon.com/message.jspa?messageID=42875>. */
826
- if (($s3_response = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls ()) && $s3_response["success"])
827
  {
828
- $cfc = array_merge ($cfc, array ("distros_auto_config_status" => "configured"));
829
- $cf_options = array ("ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" => "configured");
830
- c_ws_plugin__s2member_menu_pages::update_all_options ( /* Now configured! */$cf_options, true, false, false, false, false);
831
- return /* Successfully configured Amazon® S3/CloudFront distros. */ array ("success" => true, "code" => null, "message" => null);
832
  }
833
- if (isset ($s3_response["code"], $s3_response["message"]))
834
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
835
- return array ("success" => false, "code" => $s3_response["code"], "message" => sprintf (_x ("Unable to update existing Amazon® S3 ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"]));
836
  /**/
837
  else /* Else, we use a default error code and message. */
838
- return array ("success" => false, "code" => -88, "message" => _x ("Unable to update existing Amazon® S3 ACLs. Connection failed.", "s2member-admin", "s2member"));
839
  }
840
- else if (isset ($cf_response["code"], $cf_response["message"]))
841
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
842
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
843
  /**/
844
  else /* Else, we use a default error code and message. */
845
- return array ("success" => false, "code" => -89, "message" => _x ("Unable to create Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member"));
846
  }
847
- else if (isset ($cf_response["code"], $cf_response["message"]))
848
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
849
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
850
  /**/
851
  else /* Else, we use a default error code and message. */
852
- return array ("success" => false, "code" => -90, "message" => _x ("Unable to create Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member"));
853
  }
854
- else if (isset ($cf_response["code"], $cf_response["message"]))
855
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
856
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
857
  /**/
858
  else /* Else, we use a default error code and message. */
859
- return array ("success" => false, "code" => -91, "message" => _x ("Unable to create Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
860
  }
861
  else /* Else, we use a default error code and message. */
862
- return array ("success" => false, "code" => -92, "message" => _x ("Unable to clear existing Amazon® CloudFront Origin Access Identity.", "s2member-admin", "s2member"));
863
  }
864
- else if (isset ($cf_get_response["code"], $cf_get_response["message"]))
865
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
866
- return array ("success" => false, "code" => $cf_get_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_get_response["message"]));
867
  /**/
868
  else /* Else, we use a default error code and message. */
869
- return array ("success" => false, "code" => -93, "message" => _x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
870
  }
871
  else /* Else, we use a default error code and message. */
872
- return array ("success" => false, "code" => -94, "message" => _x ("Unable to clear existing Amazon® CloudFront Streaming Distro.", "s2member-admin", "s2member"));
873
  }
874
- else if (isset ($cf_get_response["code"], $cf_get_response["message"]))
875
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
876
- return array ("success" => false, "code" => $cf_get_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_get_response["message"]));
877
  /**/
878
  else /* Else, we use a default error code and message. */
879
- return array ("success" => false, "code" => -95, "message" => _x ("Unable to acquire existing Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member"));
880
  }
881
  else /* Else, we use a default error code and message. */
882
- return array ("success" => false, "code" => -96, "message" => _x ("Unable to clear existing Amazon® CloudFront Downloads Distro.", "s2member-admin", "s2member"));
883
  }
884
- else if (isset ($cf_get_response["code"], $cf_get_response["message"]))
885
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
886
- return array ("success" => false, "code" => $cf_get_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_get_response["message"]));
887
  /**/
888
  else /* Else, we use a default error code and message. */
889
- return array ("success" => false, "code" => -97, "message" => _x ("Unable to acquire existing Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member"));
890
  }
891
  else /* Else, we use a default error code and message. */
892
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to auto-configure Amazon® CloudFront Distros. Incomplete Amazon® CloudFront configuration options. Missing of one: Amazon® CloudFront Private Key-Pair-ID, or Private Key file contents.", "s2member-admin", "s2member"));
893
  }
894
  else /* Else, we use a default error code and message. */
895
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to auto-configure Amazon® S3/CloudFront Distros. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key. You must provide s2Member with an Amazon® S3 configuration before enabling CloudFront.", "s2member-admin", "s2member"));
896
  }
897
  /**
898
  * Acquires an Amazon® S3/CloudFront Access Origin Identity.
@@ -904,12 +918,12 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
904
  * @return array Array containing a true `success` and `etag`, `xml` elements on success, else a failure array.
905
  * Failure array will contain a failure `code`, and a failure `message`.
906
  */
907
- public static function amazon_cf_get_access_origin_identity ($access_id = FALSE)
908
  {
909
- if /* Valid parameters? */ ($access_id && is_string ($access_id))
910
  {
911
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
912
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
913
  $cfc[$option] = $option_value;
914
  /**/
915
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -917,28 +931,28 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
917
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
918
  /**/
919
  $cf_domain = "cloudfront.amazonaws.com";
920
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
921
- $cf_location = "/2010-11-01/origin-access-identity/cloudfront/" . $access_id;
922
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
923
- $cf_args = array ("method" => "GET", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
924
  /**/
925
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && (($cf_response["code"] === 404 && $cf_response["message"]) || ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"]))))
926
  {
927
- if ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"]))
928
- return array ("success" => true, "code" => null, "message" => null, "etag" => trim ($cf_response["headers"]["etag"]), "xml" => trim ($cf_response["body"]));
929
  /**/
930
  else /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
931
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Existing Amazon® CloudFront Origin Access Identity NOT found. %s", "s2member-admin", "s2member"), $cf_response["message"]));
932
  }
933
- else if (isset ($cf_response["code"], $cf_response["message"]))
934
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
935
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
936
  /**/
937
  else /* Else, we use a default error code and message. */
938
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
939
  }
940
  else /* Else, we use a default error code and message. */
941
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Invalid Access ID.", "s2member-admin", "s2member"));
942
  }
943
  /**
944
  * Deletes an Amazon® S3/CloudFront Access Origin Identity.
@@ -952,12 +966,12 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
952
  * @return array Array containing a true `success` element on success, else a failure array.
953
  * Failure array will contain a failure `code`, and a failure `message`.
954
  */
955
- public static function amazon_cf_del_access_origin_identity ($access_id = FALSE, $access_id_etag = FALSE, $access_id_xml = FALSE)
956
  {
957
- if ($access_id && is_string ($access_id) && $access_id_etag && is_string ($access_id_etag) && $access_id_xml && is_string ($access_id_xml))
958
  {
959
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
960
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
961
  $cfc[$option] = $option_value;
962
  /**/
963
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -965,23 +979,23 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
965
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
966
  /**/
967
  $cf_domain = "cloudfront.amazonaws.com";
968
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
969
- $cf_location = "/2010-11-01/origin-access-identity/cloudfront/" . $access_id;
970
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
971
- $cf_args = array ("method" => "DELETE", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "If-Match" => $access_id_etag, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
972
  /**/
973
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 204 /* Deleted. */))
974
- return /* Deleted successfully. */ array ("success" => true, "code" => null, "message" => null);
975
  /**/
976
- else if (isset ($cf_response["code"], $cf_response["message"]))
977
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
978
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
979
  /**/
980
  else /* Else, we use a default error code and message. */
981
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
982
  }
983
  else /* Else, we use a default error code and message. */
984
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to delete existing Amazon® CloudFront Origin Access Identity. Invalid Access ID, ETag, or XML config.", "s2member-admin", "s2member"));
985
  }
986
  /**
987
  * Creates an Amazon® S3/CloudFront Access Origin Identity for all Distros.
@@ -992,10 +1006,10 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
992
  * @return array Array containing a true `success` and `distros_access_id`, `distros_s3_access_id` elements on success, else a failure array.
993
  * Failure array will contain a failure `code`, and a failure `message`.
994
  */
995
- public static function amazon_cf_create_distros_access_origin_identity ()
996
  {
997
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
998
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
999
  $cfc[$option] = $option_value;
1000
  /**/
1001
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -1003,27 +1017,27 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1003
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1004
  /**/
1005
  $cf_domain = "cloudfront.amazonaws.com";
1006
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
1007
  $cf_location = "/2010-11-01/origin-access-identity/cloudfront";
1008
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
1009
- $cf_distros_access_reference = time () . "." . md5 ("access" . $s3c["bucket"] . $s3c["access_key"] . $s3c["secret_key"] . $cfc["private_key"] . $cfc["private_key_id"]);
1010
- $cf_distros_access_xml = '<?xml version="1.0" encoding="UTF-8"?><CloudFrontOriginAccessIdentityConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><CallerReference>' . esc_html ($cf_distros_access_reference) . '</CallerReference><Comment>' . esc_html (sprintf (_x ("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])) . '</Comment></CloudFrontOriginAccessIdentityConfig>';
1011
- $cf_args = array ("method" => "POST", "body" => $cf_distros_access_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
1012
  /**/
1013
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */))
1014
  {
1015
- if (preg_match ("/\<CloudFrontOriginAccessIdentity.*?\>(.+?)\<\/CloudFrontOriginAccessIdentity\>/is", $cf_response["body"], $cf_distros_access_tag) && preg_match ("/\<Id\>(.+?)\<\/Id\>/is", $cf_distros_access_tag[1], $cf_distros_access_id_tag) && preg_match ("/\<S3CanonicalUserId\>(.+?)\<\/S3CanonicalUserId\>/is", $cf_distros_access_tag[1], $cf_distros_s3_access_id_tag))
1016
- return array ("success" => true, "code" => null, "message" => null, "distros_access_id" => trim ($cf_distros_access_id_tag[1]), "distros_s3_access_id" => trim ($cf_distros_s3_access_id_tag[1]));
1017
  /**/
1018
  else /* Else, we use a default error code and message. */
1019
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to create/read Amazon® CloudFront Origin Access Identity. Unexpected response.", "s2member-admin", "s2member"));
1020
  }
1021
- else if (isset ($cf_response["code"], $cf_response["message"]))
1022
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1023
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1024
  /**/
1025
  else /* Else, we use a default error code and message. */
1026
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to create Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
1027
  }
1028
  /**
1029
  * Acquires an Amazon® S3/CloudFront Distro.
@@ -1036,12 +1050,12 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1036
  * @return array Array containing a true `success` and `etag`, `xml`, `deployed` elements on success, else a failure array.
1037
  * Failure array will contain a failure `code`, and a failure `message`.
1038
  */
1039
- public static function amazon_cf_get_distro ($distro_id = FALSE, $distro_type = FALSE)
1040
  {
1041
- if ($distro_id && is_string ($distro_id) && $distro_type && is_string ($distro_type) && in_array ($distro_type, array ("downloads", "streaming")))
1042
  {
1043
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1044
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
1045
  $cfc[$option] = $option_value;
1046
  /**/
1047
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -1049,28 +1063,28 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1049
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1050
  /**/
1051
  $cf_domain = "cloudfront.amazonaws.com";
1052
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
1053
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
1054
- $cf_location = ($distro_type === "streaming") ? "/2010-11-01/streaming-distribution/" . $distro_id : "/2010-11-01/distribution/" . $distro_id;
1055
- $cf_args = array ("method" => "GET", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
1056
  /**/
1057
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && (($cf_response["code"] === 404 && $cf_response["message"]) || ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"]))))
1058
  {
1059
- if ($cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"]))
1060
- return array ("success" => true, "code" => null, "message" => null, "etag" => trim ($cf_response["headers"]["etag"]), "xml" => trim ($cf_response["body"]), "deployed" => ((stripos ($cf_response["body"], "<Status>Deployed</Status>") !== false) ? true : false));
1061
  /**/
1062
  else /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1063
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Existing Amazon® CloudFront Distro NOT found. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1064
  }
1065
- else if (isset ($cf_response["code"], $cf_response["message"]))
1066
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1067
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to acquire existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1068
  /**/
1069
  else /* Else, we use a default error code and message. */
1070
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to acquire existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1071
  }
1072
  else /* Else, we use a default error code and message. */
1073
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to acquire existing Amazon® CloudFront Distro. Invalid Distro ID and/or Distro type.", "s2member-admin", "s2member"));
1074
  }
1075
  /**
1076
  * Disables an Amazon® S3/CloudFront Distro.
@@ -1084,16 +1098,16 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1084
  * @return array Array containing a true `success` and `etag`, `xml`, `deployed` elements on success, else a failure array.
1085
  * Failure array will contain a failure `code`, and a failure `message`.
1086
  */
1087
- public static function amazon_cf_disable_distro ($distro_id = FALSE, $distro_id_etag = FALSE, $distro_id_xml = FALSE)
1088
  {
1089
- if ($distro_id && is_string ($distro_id) && $distro_id_etag && is_string ($distro_id_etag) && $distro_id_xml && is_string ($distro_id_xml) && ($distro_id_type = (stripos ($distro_id_xml, "<StreamingDistribution") !== false) ? "streaming" : ((stripos ($distro_id_xml, "<Distribution") !== false) ? "downloads" : false)) && preg_match ("/\<CallerReference\>(.+?)\<\/CallerReference\>/is", $distro_id_xml, $distro_id_reference_tag) && ($distro_id_reference = $distro_id_reference_tag[1]))
1090
  {
1091
- if /* Only if it has NOT already been disabled. We do NOT need to do it again. */ (stripos ($distro_id_xml, "<Enabled>false</Enabled>") === false)
1092
  {
1093
- if /* Check distro status before we even begin processing. */ (stripos ($distro_id_xml, "<Status>Deployed</Status>") !== false)
1094
  {
1095
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1096
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
1097
  $cfc[$option] = $option_value;
1098
  /**/
1099
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -1101,30 +1115,30 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1101
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1102
  /**/
1103
  $cf_domain = "cloudfront.amazonaws.com";
1104
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
1105
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
1106
- $cf_location = ($distro_id_type === "streaming") ? "/2010-11-01/streaming-distribution/" . $distro_id . "/config" : "/2010-11-01/distribution/" . $distro_id . "/config";
1107
- $cf_distro_xml = ($distro_id_type === "streaming") ? '<?xml version="1.0" encoding="UTF-8"?><StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName></S3Origin><CallerReference>' . esc_html ($distro_id_reference) . '</CallerReference><Enabled>false</Enabled><TrustedSigners><Self/></TrustedSigners></StreamingDistributionConfig>' : '<?xml version="1.0" encoding="UTF-8"?><DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName></S3Origin><CallerReference>' . esc_html ($distro_id_reference) . '</CallerReference><Enabled>false</Enabled><TrustedSigners><Self/></TrustedSigners></DistributionConfig>';
1108
- $cf_args = array ("method" => "PUT", "body" => $cf_distro_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "If-Match" => $distro_id_etag, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
1109
  /**/
1110
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && $cf_response["code"] === 200 && !empty ($cf_response["headers"]["etag"]) && !empty ($cf_response["body"]))
1111
- return array ("success" => true, "code" => null, "message" => null, "etag" => trim ($cf_response["headers"]["etag"]), "xml" => trim ($cf_response["body"]), "deployed" => ((stripos ($cf_response["body"], "<Status>Deployed</Status>") !== false) ? true : false));
1112
  /**/
1113
- else if (isset ($cf_response["code"], $cf_response["message"]))
1114
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1115
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to disable existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1116
  /**/
1117
  else /* Else, we use a default error code and message. */
1118
- return array ("success" => false, "code" => -97, "message" => _x ("Unable to disable existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1119
  }
1120
  else /* Else, we use a default error code and message. */
1121
- return array ("success" => false, "code" => -98, "message" => _x ("Existing Amazon® CloudFront Distro cannot be disabled at this time. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
1122
  }
1123
  else /* Else, we use a default error code and message. */
1124
- return array ("success" => true, "code" => null, "message" => null, "etag" => $distro_id_etag, "xml" => $distro_id_xml, "deployed" => ((stripos ($distro_id_xml, "<Status>Deployed</Status>") !== false) ? true : false));
1125
  }
1126
  else /* Else, we use a default error code and message. */
1127
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to disable existing Amazon® CloudFront Distro. Invalid Distro ID, ETag, or XML config.", "s2member-admin", "s2member"));
1128
  }
1129
  /**
1130
  * Deletes an Amazon® S3/CloudFront Distro.
@@ -1138,18 +1152,18 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1138
  * @return array Array containing a true `success` element on success, else a failure array.
1139
  * Failure array will contain a failure `code`, and a failure `message`.
1140
  */
1141
- public static function amazon_cf_del_distro ($distro_id = FALSE, $distro_id_etag = FALSE, $distro_id_xml = FALSE)
1142
  {
1143
- if ($distro_id && is_string ($distro_id) && $distro_id_etag && is_string ($distro_id_etag) && $distro_id_xml && is_string ($distro_id_xml) && ($distro_id_type = (stripos ($distro_id_xml, "<StreamingDistribution") !== false) ? "streaming" : ((stripos ($distro_id_xml, "<Distribution") !== false) ? "downloads" : false)) && preg_match ("/\<CallerReference\>(.+?)\<\/CallerReference\>/is", $distro_id_xml, $distro_id_reference_tag) && ($distro_id_reference = $distro_id_reference_tag[1]))
1144
  {
1145
- if /* Check distro status before we even begin processing this deletion. */ (stripos ($distro_id_xml, "<Status>Deployed</Status>") !== false)
1146
  {
1147
- if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_disable_distro ($distro_id, $distro_id_etag, $distro_id_xml)) && $cf_response["success"])
1148
  {
1149
- if (($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro ($distro_id, $distro_id_type)) && $cf_response["success"] && $cf_response["deployed"])
1150
  {
1151
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1152
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
1153
  $cfc[$option] = $option_value;
1154
  /**/
1155
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -1157,44 +1171,44 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1157
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1158
  /**/
1159
  $cf_domain = "cloudfront.amazonaws.com";
1160
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
1161
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
1162
- $cf_location = ($distro_id_type === "streaming") ? "/2010-11-01/streaming-distribution/" . $distro_id : "/2010-11-01/distribution/" . $distro_id;
1163
- $cf_args = array ("method" => "DELETE", "headers" => array ("Host" => $cf_domain, "Date" => $cf_date, "If-Match" => $cf_response["etag"], "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
1164
  /**/
1165
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 204 /* Deleted. */))
1166
- return /* Deleted successfully. */ array ("success" => true, "code" => null, "message" => null);
1167
  /**/
1168
- else if (isset ($cf_response["code"], $cf_response["message"]))
1169
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1170
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to delete existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1171
  /**/
1172
  else /* Else, we use a default error code and message. */
1173
- return array ("success" => false, "code" => -94, "message" => _x ("Unable to delete existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1174
  }
1175
- else if (isset ($cf_response["success"], $cf_response["deployed"]) && $cf_response["success"] && !$cf_response["deployed"])
1176
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1177
- return array ("success" => false, "code" => -95, "message" => _x ("Existing Amazon® CloudFront Distro cannot be deleted at this time. Still in a `pending` state after having been disabled by s2Member. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
1178
  /**/
1179
- else if (isset ($cf_response["code"], $cf_response["message"]))
1180
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1181
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to check status of existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1182
  /**/
1183
  else /* Else, we use a default error code and message. */
1184
- return array ("success" => false, "code" => -96, "message" => _x ("Unable to check status of existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1185
  }
1186
- else if (isset ($cf_response["code"], $cf_response["message"]))
1187
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1188
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to disable existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1189
  /**/
1190
  else /* Else, we use a default error code and message. */
1191
- return array ("success" => false, "code" => -97, "message" => _x ("Unable to disable existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1192
  }
1193
  else /* Else, we use a default error code and message. */
1194
- return array ("success" => false, "code" => -98, "message" => _x ("Existing Amazon® CloudFront Distro cannot be deleted at this time. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
1195
  }
1196
  else /* Else, we use a default error code and message. */
1197
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to delete existing Amazon® CloudFront Distro. Invalid Distro ID or ETag.", "s2member-admin", "s2member"));
1198
  }
1199
  /**
1200
  * Creates an Amazon® S3/CloudFront Distro.
@@ -1206,12 +1220,12 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1206
  * @return array Array containing a true `success` and `distro_[distro_type]_id`, `distro_[distro_type]_dname` elements on success, else a failure array.
1207
  * Failure array will contain a failure `code`, and a failure `message`.
1208
  */
1209
- public static function amazon_cf_create_distro ($distro_type = FALSE)
1210
  {
1211
- if ($distro_type && is_string ($distro_type) && in_array ($distro_type, array ("downloads", "streaming")))
1212
  {
1213
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1214
- if (preg_match ("/^amazon_cf_files_/", $option) && ($option = preg_replace ("/^amazon_cf_files_/", "", $option)))
1215
  $cfc[$option] = $option_value;
1216
  /**/
1217
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
@@ -1219,57 +1233,57 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
1219
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1220
  /**/
1221
  $cf_domain = "cloudfront.amazonaws.com";
1222
- $cf_date = gmdate ("D, d M Y H:i:s") . " GMT";
1223
- $cf_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_cf_sign ($cf_date));
1224
  /**/
1225
- if /* Create a `downloads` Distro? This uses a different XML schema. */ ($distro_type === "downloads")
1226
  {
1227
  $cf_location = /* Create distro. */ "/2010-11-01/distribution";
1228
- $cf_distro_downloads_reference = time () . "." . md5 ("downloads" . $s3c["bucket"] . $s3c["access_key"] . $s3c["secret_key"] . $cfc["private_key"] . $cfc["private_key_id"] . $cfc["distro_downloads_cname"]);
1229
- $cf_distro_downloads_xml = '<?xml version="1.0" encoding="UTF-8"?><DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName><OriginAccessIdentity>origin-access-identity/cloudfront/' . esc_html ($cfc["distros_access_id"]) . '</OriginAccessIdentity></S3Origin><CallerReference>' . esc_html ($cf_distro_downloads_reference) . '</CallerReference>' . (($cfc["distro_downloads_cname"]) ? '<CNAME>' . esc_html ($cfc["distro_downloads_cname"]) . '</CNAME>' : '') . '<Comment>' . esc_html (sprintf (_x ("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])) . '</Comment><Enabled>true</Enabled><DefaultRootObject>index.html</DefaultRootObject><TrustedSigners><Self/></TrustedSigners></DistributionConfig>';
1230
- $cf_args = array ("method" => "POST", "body" => $cf_distro_downloads_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
1231
  /**/
1232
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */))
1233
  {
1234
- if (preg_match ("/\<Distribution.*?\>(.+?)\<\/Distribution\>/is", $cf_response["body"], $cf_distro_downloads_tag) && preg_match ("/\<Id\>(.+?)\<\/Id\>/is", $cf_distro_downloads_tag[1], $cf_distro_downloads_id_tag) && preg_match ("/\<DomainName\>(.+?)\<\/DomainName\>/is", $cf_distro_downloads_tag[1], $cf_distro_downloads_dname_tag))
1235
- return array ("success" => true, "code" => null, "message" => null, "distro_downloads_id" => trim ($cf_distro_downloads_id_tag[1]), "distro_downloads_dname" => trim ($cf_distro_downloads_dname_tag[1]));
1236
  /**/
1237
  else /* Else, we use a default error code and message. */
1238
- return array ("success" => false, "code" => -97, "message" => _x ("Unable to create/read Amazon® CloudFront Downloads Distro. Unexpected response.", "s2member-admin", "s2member"));
1239
  }
1240
- else if (isset ($cf_response["code"], $cf_response["message"]))
1241
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1242
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1243
  /**/
1244
  else /* Else, we use a default error code and message. */
1245
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to create Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member"));
1246
  }
1247
  /**/
1248
- else if /* Create a `streaming` Distro? A different XML schema. */ ($distro_type === "streaming")
1249
  {
1250
  $cf_location = /* Create streaming distro. */ "/2010-11-01/streaming-distribution";
1251
- $cf_distro_streaming_reference = time () . "." . md5 ("streaming" . $s3c["bucket"] . $s3c["access_key"] . $s3c["secret_key"] . $cfc["private_key"] . $cfc["private_key_id"] . $cfc["distro_streaming_cname"]);
1252
- $cf_distro_streaming_xml = '<?xml version="1.0" encoding="UTF-8"?><StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>' . esc_html ($s3c["bucket"]) . '.s3.amazonaws.com</DNSName><OriginAccessIdentity>origin-access-identity/cloudfront/' . esc_html ($cfc["distros_access_id"]) . '</OriginAccessIdentity></S3Origin><CallerReference>' . esc_html ($cf_distro_streaming_reference) . '</CallerReference>' . (($cfc["distro_streaming_cname"]) ? '<CNAME>' . esc_html ($cfc["distro_streaming_cname"]) . '</CNAME>' : '') . '<Comment>' . esc_html (sprintf (_x ("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])) . '</Comment><Enabled>true</Enabled><DefaultRootObject>index.html</DefaultRootObject><TrustedSigners><Self/></TrustedSigners></StreamingDistributionConfig>';
1253
- $cf_args = array ("method" => "POST", "body" => $cf_distro_streaming_xml, "headers" => array ("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS " . $cfc["access_key"] . ":" . $cf_signature));
1254
  /**/
1255
- if (($cf_response = c_ws_plugin__s2member_utils_urls::remote ("https://" . $cf_domain . $cf_location, false, array_merge ($cf_args, array ("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */))
1256
  {
1257
- if (preg_match ("/\<StreamingDistribution.*?\>(.+?)\<\/StreamingDistribution\>/is", $cf_response["body"], $cf_distro_streaming_tag) && preg_match ("/\<Id\>(.+?)\<\/Id\>/is", $cf_distro_streaming_tag[1], $cf_distro_streaming_id_tag) && preg_match ("/\<DomainName\>(.+?)\<\/DomainName\>/is", $cf_distro_streaming_tag[1], $cf_distro_streaming_dname_tag))
1258
- return array ("success" => true, "code" => null, "message" => null, "distro_streaming_id" => trim ($cf_distro_streaming_id_tag[1]), "distro_streaming_dname" => trim ($cf_distro_streaming_dname_tag[1]));
1259
  /**/
1260
  else /* Else, we use a default error code and message. */
1261
- return array ("success" => false, "code" => -97, "message" => _x ("Unable to create/read Amazon® CloudFront Streaming Distro. Unexpected response.", "s2member-admin", "s2member"));
1262
  }
1263
- else if (isset ($cf_response["code"], $cf_response["message"]))
1264
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1265
- return array ("success" => false, "code" => $cf_response["code"], "message" => sprintf (_x ("Unable to create Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1266
  /**/
1267
  else /* Else, we use a default error code and message. */
1268
- return array ("success" => false, "code" => -98, "message" => _x ("Unable to create Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member"));
1269
  }
1270
  }
1271
  else /* Else, we use a default error code and message. */
1272
- return array ("success" => false, "code" => -99, "message" => _x ("Unable to create Amazon® CloudFront Distro. Invalid Distro type.", "s2member-admin", "s2member"));
1273
  }
1274
  }
1275
  }
14
  * @package s2Member\Files
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_files_in"))
21
  {
22
  /**
23
  * File Download routines for s2Member ( inner processing routines ).
41
  * @return null|str If called directly with ``$create_file_download_url``, returns a string with the URL, based on configuration.
42
  * Else, this function may exit script execution after serving a File Download.
43
  */
44
+ public static function check_file_download_access($create_file_download_url = FALSE)
45
  {
46
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
47
+ do_action("ws_plugin__s2member_before_file_download_access", get_defined_vars());
48
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
49
  /**/
50
+ $_g = !empty($_GET) ? $_GET : array();
51
+ $_g = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_g));
52
  /**/
53
+ $creating = /* Creating URL? */ (is_array($create = $create_file_download_url)) ? true : false;
54
  $serving = /* If NOT creating a File Download URL, we're serving one. */ (!$creating) ? true : false;
55
  /**/
56
  $req["file_download"] = ($creating) ? @$create["file_download"] : @$_g["s2member_file_download"];
70
  $req["count_against_user"] = ($creating) ? @$create["count_against_user"] : /* N/A. */ null;
71
  $req["check_user"] = ($creating) ? @$create["check_user"] : /* N/A. */ null;
72
  /**/
73
+ if($req["file_download"] && is_string($req["file_download"]) && ($req["file_download"] = trim($req["file_download"], "/")))
74
+ if(strpos($req["file_download"], "..") === false && strpos(basename($req["file_download"]), ".") !== 0)
75
  {
76
+ $using_amazon_s3_storage = ((!$req["file_storage"] || strcasecmp((string)$req["file_storage"], "s3") === 0) && c_ws_plugin__s2member_utils_conds::using_amazon_s3_storage()) ? true : false;
77
+ $using_amazon_cf_storage = ((!$req["file_storage"] || strcasecmp((string)$req["file_storage"], "cf") === 0) && c_ws_plugin__s2member_utils_conds::using_amazon_cf_storage()) ? true : false;
78
  $using_amazon_storage = /* Either/or? */ ($using_amazon_s3_storage || $using_amazon_cf_storage) ? true : false;
79
  /**/
80
+ $excluded = apply_filters("ws_plugin__s2member_check_file_download_access_excluded", false, get_defined_vars());
81
+ $valid_file_download_key = ($req["file_download_key"] && is_string($req["file_download_key"]) && $creating && (!isset($req["check_user"]) || !filter_var($req["check_user"], FILTER_VALIDATE_BOOLEAN)) && (!isset($req["count_against_user"]) || !filter_var($req["count_against_user"], FILTER_VALIDATE_BOOLEAN))) ? true : false;
82
+ $valid_file_download_key = (!$valid_file_download_key && $req["file_download_key"] && is_string($req["file_download_key"])) ? c_ws_plugin__s2member_files_in::check_file_download_key($req["file_download"], $req["file_download_key"]) : false;
83
+ $checking_user = ($excluded || $valid_file_download_key || ($creating && (!isset($req["check_user"]) || !filter_var($req["check_user"], FILTER_VALIDATE_BOOLEAN)) && (!isset($req["count_against_user"]) || !filter_var($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true;
84
+ $updating_user_counter = (!$checking_user || ($creating && (!isset($req["count_against_user"]) || !filter_var($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true;
85
  /**/
86
+ if( /* In either case, the following routines apply whenever we ARE ``$checking_user``. */($serving || $creating) && $checking_user)
87
  {
88
+ if(!$using_amazon_storage && !file_exists($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]."/".$req["file_download"]))
89
  {
90
+ if /* We only need this section when/if we're actually serving. */($serving)
91
+ status_header(404).header("Content-Type: text/html; charset=utf-8").eval('while (@ob_end_clean ());') #
92
+ .exit(_x('<strong>404: Sorry, file not found.</strong> Please contact Support for assistance.', "s2member-front", "s2member"));
93
  /**/
94
  else /* Else return false. */
95
  return false;
96
  }
97
  /**/
98
+ else if($req["file_download_key"] && is_string($req["file_download_key"]) && !$valid_file_download_key)
99
  {
100
+ if /* We only need this section when/if we're actually serving. */($serving)
101
+ status_header(503).header("Content-Type: text/html; charset=utf-8").eval('while (@ob_end_clean ());') #
102
+ .exit(_x('<strong>503 ( Invalid Key ):</strong> Sorry, your access to this file has expired. Please contact Support for assistance.', "s2member-front", "s2member"));
103
  /**/
104
  else /* Else return false. */
105
  return false;
106
  }
107
  /**/
108
+ else if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] || ($file_downloads_enabled_by_site_owner = $min_level_4_downloads = c_ws_plugin__s2member_files::min_level_4_downloads()) === false)
109
  {
110
+ if /* We only need remote functionality when/if we're actually serving. */($serving)
111
+ if(!has_filter("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization"))
112
+ add_filter("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization", 10, 2);
113
  /**/
114
+ if /* We only need remote functionality when/if we're actually serving. */($creating)
115
+ if(has_filter("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization"))
116
+ remove_filter("ws_plugin__s2member_check_file_download_access_user", "c_ws_plugin__s2member_files_in::check_file_remote_authorization", 10, 2);
117
  /**/
118
+ if((isset($file_downloads_enabled_by_site_owner, $min_level_4_downloads) && $file_downloads_enabled_by_site_owner === false) || ($file_downloads_enabled_by_site_owner = $min_level_4_downloads = c_ws_plugin__s2member_files::min_level_4_downloads()) === false)
119
  {
120
+ if /* We only need this section when/if we're actually serving. */($serving)
121
+ status_header(503).header("Content-Type: text/html; charset=utf-8").eval('while (@ob_end_clean ());') #
122
+ .exit(_x('<strong>503: Basic File Downloads are NOT enabled yet.</strong> Please contact Support for assistance. If you are the site owner, please configure: <code>s2Member -> Download Options -> Basic Download Restrictions</code>.', "s2member-front", "s2member"));
123
  /**/
124
  else /* Else return false. */
125
  return false;
126
  }
127
  /**/
128
+ else if(!is_object($user = apply_filters("ws_plugin__s2member_check_file_download_access_user", ((is_user_logged_in()) ? wp_get_current_user() : false), get_defined_vars())) || empty($user->ID) || !($user_id = $user->ID) || !is_array($user_file_downloads = c_ws_plugin__s2member_files::user_downloads($user)) || (!$user->has_cap("administrator") && (!$user_file_downloads["allowed"] || !$user_file_downloads["allowed_days"])))
129
  {
130
+ if(preg_match("/(?:^|\/)access[_\-]s2member[_\-]level([0-9]+)\//", $req["file_download"], $m) && strlen($req_level = $m[1]) && (!is_object($user) || empty($user->ID) || !$user->has_cap("access_s2member_level".$req_level)))
131
  {
132
+ if /* We only need this section when/if we're actually serving. */($serving)
133
+ c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */("file", $req["file_download"], "level", $req_level, $_SERVER["REQUEST_URI"]).exit();
134
  /**/
135
  else /* Else return false. */
136
  return false;
137
  }
138
  /**/
139
+ else if(preg_match("/(?:^|\/)access[_\-]s2member[_\-]ccap[_\-](.+?)\//", $req["file_download"], $m) && strlen($req_ccap = preg_replace("/-/", "_", $m[1])) && (!is_object($user) || empty($user->ID) || !$user->has_cap("access_s2member_ccap_".$req_ccap)))
140
  {
141
+ if /* We only need this section when/if we're actually serving. */($serving)
142
+ c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */("file", $req["file_download"], "ccap", $req_ccap, $_SERVER["REQUEST_URI"]).exit();
143
  /**/
144
  else /* Else return false. */
145
  return false;
146
  }
147
  /**/
148
+ else if /* We only need this section when/if we're actually serving. */($serving)
149
+ c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */("file", $req["file_download"], "level", $min_level_4_downloads, $_SERVER["REQUEST_URI"]).exit();
150
  /**/
151
  else /* Else return false. */
152
  return false;
153
  }
154
  /**/
155
+ else if(preg_match("/(?:^|\/)access[_\-]s2member[_\-]level([0-9]+)\//", $req["file_download"], $m) && strlen($req_level = $m[1]) && !$user->has_cap("access_s2member_level".$req_level))
156
  {
157
+ if /* We only need this section when/if we're actually serving. */($serving)
158
+ c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */("file", $req["file_download"], "level", $req_level, $_SERVER["REQUEST_URI"]).exit();
159
  /**/
160
  else /* Else return false. */
161
  return false;
162
  }
163
  /**/
164
+ else if(preg_match("/(?:^|\/)access[_\-]s2member[_\-]ccap[_\-](.+?)\//", $req["file_download"], $m) && strlen($req_ccap = preg_replace("/-/", "_", $m[1])) && !$user->has_cap("access_s2member_ccap_".$req_ccap))
165
  {
166
+ if /* We only need this section when/if we're actually serving. */($serving)
167
+ c_ws_plugin__s2member_mo_page::wp_redirect_w_mop_vars /* Configure MOP Vars here. */("file", $req["file_download"], "ccap", $req_ccap, $_SERVER["REQUEST_URI"]).exit();
168
  /**/
169
  else /* Else return false. */
170
  return false;
171
  }
172
  /**/
173
+ else if /* In either case, the following routines apply. */($serving || $creating)
174
  {
175
  $user_previous_file_downloads = /* Downloads the User has already; in current period/cycle. */ 0;
176
  $user_already_downloaded_this_file = $user_already_downloaded_a_streaming_variation_of_this_file = false;
177
  /**/
178
+ $user_file_download_access_log = (is_array($user_file_download_access_log = get_user_option("s2member_file_download_access_log", $user_id))) ? $user_file_download_access_log : array();
179
+ $user_file_download_access_arc = (is_array($user_file_download_access_arc = get_user_option("s2member_file_download_access_arc", $user_id))) ? $user_file_download_access_arc : array();
180
  /**/
181
+ $streaming_file_extns = c_ws_plugin__s2member_utils_strings::preg_quote_deep($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"], "/");
182
+ $streaming_variations = /* Only count one streaming media file variation. */ "/\.(".implode("|", $streaming_file_extns).")$/i";
183
  /**/
184
+ foreach($user_file_download_access_log as $user_file_download_access_log_entry_key => $user_file_download_access_log_entry)
185
  {
186
+ if( /* Weed out corrupt/empty log entries. */isset($user_file_download_access_log_entry["date"], $user_file_download_access_log_entry["file"]))
187
  {
188
+ if(strtotime($user_file_download_access_log_entry["date"]) < strtotime("-".$user_file_downloads["allowed_days"]." days"))
189
  {
190
+ unset /* Remove it from the `log`. */($user_file_download_access_log[$user_file_download_access_log_entry_key]);
191
  $user_file_download_access_arc[] = /* Move `log` entry to the `archive` now. */ $user_file_download_access_log_entry;
192
  }
193
+ else if(strtotime($user_file_download_access_log_entry["date"]) >= strtotime("-".$user_file_downloads["allowed_days"]." days"))
194
  {
195
  $user_previous_file_downloads++; /* Previous files always count against this User/Member. */
196
  /**/
197
  $_user_file_download_access_log_entry = &$user_file_download_access_log[$user_file_download_access_log_entry_key];
198
  $_user_already_downloaded_this_file = $_user_already_downloaded_a_streaming_variation_of_this_file = false;
199
  /**/
200
+ if /* Already downloaded this file? If yes, mark this flag as true. */($user_file_download_access_log_entry["file"] === $req["file_download"])
201
  $user_already_downloaded_this_file = $_user_already_downloaded_this_file = /* Already downloaded this file? If yes, mark as true. */ true;
202
  /**/
203
+ else if(preg_replace($streaming_variations, "", $user_file_download_access_log_entry["file"]) === preg_replace($streaming_variations, "", $req["file_download"]))
204
  $user_already_downloaded_this_file = $_user_already_downloaded_this_file = $user_already_downloaded_a_streaming_variation_of_this_file = $_user_already_downloaded_a_streaming_variation_of_this_file = true;
205
  /**/
206
+ if( /* Updating counter? */$updating_user_counter && ($_user_already_downloaded_this_file || $_user_already_downloaded_a_streaming_variation_of_this_file))
207
  {
208
+ $_user_file_download_access_log_entry /* First, we update the last download time for this file. */["ltime"] = time();
209
  /**/
210
+ if( /* Backward compatiility here. Is this even set? */!empty($user_file_download_access_log_entry["counter"]))
211
  $_user_file_download_access_log_entry["counter"] = (int)$user_file_download_access_log_entry["counter"] + 1;
212
  else /* Backward compatiility here. Default value to `1`, if this is NOT even set yet. */
213
  $_user_file_download_access_log_entry["counter"] = 1 + 1;
215
  }
216
  }
217
  else /* Weed out empty log entries. Some older versions of s2Member may have corrupt/empty log entries. */
218
+ unset($user_file_download_access_log[$user_file_download_access_log_entry_key]); /* Remove. */
219
  }
220
+ if( /* Updating counter? */$updating_user_counter && /* Do we need a new log entry for this file? */ !$user_already_downloaded_this_file && !$user_already_downloaded_a_streaming_variation_of_this_file)
221
+ $user_file_download_access_log[] = array("date" => date("Y-m-d"), "time" => time(), "ltime" => time(), "file" => $req["file_download"], "counter" => 1);
222
  /**/
223
+ if($user_previous_file_downloads >= $user_file_downloads["allowed"] && !$user_already_downloaded_this_file && !$user_already_downloaded_a_streaming_variation_of_this_file && !$user->has_cap("administrator"))
224
  {
225
+ if /* We only need this section when/if we're actually serving. */($serving)
226
+ wp_redirect(add_query_arg(urlencode_deep(array("_s2member_seeking" => array("type" => "file", "file" => $req["file_download"], "_uri" => base64_encode($_SERVER["REQUEST_URI"])), "s2member_seeking" => "file-".$req["file_download"])), get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"])), apply_filters("ws_plugin__s2member_content_redirect_status", 301, get_defined_vars())).exit();
227
  /**/
228
  else /* Else return false. */
229
  return false;
230
  }
231
+ else if /* Save/update counter? By default, we do NOT update the counter when a URL is simply being created for access. */($updating_user_counter)
232
+ update_user_option($user_id, "s2member_file_download_access_log", c_ws_plugin__s2member_utils_arrays::array_unique($user_file_download_access_log)).update_user_option($user_id, "s2member_file_download_access_arc", c_ws_plugin__s2member_utils_arrays::array_unique($user_file_download_access_arc));
233
  }
234
  }
235
  }
236
  else /* Otherwise, we're either NOT ``$checking_user``; or permission was granted with a valid File Download Key. */
237
  {
238
+ if(!$using_amazon_storage && !file_exists($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]."/".$req["file_download"]))
239
  {
240
+ if /* We only need this section when/if we're actually serving. */($serving)
241
+ status_header(404).header("Content-Type: text/html; charset=utf-8").eval('while (@ob_end_clean ());') #
242
+ .exit(_x('<strong>404: Sorry, file not found.</strong> Please contact Support for assistance.', "s2member-front", "s2member"));
243
  /**/
244
  else /* Else return false. */
245
  return false;
246
  }
247
  }
248
  /**/
249
+ if /* In either case, the following routines apply. */($serving || $creating)
250
  {
251
+ $basename = basename($req["file_download"]);
252
+ $mimetypes = parse_ini_file(dirname(dirname(dirname(__FILE__)))."/includes/mime-types.ini");
253
+ $extension = strtolower(substr($req["file_download"], strrpos($req["file_download"], ".") + 1));
254
  /**/
255
+ $key = ($req["file_download_key"] && is_string($req["file_download_key"])) ? $req["file_download_key"] : false;
256
  /**/
257
+ $stream = (isset($req["file_stream"])) ? filter_var($req["file_stream"], FILTER_VALIDATE_BOOLEAN) : ((in_array($extension, preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_stream_extensions"]))) ? true : false);
258
+ $inline = (!$stream && isset($req["file_inline"])) ? filter_var($req["file_inline"], FILTER_VALIDATE_BOOLEAN) : (($stream || in_array($extension, preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]))) ? true : false);
259
+ $ssl = (isset($req["file_ssl"])) ? filter_var($req["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl()) ? true : false);
260
+ $storage = ($req["file_storage"] && is_string($req["file_storage"])) ? strtolower($req["file_storage"]) : false;
261
+ $remote = (isset($req["file_remote"])) ? filter_var($req["file_remote"], FILTER_VALIDATE_BOOLEAN) : false;
262
  /**/
263
+ $_basename_dir_app_data = c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]);
264
+ $rewrite_base_guess = (is_dir(dirname($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir"])."/".$_basename_dir_app_data)) ? dirname($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"])."/".$_basename_dir_app_data : content_url("/".$_basename_dir_app_data);
265
+ $rewrite_base = ($req["file_rewrite_base"] && is_string($req["file_rewrite_base"])) ? $req["file_rewrite_base"] : false;
266
+ $rewrite = $rewriting = (!$rewrite_base && isset($req["file_rewrite"])) ? filter_var($req["file_rewrite"], FILTER_VALIDATE_BOOLEAN) : (($rewrite_base) ? true : false);
267
+ unset /* A little housekeeping here. */($_basename_dir_app_data);
268
  /**/
269
+ $skip_confirmation = (isset($req["skip_confirmation"])) ? filter_var($req["skip_confirmation"], FILTER_VALIDATE_BOOLEAN) : false;
270
+ $url_to_storage_source = (isset($req["url_to_storage_source"])) ? filter_var($req["url_to_storage_source"], FILTER_VALIDATE_BOOLEAN) : false;
271
  /**/
272
+ $pathinfo = (!$using_amazon_storage) ? pathinfo(($file = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]."/".$req["file_download"])) : array();
273
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream";
274
+ $length = (!$using_amazon_storage && $file) ? filesize($file) : -1;
275
  /**/
276
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
277
+ do_action("ws_plugin__s2member_during_file_download_access", get_defined_vars());
278
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
279
  /**/
280
+ if($using_amazon_s3_storage && ($serving || ($creating && $url_to_storage_source)))
281
  {
282
+ if /* We only need this section when/if we're actually serving. */($serving)
283
+ wp_redirect(c_ws_plugin__s2member_files_in::amazon_s3_url($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype)).exit();
284
  /**/
285
  else /* Else return File Download URL. */
286
+ return apply_filters("ws_plugin__s2member_file_download_access_url", c_ws_plugin__s2member_files_in::amazon_s3_url($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype), get_defined_vars());
287
  }
288
  /**/
289
+ else if($using_amazon_cf_storage && ($serving || ($creating && $url_to_storage_source)))
290
  {
291
+ if /* We only need this section when/if we're actually serving. */($serving)
292
+ wp_redirect(c_ws_plugin__s2member_files_in::amazon_cf_url($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype)).exit();
293
  /**/
294
  else /* Else return File Download URL. */
295
+ return apply_filters("ws_plugin__s2member_file_download_access_url", c_ws_plugin__s2member_files_in::amazon_cf_url($req["file_download"], $stream, $inline, $ssl, $basename, $mimetype), get_defined_vars());
296
  }
297
  /**/
298
+ else if /* Creating a rewrite URL, pointing to local storage. */($creating && $rewriting)
299
  {
300
+ $url = ($rewrite_base) ? rtrim($rewrite_base, "/") : rtrim($rewrite_base_guess, "/");
301
+ $url .= (isset($req["file_download_key"])) ? (($key) ? "/s2member-file-download-key-".$key : "") : "";
302
+ $url .= (isset($req["file_stream"])) ? (($stream) ? "/s2member-file-stream" : "/s2member-file-stream-no") : "";
303
+ $url .= (isset($req["file_inline"])) ? (($inline) ? "/s2member-file-inline" : "/s2member-file-inline-no") : "";
304
+ $url .= (isset($req["file_storage"])) ? (($storage) ? "/s2member-file-storage-".$storage : "") : "";
305
+ $url .= (isset($req["file_remote"])) ? (($remote) ? "/s2member-file-remote" : "/s2member-file-remote-no") : "";
306
+ $url .= (isset($req["skip_confirmation"])) ? (($skip_confirmation) ? "/s2member-skip-confirmation" : "/s2member-skip-confirmation-no") : "";
307
  /**/
308
+ $url = /* File Download Access URL via `mod_rewrite` functionality. */ $url."/".$req["file_download"];
309
+ $url = ($ssl) ? preg_replace("/^https?/", "https", $url) : preg_replace("/^https?/", "http", $url);
310
  /**/
311
+ return apply_filters("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars());
312
  }
313
  /**/
314
+ else if /* Else we're creating a URL w/ a query-string; w/ local storage. */($creating)
315
  { /* Note: we don't URL encode unreserved chars. Improves media player compatibility. */
316
+ $_url_e_key = ($key) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep(urlencode($key)) : "";
317
+ $_url_e_storage = ($storage) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep(urlencode($storage)) : "";
318
+ $_url_e_file = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep(urlencode($req["file_download"]));
319
  /**/
320
+ $url = (isset($req["file_download_key"])) ? (($key && $_url_e_key) ? "&s2member_file_download_key=".$_url_e_key : "") : "";
321
+ $url .= (isset($req["file_stream"])) ? (($stream) ? "&s2member_file_stream=yes" : "&s2member_file_stream=no") : "";
322
+ $url .= (isset($req["file_inline"])) ? (($inline) ? "&s2member_file_inline=yes" : "&s2member_file_inline=no") : "";
323
+ $url .= (isset($req["file_storage"])) ? (($storage && $_url_e_storage) ? "&s2member_file_storage=".$_url_e_storage : "") : "";
324
+ $url .= (isset($req["file_remote"])) ? (($remote) ? "&s2member_file_remote=yes" : "&s2member_file_remote=no") : "";
325
+ $url .= (isset($req["skip_confirmation"])) ? (($skip_confirmation) ? "&s2member_skip_confirmation=yes" : "&s2member_skip_confirmation=no") : "";
326
  /**/
327
+ $url = site_url("/?".ltrim($url."&s2member_file_download=/".$_url_e_file, "&"));
328
+ $url = ($ssl) ? preg_replace("/^https?/", "https", $url) : preg_replace("/^https?/", "http", $url);
329
  /**/
330
+ return apply_filters("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars());
331
  }
332
  /**/
333
  else /* Else, ``if ($serving)``, use local storage option. */
334
  {
335
+ @set_time_limit /* Allow time. */(0);
336
  /**/
337
+ @ini_set /* Disable GZIP compression. */("zlib.output_compression", 0);
338
+ ((function_exists("apache_setenv")) ? @apache_setenv("no-gzip", "1") : "");
339
+ /*
340
+ Note: ``apache_setenv()`` only works when PHP is running as an Apache module.
341
+ It's also a good idea to put this at the top of your `/.htaccess` file.
342
+
343
+ <IfModule mod_rewrite.c>
344
+ RewriteEngine On
345
+ RewriteCond %{QUERY_STRING} (?:^|\?|&)s2member_file_download\=.+
346
+ RewriteRule .* - [E=no-gzip:1]
347
+ </IfModule>
348
+
349
+ */
350
+ status_header /* 200 OK status header. */(200);
351
  /**/
352
+ header("Content-Encoding:");
353
+ header("Accept-Ranges: none");
354
+ header("Content-Type: ".$mimetype);
355
+ header("Expires: ".gmdate("D, d M Y H:i:s", strtotime("-1 week"))." GMT");
356
+ header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
357
+ header("Cache-Control: no-cache, must-revalidate, max-age=0");
358
+ header("Cache-Control: post-check=0, pre-check=0", false);
359
+ header("Pragma: no-cache");
360
  /**/
361
+ header('Content-Disposition: '.(($inline) ? "inline" : "attachment").'; filename="'.$basename.'"');
362
  /**/
363
+ eval /* End/clean any output buffers that may exist already. Prep for content delivery. */('while (@ob_end_clean ());');
364
  /**/
365
+ if($length && apply_filters("ws_plugin__s2member_chunk_file_downloads", false, get_defined_vars()) && is_resource($resource = fopen($file, "rb")))
 
 
366
  {
367
+ $_chunk_size = apply_filters("ws_plugin__s2member_chunk_file_downloads_w_chunk_size", 2097152, get_defined_vars());
368
  /**/
369
+ if(apply_filters("ws_plugin__s2member_chunk_file_downloads_w_content_length", false, get_defined_vars()))
370
+ header("Content-Length: ".$length);
371
  /**/
372
+ header /* `Transfer-Encoding: chunked` conserves memory. */("Transfer-Encoding: chunked");
373
  /**/
374
+ while(!feof($resource) && ($chunk_size = strlen($data = fread($resource, $_chunk_size))))
375
+ eval('echo dechex ($chunk_size) . "\r\n". $data . "\r\n"; @flush ();');
376
  /**/
377
+ fclose($resource).exit("0\r\n\r\n");
378
  }
379
+ else if($length && apply_filters("ws_plugin__s2member_flush_file_downloads", true, get_defined_vars()) && is_resource($resource = fopen($file, "rb")))
380
  {
381
+ $_flush_size = apply_filters("ws_plugin__s2member_flush_file_downloads_w_flush_size", 2097152, get_defined_vars());
382
  /**/
383
+ if(apply_filters("ws_plugin__s2member_flush_file_downloads_w_content_length", true, get_defined_vars()))
384
+ header("Content-Length: ".$length);
385
  /**/
386
+ while(!feof($resource) && ($flush_size = strlen($data = fread($resource, $_flush_size))))
387
+ eval /* Conserves memory. */('echo $data; @flush ();');
388
  }
389
+ else if /* Else, use: ``file_get_contents()``. */($length)
390
  {
391
+ @ini_set("memory_limit", WP_MAX_MEMORY_LIMIT);
392
+ header("Content-Length: ".$length).exit(file_get_contents($file));
393
  }
394
  else /* Else, we have an empty file with no length. */
395
  {
396
+ header("Content-Length: 0").exit();
397
  }
398
  }
399
  }
400
  }
401
  /**/
402
+ else if /* We only need this section when/if we're actually serving. */($serving && $req["file_download"])
403
+ status_header(503).header("Content-Type: text/html; charset=utf-8").eval('while (@ob_end_clean ());') #
404
+ .exit(_x('<strong>503: Access denied.</strong> Invalid File Download specs.', "s2member-front", "s2member"));
405
  /**/
406
+ else if /* We only need this section when/if we're creating a URL. */($creating)
407
  return false;
408
  /**/
409
+ do_action("ws_plugin__s2member_after_file_download_access", get_defined_vars());
410
  /**/
411
  return ($creating) ? /* If creating, false. */ false : null;
412
  }
423
  *
424
  * @see s2Member\API_Functions\s2member_file_download_url()
425
  */
426
+ public static function create_file_download_url($config = FALSE, $get_streamer_array = FALSE)
427
  {
428
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
429
+ do_action("ws_plugin__s2member_before_create_file_download_url", get_defined_vars());
430
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
431
  /**/
432
+ $config = (is_array($config)) ? $config : /* This absolutely MUST be an array. */ array();
433
  /**/
434
+ $config["file_download"] = (isset($config["file_download"]) && is_string($config["file_download"])) ? trim($config["file_download"], "/") : @$config["file_download"];
435
+ $config["file_download_key"] = (isset($config["file_download"]) && is_string($config["file_download"]) && !empty($config["file_download_key"])) ? c_ws_plugin__s2member_files::file_download_key($config["file_download"], ((in_array($config["file_download_key"], array("ip-forever", "universal", "cache-compatible"))) ? $config["file_download_key"] : false)) : @$config["file_download_key"];
436
  /**/
437
  $config["url_to_storage_source"] = /* Force a streaming URL here via ``$get_streamer_array``? */ ($get_streamer_array) ? true : @$config["url_to_storage_source"];
438
  $config["file_stream"] = /* Force a streaming URL here via ``$get_streamer_array``? */ ($get_streamer_array) ? true : @$config["file_stream"];
439
  /**/
440
+ if(($_url = c_ws_plugin__s2member_files_in::check_file_download_access /* Successfully created a URL to the file? */(($create_file_download_url = $config))))
441
  {
442
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
443
+ do_action("ws_plugin__s2member_during_create_file_download_url", get_defined_vars());
444
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
445
  /**/
446
+ $extension = strtolower(substr($config["file_download"], strrpos($config["file_download"], ".") + 1));
447
+ $streaming = (isset($config["file_stream"])) ? filter_var($config["file_stream"], FILTER_VALIDATE_BOOLEAN) : ((in_array($extension, preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_stream_extensions"]))) ? true : false);
448
+ $ssl = (isset($config["file_ssl"])) ? filter_var($config["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl()) ? true : false);
449
  /**/
450
+ if($get_streamer_array && $streaming && ($cfx = "/cfx/st") && ($cfx_pos = strpos($_url, $cfx)) !== false && ($streamer = substr($_url, 0, $cfx_pos + strlen($cfx))) && ($url = c_ws_plugin__s2member_files_in::check_file_download_access(array_merge($config, array("file_stream" => false, "check_user" => false, "count_against_user" => false)))))
451
+ $return = array("streamer" => $streamer, "file" => preg_replace("/^".preg_quote($streamer, "/")."\//", "", $_url), "url" => preg_replace("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
452
  /**/
453
+ else if($get_streamer_array && $streaming && is_array($ups = c_ws_plugin__s2member_utils_urls::parse_url($_url)) && isset($ups["scheme"], $ups["host"]) && ($streamer = $ups["scheme"]."://".$ups["host"].((!empty($ups["port"])) ? ":".$ups["port"] : "")) && ($url = c_ws_plugin__s2member_files_in::check_file_download_access(array_merge($config, array("file_stream" => false, "check_user" => false, "count_against_user" => false)))))
454
+ $return = array("streamer" => $streamer, "file" => preg_replace("/^".preg_quote($streamer, "/")."\//", "", $_url), "url" => preg_replace("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
455
  /**/
456
+ else if /* If streamer, we MUST return false here; unable to acquire streamer/file. */($get_streamer_array)
457
  $return = /* We MUST return false here, unable to acquire streamer/file. */ false;
458
  /**/
459
  else /* Else return URL string ( ``$get_streamer_array`` is false ). */
460
  $return = /* Else return URL string. */ $_url;
461
  }
462
  /**/
463
+ return apply_filters("ws_plugin__s2member_create_file_download_url", ((isset($return)) ? $return : false), get_defined_vars());
464
  }
465
  /**
466
  * Checks Header Authorization for Remote File Downloads.
473
  * @param obj $user Expects a WP_User object passed in by the Filter.
474
  * @return obj A `WP_User` object, possibly obtained through Header Authorization.
475
  */
476
+ public static function check_file_remote_authorization($user = FALSE)
477
  {
478
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
479
+ do_action("ws_plugin__s2member_before_check_file_remote_authorization", get_defined_vars());
480
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
481
  /**/
482
+ $_g = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep(((!empty($_GET)) ? $_GET : array())));
483
  /**/
484
+ if(!is_object($user) && isset($_g["s2member_file_remote"]) && filter_var($_g["s2member_file_remote"], FILTER_VALIDATE_BOOLEAN))
485
  {
486
+ do_action("ws_plugin__s2member_during_check_file_remote_authorization_before", get_defined_vars());
487
  /**/
488
+ if(empty($_SERVER["PHP_AUTH_USER"]) || empty($_SERVER["PHP_AUTH_PW"]) || !user_pass_ok($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]))
489
  {
490
+ header('WWW-Authenticate: Basic realm="'.c_ws_plugin__s2member_utils_strings::esc_dq(strip_tags(_x("Members Only", "s2member-front", "s2member"))).'"');
491
  /**/
492
+ status_header /* Send an unauthorized 401 status header now. */(401);
493
+ header /* Content-Type with UTF-8. */("Content-Type: text/html; charset=utf-8");
494
+ eval /* End/clean any output buffers that may exist. */('while (@ob_end_clean ());');
495
  /**/
496
+ exit(_x('<strong>401:</strong> Sorry, access denied.', "s2member-front", "s2member"));
497
  }
498
+ else if(is_object($_user = new WP_User($_SERVER["PHP_AUTH_USER"])) && !empty($_user->ID))
499
  $user = /* Now assign ``$user``. */ $_user;
500
  /**/
501
+ do_action("ws_plugin__s2member_during_check_file_remote_authorization_after", get_defined_vars());
502
  }
503
+ return apply_filters("ws_plugin__s2member_check_file_remote_authorization", $user, get_defined_vars());
504
  }
505
  /**
506
  * Checks a File Download Key for validity.
512
  * @param str $key Input File Download Key to validate.
513
  * @return bool True if valid, else false.
514
  */
515
+ public static function check_file_download_key($file = FALSE, $key = FALSE)
516
  {
517
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
518
+ do_action("_ws_plugin__s2member_before_check_file_download_key", get_defined_vars());
519
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
520
  /**/
521
+ if($file && is_string($file) && ($file = trim($file, "/")) && $key && is_string($key))
522
  {
523
+ if($key === c_ws_plugin__s2member_files::file_download_key($file) || $key === c_ws_plugin__s2member_files::file_download_key("/".$file))
524
  $valid = /* File Download Key is valid. */ true;
525
+ else if($key === c_ws_plugin__s2member_files::file_download_key($file, "ip-forever") || $key === c_ws_plugin__s2member_files::file_download_key("/".$file, "ip-forever"))
526
  $valid = /* File Download Key is valid. */ true;
527
+ else if($key === c_ws_plugin__s2member_files::file_download_key($file, "universal") || $key === c_ws_plugin__s2member_files::file_download_key("/".$file, "universal"))
528
  $valid = /* File Download Key is valid. */ true;
529
  }
530
+ return apply_filters("ws_plugin__s2member_check_file_download_key", ((isset($valid) && $valid) ? true : false), get_defined_vars());
531
  }
532
  /**
533
  * Creates an Amazon® S3 HMAC-SHA1 signature.
538
  * @param str $string Input string/data, to be signed by this routine.
539
  * @return str An HMAC-SHA1 signature for Amazon® S3.
540
  */
541
+ public static function amazon_s3_sign($string = FALSE)
542
  {
543
  $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
544
  /**/
545
+ return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign((string)$string, $s3c["secret_key"]);
546
  }
547
  /**
548
  * Creates an Amazon® S3 HMAC-SHA1 signature URL.
558
  * @param str $mimetype The MIME content-type of the resource file.
559
  * @return str An HMAC-SHA1 signature URL for Amazon® S3.
560
  */
561
+ public static function amazon_s3_url($file = FALSE, $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = FALSE, $mimetype = FALSE)
562
  {
563
+ $file = /* Trim / force string. */ trim((string)$file, "/");
564
  /**/
565
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
566
+ if(preg_match("/^amazon_s3_files_/", $option) && ($option = preg_replace("/^amazon_s3_files_/", "", $option)))
567
  $s3c[$option] = $option_value;
568
  /**/
569
+ $s3c["expires"] = strtotime("+".apply_filters("ws_plugin__s2member_amazon_s3_file_expires_time", "30 seconds", get_defined_vars()));
570
  /**/
571
+ $s3_file = add_query_arg(c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep(urlencode_deep(array("response-cache-control" => ($s3_cache_control = "no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"), "response-content-disposition" => ($s3_content_disposition = (((bool)$inline) ? "inline" : "attachment").'; filename="'.(string)$basename.'"'), "response-content-type" => ($s3_content_type = (string)$mimetype), "response-expires" => ($s3_expires = gmdate("D, d M Y H:i:s", strtotime("-1 week"))." GMT")))), "/".$file);
572
+ $s3_raw_file = add_query_arg(array("response-cache-control" => $s3_cache_control, "response-content-disposition" => $s3_content_disposition, "response-content-type" => $s3_content_type, "response-expires" => $s3_expires), "/".$file);
573
+ $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("GET\n\n\n".$s3c["expires"]."\n"."/".$s3c["bucket"].$s3_raw_file));
574
  /**/
575
+ $s3_url = ((strtolower($s3c["bucket"]) !== $s3c["bucket"])) ? "http".(($ssl) ? "s" : "")."://s3.amazonaws.com/".$s3c["bucket"].$s3_file : "http".(($ssl) ? "s" : "")."://".$s3c["bucket"].".s3.amazonaws.com".$s3_file;
576
  /**/
577
+ return add_query_arg(c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */
578
+ (urlencode_deep(array("AWSAccessKeyId" => $s3c["access_key"], "Expires" => $s3c["expires"], "Signature" => $s3_signature))), $s3_url);
579
  }
580
  /**
581
  * Auto-configures an Amazon® S3 Bucket's ACLs.
586
  * @return array Array containing a true `success` element on success, else a failure array.
587
  * Failure array will contain a failure `code`, and a failure `message`.
588
  */
589
+ public static function amazon_s3_auto_configure_acls()
590
  {
591
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
592
+ if(preg_match("/^amazon_s3_files_/", $option) && ($option = preg_replace("/^amazon_s3_files_/", "", $option)))
593
  $s3c[$option] = $option_value;
594
  /**/
595
  $cfc["distros_s3_access_id"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_s3_access_id"];
596
  /**/
597
+ if /* Must have Amazon® S3 Bucket/Keys. */($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"])
598
  {
599
+ $s3_date = gmdate("D, d M Y H:i:s")." GMT";
600
+ $s3_location = ((strtolower($s3c["bucket"]) !== $s3c["bucket"])) ? "/".$s3c["bucket"]."/?acl" : "/?acl";
601
+ $s3_domain = ((strtolower($s3c["bucket"]) !== $s3c["bucket"])) ? "s3.amazonaws.com" : $s3c["bucket"].".s3.amazonaws.com";
602
+ $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("GET\n\n\n".$s3_date."\n/".$s3c["bucket"]."/?acl"));
603
+ $s3_args = array("method" => "GET", "headers" => array("Host" => $s3_domain, "Date" => $s3_date, "Authorization" => "AWS ".$s3c["access_key"].":".$s3_signature));
604
  /**/
605
+ if(($s3_response = c_ws_plugin__s2member_utils_urls::remote("https://".$s3_domain.$s3_location, false, array_merge($s3_args, array("timeout" => 20)), "array")) && $s3_response["code"] === 200)
606
  {
607
+ if(preg_match("/\<Owner\>(.+?)\<\/Owner\>/is", $s3_response["body"], $s3_owner_tag) && preg_match("/\<ID\>(.+?)\<\/ID\>/is", $s3_owner_tag[1], $s3_owner_id_tag) && (preg_match("/\<DisplayName\>(.*?)\<\/DisplayName\>/is", $s3_owner_tag[1], $s3_owner_display_name_tag) || ($s3_owner_display_name_tag = array("-", "Owner"))))
608
  {
609
+ $s3_owner = array("access_id" => trim($s3_owner_id_tag[1]), "display_name" => trim($s3_owner_display_name_tag[1]));
610
+ $s3_acls_xml = '<AccessControlPolicy><Owner><ID>'.esc_html($s3_owner["access_id"]).'</ID><DisplayName>'.esc_html($s3_owner["display_name"]).'</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>'.esc_html($s3_owner["access_id"]).'</ID><DisplayName>'.esc_html($s3_owner["display_name"]).'</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant>'.(($cfc["distros_s3_access_id"]) ? '<Grant><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>'.esc_html($cfc["distros_s3_access_id"]).'</ID><DisplayName>s2Member/CloudFront</DisplayName></Grantee><Permission>READ</Permission></Grant>' : '').'</AccessControlList></AccessControlPolicy>';
611
+ $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("PUT\n\napplication/xml\n".$s3_date."\n/".$s3c["bucket"]."/?acl"));
612
+ $s3_args = array("method" => "PUT", "body" => $s3_acls_xml, "headers" => array("Host" => $s3_domain, "Content-Type" => "application/xml", "Date" => $s3_date, "Authorization" => "AWS ".$s3c["access_key"].":".$s3_signature));
613
  /**/
614
+ if(($s3_response = c_ws_plugin__s2member_utils_urls::remote("https://".$s3_domain.$s3_location, false, array_merge($s3_args, array("timeout" => 20)), "array")) && $s3_response["code"] === 200)
615
  {
616
+ $s3_location = ((strtolower($s3c["bucket"]) !== $s3c["bucket"])) ? "/".$s3c["bucket"]."/?policy" : "/?policy";
617
+ ($s3_policy_id = md5(uniqid("s2Member/CloudFront:", true))).($s3_policy_sid = md5(uniqid("s2Member/CloudFront:", true)));
618
+ $s3_policy_json = '{"Version":"2008-10-17","Id":"'.c_ws_plugin__s2member_utils_strings::esc_dq($s3_policy_id).'","Statement":[{"Sid":"'.c_ws_plugin__s2member_utils_strings::esc_dq($s3_policy_sid).'","Effect":"Allow","Principal":{"CanonicalUser":"'.c_ws_plugin__s2member_utils_strings::esc_dq($cfc["distros_s3_access_id"]).'"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::'.c_ws_plugin__s2member_utils_strings::esc_dq($s3c["bucket"]).'/*"}]}';
619
+ $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("PUT\n\napplication/json\n".$s3_date."\n/".$s3c["bucket"]."/?policy"));
620
+ $s3_args = array("method" => "PUT", "body" => $s3_policy_json, "headers" => array("Host" => $s3_domain, "Content-Type" => "application/json", "Date" => $s3_date, "Authorization" => "AWS ".$s3c["access_key"].":".$s3_signature));
621
  /**/
622
+ if(!$cfc["distros_s3_access_id"] || (($s3_response = c_ws_plugin__s2member_utils_urls::remote("https://".$s3_domain.$s3_location, false, array_merge($s3_args, array("timeout" => 20)), "array")) && ($s3_response["code"] === 200 || $s3_response["code"] === 204 /* Also OK. */)))
623
  {
624
+ $s3_location = ((strtolower($s3c["bucket"]) !== $s3c["bucket"])) ? "/".$s3c["bucket"]."/crossdomain.xml" : "/crossdomain.xml";
625
+ $s3_policy_xml = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__))."/templates/cfg-files/s2-cross-xml.php")));
626
+ $s3_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_s3_sign("PUT\n\ntext/xml\n".$s3_date."\nx-amz-acl:public-read\n/".$s3c["bucket"]."/crossdomain.xml"));
627
+ $s3_args = array("method" => "PUT", "body" => $s3_policy_xml, "headers" => array("Host" => $s3_domain, "Content-Type" => "text/xml", "Date" => $s3_date, "X-Amz-Acl" => "public-read", "Authorization" => "AWS ".$s3c["access_key"].":".$s3_signature));
628
  /**/
629
+ if(($s3_response = c_ws_plugin__s2member_utils_urls::remote("https://".$s3_domain.$s3_location, false, array_merge($s3_args, array("timeout" => 20)), "array")) && $s3_response["code"] === 200)
630
+ return /* Successfully configured Amazon® S3 Bucket ACLs and Policy. */ array("success" => true, "code" => null, "message" => null);
631
  /**/
632
+ else if(isset($s3_response["code"], $s3_response["message"]))
633
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
634
+ return array("success" => false, "code" => $s3_response["code"], "message" => sprintf(_x("Unable to update existing Amazon® S3 Cross-Domain Policy. %s", "s2member-admin", "s2member"), $s3_response["message"]));
635
  /**/
636
  else /* Else, we use a default error code and message. */
637
+ return array("success" => false, "code" => -94, "message" => _x("Unable to update existing Amazon® S3 Cross-Domain Policy. Connection failed.", "s2member-admin", "s2member"));
638
  }
639
+ else if(isset($s3_response["code"], $s3_response["message"]))
640
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
641
+ return array("success" => false, "code" => $s3_response["code"], "message" => sprintf(_x("Unable to update existing Amazon® S3 Bucket Policy. %s", "s2member-admin", "s2member"), $s3_response["message"]));
642
  /**/
643
  else /* Else, we use a default error code and message. */
644
+ return array("success" => false, "code" => -95, "message" => _x("Unable to update existing Amazon® S3 Bucket Policy. Connection failed.", "s2member-admin", "s2member"));
645
  }
646
+ else if(isset($s3_response["code"], $s3_response["message"]))
647
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
648
+ return array("success" => false, "code" => $s3_response["code"], "message" => sprintf(_x("Unable to update existing Amazon® S3 Bucket ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"]));
649
  /**/
650
  else /* Else, we use a default error code and message. */
651
+ return array("success" => false, "code" => -96, "message" => _x("Unable to update existing Amazon® S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member"));
652
  }
653
  else /* Else, we use a default error code and message. */
654
+ return array("success" => false, "code" => -97, "message" => _x("Unable to acquire/read existing Amazon® S3 Bucket ACLs. Unexpected response.", "s2member-admin", "s2member"));
655
  }
656
+ else if(isset($s3_response["code"], $s3_response["message"]))
657
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
658
+ return array("success" => false, "code" => $s3_response["code"], "message" => sprintf(_x("Unable to acquire existing Amazon® S3 Bucket ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"]));
659
  /**/
660
  else /* Else, we use a default error code and message. */
661
+ return array("success" => false, "code" => -98, "message" => _x("Unable to acquire existing Amazon® S3 Bucket ACLs. Connection failed.", "s2member-admin", "s2member"));
662
  }
663
  else /* Else, we use a default error code and message. */
664
+ return array("success" => false, "code" => -99, "message" => _x("Unable to auto-configure existing Amazon® S3 Bucket ACLs. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key.", "s2member-admin", "s2member"));
665
  }
666
  /**
667
  * Creates an Amazon® CloudFront HMAC-SHA1 signature.
672
  * @param str $string Input string/data, to be signed by this routine.
673
  * @return str An HMAC-SHA1 signature for Amazon® CloudFront.
674
  */
675
+ public static function amazon_cf_sign($string = FALSE)
676
  {
677
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
678
  /**/
679
+ return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign((string)$string, ($cfc["secret_key"] = $s3c["secret_key"]));
680
  }
681
  /**
682
  * Creates an Amazon® CloudFront RSA-SHA1 signature.
690
  * @todo Double underscores *( i.e. base64 padding chars )* in the signature seem to cause issues for Amazon® CloudFront?
691
  * See ticket: {@link https://forums.aws.amazon.com/thread.jspa?messageID=286182&#286182}
692
  */
693
+ public static function amazon_cf_rsa_sign($string = FALSE)
694
  {
695
  $cfc["private_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"];
696
  /**/
697
+ return c_ws_plugin__s2member_utils_strings::rsa_sha1_sign((string)$string, $cfc["private_key"]);
698
  }
699
  /**
700
  * Creates an Amazon® CloudFront RSA-SHA1 signature URL.
710
  * @param str $mimetype The MIME content-type of the resource file.
711
  * @return str An RSA-SHA1 signature URL for Amazon® CloudFront.
712
  */
713
+ public static function amazon_cf_url($file = FALSE, $stream = FALSE, $inline = FALSE, $ssl = FALSE, $basename = FALSE, $mimetype = FALSE)
714
  {
715
+ $file = /* Trim / force string. */ trim((string)$file, "/");
716
  /**/
717
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
718
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
719
  $cfc[$option] = $option_value;
720
  /**/
721
+ $cfc["expires"] = strtotime("+".apply_filters("ws_plugin__s2member_amazon_cf_file_expires_time", "24 hours", get_defined_vars()));
722
  /**/
723
+ $cf_extn = /* Parses the file extension out so we can scan it in some special scenarios. */ strtolower(substr($file, strrpos($file, ".") + 1));
724
+ $cf_ip_res = /* Do NOT restrict access to a particular IP during `localhost` development. The IP may NOT be the same one Amazon® CloudFront sees. */ (c_ws_plugin__s2member_utils_conds::is_localhost()) ? false : true;
725
+ $cf_stream_extn_resource_exclusions = array_unique((array)apply_filters("ws_plugin__s2member_amazon_cf_file_streaming_extension_resource_exclusions", array("mp3" /* MP3 files should NOT include an extension in their resource reference. */), get_defined_vars()));
726
+ $cf_resource = ($stream) ? ((in_array($cf_extn, $cf_stream_extn_resource_exclusions)) ? substr($file, 0, strrpos($file, ".")) : $file) : "http".(($ssl) ? "s" : "")."://".(($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"])."/".$file;
727
+ $cf_url = ($stream) ? "rtmp".(($ssl) ? "e" : "")."://".(($cfc["distro_streaming_cname"]) ? $cfc["distro_streaming_cname"] : $cfc["distro_streaming_dname"])."/cfx/st/".$file : "http".(($ssl) ? "s" : "")."://".(($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"])."/".$file;
728
+ $cf_policy = '{"Statement":[{"Resource":"'.c_ws_plugin__s2member_utils_strings::esc_dq($cf_resource).'","Condition":{'.(($cf_ip_res) ? '"IpAddress":{"AWS:SourceIp":"'.c_ws_plugin__s2member_utils_strings::esc_dq($_SERVER["REMOTE_ADDR"]).'/32"},' : '').'"DateLessThan":{"AWS:EpochTime":'.(int)$cfc["expires"].'}}}]}';
729
  /**/
730
+ $cf_signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_sign($cf_policy);
731
+ $cf_base64_url_safe_policy = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($cf_policy, array("+", "=", "/"), array("-", "_", "~"), false);
732
+ $cf_base64_url_safe_signature = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($cf_signature, array("+", "=", "/"), array("-", "_", "~"), false);
733
  /**/
734
+ return add_query_arg(c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */
735
+ (urlencode_deep(array("Policy" => $cf_base64_url_safe_policy, "Signature" => $cf_base64_url_safe_signature, "Key-Pair-Id" => $cfc["private_key_id"]))), $cf_url);
736
  }
737
  /**
738
  * Auto-configures Amazon® S3/CloudFront distros.
743
  * @return array Array containing a true `success` element on success, else a failure array.
744
  * Failure array will contain a failure `code`, and a failure `message`.
745
  */
746
+ public static function amazon_cf_auto_configure_distros()
747
  {
748
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
749
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
750
  $cfc[$option] = $option_value;
751
  /**/
752
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
753
  $cfc["access_key"] = $s3c["access_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"];
754
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
755
  /**/
756
+ if /* We MUST have an Amazon® S3 Bucket and Keys. */($s3c["bucket"] && $s3c["access_key"] && $s3c["secret_key"])
757
  {
758
+ if /* We MUST have Amazon® CloudFront Keys in order to auto-configure. */($cfc["private_key"] && $cfc["private_key_id"])
759
  {
760
+ if(!$cfc["distro_downloads_id"] || ($cfc["distro_downloads_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro($cfc["distro_downloads_id"], "downloads")) && ($cf_get_response["success"] || $cf_get_response["code"] === 404)))
761
  {
762
+ if(!$cfc["distro_downloads_id"] || ($cfc["distro_downloads_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404))
763
  $cf_distro_downloads_clear = /* Clear, ready for a new one. */ true;
764
  /**/
765
+ else if($cfc["distro_downloads_id"] && $cf_get_response && $cf_get_response["success"] && !$cf_get_response["deployed"])
766
+ return array("success" => false, "code" => -86, "message" => _x("Unable to delete existing Amazon® CloudFront Downloads Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
767
  /**/
768
+ else if($cfc["distro_downloads_id"] && $cf_get_response && $cf_get_response["success"] && $cf_get_response["deployed"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_distro($cfc["distro_downloads_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"])
769
  $cf_distro_downloads_clear = /* Clear, ready for a new one. */ true;
770
  /**/
771
+ else if(isset($cf_del_response["code"], $cf_del_response["message"]))
772
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
773
+ return array("success" => false, "code" => $cf_del_response["code"], "message" => sprintf(_x("Unable to delete existing Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_del_response["message"]));
774
  /**/
775
+ if /* Successfully cleared? Ready for a new one? */(isset($cf_distro_downloads_clear) && $cf_distro_downloads_clear)
776
  {
777
+ unset /* Unset these before processing additional routines. Prevents problems in error reporting. */($cf_get_response, $cf_del_response);
778
  /**/
779
+ if(!$cfc["distro_streaming_id"] || ($cfc["distro_streaming_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro($cfc["distro_streaming_id"], "streaming")) && ($cf_get_response["success"] || $cf_get_response["code"] === 404)))
780
  {
781
+ if(!$cfc["distro_streaming_id"] || ($cfc["distro_streaming_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404))
782
  $cf_distro_streaming_clear = /* Clear, ready for a new one. */ true;
783
  /**/
784
+ else if($cfc["distro_streaming_id"] && $cf_get_response && $cf_get_response["success"] && !$cf_get_response["deployed"])
785
+ return array("success" => false, "code" => -87, "message" => _x("Unable to delete existing Amazon® CloudFront Streaming Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
786
  /**/
787
+ else if($cfc["distro_streaming_id"] && $cf_get_response && $cf_get_response["success"] && $cf_get_response["deployed"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_distro($cfc["distro_streaming_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"])
788
  $cf_distro_streaming_clear = /* Clear, ready for a new one. */ true;
789
  /**/
790
+ else if(isset($cf_del_response["code"], $cf_del_response["message"]))
791
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
792
+ return array("success" => false, "code" => $cf_del_response["code"], "message" => sprintf(_x("Unable to delete existing Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_del_response["message"]));
793
  /**/
794
+ if /* Successfully cleared? Ready for a new one? */(isset($cf_distro_streaming_clear) && $cf_distro_streaming_clear)
795
  {
796
+ unset /* Unset these before processing additional routines. Prevents problems in error reporting. */($cf_get_response, $cf_del_response);
797
  /**/
798
+ if(!$cfc["distros_access_id"] || ($cfc["distros_access_id"] && ($cf_get_response = c_ws_plugin__s2member_files_in::amazon_cf_get_access_origin_identity($cfc["distros_access_id"])) && ($cf_get_response["success"] || $cf_get_response["code"] === 404)))
799
  {
800
+ if(!$cfc["distros_access_id"] || ($cfc["distros_access_id"] && $cf_get_response && !$cf_get_response["success"] && $cf_get_response["code"] === 404))
801
  $cf_distros_access_clear = /* Clear, ready for a new one. */ true;
802
  /**/
803
+ else if($cfc["distros_access_id"] && $cf_get_response && $cf_get_response["success"] && ($cf_del_response = c_ws_plugin__s2member_files_in::amazon_cf_del_access_origin_identity($cfc["distros_access_id"], $cf_get_response["etag"], $cf_get_response["xml"])) && $cf_del_response["success"])
804
  $cf_distros_access_clear = /* Clear, ready for a new one. */ true;
805
  /**/
806
+ else if(isset($cf_del_response["code"], $cf_del_response["message"]))
807
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
808
+ return array("success" => false, "code" => $cf_del_response["code"], "message" => sprintf(_x("Unable to delete existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_del_response["message"]));
809
  /**/
810
+ if /* Successfully cleared? Ready for a new one? */(isset($cf_distros_access_clear) && $cf_distros_access_clear)
811
  {
812
+ unset /* Unset these before processing additional routines. Prevents problems in error reporting. */($cf_get_response, $cf_del_response);
813
  /**/
814
+ $cfc = array_merge($cfc, array("distros_access_id" => "", "distros_s3_access_id" => "", "distro_downloads_id" => "", "distro_downloads_dname" => "", "distro_streaming_id" => "", "distro_streaming_dname" => "", "distros_auto_config_status" => ""));
815
+ $cf_options = array("ws_plugin__s2member_amazon_cf_files_distros_access_id" => "", "ws_plugin__s2member_amazon_cf_files_distros_s3_access_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_downloads_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_downloads_dname" => "", "ws_plugin__s2member_amazon_cf_files_distro_streaming_id" => "", "ws_plugin__s2member_amazon_cf_files_distro_streaming_dname" => "", "ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" => "");
816
+ c_ws_plugin__s2member_menu_pages::update_all_options($cf_options, true, false, false, false, false);
817
  /**/
818
+ if(($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distros_access_origin_identity()) && $cf_response["success"])
819
  {
820
+ $cfc = array_merge($cfc, array("distros_access_id" => $cf_response["distros_access_id"], "distros_s3_access_id" => $cf_response["distros_s3_access_id"]));
821
+ $cf_options = array("ws_plugin__s2member_amazon_cf_files_distros_access_id" => $cf_response["distros_access_id"], "ws_plugin__s2member_amazon_cf_files_distros_s3_access_id" => $cf_response["distros_s3_access_id"]);
822
+ c_ws_plugin__s2member_menu_pages::update_all_options($cf_options, true, false, false, false, false);
823
  /**/
824
+ if(($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distro("downloads")) && $cf_response["success"])
825
  {
826
+ $cfc = array_merge($cfc, array("distro_downloads_id" => $cf_response["distro_downloads_id"], "distro_downloads_dname" => $cf_response["distro_downloads_dname"]));
827
+ $cf_options = array("ws_plugin__s2member_amazon_cf_files_distro_downloads_id" => $cf_response["distro_downloads_id"], "ws_plugin__s2member_amazon_cf_files_distro_downloads_dname" => $cf_response["distro_downloads_dname"]);
828
+ c_ws_plugin__s2member_menu_pages::update_all_options($cf_options, true, false, false, false, false);
829
  /**/
830
+ if(($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_create_distro("streaming")) && $cf_response["success"])
831
  {
832
+ $cfc = array_merge($cfc, array("distro_streaming_id" => $cf_response["distro_streaming_id"], "distro_streaming_dname" => $cf_response["distro_streaming_dname"]));
833
+ $cf_options = array("ws_plugin__s2member_amazon_cf_files_distro_streaming_id" => $cf_response["distro_streaming_id"], "ws_plugin__s2member_amazon_cf_files_distro_streaming_dname" => $cf_response["distro_streaming_dname"]);
834
+ c_ws_plugin__s2member_menu_pages::update_all_options($cf_options, true, false, false, false, false);
835
  /**/
836
+ for($a = 1, $attempts = 4, $sleep = 2, sleep($sleep); $a <= $attempts; $a++, (($a <= $attempts) ? sleep($sleep) : null))
837
  /* Allow a generous propagation time here. Amazon's high-availability services do NOT guarantee real-time updates.
838
  Since we DO need a fully propagated Origin Access Identity now, we need to make several attempts at success.
839
  For further details, please see this thread: <https://forums.aws.amazon.com/message.jspa?messageID=42875>. */
840
+ if(($s3_response = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls()) && $s3_response["success"])
841
  {
842
+ $cfc = array_merge($cfc, array("distros_auto_config_status" => "configured"));
843
+ $cf_options = array("ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" => "configured");
844
+ c_ws_plugin__s2member_menu_pages::update_all_options( /* Now configured! */$cf_options, true, false, false, false, false);
845
+ return /* Successfully configured Amazon® S3/CloudFront distros. */ array("success" => true, "code" => null, "message" => null);
846
  }
847
+ if(isset($s3_response["code"], $s3_response["message"]))
848
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® S3 API call. Feel free to exclude `%s` if you like. */
849
+ return array("success" => false, "code" => $s3_response["code"], "message" => sprintf(_x("Unable to update existing Amazon® S3 ACLs. %s", "s2member-admin", "s2member"), $s3_response["message"]));
850
  /**/
851
  else /* Else, we use a default error code and message. */
852
+ return array("success" => false, "code" => -88, "message" => _x("Unable to update existing Amazon® S3 ACLs. Connection failed.", "s2member-admin", "s2member"));
853
  }
854
+ else if(isset($cf_response["code"], $cf_response["message"]))
855
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
856
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to create Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
857
  /**/
858
  else /* Else, we use a default error code and message. */
859
+ return array("success" => false, "code" => -89, "message" => _x("Unable to create Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member"));
860
  }
861
+ else if(isset($cf_response["code"], $cf_response["message"]))
862
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
863
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to create Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
864
  /**/
865
  else /* Else, we use a default error code and message. */
866
+ return array("success" => false, "code" => -90, "message" => _x("Unable to create Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member"));
867
  }
868
+ else if(isset($cf_response["code"], $cf_response["message"]))
869
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
870
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to create Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
871
  /**/
872
  else /* Else, we use a default error code and message. */
873
+ return array("success" => false, "code" => -91, "message" => _x("Unable to create Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
874
  }
875
  else /* Else, we use a default error code and message. */
876
+ return array("success" => false, "code" => -92, "message" => _x("Unable to clear existing Amazon® CloudFront Origin Access Identity.", "s2member-admin", "s2member"));
877
  }
878
+ else if(isset($cf_get_response["code"], $cf_get_response["message"]))
879
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
880
+ return array("success" => false, "code" => $cf_get_response["code"], "message" => sprintf(_x("Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_get_response["message"]));
881
  /**/
882
  else /* Else, we use a default error code and message. */
883
+ return array("success" => false, "code" => -93, "message" => _x("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
884
  }
885
  else /* Else, we use a default error code and message. */
886
+ return array("success" => false, "code" => -94, "message" => _x("Unable to clear existing Amazon® CloudFront Streaming Distro.", "s2member-admin", "s2member"));
887
  }
888
+ else if(isset($cf_get_response["code"], $cf_get_response["message"]))
889
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
890
+ return array("success" => false, "code" => $cf_get_response["code"], "message" => sprintf(_x("Unable to acquire existing Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_get_response["message"]));
891
  /**/
892
  else /* Else, we use a default error code and message. */
893
+ return array("success" => false, "code" => -95, "message" => _x("Unable to acquire existing Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member"));
894
  }
895
  else /* Else, we use a default error code and message. */
896
+ return array("success" => false, "code" => -96, "message" => _x("Unable to clear existing Amazon® CloudFront Downloads Distro.", "s2member-admin", "s2member"));
897
  }
898
+ else if(isset($cf_get_response["code"], $cf_get_response["message"]))
899
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
900
+ return array("success" => false, "code" => $cf_get_response["code"], "message" => sprintf(_x("Unable to acquire existing Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_get_response["message"]));
901
  /**/
902
  else /* Else, we use a default error code and message. */
903
+ return array("success" => false, "code" => -97, "message" => _x("Unable to acquire existing Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member"));
904
  }
905
  else /* Else, we use a default error code and message. */
906
+ return array("success" => false, "code" => -98, "message" => _x("Unable to auto-configure Amazon® CloudFront Distros. Incomplete Amazon® CloudFront configuration options. Missing of one: Amazon® CloudFront Private Key-Pair-ID, or Private Key file contents.", "s2member-admin", "s2member"));
907
  }
908
  else /* Else, we use a default error code and message. */
909
+ return array("success" => false, "code" => -99, "message" => _x("Unable to auto-configure Amazon® S3/CloudFront Distros. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key. You must provide s2Member with an Amazon® S3 configuration before enabling CloudFront.", "s2member-admin", "s2member"));
910
  }
911
  /**
912
  * Acquires an Amazon® S3/CloudFront Access Origin Identity.
918
  * @return array Array containing a true `success` and `etag`, `xml` elements on success, else a failure array.
919
  * Failure array will contain a failure `code`, and a failure `message`.
920
  */
921
+ public static function amazon_cf_get_access_origin_identity($access_id = FALSE)
922
  {
923
+ if /* Valid parameters? */($access_id && is_string($access_id))
924
  {
925
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
926
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
927
  $cfc[$option] = $option_value;
928
  /**/
929
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
931
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
932
  /**/
933
  $cf_domain = "cloudfront.amazonaws.com";
934
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
935
+ $cf_location = "/2010-11-01/origin-access-identity/cloudfront/".$access_id;
936
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
937
+ $cf_args = array("method" => "GET", "headers" => array("Host" => $cf_domain, "Date" => $cf_date, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
938
  /**/
939
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && (($cf_response["code"] === 404 && $cf_response["message"]) || ($cf_response["code"] === 200 && !empty($cf_response["headers"]["etag"]) && !empty($cf_response["body"]))))
940
  {
941
+ if($cf_response["code"] === 200 && !empty($cf_response["headers"]["etag"]) && !empty($cf_response["body"]))
942
+ return array("success" => true, "code" => null, "message" => null, "etag" => trim($cf_response["headers"]["etag"]), "xml" => trim($cf_response["body"]));
943
  /**/
944
  else /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
945
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Existing Amazon® CloudFront Origin Access Identity NOT found. %s", "s2member-admin", "s2member"), $cf_response["message"]));
946
  }
947
+ else if(isset($cf_response["code"], $cf_response["message"]))
948
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
949
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
950
  /**/
951
  else /* Else, we use a default error code and message. */
952
+ return array("success" => false, "code" => -98, "message" => _x("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
953
  }
954
  else /* Else, we use a default error code and message. */
955
+ return array("success" => false, "code" => -99, "message" => _x("Unable to acquire existing Amazon® CloudFront Origin Access Identity. Invalid Access ID.", "s2member-admin", "s2member"));
956
  }
957
  /**
958
  * Deletes an Amazon® S3/CloudFront Access Origin Identity.
966
  * @return array Array containing a true `success` element on success, else a failure array.
967
  * Failure array will contain a failure `code`, and a failure `message`.
968
  */
969
+ public static function amazon_cf_del_access_origin_identity($access_id = FALSE, $access_id_etag = FALSE, $access_id_xml = FALSE)
970
  {
971
+ if($access_id && is_string($access_id) && $access_id_etag && is_string($access_id_etag) && $access_id_xml && is_string($access_id_xml))
972
  {
973
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
974
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
975
  $cfc[$option] = $option_value;
976
  /**/
977
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
979
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
980
  /**/
981
  $cf_domain = "cloudfront.amazonaws.com";
982
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
983
+ $cf_location = "/2010-11-01/origin-access-identity/cloudfront/".$access_id;
984
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
985
+ $cf_args = array("method" => "DELETE", "headers" => array("Host" => $cf_domain, "Date" => $cf_date, "If-Match" => $access_id_etag, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
986
  /**/
987
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 204 /* Deleted. */))
988
+ return /* Deleted successfully. */ array("success" => true, "code" => null, "message" => null);
989
  /**/
990
+ else if(isset($cf_response["code"], $cf_response["message"]))
991
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
992
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to delete existing Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
993
  /**/
994
  else /* Else, we use a default error code and message. */
995
+ return array("success" => false, "code" => -98, "message" => _x("Unable to delete existing Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
996
  }
997
  else /* Else, we use a default error code and message. */
998
+ return array("success" => false, "code" => -99, "message" => _x("Unable to delete existing Amazon® CloudFront Origin Access Identity. Invalid Access ID, ETag, or XML config.", "s2member-admin", "s2member"));
999
  }
1000
  /**
1001
  * Creates an Amazon® S3/CloudFront Access Origin Identity for all Distros.
1006
  * @return array Array containing a true `success` and `distros_access_id`, `distros_s3_access_id` elements on success, else a failure array.
1007
  * Failure array will contain a failure `code`, and a failure `message`.
1008
  */
1009
+ public static function amazon_cf_create_distros_access_origin_identity()
1010
  {
1011
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1012
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
1013
  $cfc[$option] = $option_value;
1014
  /**/
1015
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
1017
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1018
  /**/
1019
  $cf_domain = "cloudfront.amazonaws.com";
1020
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
1021
  $cf_location = "/2010-11-01/origin-access-identity/cloudfront";
1022
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
1023
+ $cf_distros_access_reference = time().".".md5("access".$s3c["bucket"].$s3c["access_key"].$s3c["secret_key"].$cfc["private_key"].$cfc["private_key_id"]);
1024
+ $cf_distros_access_xml = '<?xml version="1.0" encoding="UTF-8"?><CloudFrontOriginAccessIdentityConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><CallerReference>'.esc_html($cf_distros_access_reference).'</CallerReference><Comment>'.esc_html(sprintf(_x("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])).'</Comment></CloudFrontOriginAccessIdentityConfig>';
1025
+ $cf_args = array("method" => "POST", "body" => $cf_distros_access_xml, "headers" => array("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
1026
  /**/
1027
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */))
1028
  {
1029
+ if(preg_match("/\<CloudFrontOriginAccessIdentity.*?\>(.+?)\<\/CloudFrontOriginAccessIdentity\>/is", $cf_response["body"], $cf_distros_access_tag) && preg_match("/\<Id\>(.+?)\<\/Id\>/is", $cf_distros_access_tag[1], $cf_distros_access_id_tag) && preg_match("/\<S3CanonicalUserId\>(.+?)\<\/S3CanonicalUserId\>/is", $cf_distros_access_tag[1], $cf_distros_s3_access_id_tag))
1030
+ return array("success" => true, "code" => null, "message" => null, "distros_access_id" => trim($cf_distros_access_id_tag[1]), "distros_s3_access_id" => trim($cf_distros_s3_access_id_tag[1]));
1031
  /**/
1032
  else /* Else, we use a default error code and message. */
1033
+ return array("success" => false, "code" => -98, "message" => _x("Unable to create/read Amazon® CloudFront Origin Access Identity. Unexpected response.", "s2member-admin", "s2member"));
1034
  }
1035
+ else if(isset($cf_response["code"], $cf_response["message"]))
1036
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1037
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to create Amazon® CloudFront Origin Access Identity. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1038
  /**/
1039
  else /* Else, we use a default error code and message. */
1040
+ return array("success" => false, "code" => -99, "message" => _x("Unable to create Amazon® CloudFront Origin Access Identity. Connection failed.", "s2member-admin", "s2member"));
1041
  }
1042
  /**
1043
  * Acquires an Amazon® S3/CloudFront Distro.
1050
  * @return array Array containing a true `success` and `etag`, `xml`, `deployed` elements on success, else a failure array.
1051
  * Failure array will contain a failure `code`, and a failure `message`.
1052
  */
1053
+ public static function amazon_cf_get_distro($distro_id = FALSE, $distro_type = FALSE)
1054
  {
1055
+ if($distro_id && is_string($distro_id) && $distro_type && is_string($distro_type) && in_array($distro_type, array("downloads", "streaming")))
1056
  {
1057
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1058
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
1059
  $cfc[$option] = $option_value;
1060
  /**/
1061
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
1063
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1064
  /**/
1065
  $cf_domain = "cloudfront.amazonaws.com";
1066
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
1067
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
1068
+ $cf_location = ($distro_type === "streaming") ? "/2010-11-01/streaming-distribution/".$distro_id : "/2010-11-01/distribution/".$distro_id;
1069
+ $cf_args = array("method" => "GET", "headers" => array("Host" => $cf_domain, "Date" => $cf_date, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
1070
  /**/
1071
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && (($cf_response["code"] === 404 && $cf_response["message"]) || ($cf_response["code"] === 200 && !empty($cf_response["headers"]["etag"]) && !empty($cf_response["body"]))))
1072
  {
1073
+ if($cf_response["code"] === 200 && !empty($cf_response["headers"]["etag"]) && !empty($cf_response["body"]))
1074
+ return array("success" => true, "code" => null, "message" => null, "etag" => trim($cf_response["headers"]["etag"]), "xml" => trim($cf_response["body"]), "deployed" => ((stripos($cf_response["body"], "<Status>Deployed</Status>") !== false) ? true : false));
1075
  /**/
1076
  else /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1077
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Existing Amazon® CloudFront Distro NOT found. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1078
  }
1079
+ else if(isset($cf_response["code"], $cf_response["message"]))
1080
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1081
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to acquire existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1082
  /**/
1083
  else /* Else, we use a default error code and message. */
1084
+ return array("success" => false, "code" => -98, "message" => _x("Unable to acquire existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1085
  }
1086
  else /* Else, we use a default error code and message. */
1087
+ return array("success" => false, "code" => -99, "message" => _x("Unable to acquire existing Amazon® CloudFront Distro. Invalid Distro ID and/or Distro type.", "s2member-admin", "s2member"));
1088
  }
1089
  /**
1090
  * Disables an Amazon® S3/CloudFront Distro.
1098
  * @return array Array containing a true `success` and `etag`, `xml`, `deployed` elements on success, else a failure array.
1099
  * Failure array will contain a failure `code`, and a failure `message`.
1100
  */
1101
+ public static function amazon_cf_disable_distro($distro_id = FALSE, $distro_id_etag = FALSE, $distro_id_xml = FALSE)
1102
  {
1103
+ if($distro_id && is_string($distro_id) && $distro_id_etag && is_string($distro_id_etag) && $distro_id_xml && is_string($distro_id_xml) && ($distro_id_type = (stripos($distro_id_xml, "<StreamingDistribution") !== false) ? "streaming" : ((stripos($distro_id_xml, "<Distribution") !== false) ? "downloads" : false)) && preg_match("/\<CallerReference\>(.+?)\<\/CallerReference\>/is", $distro_id_xml, $distro_id_reference_tag) && ($distro_id_reference = $distro_id_reference_tag[1]))
1104
  {
1105
+ if /* Only if it has NOT already been disabled. We do NOT need to do it again. */(stripos($distro_id_xml, "<Enabled>false</Enabled>") === false)
1106
  {
1107
+ if /* Check distro status before we even begin processing. */(stripos($distro_id_xml, "<Status>Deployed</Status>") !== false)
1108
  {
1109
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1110
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
1111
  $cfc[$option] = $option_value;
1112
  /**/
1113
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
1115
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1116
  /**/
1117
  $cf_domain = "cloudfront.amazonaws.com";
1118
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
1119
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
1120
+ $cf_location = ($distro_id_type === "streaming") ? "/2010-11-01/streaming-distribution/".$distro_id."/config" : "/2010-11-01/distribution/".$distro_id."/config";
1121
+ $cf_distro_xml = ($distro_id_type === "streaming") ? '<?xml version="1.0" encoding="UTF-8"?><StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>'.esc_html($s3c["bucket"]).'.s3.amazonaws.com</DNSName></S3Origin><CallerReference>'.esc_html($distro_id_reference).'</CallerReference><Enabled>false</Enabled><TrustedSigners><Self/></TrustedSigners></StreamingDistributionConfig>' : '<?xml version="1.0" encoding="UTF-8"?><DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>'.esc_html($s3c["bucket"]).'.s3.amazonaws.com</DNSName></S3Origin><CallerReference>'.esc_html($distro_id_reference).'</CallerReference><Enabled>false</Enabled><TrustedSigners><Self/></TrustedSigners></DistributionConfig>';
1122
+ $cf_args = array("method" => "PUT", "body" => $cf_distro_xml, "headers" => array("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "If-Match" => $distro_id_etag, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
1123
  /**/
1124
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && $cf_response["code"] === 200 && !empty($cf_response["headers"]["etag"]) && !empty($cf_response["body"]))
1125
+ return array("success" => true, "code" => null, "message" => null, "etag" => trim($cf_response["headers"]["etag"]), "xml" => trim($cf_response["body"]), "deployed" => ((stripos($cf_response["body"], "<Status>Deployed</Status>") !== false) ? true : false));
1126
  /**/
1127
+ else if(isset($cf_response["code"], $cf_response["message"]))
1128
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1129
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to disable existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1130
  /**/
1131
  else /* Else, we use a default error code and message. */
1132
+ return array("success" => false, "code" => -97, "message" => _x("Unable to disable existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1133
  }
1134
  else /* Else, we use a default error code and message. */
1135
+ return array("success" => false, "code" => -98, "message" => _x("Existing Amazon® CloudFront Distro cannot be disabled at this time. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
1136
  }
1137
  else /* Else, we use a default error code and message. */
1138
+ return array("success" => true, "code" => null, "message" => null, "etag" => $distro_id_etag, "xml" => $distro_id_xml, "deployed" => ((stripos($distro_id_xml, "<Status>Deployed</Status>") !== false) ? true : false));
1139
  }
1140
  else /* Else, we use a default error code and message. */
1141
+ return array("success" => false, "code" => -99, "message" => _x("Unable to disable existing Amazon® CloudFront Distro. Invalid Distro ID, ETag, or XML config.", "s2member-admin", "s2member"));
1142
  }
1143
  /**
1144
  * Deletes an Amazon® S3/CloudFront Distro.
1152
  * @return array Array containing a true `success` element on success, else a failure array.
1153
  * Failure array will contain a failure `code`, and a failure `message`.
1154
  */
1155
+ public static function amazon_cf_del_distro($distro_id = FALSE, $distro_id_etag = FALSE, $distro_id_xml = FALSE)
1156
  {
1157
+ if($distro_id && is_string($distro_id) && $distro_id_etag && is_string($distro_id_etag) && $distro_id_xml && is_string($distro_id_xml) && ($distro_id_type = (stripos($distro_id_xml, "<StreamingDistribution") !== false) ? "streaming" : ((stripos($distro_id_xml, "<Distribution") !== false) ? "downloads" : false)) && preg_match("/\<CallerReference\>(.+?)\<\/CallerReference\>/is", $distro_id_xml, $distro_id_reference_tag) && ($distro_id_reference = $distro_id_reference_tag[1]))
1158
  {
1159
+ if /* Check distro status before we even begin processing this deletion. */(stripos($distro_id_xml, "<Status>Deployed</Status>") !== false)
1160
  {
1161
+ if(($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_disable_distro($distro_id, $distro_id_etag, $distro_id_xml)) && $cf_response["success"])
1162
  {
1163
+ if(($cf_response = c_ws_plugin__s2member_files_in::amazon_cf_get_distro($distro_id, $distro_id_type)) && $cf_response["success"] && $cf_response["deployed"])
1164
  {
1165
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1166
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
1167
  $cfc[$option] = $option_value;
1168
  /**/
1169
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
1171
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1172
  /**/
1173
  $cf_domain = "cloudfront.amazonaws.com";
1174
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
1175
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
1176
+ $cf_location = ($distro_id_type === "streaming") ? "/2010-11-01/streaming-distribution/".$distro_id : "/2010-11-01/distribution/".$distro_id;
1177
+ $cf_args = array("method" => "DELETE", "headers" => array("Host" => $cf_domain, "Date" => $cf_date, "If-Match" => $cf_response["etag"], "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
1178
  /**/
1179
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 204 /* Deleted. */))
1180
+ return /* Deleted successfully. */ array("success" => true, "code" => null, "message" => null);
1181
  /**/
1182
+ else if(isset($cf_response["code"], $cf_response["message"]))
1183
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1184
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to delete existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1185
  /**/
1186
  else /* Else, we use a default error code and message. */
1187
+ return array("success" => false, "code" => -94, "message" => _x("Unable to delete existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1188
  }
1189
+ else if(isset($cf_response["success"], $cf_response["deployed"]) && $cf_response["success"] && !$cf_response["deployed"])
1190
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1191
+ return array("success" => false, "code" => -95, "message" => _x("Existing Amazon® CloudFront Distro cannot be deleted at this time. Still in a `pending` state after having been disabled by s2Member. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
1192
  /**/
1193
+ else if(isset($cf_response["code"], $cf_response["message"]))
1194
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1195
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to check status of existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1196
  /**/
1197
  else /* Else, we use a default error code and message. */
1198
+ return array("success" => false, "code" => -96, "message" => _x("Unable to check status of existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1199
  }
1200
+ else if(isset($cf_response["code"], $cf_response["message"]))
1201
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1202
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to disable existing Amazon® CloudFront Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1203
  /**/
1204
  else /* Else, we use a default error code and message. */
1205
+ return array("success" => false, "code" => -97, "message" => _x("Unable to disable existing Amazon® CloudFront Distro. Connection failed.", "s2member-admin", "s2member"));
1206
  }
1207
  else /* Else, we use a default error code and message. */
1208
+ return array("success" => false, "code" => -98, "message" => _x("Existing Amazon® CloudFront Distro cannot be deleted at this time. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again.", "s2member-admin", "s2member"));
1209
  }
1210
  else /* Else, we use a default error code and message. */
1211
+ return array("success" => false, "code" => -99, "message" => _x("Unable to delete existing Amazon® CloudFront Distro. Invalid Distro ID or ETag.", "s2member-admin", "s2member"));
1212
  }
1213
  /**
1214
  * Creates an Amazon® S3/CloudFront Distro.
1220
  * @return array Array containing a true `success` and `distro_[distro_type]_id`, `distro_[distro_type]_dname` elements on success, else a failure array.
1221
  * Failure array will contain a failure `code`, and a failure `message`.
1222
  */
1223
+ public static function amazon_cf_create_distro($distro_type = FALSE)
1224
  {
1225
+ if($distro_type && is_string($distro_type) && in_array($distro_type, array("downloads", "streaming")))
1226
  {
1227
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $option => $option_value)
1228
+ if(preg_match("/^amazon_cf_files_/", $option) && ($option = preg_replace("/^amazon_cf_files_/", "", $option)))
1229
  $cfc[$option] = $option_value;
1230
  /**/
1231
  $s3c["bucket"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"];
1233
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
1234
  /**/
1235
  $cf_domain = "cloudfront.amazonaws.com";
1236
+ $cf_date = gmdate("D, d M Y H:i:s")." GMT";
1237
+ $cf_signature = base64_encode(c_ws_plugin__s2member_files_in::amazon_cf_sign($cf_date));
1238
  /**/
1239
+ if /* Create a `downloads` Distro? This uses a different XML schema. */($distro_type === "downloads")
1240
  {
1241
  $cf_location = /* Create distro. */ "/2010-11-01/distribution";
1242
+ $cf_distro_downloads_reference = time().".".md5("downloads".$s3c["bucket"].$s3c["access_key"].$s3c["secret_key"].$cfc["private_key"].$cfc["private_key_id"].$cfc["distro_downloads_cname"]);
1243
+ $cf_distro_downloads_xml = '<?xml version="1.0" encoding="UTF-8"?><DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>'.esc_html($s3c["bucket"]).'.s3.amazonaws.com</DNSName><OriginAccessIdentity>origin-access-identity/cloudfront/'.esc_html($cfc["distros_access_id"]).'</OriginAccessIdentity></S3Origin><CallerReference>'.esc_html($cf_distro_downloads_reference).'</CallerReference>'.(($cfc["distro_downloads_cname"]) ? '<CNAME>'.esc_html($cfc["distro_downloads_cname"]).'</CNAME>' : '').'<Comment>'.esc_html(sprintf(_x("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])).'</Comment><Enabled>true</Enabled><DefaultRootObject>index.html</DefaultRootObject><TrustedSigners><Self/></TrustedSigners></DistributionConfig>';
1244
+ $cf_args = array("method" => "POST", "body" => $cf_distro_downloads_xml, "headers" => array("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
1245
  /**/
1246
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */))
1247
  {
1248
+ if(preg_match("/\<Distribution.*?\>(.+?)\<\/Distribution\>/is", $cf_response["body"], $cf_distro_downloads_tag) && preg_match("/\<Id\>(.+?)\<\/Id\>/is", $cf_distro_downloads_tag[1], $cf_distro_downloads_id_tag) && preg_match("/\<DomainName\>(.+?)\<\/DomainName\>/is", $cf_distro_downloads_tag[1], $cf_distro_downloads_dname_tag))
1249
+ return array("success" => true, "code" => null, "message" => null, "distro_downloads_id" => trim($cf_distro_downloads_id_tag[1]), "distro_downloads_dname" => trim($cf_distro_downloads_dname_tag[1]));
1250
  /**/
1251
  else /* Else, we use a default error code and message. */
1252
+ return array("success" => false, "code" => -97, "message" => _x("Unable to create/read Amazon® CloudFront Downloads Distro. Unexpected response.", "s2member-admin", "s2member"));
1253
  }
1254
+ else if(isset($cf_response["code"], $cf_response["message"]))
1255
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1256
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to create Amazon® CloudFront Downloads Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1257
  /**/
1258
  else /* Else, we use a default error code and message. */
1259
+ return array("success" => false, "code" => -98, "message" => _x("Unable to create Amazon® CloudFront Downloads Distro. Connection failed.", "s2member-admin", "s2member"));
1260
  }
1261
  /**/
1262
+ else if /* Create a `streaming` Distro? A different XML schema. */($distro_type === "streaming")
1263
  {
1264
  $cf_location = /* Create streaming distro. */ "/2010-11-01/streaming-distribution";
1265
+ $cf_distro_streaming_reference = time().".".md5("streaming".$s3c["bucket"].$s3c["access_key"].$s3c["secret_key"].$cfc["private_key"].$cfc["private_key_id"].$cfc["distro_streaming_cname"]);
1266
+ $cf_distro_streaming_xml = '<?xml version="1.0" encoding="UTF-8"?><StreamingDistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-11-01/"><S3Origin><DNSName>'.esc_html($s3c["bucket"]).'.s3.amazonaws.com</DNSName><OriginAccessIdentity>origin-access-identity/cloudfront/'.esc_html($cfc["distros_access_id"]).'</OriginAccessIdentity></S3Origin><CallerReference>'.esc_html($cf_distro_streaming_reference).'</CallerReference>'.(($cfc["distro_streaming_cname"]) ? '<CNAME>'.esc_html($cfc["distro_streaming_cname"]).'</CNAME>' : '').'<Comment>'.esc_html(sprintf(_x("Created by s2Member, for S3 Bucket: %s.", "s2member-admin", "s2member"), $s3c["bucket"])).'</Comment><Enabled>true</Enabled><DefaultRootObject>index.html</DefaultRootObject><TrustedSigners><Self/></TrustedSigners></StreamingDistributionConfig>';
1267
+ $cf_args = array("method" => "POST", "body" => $cf_distro_streaming_xml, "headers" => array("Host" => $cf_domain, "Content-Type" => "application/xml", "Date" => $cf_date, "Authorization" => "AWS ".$cfc["access_key"].":".$cf_signature));
1268
  /**/
1269
+ if(($cf_response = c_ws_plugin__s2member_utils_urls::remote("https://".$cf_domain.$cf_location, false, array_merge($cf_args, array("timeout" => 20)), "array")) && ($cf_response["code"] === 200 || $cf_response["code"] === 201 /* Created. */))
1270
  {
1271
+ if(preg_match("/\<StreamingDistribution.*?\>(.+?)\<\/StreamingDistribution\>/is", $cf_response["body"], $cf_distro_streaming_tag) && preg_match("/\<Id\>(.+?)\<\/Id\>/is", $cf_distro_streaming_tag[1], $cf_distro_streaming_id_tag) && preg_match("/\<DomainName\>(.+?)\<\/DomainName\>/is", $cf_distro_streaming_tag[1], $cf_distro_streaming_dname_tag))
1272
+ return array("success" => true, "code" => null, "message" => null, "distro_streaming_id" => trim($cf_distro_streaming_id_tag[1]), "distro_streaming_dname" => trim($cf_distro_streaming_dname_tag[1]));
1273
  /**/
1274
  else /* Else, we use a default error code and message. */
1275
+ return array("success" => false, "code" => -97, "message" => _x("Unable to create/read Amazon® CloudFront Streaming Distro. Unexpected response.", "s2member-admin", "s2member"));
1276
  }
1277
+ else if(isset($cf_response["code"], $cf_response["message"]))
1278
  /* translators: In this translation, `%s` may be filled with an English message, which comes from the Amazon® CloudFront API call. Feel free to exclude `%s` if you like. */
1279
+ return array("success" => false, "code" => $cf_response["code"], "message" => sprintf(_x("Unable to create Amazon® CloudFront Streaming Distro. %s", "s2member-admin", "s2member"), $cf_response["message"]));
1280
  /**/
1281
  else /* Else, we use a default error code and message. */
1282
+ return array("success" => false, "code" => -98, "message" => _x("Unable to create Amazon® CloudFront Streaming Distro. Connection failed.", "s2member-admin", "s2member"));
1283
  }
1284
  }
1285
  else /* Else, we use a default error code and message. */
1286
+ return array("success" => false, "code" => -99, "message" => _x("Unable to create Amazon® CloudFront Distro. Invalid Distro type.", "s2member-admin", "s2member"));
1287
  }
1288
  }
1289
  }
includes/classes/files.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Files
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_files"))
21
  {
22
  /**
23
  * File Download routines for s2Member.
@@ -41,11 +41,11 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
41
  * @return null|str If called directly with ``$create_file_download_url``, returns a string with the URL, based on configuration.
42
  * Else, this function may exit script execution after serving a File Download.
43
  */
44
- public static function check_file_download_access ($create_file_download_url = FALSE) /* Calls inner routine. */
45
  {
46
- if (is_array ($create_file_download_url) || !empty ($_GET["s2member_file_download"])) /* Call inner routine? */
47
  {
48
- return c_ws_plugin__s2member_files_in::check_file_download_access ($create_file_download_url);
49
  }
50
  }
51
  /**
@@ -61,9 +61,9 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
61
  *
62
  * @see s2Member\API_Functions\s2member_file_download_url()
63
  */
64
- public static function create_file_download_url ($config = FALSE, $get_streamer_array = FALSE) /* Calls inner routine. */
65
  {
66
- return c_ws_plugin__s2member_files_in::create_file_download_url ($config, $get_streamer_array);
67
  }
68
  /**
69
  * Auto-configures an Amazon® S3 Bucket's ACLs.
@@ -74,9 +74,9 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
74
  * @return bool|array True on success, else array on failure.
75
  * Failure array will contain a failure `code`, and a failure `message`.
76
  */
77
- public static function amazon_s3_auto_configure_acls () /* Calls inner routine. */
78
  {
79
- return c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls ();
80
  }
81
  /**
82
  * Auto-configures Amazon® S3/CloudFront distros.
@@ -87,9 +87,9 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
87
  * @return bool|array True on success, else array on failure.
88
  * Failure array will contain a failure `code`, and a failure `message`.
89
  */
90
- public static function amazon_s3_cf_auto_configure_distros () /* Calls inner routine. */
91
  {
92
- return c_ws_plugin__s2member_files_in::amazon_s3_cf_auto_configure_distros ();
93
  }
94
  /**
95
  * Determines the max period ( in days ), for Download Access.
@@ -102,17 +102,17 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
102
  *
103
  * @deprecated Deprecated in v111029. This function is no longer used by s2Member.
104
  */
105
- public static function max_download_period /* No longer used by s2Member. */ ()
106
  {
107
- do_action ("ws_plugin__s2member_before_max_download_period", get_defined_vars ());
108
  /**/
109
- for ($n = 0, $max = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
110
- if (!empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed"]))
111
- if (!empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"]))
112
- if (($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"]))
113
  $max = ($max < $days) ? $days : $max;
114
  /**/
115
- return apply_filters ("ws_plugin__s2member_max_download_period", (($max > 365) ? 365 : $max), get_defined_vars ());
116
  }
117
  /**
118
  * Determines the minimum Level required for File Download Access.
@@ -122,17 +122,17 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
122
  *
123
  * @return bool|int False if no access is allowed, else Level number (int) 0+.
124
  */
125
- public static function min_level_4_downloads () /* Multipurpose. False if no access. */
126
  {
127
- do_action ("ws_plugin__s2member_before_min_level_4_downloads", get_defined_vars ());
128
  /**/
129
- for ($n = 0, $min = false; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
130
- if (!empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed"]))
131
- if (!empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"]))
132
- if (($min = $n) >= 0)
133
  break;
134
  /**/
135
- return apply_filters ("ws_plugin__s2member_min_level_4_downloads", ((is_int ($min)) ? $min : false), get_defined_vars ());
136
  }
137
  /**
138
  * Creates a File Download Key.
@@ -149,26 +149,26 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
149
  * `universal` and/or `cache-compatible` = a Download Key which never expires, and is NOT tied to any specific User. Use at your own risk.
150
  * @return str A Download Key. MD5 hash, 32 characters, URL-safe.
151
  */
152
- public static function file_download_key ($file = FALSE, $directive = FALSE)
153
  {
154
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
155
- do_action ("ws_plugin__s2member_before_file_download_key", get_defined_vars ());
156
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
157
  /**/
158
- $file = ($file && is_string ($file) && ($file = trim ($file, "/"))) ? $file : "";
159
  /**/
160
- if ($directive === "ip-forever" && c_ws_plugin__s2member_no_cache::no_cache_constants (true))
161
- $salt = $file . $_SERVER["REMOTE_ADDR"];
162
  /**/
163
- else if ($directive === "universal" || $directive === "cache-compatible" || $directive)
164
  $salt = /* Just the file name. This IS cachable. */ $file;
165
  /**/
166
- else if (c_ws_plugin__s2member_no_cache::no_cache_constants (true))
167
- $salt = date ("Y-m-d") . $_SERVER["REMOTE_ADDR"] . $_SERVER["HTTP_USER_AGENT"] . $file;
168
  /**/
169
- $key = (!empty ($salt)) ? md5 (c_ws_plugin__s2member_utils_encryption::xencrypt ($salt, false, false)) : "";
170
  /**/
171
- return apply_filters ("ws_plugin__s2member_file_download_key", $key, get_defined_vars ());
172
  }
173
  /**
174
  * Download details on a per-User basis.
@@ -186,40 +186,40 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
186
  * @note Calculations returned by this function do NOT include File Downloads that were accessed with an Advanced File Download Key.
187
  * @todo Make it possible for s2Member to keep a count of files downloaded with an Advanced Download Key.
188
  */
189
- public static function user_downloads ($user = FALSE, $not_counting_this_particular_file = FALSE, $user_log = FALSE, $user_arc = FALSE)
190
  {
191
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
192
- do_action ("ws_plugin__s2member_before_user_downloads", get_defined_vars ());
193
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
194
  /**/
195
  $allowed = $allowed_days = $currently = 0; /* Initialize these to zero. */
196
- $log = $arc = array (); /* Initialize these to a default empty array value. */
197
  /**/
198
- if ((is_object ($user) || is_object ($user = (is_user_logged_in ()) ? wp_get_current_user () : false)) && !empty ($user->ID) && ($user_id = $user->ID))
199
  {
200
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
201
  {
202
- if ($user->has_cap ("access_s2member_level" . $n)) /* Do they have access? */
203
  {
204
- if (!empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed"]) && !empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"]))
205
  {
206
- $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed"];
207
- $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"];
208
  }
209
- if ($user->has_cap ("s2member_level" . $n)) /* We can stop now, if this is their Role. */
210
  break; /* Break now. */
211
  }
212
  }
213
- $log = (is_array ($user_log)) ? $user_log : ((is_array ($log = get_user_option ("s2member_file_download_access_log", $user_id)) && $log !== array (false)) ? $log : array ());
214
- $arc = (is_array ($user_arc)) ? $user_arc : ((is_array ($arc = get_user_option ("s2member_file_download_access_arc", $user_id)) && $arc !== array (false)) ? $arc : array ());
215
  /**/
216
- foreach (($user_file_download_access_log = $log) as $user_file_download_access_log_entry_key => $user_file_download_access_log_entry)
217
- if (isset ($user_file_download_access_log_entry["date"]) && strtotime ($user_file_download_access_log_entry["date"]) >= strtotime ("-" . $allowed_days . " days"))
218
- if (isset ($user_file_download_access_log_entry["file"]) && $user_file_download_access_log_entry["file"] !== $not_counting_this_particular_file)
219
  $currently = $currently + 1;
220
  }
221
  /**/
222
- return apply_filters ("ws_plugin__s2member_user_downloads", array ("allowed" => $allowed, "allowed_days" => $allowed_days, "currently" => $currently, "log" => $log, "archive" => $arc), get_defined_vars ());
223
  }
224
  /**
225
  * Total downloads of a particular file; possibly by a particular User.
@@ -235,26 +235,26 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
235
  * @note Calculations returned by this function do NOT include File Downloads that were accessed with an Advanced File Download Key.
236
  * @todo Make it possible for s2Member to keep a count of files downloaded with an Advanced Download Key.
237
  */
238
- public static function total_downloads_of ($file = FALSE, $user_id = FALSE, $check_archives_too = TRUE)
239
  {
240
  global $wpdb; /* Global database object reference. */
241
  /**/
242
- if ($file && is_string ($file)) /* Was ``$file`` passed in properly? */
243
  {
244
- if (is_array ($results = $wpdb->get_results ("SELECT `meta_key`, `meta_value` FROM `" . $wpdb->usermeta . "` WHERE " . ((is_numeric ($user_id)) ? "`user_id` = '" . esc_sql ($user_id) . "' AND " : "") . "(`meta_key` = '" . $wpdb->prefix . "s2member_file_download_access_log'" . (($check_archives_too) ? " OR `meta_key` = '" . $wpdb->prefix . "s2member_file_download_access_arc'" : "") . ") AND `meta_value` REGEXP '.*\"file\";s:[0-9]+:\"" . esc_sql ($file) . "\".*'")))
245
  {
246
- foreach ($results as $r /* Go through the entire array of results found in the `REGEXP` database query above. */)
247
- if (is_array ($la_entries = /* Unserialize the array. */ maybe_unserialize ($r->meta_value)) && !empty ($la_entries))
248
  /**/
249
- foreach ($la_entries as $la_entry /* Go through all of the entries in each result ``$r``; collecting `counter` values. */)
250
- if (!empty ($la_entry["file"]) && $la_entry["file"] === $file && /* Back compatibility. Is `counter` even set? */ (!empty ($la_entry["counter"]) || ($la_entry["counter"] = 1)))
251
  {
252
- $total = (!empty ($total)) ? $total + (int)$la_entry["counter"] : (int)$la_entry["counter"];
253
  break; /* Break now. No need to continue looping; ``$file`` found in these entries. */
254
  }
255
  }
256
  }
257
- return (!empty ($total)) ? $total : /* Else return zero by default. */ 0;
258
  }
259
  /**
260
  * Total unique downloads of a particular file; possibly by a particular User.
@@ -270,26 +270,107 @@ if (!class_exists ("c_ws_plugin__s2member_files"))
270
  * @note Calculations returned by this function do NOT include File Downloads that were accessed with an Advanced File Download Key.
271
  * @todo Make it possible for s2Member to keep a count of files downloaded with an Advanced Download Key.
272
  */
273
- public static function total_unique_downloads_of ($file = FALSE, $user_id = FALSE, $check_archives_too = TRUE)
274
  {
275
  global $wpdb; /* Global database object reference. */
276
  /**/
277
- if ($file && is_string ($file)) /* Was ``$file`` passed in properly? */
278
  {
279
- if (is_array ($results = $wpdb->get_results ("SELECT `meta_key`, `meta_value` FROM `" . $wpdb->usermeta . "` WHERE " . ((is_numeric ($user_id)) ? "`user_id` = '" . esc_sql ($user_id) . "' AND " : "") . "(`meta_key` = '" . $wpdb->prefix . "s2member_file_download_access_log'" . (($check_archives_too) ? " OR `meta_key` = '" . $wpdb->prefix . "s2member_file_download_access_arc'" : "") . ") AND `meta_value` REGEXP '.*\"file\";s:[0-9]+:\"" . esc_sql ($file) . "\".*'")))
280
  {
281
- foreach ($results as $r /* Go through the entire array of results found in the `REGEXP` database query above. */)
282
- if (is_array ($la_entries = /* Unserialize the array. */ maybe_unserialize ($r->meta_value)) && !empty ($la_entries))
283
  /**/
284
- foreach ($la_entries as $la_entry /* Go through all of the entries in each result ``$r``; collecting `counter` values. */)
285
- if (!empty ($la_entry["file"]) && $la_entry["file"] === $file && /* Back compatibility. Is `counter` even set? */ (!empty ($la_entry["counter"]) || ($la_entry["counter"] = 1)))
286
  {
287
- $total = (!empty ($total)) ? /* Only count `1` here ( i.e. unique downloads ). */ $total + 1 : 1;
288
  break; /* Break now. No need to continue looping; ``$file`` found in these entries. */
289
  }
290
  }
291
  }
292
- return (!empty ($total)) ? $total : /* Else return zero by default. */ 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  }
294
  }
295
  }
14
  * @package s2Member\Files
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_files"))
21
  {
22
  /**
23
  * File Download routines for s2Member.
41
  * @return null|str If called directly with ``$create_file_download_url``, returns a string with the URL, based on configuration.
42
  * Else, this function may exit script execution after serving a File Download.
43
  */
44
+ public static function check_file_download_access($create_file_download_url = FALSE) /* Calls inner routine. */
45
  {
46
+ if(is_array($create_file_download_url) || !empty($_GET["s2member_file_download"])) /* Call inner routine? */
47
  {
48
+ return c_ws_plugin__s2member_files_in::check_file_download_access($create_file_download_url);
49
  }
50
  }
51
  /**
61
  *
62
  * @see s2Member\API_Functions\s2member_file_download_url()
63
  */
64
+ public static function create_file_download_url($config = FALSE, $get_streamer_array = FALSE) /* Calls inner routine. */
65
  {
66
+ return c_ws_plugin__s2member_files_in::create_file_download_url($config, $get_streamer_array);
67
  }
68
  /**
69
  * Auto-configures an Amazon® S3 Bucket's ACLs.
74
  * @return bool|array True on success, else array on failure.
75
  * Failure array will contain a failure `code`, and a failure `message`.
76
  */
77
+ public static function amazon_s3_auto_configure_acls() /* Calls inner routine. */
78
  {
79
+ return c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls();
80
  }
81
  /**
82
  * Auto-configures Amazon® S3/CloudFront distros.
87
  * @return bool|array True on success, else array on failure.
88
  * Failure array will contain a failure `code`, and a failure `message`.
89
  */
90
+ public static function amazon_s3_cf_auto_configure_distros() /* Calls inner routine. */
91
  {
92
+ return c_ws_plugin__s2member_files_in::amazon_s3_cf_auto_configure_distros();
93
  }
94
  /**
95
  * Determines the max period ( in days ), for Download Access.
102
  *
103
  * @deprecated Deprecated in v111029. This function is no longer used by s2Member.
104
  */
105
+ public static function max_download_period /* No longer used by s2Member. */()
106
  {
107
+ do_action("ws_plugin__s2member_before_max_download_period", get_defined_vars());
108
  /**/
109
+ for($n = 0, $max = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
110
+ if(!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed"]))
111
+ if(!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed_days"]))
112
+ if(($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed_days"]))
113
  $max = ($max < $days) ? $days : $max;
114
  /**/
115
+ return apply_filters("ws_plugin__s2member_max_download_period", (($max > 365) ? 365 : $max), get_defined_vars());
116
  }
117
  /**
118
  * Determines the minimum Level required for File Download Access.
122
  *
123
  * @return bool|int False if no access is allowed, else Level number (int) 0+.
124
  */
125
+ public static function min_level_4_downloads() /* Multipurpose. False if no access. */
126
  {
127
+ do_action("ws_plugin__s2member_before_min_level_4_downloads", get_defined_vars());
128
  /**/
129
+ for($n = 0, $min = false; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
130
+ if(!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed"]))
131
+ if(!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed_days"]))
132
+ if(($min = $n) >= 0)
133
  break;
134
  /**/
135
+ return apply_filters("ws_plugin__s2member_min_level_4_downloads", ((is_int($min)) ? $min : false), get_defined_vars());
136
  }
137
  /**
138
  * Creates a File Download Key.
149
  * `universal` and/or `cache-compatible` = a Download Key which never expires, and is NOT tied to any specific User. Use at your own risk.
150
  * @return str A Download Key. MD5 hash, 32 characters, URL-safe.
151
  */
152
+ public static function file_download_key($file = FALSE, $directive = FALSE)
153
  {
154
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
155
+ do_action("ws_plugin__s2member_before_file_download_key", get_defined_vars());
156
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
157
  /**/
158
+ $file = ($file && is_string($file) && ($file = trim($file, "/"))) ? $file : "";
159
  /**/
160
+ if($directive === "ip-forever" && c_ws_plugin__s2member_no_cache::no_cache_constants(true))
161
+ $salt = $file.$_SERVER["REMOTE_ADDR"];
162
  /**/
163
+ else if($directive === "universal" || $directive === "cache-compatible" || $directive)
164
  $salt = /* Just the file name. This IS cachable. */ $file;
165
  /**/
166
+ else if(c_ws_plugin__s2member_no_cache::no_cache_constants(true))
167
+ $salt = date("Y-m-d").$_SERVER["REMOTE_ADDR"].$_SERVER["HTTP_USER_AGENT"].$file;
168
  /**/
169
+ $key = (!empty($salt)) ? md5(c_ws_plugin__s2member_utils_encryption::xencrypt($salt, false, false)) : "";
170
  /**/
171
+ return apply_filters("ws_plugin__s2member_file_download_key", $key, get_defined_vars());
172
  }
173
  /**
174
  * Download details on a per-User basis.
186
  * @note Calculations returned by this function do NOT include File Downloads that were accessed with an Advanced File Download Key.
187
  * @todo Make it possible for s2Member to keep a count of files downloaded with an Advanced Download Key.
188
  */
189
+ public static function user_downloads($user = FALSE, $not_counting_this_particular_file = FALSE, $user_log = FALSE, $user_arc = FALSE)
190
  {
191
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
192
+ do_action("ws_plugin__s2member_before_user_downloads", get_defined_vars());
193
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
194
  /**/
195
  $allowed = $allowed_days = $currently = 0; /* Initialize these to zero. */
196
+ $log = $arc = array(); /* Initialize these to a default empty array value. */
197
  /**/
198
+ if((is_object($user) || is_object($user = (is_user_logged_in()) ? wp_get_current_user() : false)) && !empty($user->ID) && ($user_id = $user->ID))
199
  {
200
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
201
  {
202
+ if($user->has_cap("access_s2member_level".$n)) /* Do they have access? */
203
  {
204
+ if(!empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed"]) && !empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed_days"]))
205
  {
206
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed"];
207
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed_days"];
208
  }
209
+ if($user->has_cap("s2member_level".$n)) /* We can stop now, if this is their Role. */
210
  break; /* Break now. */
211
  }
212
  }
213
+ $log = (is_array($user_log)) ? $user_log : ((is_array($log = get_user_option("s2member_file_download_access_log", $user_id)) && $log !== array(false)) ? $log : array());
214
+ $arc = (is_array($user_arc)) ? $user_arc : ((is_array($arc = get_user_option("s2member_file_download_access_arc", $user_id)) && $arc !== array(false)) ? $arc : array());
215
  /**/
216
+ foreach(($user_file_download_access_log = $log) as $user_file_download_access_log_entry_key => $user_file_download_access_log_entry)
217
+ if(isset($user_file_download_access_log_entry["date"]) && strtotime($user_file_download_access_log_entry["date"]) >= strtotime("-".$allowed_days." days"))
218
+ if(isset($user_file_download_access_log_entry["file"]) && $user_file_download_access_log_entry["file"] !== $not_counting_this_particular_file)
219
  $currently = $currently + 1;
220
  }
221
  /**/
222
+ return apply_filters("ws_plugin__s2member_user_downloads", array("allowed" => $allowed, "allowed_days" => $allowed_days, "currently" => $currently, "log" => $log, "archive" => $arc), get_defined_vars());
223
  }
224
  /**
225
  * Total downloads of a particular file; possibly by a particular User.
235
  * @note Calculations returned by this function do NOT include File Downloads that were accessed with an Advanced File Download Key.
236
  * @todo Make it possible for s2Member to keep a count of files downloaded with an Advanced Download Key.
237
  */
238
+ public static function total_downloads_of($file = FALSE, $user_id = FALSE, $check_archives_too = TRUE)
239
  {
240
  global $wpdb; /* Global database object reference. */
241
  /**/
242
+ if($file && is_string($file)) /* Was ``$file`` passed in properly? */
243
  {
244
+ if(is_array($results = $wpdb->get_results("SELECT `meta_key`, `meta_value` FROM `".$wpdb->usermeta."` WHERE ".((is_numeric($user_id)) ? "`user_id` = '".esc_sql($user_id)."' AND " : "")."(`meta_key` = '".$wpdb->prefix."s2member_file_download_access_log'".(($check_archives_too) ? " OR `meta_key` = '".$wpdb->prefix."s2member_file_download_access_arc'" : "").") AND `meta_value` REGEXP '.*\"file\";s:[0-9]+:\"".esc_sql($file)."\".*'")))
245
  {
246
+ foreach($results as $r /* Go through the entire array of results found in the `REGEXP` database query above. */)
247
+ if(is_array($la_entries = /* Unserialize the array. */ maybe_unserialize($r->meta_value)) && !empty($la_entries))
248
  /**/
249
+ foreach($la_entries as $la_entry /* Go through all of the entries in each result ``$r``; collecting `counter` values. */)
250
+ if(!empty($la_entry["file"]) && $la_entry["file"] === $file && /* Back compatibility. Is `counter` even set? */ (!empty($la_entry["counter"]) || ($la_entry["counter"] = 1)))
251
  {
252
+ $total = (!empty($total)) ? $total + (int)$la_entry["counter"] : (int)$la_entry["counter"];
253
  break; /* Break now. No need to continue looping; ``$file`` found in these entries. */
254
  }
255
  }
256
  }
257
+ return (!empty($total)) ? $total : /* Else return zero by default. */ 0;
258
  }
259
  /**
260
  * Total unique downloads of a particular file; possibly by a particular User.
270
  * @note Calculations returned by this function do NOT include File Downloads that were accessed with an Advanced File Download Key.
271
  * @todo Make it possible for s2Member to keep a count of files downloaded with an Advanced Download Key.
272
  */
273
+ public static function total_unique_downloads_of($file = FALSE, $user_id = FALSE, $check_archives_too = TRUE)
274
  {
275
  global $wpdb; /* Global database object reference. */
276
  /**/
277
+ if($file && is_string($file)) /* Was ``$file`` passed in properly? */
278
  {
279
+ if(is_array($results = $wpdb->get_results("SELECT `meta_key`, `meta_value` FROM `".$wpdb->usermeta."` WHERE ".((is_numeric($user_id)) ? "`user_id` = '".esc_sql($user_id)."' AND " : "")."(`meta_key` = '".$wpdb->prefix."s2member_file_download_access_log'".(($check_archives_too) ? " OR `meta_key` = '".$wpdb->prefix."s2member_file_download_access_arc'" : "").") AND `meta_value` REGEXP '.*\"file\";s:[0-9]+:\"".esc_sql($file)."\".*'")))
280
  {
281
+ foreach($results as $r /* Go through the entire array of results found in the `REGEXP` database query above. */)
282
+ if(is_array($la_entries = /* Unserialize the array. */ maybe_unserialize($r->meta_value)) && !empty($la_entries))
283
  /**/
284
+ foreach($la_entries as $la_entry /* Go through all of the entries in each result ``$r``; collecting `counter` values. */)
285
+ if(!empty($la_entry["file"]) && $la_entry["file"] === $file && /* Back compatibility. Is `counter` even set? */ (!empty($la_entry["counter"]) || ($la_entry["counter"] = 1)))
286
  {
287
+ $total = (!empty($total)) ? /* Only count `1` here ( i.e. unique downloads ). */ $total + 1 : 1;
288
  break; /* Break now. No need to continue looping; ``$file`` found in these entries. */
289
  }
290
  }
291
  }
292
+ return (!empty($total)) ? $total : /* Else return zero by default. */ 0;
293
+ }
294
+ /**
295
+ * Checks for GZIP rules in root `.htaccess` file.
296
+ *
297
+ * @package s2Member\Files
298
+ * @since 120212
299
+ *
300
+ * @return bool True if rules exist, else false.
301
+ */
302
+ public static function no_gzip_rules_in_root_htaccess()
303
+ {
304
+ $start_line = /* Beginning line for this entry. */ "# BEGIN s2Member GZIP exclusions";
305
+ $end_line = /* Identifying end line for this entry. */ "# END s2Member GZIP exclusions";
306
+ $htaccess = /* Location of this `.htaccess` file. */ ABSPATH.".htaccess";
307
+ /**/
308
+ if(file_exists($htaccess) && is_readable($htaccess) && ($htaccess_contents = file_get_contents($htaccess)) !== false && is_string($htaccess_contents = trim($htaccess_contents)))
309
+ return preg_match("/".preg_quote($start_line, "/")."[\r\n]+.*?[\r\n]+".preg_quote($end_line, "/")."[\r\n]{0,2}/is", $htaccess_contents);
310
+ /**/
311
+ return /* Default return `false`. */ false;
312
+ }
313
+ /**
314
+ * Writes no GZIP rules into root `.htaccess` file.
315
+ *
316
+ * @package s2Member\Files
317
+ * @since 120212
318
+ *
319
+ * @return bool True if successfull, else false on any type of failure.
320
+ */
321
+ public static function write_no_gzip_into_root_htaccess()
322
+ {
323
+ if(c_ws_plugin__s2member_files::remove_no_gzip_from_root_htaccess() /* Must first be able to remove any existing entry. */)
324
+ {
325
+ $start_line = /* Beginning line for this entry. */ "# BEGIN s2Member GZIP exclusions";
326
+ $end_line = /* Identifying end line for this entry. */ "# END s2Member GZIP exclusions";
327
+ $htaccess = /* Location of this `.htaccess` file we need to write in. */ ABSPATH.".htaccess";
328
+ $ideally_position_before = /* Ideally, we can position before this entry. */ "# BEGIN WordPress";
329
+ /**/
330
+ $no_gzip = $start_line."\n".trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_no_gzip_htaccess"])))."\n".$end_line;
331
+ /**/
332
+ if(file_exists($htaccess) && is_readable($htaccess) && is_writable($htaccess) && ($htaccess_contents = file_get_contents($htaccess)) !== false && is_string($htaccess_contents = trim($htaccess_contents)))
333
+ {
334
+ if(stripos /* If we can position in the ideal location, that's awesome. Let's do that now. */($htaccess_contents, $ideally_position_before) !== false)
335
+ $htaccess_contents = trim(str_ireplace($ideally_position_before, $no_gzip."\n\n".$ideally_position_before, $htaccess_contents));
336
+ /**/
337
+ else /* Else, let's put it at the very top of the file by default. */
338
+ $htaccess_contents = trim($no_gzip."\n\n".$htaccess_contents);
339
+ /**/
340
+ return file_put_contents($htaccess, $htaccess_contents);
341
+ }
342
+ else if(!file_exists($htaccess) && is_writable(dirname($htaccess)))
343
+ {
344
+ return file_put_contents($htaccess, $no_gzip);
345
+ }
346
+ }
347
+ return /* Default return `false`. */ false;
348
+ }
349
+ /**
350
+ * Removes no GZIP rules in root `.htaccess` file.
351
+ *
352
+ * @package s2Member\Files
353
+ * @since 120212
354
+ *
355
+ * @return bool True if successfull, else false on any type of failure.
356
+ */
357
+ public static function remove_no_gzip_from_root_htaccess()
358
+ {
359
+ $start_line = /* Beginning line for this entry. */ "# BEGIN s2Member GZIP exclusions";
360
+ $end_line = /* Identifying end line for this entry. */ "# END s2Member GZIP exclusions";
361
+ $htaccess = /* Location of this `.htaccess` file we need to write in. */ ABSPATH.".htaccess";
362
+ /**/
363
+ if(file_exists($htaccess) && is_readable($htaccess) && is_writable($htaccess) && ($htaccess_contents = file_get_contents($htaccess)) !== false && is_string($htaccess_contents = trim($htaccess_contents)))
364
+ {
365
+ $htaccess_contents = trim(preg_replace("/".preg_quote($start_line, "/")."[\r\n]+.*?[\r\n]+".preg_quote($end_line, "/")."[\r\n]{0,2}/is", "", $htaccess_contents));
366
+ /**/
367
+ return /* Check for `false`, because this could return `0` if the file is now empty. */ (file_put_contents($htaccess, $htaccess_contents) !== false);
368
+ }
369
+ else if(!file_exists($htaccess) /* Return `true` here, we're OK. */)
370
+ {
371
+ return true;
372
+ }
373
+ return /* Default return `false`. */ false;
374
  }
375
  }
376
  }
includes/classes/installation.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Installation
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_installation"))
21
  {
22
  /**
23
  * Installation routines for s2Member.
@@ -35,108 +35,108 @@ if (!class_exists ("c_ws_plugin__s2member_installation"))
35
  *
36
  * @return null
37
  */
38
- public static function activate ($reactivation_reason = FALSE)
39
  {
40
  global $wpdb; /* Global database object reference. */
41
  global $current_site, $current_blog; /* Multisite. */
42
  /**/
43
- do_action ("ws_plugin__s2member_before_activation", get_defined_vars ());
44
  /**/
45
- c_ws_plugin__s2member_roles_caps::config_roles (); /* Config Roles/Caps. */
46
- update_option ("ws_plugin__s2member_activated_levels", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]);
47
  /**/
48
- if (!is_dir ($files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]))
49
- if (is_writable (dirname (c_ws_plugin__s2member_utils_dirs::strip_dir_app_data ($files_dir))))
50
- mkdir ($files_dir, 0777, true);
51
  /**/
52
- if (is_dir ($files_dir) && is_writable ($files_dir))
53
- if (!file_exists ($htaccess = $files_dir . "/.htaccess") || !apply_filters ("ws_plugin__s2member_preserve_files_dir_htaccess", false, get_defined_vars ()))
54
- file_put_contents ($htaccess, trim (c_ws_plugin__s2member_utilities::evl (file_get_contents ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir_htaccess"]))));
55
  /**/
56
- if (!is_dir ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
57
- if (is_writable (dirname (c_ws_plugin__s2member_utils_dirs::strip_dir_app_data ($logs_dir))))
58
- mkdir ($logs_dir, 0777, true);
59
  /**/
60
- if (is_dir ($logs_dir) && is_writable ($logs_dir))
61
- if (!file_exists ($htaccess = $logs_dir . "/.htaccess") || !apply_filters ("ws_plugin__s2member_preserve_logs_dir_htaccess", false, get_defined_vars ()))
62
- file_put_contents ($htaccess, trim (c_ws_plugin__s2member_utilities::evl (file_get_contents ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir_htaccess"]))));
63
  /**/
64
- (!is_array (get_option ("ws_plugin__s2member_cache"))) ? update_option ("ws_plugin__s2member_cache", array ()) : null;
65
- (!is_array (get_option ("ws_plugin__s2member_notices"))) ? update_option ("ws_plugin__s2member_notices", array ()) : null;
66
- (!is_array (get_option ("ws_plugin__s2member_options"))) ? update_option ("ws_plugin__s2member_options", array ()) : null;
67
- (!is_numeric (get_option ("ws_plugin__s2member_configured"))) ? update_option ("ws_plugin__s2member_configured", "0") : null;
68
  /**/
69
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"]) /* If we are re-activating. */
 
 
 
 
 
70
  {
71
- $v = get_option ("ws_plugin__s2member_activated_version"); /* Currently. */
72
  /**/
73
- if (!$v || !version_compare ($v, "3.2", ">=")) /* Needs to be upgraded? */
74
  /* Version 3.2 is where `meta_key` names were changed. They're prefixed now. */
75
  {
76
  $like = "`meta_key` LIKE 's2member\_%' AND `meta_key` NOT LIKE '%s2member\_originating\_blog%'";
77
- $wpdb->query ("UPDATE `" . $wpdb->usermeta . "` SET `meta_key` = CONCAT('" . $wpdb->prefix . "', `meta_key`) WHERE " . $like);
78
  }
79
  /**/
80
- if (!$v || !version_compare ($v, "3.2.5", ">=")) /* Needs to be upgraded? */
81
  /* Version 3.2.5 is where transient names were changed. They're prefixed now. */
82
  {
83
- $wpdb->query ("DELETE FROM `" . $wpdb->options . "` WHERE `option_name` LIKE '\_transient\_%'");
84
  }
85
  /**/
86
- if (!$v || !version_compare ($v, "3.2.6", ">=")) /* Needs to be upgraded? */
87
  /* Version 3.2.6 fixed `s2member_ccaps_req` being stored empty and/or w/ one empty element in the array. */
88
  {
89
- $wpdb->query ("DELETE FROM `" . $wpdb->postmeta . "` WHERE `meta_key` = 's2member_ccaps_req' AND `meta_value` IN('','a:0:{}','a:1:{i:0;s:0:\"\";}')");
90
  }
91
  /**/
92
- if (!$v || !version_compare ($v, "110912", ">=") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["filter_wp_query"] === array ("all"))
93
  /* s2Member v110912 changed the way the "all" option for Alternative Views was handled. */
94
  {
95
  $notice = '<strong>IMPORTANT:</strong> This version of s2Member® changes the way your <code>Alternative View Protections</code> work. Please review your options under: <code>s2Member -> Restriction Options -> Alternative View Protections</code>.<br />';
96
- c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, array ("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
97
  }
98
  /**/
99
- $notice = '<strong>s2Member</strong> has been <strong>reactivated</strong>, with ' . (($reactivation_reason === "levels") ? '<code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) . '</code> Membership Levels' : 'the latest version') . '.<br />';
100
- $notice .= 'You now have version ' . esc_html (WS_PLUGIN__S2MEMBER_VERSION) . '. Your existing configuration remains.';
101
  /**/
102
- if (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ()) /* No Changelog on a Multisite Blog Farm. */
103
- $notice .= '<br />Have fun, <a href="' . esc_attr (admin_url ("/admin.php?page=ws-plugin--s2member-info#rm-changelog")) . '">read the Changelog</a>, and make some money! :-)';
104
  /**/
105
- c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, array ("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
106
  }
107
  else /* Otherwise (initial activation); we'll help the Site Owner out by giving them a link to the Quick Start Guide. */
108
  {
109
  $notice = '<strong>Note:</strong> s2Member adds some new data columns to your list of Users/Members. If your list gets overcrowded, please use the <strong>Screen Options</strong> tab <em>( upper right-hand corner )</em>. With WordPress® Screen Options, you can add/remove specific data columns; thereby making the most important data easier to read. For example, if you create Custom Registration/Profile Fields with s2Member, those Custom Fields will result in new data columns; which can cause your list of Users/Members to become nearly unreadable. So just use the Screen Options tab to clean things up.';
110
  /**/
111
- c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "blog:users.php", false, false, true);
112
  /**/
113
- $notice = '<strong>s2Member</strong> v' . esc_html (WS_PLUGIN__S2MEMBER_VERSION) . ' has been <strong>activated</strong>. Nice work!<br />';
114
- $notice .= 'Have fun, <a href="' . esc_attr (admin_url ("/admin.php?page=ws-plugin--s2member-start")) . '">read the Quick Start Guide</a>, and make some money! :-)';
115
  /**/
116
- c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, array ("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
117
  }
118
  /**/
119
- if (is_multisite () && is_main_site ()) /* Network activation routines. */
120
  {
121
- foreach ((array)($users = $wpdb->get_results ("SELECT `ID` FROM `" . $wpdb->users . "`")) as $user)
122
- if (!($originating_blog = get_user_meta ($user->ID, "s2member_originating_blog", true)))
123
- update_user_meta ($user->ID, "s2member_originating_blog", $current_site->blog_id);
124
  /**/
125
- $notice = '<strong>Multisite Network</strong> updated automatically by <strong>s2Member</strong> v' . esc_html (WS_PLUGIN__S2MEMBER_VERSION) . '.<br />';
126
  $notice .= 'You\'ll want to configure s2Member\'s Multisite options now.<br />';
127
  $notice .= 'In the Dashboard for your Main Site, see:<br />';
128
  $notice .= '<code>s2Member -> Multisite ( Config )</code>.';
129
  /**/
130
- c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, array ("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
131
  /**/
132
- update_site_option ("ws_plugin__s2member_options", (array)get_option ("ws_plugin__s2member_options"));
133
  /**/
134
- update_option ("ws_plugin__s2member_activated_mms_version", WS_PLUGIN__S2MEMBER_VERSION);
135
  }
136
  /**/
137
- update_option ("ws_plugin__s2member_activated_version", WS_PLUGIN__S2MEMBER_VERSION);
138
  /**/
139
- do_action ("ws_plugin__s2member_after_activation", get_defined_vars ());
140
  /**/
141
  return; /* Return for uniformity. */
142
  }
@@ -148,34 +148,36 @@ if (!class_exists ("c_ws_plugin__s2member_installation"))
148
  *
149
  * @return null
150
  */
151
- public static function deactivate ()
152
  {
153
  global $wpdb; /* Global database object reference. */
154
  global $current_site, $current_blog; /* Multisite. */
155
  /**/
156
- do_action ("ws_plugin__s2member_before_deactivation", get_defined_vars ());
157
  /**/
158
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"])
159
  {
160
- c_ws_plugin__s2member_roles_caps::unlink_roles (); /* Unlink Roles/Caps. */
 
 
161
  /**/
162
- if (is_dir ($files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]))
163
  {
164
- if (file_exists ($htaccess = $files_dir . "/.htaccess"))
165
- if (is_writable ($htaccess))
166
  unlink($htaccess);
167
  /**/
168
- @rmdir($files_dir) . @rmdir (c_ws_plugin__s2member_utils_dirs::strip_dir_app_data ($files_dir));
169
  }
170
  /**/
171
- if (is_dir ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
172
  {
173
- foreach (scandir ($logs_dir) as $log_file)
174
- if (is_file ($log_file = $logs_dir . "/" . $log_file))
175
- if (is_writable ($log_file))
176
  unlink($log_file);
177
  /**/
178
- @rmdir($logs_dir) . @rmdir (c_ws_plugin__s2member_utils_dirs::strip_dir_app_data ($logs_dir));
179
  }
180
  /**/
181
  delete_option("ws_plugin__s2member_cache");
@@ -186,19 +188,19 @@ if (!class_exists ("c_ws_plugin__s2member_installation"))
186
  delete_option("ws_plugin__s2member_activated_version");
187
  delete_option("ws_plugin__s2member_activated_mms_version");
188
  /**/
189
- if (is_multisite () && is_main_site ()) /* Site options? */
190
  delete_site_option("ws_plugin__s2member_options");
191
  /**/
192
- $wpdb->query ("DELETE FROM `" . $wpdb->options . "` WHERE `option_name` LIKE '%" . esc_sql (like_escape ("s2member_")) . "%'");
193
- $wpdb->query ("DELETE FROM `" . $wpdb->options . "` WHERE `option_name` LIKE '" . esc_sql (like_escape ("_transient_s2m_")) . "%'");
194
- $wpdb->query ("DELETE FROM `" . $wpdb->options . "` WHERE `option_name` LIKE '" . esc_sql (like_escape ("_transient_timeout_s2m_")) . "%'");
195
- $wpdb->query ("DELETE FROM `" . $wpdb->postmeta . "` WHERE `meta_key` LIKE '%" . esc_sql (like_escape ("s2member_")) . "%'");
196
- $wpdb->query ("DELETE FROM `" . $wpdb->usermeta . "` WHERE `meta_key` LIKE '%" . esc_sql (like_escape ("s2member_")) . "%'");
197
  /**/
198
- do_action ("ws_plugin__s2member_during_deactivation", get_defined_vars ());
199
  }
200
  /**/
201
- do_action ("ws_plugin__s2member_after_deactivation", get_defined_vars ());
202
  /**/
203
  return; /* Return for uniformity. */
204
  }
14
  * @package s2Member\Installation
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_installation"))
21
  {
22
  /**
23
  * Installation routines for s2Member.
35
  *
36
  * @return null
37
  */
38
+ public static function activate($reactivation_reason = FALSE)
39
  {
40
  global $wpdb; /* Global database object reference. */
41
  global $current_site, $current_blog; /* Multisite. */
42
  /**/
43
+ do_action("ws_plugin__s2member_before_activation", get_defined_vars());
44
  /**/
45
+ c_ws_plugin__s2member_roles_caps::config_roles(); /* Config Roles/Caps. */
46
+ update_option("ws_plugin__s2member_activated_levels", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]);
47
  /**/
48
+ if(!is_dir($files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]))
49
+ if(is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($files_dir))))
50
+ mkdir($files_dir, 0777, true);
51
  /**/
52
+ if(is_dir($files_dir) && is_writable($files_dir))
53
+ if(!file_exists($htaccess = $files_dir."/.htaccess") || !apply_filters("ws_plugin__s2member_preserve_files_dir_htaccess", false, get_defined_vars()))
54
+ file_put_contents($htaccess, trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir_htaccess"]))));
55
  /**/
56
+ c_ws_plugin__s2member_files::write_no_gzip_into_root_htaccess /* Handle the root `.htaccess` file as well now, for GZIP exclusions. */();
 
 
57
  /**/
58
+ if(!is_dir($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
59
+ if(is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($logs_dir))))
60
+ mkdir($logs_dir, 0777, true);
61
  /**/
62
+ if(is_dir($logs_dir) && is_writable($logs_dir))
63
+ if(!file_exists($htaccess = $logs_dir."/.htaccess") || !apply_filters("ws_plugin__s2member_preserve_logs_dir_htaccess", false, get_defined_vars()))
64
+ file_put_contents($htaccess, trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir_htaccess"]))));
 
65
  /**/
66
+ (!is_array(get_option("ws_plugin__s2member_cache"))) ? update_option("ws_plugin__s2member_cache", array()) : null;
67
+ (!is_array(get_option("ws_plugin__s2member_notices"))) ? update_option("ws_plugin__s2member_notices", array()) : null;
68
+ (!is_array(get_option("ws_plugin__s2member_options"))) ? update_option("ws_plugin__s2member_options", array()) : null;
69
+ (!is_numeric(get_option("ws_plugin__s2member_configured"))) ? update_option("ws_plugin__s2member_configured", "0") : null;
70
+ /**/
71
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"]) /* If we are re-activating. */
72
  {
73
+ $v = get_option("ws_plugin__s2member_activated_version"); /* Currently. */
74
  /**/
75
+ if(!$v || !version_compare($v, "3.2", ">=")) /* Needs to be upgraded? */
76
  /* Version 3.2 is where `meta_key` names were changed. They're prefixed now. */
77
  {
78
  $like = "`meta_key` LIKE 's2member\_%' AND `meta_key` NOT LIKE '%s2member\_originating\_blog%'";
79
+ $wpdb->query("UPDATE `".$wpdb->usermeta."` SET `meta_key` = CONCAT('".$wpdb->prefix."', `meta_key`) WHERE ".$like);
80
  }
81
  /**/
82
+ if(!$v || !version_compare($v, "3.2.5", ">=")) /* Needs to be upgraded? */
83
  /* Version 3.2.5 is where transient names were changed. They're prefixed now. */
84
  {
85
+ $wpdb->query("DELETE FROM `".$wpdb->options."` WHERE `option_name` LIKE '\_transient\_%'");
86
  }
87
  /**/
88
+ if(!$v || !version_compare($v, "3.2.6", ">=")) /* Needs to be upgraded? */
89
  /* Version 3.2.6 fixed `s2member_ccaps_req` being stored empty and/or w/ one empty element in the array. */
90
  {
91
+ $wpdb->query("DELETE FROM `".$wpdb->postmeta."` WHERE `meta_key` = 's2member_ccaps_req' AND `meta_value` IN('','a:0:{}','a:1:{i:0;s:0:\"\";}')");
92
  }
93
  /**/
94
+ if(!$v || !version_compare($v, "110912", ">=") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["filter_wp_query"] === array("all"))
95
  /* s2Member v110912 changed the way the "all" option for Alternative Views was handled. */
96
  {
97
  $notice = '<strong>IMPORTANT:</strong> This version of s2Member® changes the way your <code>Alternative View Protections</code> work. Please review your options under: <code>s2Member -> Restriction Options -> Alternative View Protections</code>.<br />';
98
+ c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, array("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
99
  }
100
  /**/
101
+ $notice = '<strong>s2Member</strong> has been <strong>reactivated</strong>, with '.(($reactivation_reason === "levels") ? '<code>'.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]).'</code> Membership Levels' : 'the latest version').'.<br />';
102
+ $notice .= 'You now have version '.esc_html(WS_PLUGIN__S2MEMBER_VERSION).'. Your existing configuration remains.';
103
  /**/
104
+ if(!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) /* No Changelog on a Multisite Blog Farm. */
105
+ $notice .= '<br />Have fun, <a href="'.esc_attr(admin_url("/admin.php?page=ws-plugin--s2member-info#rm-changelog")).'">read the Changelog</a>, and make some money! :-)';
106
  /**/
107
+ c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, array("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
108
  }
109
  else /* Otherwise (initial activation); we'll help the Site Owner out by giving them a link to the Quick Start Guide. */
110
  {
111
  $notice = '<strong>Note:</strong> s2Member adds some new data columns to your list of Users/Members. If your list gets overcrowded, please use the <strong>Screen Options</strong> tab <em>( upper right-hand corner )</em>. With WordPress® Screen Options, you can add/remove specific data columns; thereby making the most important data easier to read. For example, if you create Custom Registration/Profile Fields with s2Member, those Custom Fields will result in new data columns; which can cause your list of Users/Members to become nearly unreadable. So just use the Screen Options tab to clean things up.';
112
  /**/
113
+ c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "blog:users.php", false, false, true);
114
  /**/
115
+ $notice = '<strong>s2Member</strong> v'.esc_html(WS_PLUGIN__S2MEMBER_VERSION).' has been <strong>activated</strong>. Nice work!<br />';
116
+ $notice .= 'Have fun, <a href="'.esc_attr(admin_url("/admin.php?page=ws-plugin--s2member-start")).'">read the Quick Start Guide</a>, and make some money! :-)';
117
  /**/
118
+ c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, array("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
119
  }
120
  /**/
121
+ if(is_multisite() && is_main_site()) /* Network activation routines. */
122
  {
123
+ $wpdb->query("INSERT INTO `".$wpdb->usermeta."` (`user_id`, `meta_key`, `meta_value`) SELECT `ID`, 's2member_originating_blog', '".esc_sql($current_site->blog_id)."' FROM `".$wpdb->users."` WHERE `ID` NOT IN (SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE `meta_key` = 's2member_originating_blog')");
 
 
124
  /**/
125
+ $notice = '<strong>Multisite Network</strong> updated automatically by <strong>s2Member</strong> v'.esc_html(WS_PLUGIN__S2MEMBER_VERSION).'.<br />';
126
  $notice .= 'You\'ll want to configure s2Member\'s Multisite options now.<br />';
127
  $notice .= 'In the Dashboard for your Main Site, see:<br />';
128
  $notice .= '<code>s2Member -> Multisite ( Config )</code>.';
129
  /**/
130
+ c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, array("blog|network:plugins.php", "blog|network:ws-plugin--s2member-start", "blog|network:ws-plugin--s2member-mms-ops", "blog|network:ws-plugin--s2member-gen-ops", "blog|network:ws-plugin--s2member-res-ops"));
131
  /**/
132
+ update_site_option("ws_plugin__s2member_options", (array)get_option("ws_plugin__s2member_options"));
133
  /**/
134
+ update_option("ws_plugin__s2member_activated_mms_version", WS_PLUGIN__S2MEMBER_VERSION);
135
  }
136
  /**/
137
+ update_option("ws_plugin__s2member_activated_version", WS_PLUGIN__S2MEMBER_VERSION);
138
  /**/
139
+ do_action("ws_plugin__s2member_after_activation", get_defined_vars());
140
  /**/
141
  return; /* Return for uniformity. */
142
  }
148
  *
149
  * @return null
150
  */
151
+ public static function deactivate()
152
  {
153
  global $wpdb; /* Global database object reference. */
154
  global $current_site, $current_blog; /* Multisite. */
155
  /**/
156
+ do_action("ws_plugin__s2member_before_deactivation", get_defined_vars());
157
  /**/
158
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"])
159
  {
160
+ c_ws_plugin__s2member_roles_caps::unlink_roles(); /* Unlink Roles/Caps. */
161
+ /**/
162
+ c_ws_plugin__s2member_files::remove_no_gzip_from_root_htaccess /* Remove GZIP exclusions. */();
163
  /**/
164
+ if(is_dir($files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]))
165
  {
166
+ if(file_exists($htaccess = $files_dir."/.htaccess"))
167
+ if(is_writable($htaccess))
168
  unlink($htaccess);
169
  /**/
170
+ @rmdir($files_dir).@rmdir(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($files_dir));
171
  }
172
  /**/
173
+ if(is_dir($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
174
  {
175
+ foreach(scandir($logs_dir) as $log_file)
176
+ if(is_file($log_file = $logs_dir."/".$log_file))
177
+ if(is_writable($log_file))
178
  unlink($log_file);
179
  /**/
180
+ @rmdir($logs_dir).@rmdir(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($logs_dir));
181
  }
182
  /**/
183
  delete_option("ws_plugin__s2member_cache");
188
  delete_option("ws_plugin__s2member_activated_version");
189
  delete_option("ws_plugin__s2member_activated_mms_version");
190
  /**/
191
+ if(is_multisite() && is_main_site()) /* Site options? */
192
  delete_site_option("ws_plugin__s2member_options");
193
  /**/
194
+ $wpdb->query("DELETE FROM `".$wpdb->options."` WHERE `option_name` LIKE '%".esc_sql(like_escape("s2member_"))."%'");
195
+ $wpdb->query("DELETE FROM `".$wpdb->options."` WHERE `option_name` LIKE '".esc_sql(like_escape("_transient_s2m_"))."%'");
196
+ $wpdb->query("DELETE FROM `".$wpdb->options."` WHERE `option_name` LIKE '".esc_sql(like_escape("_transient_timeout_s2m_"))."%'");
197
+ $wpdb->query("DELETE FROM `".$wpdb->postmeta."` WHERE `meta_key` LIKE '%".esc_sql(like_escape("s2member_"))."%'");
198
+ $wpdb->query("DELETE FROM `".$wpdb->usermeta."` WHERE `meta_key` LIKE '%".esc_sql(like_escape("s2member_"))."%'");
199
  /**/
200
+ do_action("ws_plugin__s2member_during_deactivation", get_defined_vars());
201
  }
202
  /**/
203
+ do_action("ws_plugin__s2member_after_deactivation", get_defined_vars());
204
  /**/
205
  return; /* Return for uniformity. */
206
  }
includes/classes/login-customizations.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Login_Customizations
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_login_customizations"))
21
  {
22
  /**
23
  * Login customizations.
@@ -38,13 +38,13 @@ if (!class_exists ("c_ws_plugin__s2member_login_customizations"))
38
  * @param str $url Expects a login header URL passed in by the Filter.
39
  * @return str A URL based on s2Member's UI configuration.
40
  */
41
- public static function login_header_url ($url = FALSE)
42
  {
43
- do_action ("ws_plugin__s2member_before_login_header_url", get_defined_vars ());
44
  /**/
45
  $url = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"];
46
  /**/
47
- return apply_filters ("ws_plugin__s2member_login_header_url", $url, get_defined_vars ());
48
  }
49
  /**
50
  * Filters the login/registration logo title.
@@ -57,13 +57,13 @@ if (!class_exists ("c_ws_plugin__s2member_login_customizations"))
57
  * @param str $title Expects a title passed in by the Filter.
58
  * @return str A title based on s2Member's UI configuration.
59
  */
60
- public static function login_header_title ($title = FALSE)
61
  {
62
- do_action ("ws_plugin__s2member_before_login_header_title", get_defined_vars ());
63
  /**/
64
  $title = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"];
65
  /**/
66
- return apply_filters ("ws_plugin__s2member_login_header_title", $title, get_defined_vars ());
67
  }
68
  /**
69
  * Styles login/registration *( i.e. `/wp-login.php` )*.
@@ -75,72 +75,71 @@ if (!class_exists ("c_ws_plugin__s2member_login_customizations"))
75
  *
76
  * @return void
77
  */
78
- public static function login_header_styles ()
79
  {
80
  $s = ""; /* Initialize styles string here to give Hooks a chance. */
81
- $a = array (); /* Initialize here to give Filters a chance. */
82
  /**/
83
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
84
- do_action ("ws_plugin__s2member_before_login_header_styles", get_defined_vars ());
85
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
86
  /**/
87
  $a[] = '<style type="text/css">'; /* Open style tag, then give Filters a chance below. */
88
- $i = apply_filters ("ws_plugin__s2member_login_header_styles_important", " !important", get_defined_vars ());
89
- $a = apply_filters ("ws_plugin__s2member_login_header_styles_array_after_open", $a, get_defined_vars ());
90
  /**/
91
- $a[] = 'html, body { border:0' . $i . '; background:none' . $i . '; }'; /* Clear existing. */
92
- $a[] = 'html { background-color:#' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . $i . '; }';
93
- $a[] = 'html { background-image:url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"] . ')' . $i . '; }';
94
- $a[] = 'html { background-repeat:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image_repeat"] . $i . '; }';
95
  /**/
96
- $a[] = 'body, body * { font-size:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_size"] . $i . '; }';
97
- $a[] = 'body, body * { font-family:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_family"] . $i . '; }';
98
  /**/
99
- $a[] = 'div#login { width:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"] . 'px' . $i . '; }';
100
- $a[] = 'div#login h1 a { background:url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"] . ') no-repeat top center' . $i . '; }';
101
- $a[] = 'div#login h1 a { display:block' . $i . '; width:100%' . $i . '; height:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"] . 'px' . $i . '; }';
102
  /**/
103
- $a[] = '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"] . $i . '; -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"] . $i . '; 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"] . $i . '; }';
104
  /**/
105
- $a[] = '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"] . $i . '; text-shadow:1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . $i . '; }';
106
- $a[] = 'div#login p#backtoblog, div#login p#backtoblog a, div#login p#backtoblog a:hover, div#login p#backtoblog a:active, div#login p#backtoblog a:focus { color:#' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . $i . '; text-shadow:1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . $i . '; }';
107
  /**/
108
- $a[] = 'div#login form p { margin:2px 0 16px 0' . $i . '; }'; /* Handles paragraph margins inside the form. */
109
- $a[] = 'div#login form input[type="text"], div#login form input[type="email"], div#login form input[type="password"], div#login form textarea, div#login form select { font-weight:normal' . $i . '; color:#333333' . $i . '; background:none repeat scroll 0 0 #FBFBFB' . $i . '; border:1px solid #E5E5E5' . $i . '; font-size:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_field_size"] . $i . '; margin:0' . $i . '; padding:3px' . $i . '; -moz-border-radius:3px' . $i . '; -webkit-border-radius:3px' . $i . '; border-radius:3px' . $i . '; width:100%' . $i . '; width:98%' . $i . ' !ie<8; margin-right:2%' . $i . ' !ie<8; box-sizing:border-box' . $i . '; -ms-box-sizing:border-box' . $i . '; -moz-box-sizing:border-box' . $i . '; -webkit-box-sizing:border-box' . $i . '; }';
110
- $a[] = 'div#login form select { width:99.5%' . $i . ' !ie<8; } div#login form select > option { font-size:' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_field_size"] . $i . '; }';
111
- $a[] = 'div#login form label { cursor:pointer' . $i . '; } div#login form label.ws-plugin--s2member-custom-reg-field-op-l { opacity:0.7' . $i . '; font-size:90%' . $i . '; vertical-align:middle' . $i . '; }';
112
- $a[] = 'div#login form input[type="checkbox"], div#login form input[type="radio"] { margin:0 3px 0 0' . $i . '; vertical-align:middle' . $i . '; }';
113
- $a[] = 'div#login form input#ws-plugin--s2member-custom-reg-field-user-pass2[type="password"] { margin-top:5px' . $i . '; }';
114
  /**/
115
- $a[] = 'div#login form div.ws-plugin--s2member-custom-reg-field-divider-section { margin:2px 0 16px 0' . $i . '; border:0' . $i . '; height:1px' . $i . '; line-height:1px' . $i . '; background:#CCCCCC' . $i . '; }';
116
- $a[] = 'div#login form div.ws-plugin--s2member-custom-reg-field-divider-section-title { margin:2px 0 16px 0' . $i . '; border:0 solid #CCCCCC' . $i . '; border-width:0 0 1px 0' . $i . '; padding:0 0 10px 0' . $i . '; font-size:110%' . $i . '; }';
117
  /**/
118
- $a[] = 'div#login form p.submit { margin-bottom:0' . $i . '; }';
119
- $a[] = '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:#666666' . $i . '; text-shadow:2px 2px 5px #EEEEEE' . $i . '; border:1px solid #999999' . $i . '; background:#FBFBFB' . $i . '; padding:5px' . $i . '; -moz-border-radius:3px' . $i . '; -webkit-border-radius:3px' . $i . '; border-radius:3px' . $i . '; }';
120
- $a[] = 'div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color:#000000' . $i . '; text-shadow:2px 2px 5px #CCCCCC' . $i . '; border-color:#000000' . $i . '; }';
121
- $a[] = 'div#login form#registerform { padding-bottom:16px' . $i . '; } div#login form#registerform p.submit { float:none' . $i . '; margin-top:-10px' . $i . '; } div#login form#registerform input[type="submit"] { float:none' . $i . '; width:100%' . $i . '; width:98%' . $i . ' !ie<8; margin-right:2%' . $i . ' !ie<8; box-sizing:border-box' . $i . '; -ms-box-sizing:border-box' . $i . '; -moz-box-sizing:border-box' . $i . '; -webkit-box-sizing:border-box' . $i . '; }';
122
- $a[] = 'div#login form#lostpasswordform { padding-bottom:16px' . $i . '; } div#login form#lostpasswordform p.submit { float:none' . $i . '; } div#login form#lostpasswordform input[type="submit"] { float:none' . $i . '; width:100%' . $i . '; width:98%' . $i . ' !ie<8; margin-right:2%' . $i . ' !ie<8; box-sizing:border-box' . $i . '; -ms-box-sizing:border-box' . $i . '; -moz-box-sizing:border-box' . $i . '; -webkit-box-sizing:border-box' . $i . '; }';
123
  /**/
124
- $a[] = 'div.ws-plugin--s2member-password-strength { margin-top:3px' . $i . '; font-color:#000000' . $i . '; background-color:#EEEEEE' . $i . '; padding:3px' . $i . '; -moz-border-radius:3px' . $i . '; -webkit-border-radius:3px' . $i . '; border-radius:3px' . $i . '; } div.ws-plugin--s2member-password-strength-short { background-color:#FFA0A0' . $i . '; } div.ws-plugin--s2member-password-strength-bad { background-color:#FFB78C' . $i . '; } div.ws-plugin--s2member-password-strength-good { background-color:#FFEC8B' . $i . '; } div.ws-plugin--s2member-password-strength-strong { background-color:#C3FF88' . $i . '; } div.ws-plugin--s2member-password-strength-mismatch { background-color:#D6C1AB' . $i . '; }';
125
  /**/
126
- $a[] = 'div#login form#registerform p#reg_passmail { font-style:italic' . $i . '; }';
127
  /**/
128
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
129
- $a[] = 'p#reg_passmail { display:none' . $i . '; }';
130
  /**/
131
- $a = apply_filters ("ws_plugin__s2member_login_header_styles_array_before_close", $a, get_defined_vars ());
132
  $a[] = '</style>'; /* Now close style tag. There are other Filters below. */
133
  /**/
134
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
135
- do_action ("ws_plugin__s2member_during_login_header_styles", get_defined_vars ());
136
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
137
  /**/
138
- $a = apply_filters ("ws_plugin__s2member_login_header_styles_array", $a, get_defined_vars ());
139
- $s .= "\n" . implode ("\n", $a) . "\n\n"; /* Now put all array elements together. */
140
  /**/
141
- echo apply_filters ("ws_plugin__s2member_login_header_styles", $s, get_defined_vars ());
142
  /**/
143
- do_action ("ws_plugin__s2member_after_login_header_styles", get_defined_vars ());
144
  /**/
145
  return; /* Return for uniformity. */
146
  }
@@ -154,22 +153,22 @@ if (!class_exists ("c_ws_plugin__s2member_login_customizations"))
154
  *
155
  * @return void
156
  */
157
- public static function login_footer_design ()
158
  {
159
- do_action ("ws_plugin__s2member_before_login_footer_design", get_defined_vars ());
160
  /**/
161
- if (($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_footer_design"]))
162
  /**/
163
- if (is_multisite () && c_ws_plugin__s2member_utils_conds::is_multisite_farm () && !is_main_site ())
164
  {
165
- echo $code . "\n"; /* No PHP here. */
166
  }
167
  else /* Otherwise, safe to allow PHP code. */
168
  {
169
- eval("?>" . $code);
170
  }
171
  /**/
172
- do_action ("ws_plugin__s2member_after_login_footer_design", get_defined_vars ());
173
  /**/
174
  return; /* Return for uniformity. */
175
  }
14
  * @package s2Member\Login_Customizations
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_login_customizations"))
21
  {
22
  /**
23
  * Login customizations.
38
  * @param str $url Expects a login header URL passed in by the Filter.
39
  * @return str A URL based on s2Member's UI configuration.
40
  */
41
+ public static function login_header_url($url = FALSE)
42
  {
43
+ do_action("ws_plugin__s2member_before_login_header_url", get_defined_vars());
44
  /**/
45
  $url = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"];
46
  /**/
47
+ return apply_filters("ws_plugin__s2member_login_header_url", $url, get_defined_vars());
48
  }
49
  /**
50
  * Filters the login/registration logo title.
57
  * @param str $title Expects a title passed in by the Filter.
58
  * @return str A title based on s2Member's UI configuration.
59
  */
60
+ public static function login_header_title($title = FALSE)
61
  {
62
+ do_action("ws_plugin__s2member_before_login_header_title", get_defined_vars());
63
  /**/
64
  $title = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"];
65
  /**/
66
+ return apply_filters("ws_plugin__s2member_login_header_title", $title, get_defined_vars());
67
  }
68
  /**
69
  * Styles login/registration *( i.e. `/wp-login.php` )*.
75
  *
76
  * @return void
77
  */
78
+ public static function login_header_styles()
79
  {
80
  $s = ""; /* Initialize styles string here to give Hooks a chance. */
81
+ $a = array(); /* Initialize here to give Filters a chance. */
82
  /**/
83
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
84
+ do_action("ws_plugin__s2member_before_login_header_styles", get_defined_vars());
85
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
86
  /**/
87
  $a[] = '<style type="text/css">'; /* Open style tag, then give Filters a chance below. */
88
+ $i = apply_filters("ws_plugin__s2member_login_header_styles_important", " !important", get_defined_vars());
89
+ $a = apply_filters("ws_plugin__s2member_login_header_styles_array_after_open", $a, get_defined_vars());
90
  /**/
91
+ $a[] = 'html, body { border:0'.$i.'; background:none'.$i.'; }'; /* Clear existing. */
92
+ $a[] = 'html { background-color:#'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"].$i.'; }';
93
+ $a[] = 'html { background-image:url('.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"].')'.$i.'; }';
94
+ $a[] = 'html { background-repeat:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image_repeat"].$i.'; }';
95
  /**/
96
+ $a[] = 'body, body * { font-size:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_size"].$i.'; }';
97
+ $a[] = 'body, body * { font-family:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_family"].$i.'; }';
98
  /**/
99
+ $a[] = 'div#login { width:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"].'px'.$i.'; }';
100
+ $a[] = 'div#login h1 a { background:url('.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"].') no-repeat top center'.$i.'; }';
101
+ $a[] = 'div#login h1 a { display:block'.$i.'; width:100%'.$i.'; height:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"].'px'.$i.'; }';
102
  /**/
103
+ $a[] = '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"].$i.'; -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"].$i.'; 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"].$i.'; }';
104
  /**/
105
+ $a[] = '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"].$i.'; text-shadow:1px 1px 3px #'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"].$i.'; }';
106
+ $a[] = 'div#login p#backtoblog, div#login p#backtoblog a, div#login p#backtoblog a:hover, div#login p#backtoblog a:active, div#login p#backtoblog a:focus { color:#'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"].$i.'; text-shadow:1px 1px 3px #'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"].$i.'; }';
107
  /**/
108
+ $a[] = 'div#login form p { margin:2px 0 16px 0'.$i.'; }'; /* Handles paragraph margins inside the form. */
109
+ $a[] = 'div#login form input[type="text"], div#login form input[type="email"], div#login form input[type="password"], div#login form textarea, div#login form select { font-weight:normal'.$i.'; color:#333333'.$i.'; background:none repeat scroll 0 0 #FBFBFB'.$i.'; border:1px solid #E5E5E5'.$i.'; font-size:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_field_size"].$i.'; margin:0'.$i.'; padding:3px'.$i.'; -moz-border-radius:3px'.$i.'; -webkit-border-radius:3px'.$i.'; border-radius:3px'.$i.'; width:100%'.$i.'; width:98%'.$i.' !ie<8; margin-right:2%'.$i.' !ie<8; box-sizing:border-box'.$i.'; -ms-box-sizing:border-box'.$i.'; -moz-box-sizing:border-box'.$i.'; -webkit-box-sizing:border-box'.$i.'; }';
110
+ $a[] = 'div#login form select { width:99.5%'.$i.' !ie<8; } div#login form select > option { font-size:'.$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_font_field_size"].$i.'; }';
111
+ $a[] = 'div#login form label { cursor:pointer'.$i.'; } div#login form label.ws-plugin--s2member-custom-reg-field-op-l { opacity:0.7'.$i.'; font-size:90%'.$i.'; vertical-align:middle'.$i.'; }';
112
+ $a[] = 'div#login form input[type="checkbox"], div#login form input[type="radio"] { margin:0 3px 0 0'.$i.'; vertical-align:middle'.$i.'; }';
113
+ $a[] = 'div#login form input#ws-plugin--s2member-custom-reg-field-user-pass2[type="password"] { margin-top:5px'.$i.'; }';
114
  /**/
115
+ $a[] = 'div#login form div.ws-plugin--s2member-custom-reg-field-divider-section { margin:2px 0 16px 0'.$i.'; border:0'.$i.'; height:1px'.$i.'; line-height:1px'.$i.'; background:#CCCCCC'.$i.'; }';
116
+ $a[] = 'div#login form div.ws-plugin--s2member-custom-reg-field-divider-section-title { margin:2px 0 16px 0'.$i.'; border:0 solid #CCCCCC'.$i.'; border-width:0 0 1px 0'.$i.'; padding:0 0 10px 0'.$i.'; font-size:110%'.$i.'; }';
117
  /**/
118
+ $a[] = '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:#666666'.$i.'; text-shadow:2px 2px 5px #EEEEEE'.$i.'; border:1px solid #999999'.$i.'; background:#FBFBFB'.$i.'; padding:5px'.$i.'; -moz-border-radius:3px'.$i.'; -webkit-border-radius:3px'.$i.'; border-radius:3px'.$i.'; }';
119
+ $a[] = 'div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color:#000000'.$i.'; text-shadow:2px 2px 5px #CCCCCC'.$i.'; border-color:#000000'.$i.'; }';
120
+ $a[] = 'div#login form#registerform { padding-bottom:16px'.$i.'; } div#login form#registerform p.submit { float:none'.$i.'; margin-top:-10px'.$i.'; } div#login form#registerform input[type="submit"] { float:none'.$i.'; width:100%'.$i.'; width:98%'.$i.' !ie<8; margin-right:2%'.$i.' !ie<8; box-sizing:border-box'.$i.'; -ms-box-sizing:border-box'.$i.'; -moz-box-sizing:border-box'.$i.'; -webkit-box-sizing:border-box'.$i.'; }';
121
+ $a[] = 'div#login form#lostpasswordform { padding-bottom:16px'.$i.'; } div#login form#lostpasswordform p.submit { float:none'.$i.'; } div#login form#lostpasswordform input[type="submit"] { float:none'.$i.'; width:100%'.$i.'; width:98%'.$i.' !ie<8; margin-right:2%'.$i.' !ie<8; box-sizing:border-box'.$i.'; -ms-box-sizing:border-box'.$i.'; -moz-box-sizing:border-box'.$i.'; -webkit-box-sizing:border-box'.$i.'; }';
 
122
  /**/
123
+ $a[] = 'div.ws-plugin--s2member-password-strength { margin-top:3px'.$i.'; font-color:#000000'.$i.'; background-color:#EEEEEE'.$i.'; padding:3px'.$i.'; -moz-border-radius:3px'.$i.'; -webkit-border-radius:3px'.$i.'; border-radius:3px'.$i.'; } div.ws-plugin--s2member-password-strength-short { background-color:#FFA0A0'.$i.'; } div.ws-plugin--s2member-password-strength-bad { background-color:#FFB78C'.$i.'; } div.ws-plugin--s2member-password-strength-good { background-color:#FFEC8B'.$i.'; } div.ws-plugin--s2member-password-strength-strong { background-color:#C3FF88'.$i.'; } div.ws-plugin--s2member-password-strength-mismatch { background-color:#D6C1AB'.$i.'; }';
124
  /**/
125
+ $a[] = 'div#login form#registerform p#reg_passmail { font-style:italic'.$i.'; }';
126
  /**/
127
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
128
+ $a[] = 'p#reg_passmail { display:none'.$i.'; }';
129
  /**/
130
+ $a = apply_filters("ws_plugin__s2member_login_header_styles_array_before_close", $a, get_defined_vars());
131
  $a[] = '</style>'; /* Now close style tag. There are other Filters below. */
132
  /**/
133
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
134
+ do_action("ws_plugin__s2member_during_login_header_styles", get_defined_vars());
135
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
136
  /**/
137
+ $a = apply_filters("ws_plugin__s2member_login_header_styles_array", $a, get_defined_vars());
138
+ $s .= "\n".implode("\n", $a)."\n\n"; /* Now put all array elements together. */
139
  /**/
140
+ echo apply_filters("ws_plugin__s2member_login_header_styles", $s, get_defined_vars());
141
  /**/
142
+ do_action("ws_plugin__s2member_after_login_header_styles", get_defined_vars());
143
  /**/
144
  return; /* Return for uniformity. */
145
  }
153
  *
154
  * @return void
155
  */
156
+ public static function login_footer_design()
157
  {
158
+ do_action("ws_plugin__s2member_before_login_footer_design", get_defined_vars());
159
  /**/
160
+ if(($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_footer_design"]))
161
  /**/
162
+ if(is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site())
163
  {
164
+ echo $code."\n"; /* No PHP here. */
165
  }
166
  else /* Otherwise, safe to allow PHP code. */
167
  {
168
+ eval("?>".$code);
169
  }
170
  /**/
171
+ do_action("ws_plugin__s2member_after_login_footer_design", get_defined_vars());
172
  /**/
173
  return; /* Return for uniformity. */
174
  }
includes/classes/menu-pages.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Menu_Pages
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
21
  {
22
  /**
23
  * Administrative menu pages.
@@ -35,7 +35,7 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
35
  *
36
  * @var array
37
  */
38
- public static $pre_display_errors = array ();
39
  /**
40
  * Saves all options from any menu page.
41
  *
@@ -53,77 +53,77 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
53
  * @param bool $request_refresh Optional. Defaults to false. If true, resulting `success` notice will include a link to refresh the menu page.
54
  * @return bool True if all s2Member options were updated successfully, else false.
55
  */
56
- public static function update_all_options ($new_options = FALSE, $verified = FALSE, $update_other = TRUE, $display_notices = TRUE, $enqueue_notices = FALSE, $request_refresh = FALSE)
57
  {
58
  $updated_all_options = false; /* Initialize this to a value of false. Initializing this variable here makes it an available reference-variable to Hooks/Filters. */
59
  /**/
60
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
61
- do_action ("ws_plugin__s2member_before_update_all_options", get_defined_vars ()); /* If you use this Hook, be sure to use ``wp_verify_nonce()``. */
62
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
63
  /**/
64
- if ($verified || (!empty ($_POST["ws_plugin__s2member_options_save"]) && ($nonce = $_POST["ws_plugin__s2member_options_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-options-save")))
65
  {
66
  $options = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]; /* Acquire the full existing configuration options array here. */
67
  /**/
68
- $new_options = (is_array ($new_options)) ? $new_options : ((!empty ($_POST) && is_array ($_POST)) ? stripslashes_deep ($_POST) : array ());
69
- $new_options = c_ws_plugin__s2member_utils_strings::trim_deep ($new_options);
70
  /**/
71
- foreach ($new_options as $key => $value) /* Find all keys contained within ``$new_options`` matching `^ws_plugin__s2member_`. */
72
- if (strpos ($key, "ws_plugin__s2member_") === 0) /* A relevant ``$new_options`` key matching `^ws_plugin__s2member_`? */
73
  /**/
74
- if ($key === "ws_plugin__s2member_configured") /* s2Member is now configured ( according to these options )? */
75
- ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"] = $value) . update_option ("ws_plugin__s2member_configured", $value);
76
  /**/
77
- else if (!is_array ($value) || (is_array ($value) && /* Updating an array? */ array_shift ($value) === "update-signal"))
78
- $options[preg_replace ("/^" . preg_quote ("ws_plugin__s2member_", "/") . "/", "", $key)] = $value;
79
  /**/
80
- unset ($key, $value); /* Unset these utility variables now. This prevents bleeding vars into Hooks/Filters that are of no use. */
81
  /**/
82
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
83
- do_action ("ws_plugin__s2member_during_update_all_options", get_defined_vars ()); /* If you use this Hook, be sure to use ``wp_verify_nonce()``. */
84
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
85
  /**/
86
- $options = ws_plugin__s2member_configure_options_and_their_defaults (($options = array_merge ($options, array ("options_version" => (string)($options["options_version"] + 0.001)))));
87
- update_option ("ws_plugin__s2member_options", $options) . ((is_multisite () && is_main_site ()) ? update_site_option ("ws_plugin__s2member_options", $options) : null) . update_option ("ws_plugin__s2member_cache", array ());
88
  /**/
89
- if ($update_other === true || in_array ("auto_eot_system", (array)$update_other)) /* Handle the Auto-EOT System now ( enable/disable ). */
90
- ($options["auto_eot_system_enabled"] == 1) ? c_ws_plugin__s2member_auto_eots::add_auto_eot_system () : c_ws_plugin__s2member_auto_eots::delete_auto_eot_system ();
91
  /**/
92
- if (($display_notices === true || in_array ("success", (array)$display_notices)) && ($notice = '<strong>Options saved.' . (($request_refresh) ? ' Please <a href="' . esc_attr ($_SERVER["REQUEST_URI"]) . '">refresh</a>.' : '') . '</strong>'))
93
- ($enqueue_notices === true || in_array ("success", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*") : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice);
94
  /**/
95
- if (empty ($_GET["page"]) || $_GET["page"] !== "ws-plugin--s2member-mms-ops") /* Do NOT display page-conflict-warnings on the Main Multisite Configuration panel. */
96
  {
97
- if (!$options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>NOTE:</strong> s2Member security restrictions will NOT be enforced until you\'ve configured a Membership Options Page. See: <code>s2Member -> General Options -> Membership Options Page</code>.'))
98
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
99
  /**/
100
- if ($options["login_welcome_page"] && $options["login_welcome_page"] === $options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is the same as your Membership Options Page. Please correct this. See: <code>s2Member -> General Options -> Login Welcome Page</code>.'))
101
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
102
  /**/
103
- if ($options["membership_options_page"] && (string)get_option ("page_on_front") === $options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Membership Options Page is currently configured as your Home Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Membership Options Page</code>.'))
104
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
105
  /**/
106
- if ($options["login_welcome_page"] && (string)get_option ("page_on_front") === $options["login_welcome_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is currently configured as your Home Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Login Welcome Page</code>.'))
107
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
108
  /**/
109
- if ($options["membership_options_page"] && (string)get_option ("page_for_posts") === $options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Membership Options Page is currently configured as your Posts Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Membership Options Page</code>.'))
110
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
111
  /**/
112
- if ($options["login_welcome_page"] && (string)get_option ("page_for_posts") === $options["login_welcome_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is currently configured as your Posts Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Login Welcome Page</code>.'))
113
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
114
  /**/
115
- if ($options["file_download_limit_exceeded_page"] && $options["file_download_limit_exceeded_page"] === $options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Download Limit Exceeded Page is the same as your Membership Options Page. Please correct this. See: <code>s2Member -> Download Options</code>.'))
116
- ($enqueue_notices === true || in_array ("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice ($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice ($notice, true);
117
  }
118
  /**/
119
  $updated_all_options = true; /* Flag indicating this routine was processed successfully; and that all s2Member options have been updated successfully.*/
120
  }
121
  /**/
122
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
123
- do_action ("ws_plugin__s2member_after_update_all_options", get_defined_vars ()); /* If you use this Hook, be sure to use ``wp_verify_nonce()``. */
124
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
125
  /**/
126
- return apply_filters ("ws_plugin__s2member_update_all_options", (($updated_all_options) ? true : false), get_defined_vars ());
127
  }
128
  /**
129
  * Adds option menus / sub-menus.
@@ -135,89 +135,89 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
135
  *
136
  * @return null
137
  */
138
- public static function add_admin_options ()
139
  {
140
- do_action ("ws_plugin__s2member_before_add_admin_options", get_defined_vars ());
141
  /**/
142
- add_filter ("plugin_action_links", "c_ws_plugin__s2member_menu_pages::_add_settings_link", 10, 2);
143
  /**/
144
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_create_menu_items", true, get_defined_vars ()))
145
  {
146
- if ((is_multisite () && c_ws_plugin__s2member_utils_conds::is_multisite_farm () && !is_main_site ()) || apply_filters ("ws_plugin__s2member_during_add_admin_options_clear_right_side", false, get_defined_vars ()))
147
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu_pages"] = array (); /* Clear right side. */
148
  /**/
149
- $menu = apply_filters ("ws_plugin__s2member_during_add_admin_options_menu_slug", "ws-plugin--s2member-start", get_defined_vars ());
150
  /**/
151
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_menu_page", true, get_defined_vars ()))
152
- add_menu_page ("s2Member®", "s2Member®", "create_users", $menu, "c_ws_plugin__s2member_menu_pages::start_page", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images/brand-favicon.png");
153
  /**/
154
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_start_page", true, get_defined_vars ()))
155
- add_submenu_page ($menu, "s2Member Quick-Start Guide", "Quick-Start Guide", "create_users", "ws-plugin--s2member-start", "c_ws_plugin__s2member_menu_pages::start_page");
156
  /**/
157
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_divider_1", true, get_defined_vars ())) /* Divider. */
158
- add_submenu_page ($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
159
  /**/
160
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_mms_ops_page", (!is_multisite () || is_main_site ()), get_defined_vars ()))
161
- add_submenu_page ($menu, "s2Member Multisite Configuration", "Multisite (Config)", "create_users", "ws-plugin--s2member-mms-ops", "c_ws_plugin__s2member_menu_pages::mms_ops_page");
162
  /**/
163
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_gen_ops_page", true, get_defined_vars ()))
164
- add_submenu_page ($menu, "s2Member General Options", "General Options", "create_users", "ws-plugin--s2member-gen-ops", "c_ws_plugin__s2member_menu_pages::gen_ops_page");
165
  /**/
166
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_res_ops_page", true, get_defined_vars ()))
167
- add_submenu_page ($menu, "s2Member Restriction Options", "Restriction Options", "create_users", "ws-plugin--s2member-res-ops", "c_ws_plugin__s2member_menu_pages::res_ops_page");
168
  /**/
169
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_down_ops_page", (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ()), get_defined_vars ()))
170
- add_submenu_page ($menu, "s2Member Download Options", "Download Options", "create_users", "ws-plugin--s2member-down-ops", "c_ws_plugin__s2member_menu_pages::down_ops_page");
171
  /**/
172
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_divider_2", true, get_defined_vars ())) /* Divider. */
173
- add_submenu_page ($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
174
  /**/
175
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_new_user_page", true, get_defined_vars ())) /* Shortcut. */
176
- add_submenu_page ($menu, "s2Member / Add A Member", "Add A Member", "create_users", "user-new.php");
177
  /**/
178
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_browse_users_page", true, get_defined_vars ())) /* Shortcut. */
179
- add_submenu_page ($menu, "s2Member / Browse Members", "Browse Members", "create_users", "users.php");
180
  /**/
181
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_divider_3", true, get_defined_vars ())) /* Divider. */
182
- add_submenu_page ($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
183
  /**/
184
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_paypal_ops_page", true, get_defined_vars ()))
185
- add_submenu_page ($menu, "s2Member PayPal Options", "PayPal® Options", "create_users", "ws-plugin--s2member-paypal-ops", "c_ws_plugin__s2member_menu_pages::paypal_ops_page");
186
  /**/
187
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_paypal_buttons_page", true, get_defined_vars ()))
188
- add_submenu_page ($menu, "s2Member PayPal® Buttons", "PayPal® Buttons", "create_users", "ws-plugin--s2member-paypal-buttons", "c_ws_plugin__s2member_menu_pages::paypal_buttons_page");
189
  /**/
190
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_divider_4", true, get_defined_vars ())) /* Divider. */
191
- add_submenu_page ($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
192
  /**/
193
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_trk_ops_page", true, get_defined_vars ()))
194
- add_submenu_page ($menu, "s2Member API / Tracking", "API / Tracking", "create_users", "ws-plugin--s2member-trk-ops", "c_ws_plugin__s2member_menu_pages::trk_ops_page");
195
  /**/
196
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_els_ops_page", true, get_defined_vars ()))
197
- add_submenu_page ($menu, "s2Member API / List Servers", "API / List Servers", "create_users", "ws-plugin--s2member-els-ops", "c_ws_plugin__s2member_menu_pages::els_ops_page");
198
  /**/
199
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_api_ops_page", true, get_defined_vars ()))
200
- add_submenu_page ($menu, "s2Member API / Notifications", "API / Notifications", "create_users", "ws-plugin--s2member-api-ops", "c_ws_plugin__s2member_menu_pages::api_ops_page");
201
  /**/
202
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_scripting_page", true, get_defined_vars ()))
203
- add_submenu_page ($menu, "s2Member API / Scripting", "API / Scripting", "create_users", "ws-plugin--s2member-scripting", "c_ws_plugin__s2member_menu_pages::scripting_page");
204
  /**/
205
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_divider_5", true, get_defined_vars ())) /* Divider. */
206
- add_submenu_page ($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
207
  /**/
208
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_integrations_page", (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ()), get_defined_vars ()))
209
- add_submenu_page ($menu, "s2Member / Other Integrations", "Other Integrations", "create_users", "ws-plugin--s2member-integrations", "c_ws_plugin__s2member_menu_pages::integrations_page");
210
  /**/
211
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_divider_6", true, get_defined_vars ())) /* Divider. */
212
- add_submenu_page ($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
213
  /**/
214
- if (apply_filters ("ws_plugin__s2member_during_add_admin_options_add_info_page", (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ()), get_defined_vars ()))
215
- add_submenu_page ($menu, "s2Member Information", "s2Member Info", "create_users", "ws-plugin--s2member-info", "c_ws_plugin__s2member_menu_pages::info_page");
216
  /**/
217
- do_action ("ws_plugin__s2member_during_add_admin_options_additional_pages", get_defined_vars ());
218
  }
219
  /**/
220
- do_action ("ws_plugin__s2member_after_add_admin_options", get_defined_vars ());
221
  /**/
222
  return; /* Return for uniformity. */
223
  }
@@ -231,28 +231,28 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
231
  *
232
  * @return null
233
  */
234
- public static function add_network_admin_options ()
235
  {
236
- do_action ("ws_plugin__s2member_before_add_network_admin_options", get_defined_vars ());
237
  /**/
238
- if (apply_filters ("ws_plugin__s2member_during_add_network_admin_options_create_menu_items", true, get_defined_vars ()))
239
  {
240
- if ((is_multisite () && c_ws_plugin__s2member_utils_conds::is_multisite_farm () && !is_main_site ()) || apply_filters ("ws_plugin__s2member_during_add_network_admin_options_clear_right_side", false, get_defined_vars ()))
241
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu_pages"] = array (); /* Clear right side. */
242
  /**/
243
  $menu = "ws-plugin--s2member-mms-ops"; /* Used below for nesting additional sub-menu pages. */
244
  /**/
245
- add_menu_page ("s2Member®", "s2Member®", "create_users", $menu, "c_ws_plugin__s2member_menu_pages::mms_ops_page", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images/brand-favicon.png");
246
  /**/
247
- add_submenu_page ($menu, "s2Member Multisite ( Configuration )", "Multisite (Config)", "create_users", "ws-plugin--s2member-mms-ops", "c_ws_plugin__s2member_menu_pages::mms_ops_page");
248
  /**/
249
- if (apply_filters ("ws_plugin__s2member_during_add_network_admin_options_add_info_page", (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ()), get_defined_vars ()))
250
- add_submenu_page ($menu, "s2Member Information", "s2Member Info", "create_users", "ws-plugin--s2member-info", "c_ws_plugin__s2member_menu_pages::info_page");
251
  /**/
252
- do_action ("ws_plugin__s2member_during_add_network_admin_options_additional_pages", get_defined_vars ());
253
  }
254
  /**/
255
- do_action ("ws_plugin__s2member_after_add_network_admin_options", get_defined_vars ());
256
  /**/
257
  return; /* Return for uniformity. */
258
  }
@@ -268,23 +268,23 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
268
  * @param str $plugin_file Expects path to a plugin file. We need to test against this for s2Member.
269
  * @return array An array of links, Filtered by this routine.
270
  */
271
- public static function _add_settings_link ($actions = FALSE, $plugin_file = FALSE)
272
  {
273
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
274
- do_action ("_ws_plugin__s2member_before_add_settings_link", get_defined_vars ());
275
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
276
  /**/
277
- if ($plugin_file === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["plugin_basename"] && is_array ($actions))
278
  {
279
- $settings = '<a href="' . esc_attr (admin_url ("/admin.php?page=ws-plugin--s2member-gen-ops")) . '">Settings</a>';
280
- array_unshift ($actions, apply_filters ("ws_plugin__s2member_add_settings_link", $settings, get_defined_vars ()));
281
  /**/
282
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
283
- do_action ("_ws_plugin__s2member_during_add_settings_link", get_defined_vars ());
284
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
285
  }
286
  /**/
287
- return apply_filters ("_ws_plugin__s2member_add_settings_link", $actions, get_defined_vars ());
288
  }
289
  /**
290
  * Enqueue scripts for administrative menu pages.
@@ -296,25 +296,25 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
296
  *
297
  * @return null
298
  */
299
- public static function add_admin_scripts ()
300
  {
301
- do_action ("ws_plugin__s2member_before_add_admin_scripts", get_defined_vars ());
302
  /**/
303
- if (!empty ($_GET["page"]) && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
304
  {
305
  wp_enqueue_script("jquery");
306
  wp_enqueue_script("thickbox");
307
  wp_enqueue_script("media-upload");
308
  wp_enqueue_script("jquery-ui-core");
309
- wp_enqueue_script ("jquery-sprintf", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/includes/jquery/jquery.sprintf/jquery.sprintf-min.js", array ("jquery"), c_ws_plugin__s2member_utilities::ver_checksum ());
310
- wp_enqueue_script ("jquery-json-ps", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/includes/jquery/jquery.json-ps/jquery.json-ps-min.js", array ("jquery"), c_ws_plugin__s2member_utilities::ver_checksum ());
311
- wp_enqueue_script ("jquery-ui-effects", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/includes/jquery/jquery.ui-effects/jquery.ui-effects-min.js", array ("jquery", "jquery-ui-core"), c_ws_plugin__s2member_utilities::ver_checksum ());
312
- wp_enqueue_script ("ws-plugin--s2member-menu-pages", site_url ("/?ws_plugin__s2member_menu_pages_js=" . urlencode (mt_rand ())), array ("jquery", "thickbox", "media-upload", "jquery-sprintf", "jquery-json-ps", "jquery-ui-core", "jquery-ui-effects", "password-strength-meter"), c_ws_plugin__s2member_utilities::ver_checksum ());
313
  /**/
314
- do_action ("ws_plugin__s2member_during_add_admin_scripts", get_defined_vars ());
315
  }
316
  /**/
317
- do_action ("ws_plugin__s2member_after_add_admin_scripts", get_defined_vars ());
318
  /**/
319
  return; /* Return for uniformity. */
320
  }
@@ -328,19 +328,19 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
328
  *
329
  * @return null
330
  */
331
- public static function add_admin_styles ()
332
  {
333
- do_action ("ws_plugin__s2member_before_add_admin_styles", get_defined_vars ());
334
  /**/
335
- if (!empty ($_GET["page"]) && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
336
  {
337
  wp_enqueue_style("thickbox");
338
- wp_enqueue_style ("ws-plugin--s2member-menu-pages", site_url ("/?ws_plugin__s2member_menu_pages_css=" . urlencode (mt_rand ())), array ("thickbox"), c_ws_plugin__s2member_utilities::ver_checksum (), "all");
339
  /**/
340
- do_action ("ws_plugin__s2member_during_add_admin_styles", get_defined_vars ());
341
  }
342
  /**/
343
- do_action ("ws_plugin__s2member_after_add_admin_styles", get_defined_vars ());
344
  /**/
345
  return; /* Return for uniformity. */
346
  }
@@ -352,13 +352,13 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
352
  *
353
  * @return null
354
  */
355
- public static function start_page ()
356
  {
357
- do_action ("ws_plugin__s2member_before_start_page", get_defined_vars ());
358
  /**/
359
- include_once dirname (dirname (__FILE__)) . "/menu-pages/start.inc.php";
360
  /**/
361
- do_action ("ws_plugin__s2member_after_start_page", get_defined_vars ());
362
  /**/
363
  return; /* Return for uniformity. */
364
  }
@@ -370,16 +370,16 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
370
  *
371
  * @return null
372
  */
373
- public static function mms_ops_page ()
374
  {
375
- do_action ("ws_plugin__s2member_before_mms_ops_page", get_defined_vars ());
376
  /**/
377
- if (c_ws_plugin__s2member_menu_pages::update_all_options ())
378
- c_ws_plugin__s2member_mms_patches::mms_patches (true);
379
  /**/
380
- include_once dirname (dirname (__FILE__)) . "/menu-pages/mms-ops.inc.php";
381
  /**/
382
- do_action ("ws_plugin__s2member_after_mms_ops_page", get_defined_vars ());
383
  /**/
384
  return; /* Return for uniformity. */
385
  }
@@ -391,15 +391,15 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
391
  *
392
  * @return null
393
  */
394
- public static function gen_ops_page ()
395
  {
396
- do_action ("ws_plugin__s2member_before_gen_ops_page", get_defined_vars ());
397
  /**/
398
- c_ws_plugin__s2member_menu_pages::update_all_options ();
399
  /**/
400
- include_once dirname (dirname (__FILE__)) . "/menu-pages/gen-ops.inc.php";
401
  /**/
402
- do_action ("ws_plugin__s2member_after_gen_ops_page", get_defined_vars ());
403
  /**/
404
  return; /* Return for uniformity. */
405
  }
@@ -411,15 +411,15 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
411
  *
412
  * @return null
413
  */
414
- public static function res_ops_page ()
415
  {
416
- do_action ("ws_plugin__s2member_before_res_ops_page", get_defined_vars ());
417
  /**/
418
- c_ws_plugin__s2member_menu_pages::update_all_options ();
419
  /**/
420
- include_once dirname (dirname (__FILE__)) . "/menu-pages/res-ops.inc.php";
421
  /**/
422
- do_action ("ws_plugin__s2member_after_res_ops_page", get_defined_vars ());
423
  /**/
424
  return; /* Return for uniformity. */
425
  }
@@ -431,41 +431,41 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
431
  *
432
  * @return null
433
  */
434
- public static function paypal_ops_page ()
435
  {
436
- do_action ("ws_plugin__s2member_before_paypal_ops_page", get_defined_vars ());
437
  /**/
438
- c_ws_plugin__s2member_menu_pages::update_all_options ();
439
  /**/
440
  $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
441
  /**/
442
- if (!is_dir ($logs_dir) && is_writable (dirname (c_ws_plugin__s2member_utils_dirs::strip_dir_app_data ($logs_dir))))
443
- mkdir ($logs_dir, 0777, true) . clearstatcache ();
444
  /**/
445
- $htaccess = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"] . "/.htaccess";
446
- $htaccess_contents = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir_htaccess"])));
447
  /**/
448
- if (is_dir ($logs_dir) && is_writable ($logs_dir) && !file_exists ($htaccess))
449
- file_put_contents ($htaccess, $htaccess_contents) . clearstatcache ();
450
  /**/
451
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) /* Logging enabled? */
452
  {
453
- if (!is_dir ($logs_dir)) /* If the security-enabled logs directory does not exist yet. */
454
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('The security-enabled logs directory ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($logs_dir)) . '</code> ) does not exist. Please create this directory manually &amp; make it writable ( chmod 777 ).', true);
455
  /**/
456
- else if (!is_writable ($logs_dir)) /* If the logs directory is not writable yet. */
457
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('Permissions error. The security-enabled logs directory ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($logs_dir)) . '</code> ) is not writable. Please make this directory writable ( chmod 777 ).', true);
458
  /**/
459
- if (!file_exists ($htaccess)) /* If the .htaccess file has not been created yet. */
460
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('The .htaccess protection file ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($htaccess)) . '</code> ) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>' . esc_html ($htaccess_contents) . '</pre>', true);
461
  /**/
462
- else if (!preg_match ("/deny from all/i", file_get_contents ($htaccess))) /* Else if the .htaccess file does not offer the required protection. */
463
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('Unprotected. The .htaccess protection file ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($htaccess)) . '</code> ) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>' . esc_html ($htaccess_contents) . '</pre>', true);
464
  }
465
  /**/
466
- include_once dirname (dirname (__FILE__)) . "/menu-pages/paypal-ops.inc.php";
467
  /**/
468
- do_action ("ws_plugin__s2member_after_paypal_ops_page", get_defined_vars ());
469
  /**/
470
  return; /* Return for uniformity. */
471
  }
@@ -477,47 +477,56 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
477
  *
478
  * @return null
479
  */
480
- public static function down_ops_page ()
481
  {
482
- do_action ("ws_plugin__s2member_before_down_ops_page", get_defined_vars ());
483
  /**/
484
- c_ws_plugin__s2member_menu_pages::update_all_options ();
485
  /**/
486
  $files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"];
487
  /**/
488
- if (!is_dir ($files_dir) && is_writable (dirname (c_ws_plugin__s2member_utils_dirs::strip_dir_app_data ($files_dir))))
489
- mkdir ($files_dir, 0777, true) . clearstatcache ();
490
  /**/
491
- $htaccess = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/.htaccess";
492
- $htaccess_contents = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir_htaccess"])));
493
  /**/
494
- if (is_dir ($files_dir) && is_writable ($files_dir) && !file_exists ($htaccess))
495
- file_put_contents ($htaccess, $htaccess_contents) . clearstatcache ();
496
  /**/
497
- if (!is_dir ($files_dir)) /* If the security-enabled files directory does not exist yet. */
498
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('The security-enabled files directory ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($files_dir)) . '</code> ) does not exist. Please create this directory manually.', true);
499
  /**/
500
- if (!file_exists ($htaccess)) /* If the .htaccess file has not been created yet. */
501
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('The .htaccess protection file ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($htaccess)) . '</code> ) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>' . esc_html ($htaccess_contents) . '</pre>', true);
502
  /**/
503
- else if (!preg_match ("/deny from all/i", file_get_contents ($htaccess))) /* Else if the .htaccess file does not offer the required protection. */
504
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('Unprotected. The .htaccess protection file ( <code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($htaccess)) . '</code> ) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>' . esc_html ($htaccess_contents) . '</pre>', true);
505
  /**/
506
- if (!empty ($_POST["ws_plugin__s2member_amazon_cf_files_auto_configure_distros"]) && ($nonce = $_POST["ws_plugin__s2member_amazon_cf_files_auto_configure_distros"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-amazon-cf-files-auto-configure-distros"))
507
- if (($amazon_cf_auto_configure_distros = c_ws_plugin__s2member_files_in::amazon_cf_auto_configure_distros ()) && $amazon_cf_auto_configure_distros["success"])
508
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('Amazon® CloudFront Distributions auto-configured successfully. Please allow 30 minutes for propagation.' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) ? '<br /><em>Downloads Distribution CNAME: <code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]) . '</code></em>' : '') . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? '<br /><em>Streaming Distribution CNAME: <code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]) . '</code></em>' : ''));
 
 
 
 
 
 
 
 
 
509
  else /* Else there was an error. We need to report this back to the site owner so they can understand what's going on. */
510
- (c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"] = true) . c_ws_plugin__s2member_admin_notices::display_admin_notice ('Unable to auto-configure Amazon® CloudFront Distributions.<br />Error code: <code>' . esc_html ($amazon_cf_auto_configure_distros["code"]) . '</code>. Error Message: <code>' . esc_html ($amazon_cf_auto_configure_distros["message"]) . '</code>', true);
511
  /**/
512
- if (!empty ($_POST["ws_plugin__s2member_amazon_s3_files_auto_configure_acls"]) && ($nonce = $_POST["ws_plugin__s2member_amazon_s3_files_auto_configure_acls"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-amazon-s3-files-auto-configure-acls"))
513
- if (($amazon_s3_auto_configure_acls = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls ()) && $amazon_s3_auto_configure_acls["success"])
514
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('Amazon® S3 ACLs auto-configured successfully.');
515
  else /* Else there was an error. We need to report this back to the site owner so they can understand what's going on. */
516
- (c_ws_plugin__s2member_menu_pages::$pre_display_errors["s3_files_auto_configure_acls"] = true) . c_ws_plugin__s2member_admin_notices::display_admin_notice ('Unable to auto-configure Amazon® S3 ACLs.<br />Error code: <code>' . esc_html ($amazon_s3_auto_configure_acls["code"]) . '</code>. Error Message: <code>' . esc_html ($amazon_s3_auto_configure_acls["message"]) . '</code>', true);
517
  /**/
518
- include_once dirname (dirname (__FILE__)) . "/menu-pages/down-ops.inc.php";
519
  /**/
520
- do_action ("ws_plugin__s2member_after_down_ops_page", get_defined_vars ());
521
  /**/
522
  return; /* Return for uniformity. */
523
  }
@@ -529,15 +538,15 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
529
  *
530
  * @return null
531
  */
532
- public static function trk_ops_page ()
533
  {
534
- do_action ("ws_plugin__s2member_before_trk_ops_page", get_defined_vars ());
535
  /**/
536
- c_ws_plugin__s2member_menu_pages::update_all_options ();
537
  /**/
538
- include_once dirname (dirname (__FILE__)) . "/menu-pages/trk-ops.inc.php";
539
  /**/
540
- do_action ("ws_plugin__s2member_after_trk_ops_page", get_defined_vars ());
541
  /**/
542
  return; /* Return for uniformity. */
543
  }
@@ -549,15 +558,15 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
549
  *
550
  * @return null
551
  */
552
- public static function els_ops_page ()
553
  {
554
- do_action ("ws_plugin__s2member_before_els_ops_page", get_defined_vars ());
555
  /**/
556
- c_ws_plugin__s2member_menu_pages::update_all_options ();
557
  /**/
558
- include_once dirname (dirname (__FILE__)) . "/menu-pages/els-ops.inc.php";
559
  /**/
560
- do_action ("ws_plugin__s2member_after_els_ops_page", get_defined_vars ());
561
  /**/
562
  return; /* Return for uniformity. */
563
  }
@@ -569,15 +578,15 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
569
  *
570
  * @return null
571
  */
572
- public static function api_ops_page ()
573
  {
574
- do_action ("ws_plugin__s2member_before_api_ops_page", get_defined_vars ());
575
  /**/
576
- c_ws_plugin__s2member_menu_pages::update_all_options ();
577
  /**/
578
- include_once dirname (dirname (__FILE__)) . "/menu-pages/api-ops.inc.php";
579
  /**/
580
- do_action ("ws_plugin__s2member_after_api_ops_page", get_defined_vars ());
581
  /**/
582
  return; /* Return for uniformity. */
583
  }
@@ -589,16 +598,16 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
589
  *
590
  * @return null
591
  */
592
- public static function paypal_buttons_page ()
593
  {
594
- do_action ("ws_plugin__s2member_before_paypal_buttons_page", get_defined_vars ());
595
  /**/
596
- if (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"] || !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_username"] || !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_password"] || !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_signature"])
597
- c_ws_plugin__s2member_admin_notices::display_admin_notice ('Please configure <code>s2Member -> PayPal® Options</code> first. Once all of your PayPal® Options are configured; including your Email Address, API Username, Password, and Signature; return to this page &amp; generate your PayPal® Button(s).', true);
598
  /**/
599
- include_once dirname (dirname (__FILE__)) . "/menu-pages/paypal-buttons.inc.php";
600
  /**/
601
- do_action ("ws_plugin__s2member_after_paypal_buttons_page", get_defined_vars ());
602
  /**/
603
  return; /* Return for uniformity. */
604
  }
@@ -610,13 +619,13 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
610
  *
611
  * @return null
612
  */
613
- public static function scripting_page ()
614
  {
615
- do_action ("ws_plugin__s2member_before_scripting_page", get_defined_vars ());
616
  /**/
617
- include_once dirname (dirname (__FILE__)) . "/menu-pages/scripting.inc.php";
618
  /**/
619
- do_action ("ws_plugin__s2member_after_scripting_page", get_defined_vars ());
620
  /**/
621
  return; /* Return for uniformity. */
622
  }
@@ -628,13 +637,13 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
628
  *
629
  * @return null
630
  */
631
- public static function integrations_page ()
632
  {
633
- do_action ("ws_plugin__s2member_before_integrations_page", get_defined_vars ());
634
  /**/
635
- include_once dirname (dirname (__FILE__)) . "/menu-pages/integrations.inc.php";
636
  /**/
637
- do_action ("ws_plugin__s2member_after_integrations_page", get_defined_vars ());
638
  /**/
639
  return; /* Return for uniformity. */
640
  }
@@ -646,13 +655,13 @@ if (!class_exists ("c_ws_plugin__s2member_menu_pages"))
646
  *
647
  * @return null
648
  */
649
- public static function info_page ()
650
  {
651
- do_action ("ws_plugin__s2member_before_info_page", get_defined_vars ());
652
  /**/
653
- include_once dirname (dirname (__FILE__)) . "/menu-pages/info.inc.php";
654
  /**/
655
- do_action ("ws_plugin__s2member_after_info_page", get_defined_vars ());
656
  /**/
657
  return; /* Return for uniformity. */
658
  }
14
  * @package s2Member\Menu_Pages
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_menu_pages"))
21
  {
22
  /**
23
  * Administrative menu pages.
35
  *
36
  * @var array
37
  */
38
+ public static $pre_display_errors = array();
39
  /**
40
  * Saves all options from any menu page.
41
  *
53
  * @param bool $request_refresh Optional. Defaults to false. If true, resulting `success` notice will include a link to refresh the menu page.
54
  * @return bool True if all s2Member options were updated successfully, else false.
55
  */
56
+ public static function update_all_options($new_options = FALSE, $verified = FALSE, $update_other = TRUE, $display_notices = TRUE, $enqueue_notices = FALSE, $request_refresh = FALSE)
57
  {
58
  $updated_all_options = false; /* Initialize this to a value of false. Initializing this variable here makes it an available reference-variable to Hooks/Filters. */
59
  /**/
60
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
61
+ do_action("ws_plugin__s2member_before_update_all_options", get_defined_vars()); /* If you use this Hook, be sure to use ``wp_verify_nonce()``. */
62
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
63
  /**/
64
+ if($verified || (!empty($_POST["ws_plugin__s2member_options_save"]) && ($nonce = $_POST["ws_plugin__s2member_options_save"]) && wp_verify_nonce($nonce, "ws-plugin--s2member-options-save")))
65
  {
66
  $options = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]; /* Acquire the full existing configuration options array here. */
67
  /**/
68
+ $new_options = (is_array($new_options)) ? $new_options : ((!empty($_POST) && is_array($_POST)) ? stripslashes_deep($_POST) : array());
69
+ $new_options = c_ws_plugin__s2member_utils_strings::trim_deep($new_options);
70
  /**/
71
+ foreach($new_options as $key => $value) /* Find all keys contained within ``$new_options`` matching `^ws_plugin__s2member_`. */
72
+ if(strpos($key, "ws_plugin__s2member_") === 0) /* A relevant ``$new_options`` key matching `^ws_plugin__s2member_`? */
73
  /**/
74
+ if($key === "ws_plugin__s2member_configured") /* s2Member is now configured ( according to these options )? */
75
+ ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"] = $value).update_option("ws_plugin__s2member_configured", $value);
76
  /**/
77
+ else if(!is_array($value) || (is_array($value) && /* Updating an array? */ array_shift($value) === "update-signal"))
78
+ $options[preg_replace("/^".preg_quote("ws_plugin__s2member_", "/")."/", "", $key)] = $value;
79
  /**/
80
+ unset($key, $value); /* Unset these utility variables now. This prevents bleeding vars into Hooks/Filters that are of no use. */
81
  /**/
82
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
83
+ do_action("ws_plugin__s2member_during_update_all_options", get_defined_vars()); /* If you use this Hook, be sure to use ``wp_verify_nonce()``. */
84
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
85
  /**/
86
+ $options = ws_plugin__s2member_configure_options_and_their_defaults(($options = array_merge($options, array("options_version" => (string)($options["options_version"] + 0.001)))));
87
+ update_option("ws_plugin__s2member_options", $options).((is_multisite() && is_main_site()) ? update_site_option("ws_plugin__s2member_options", $options) : null).update_option("ws_plugin__s2member_cache", array());
88
  /**/
89
+ if($update_other === true || in_array("auto_eot_system", (array)$update_other)) /* Handle the Auto-EOT System now ( enable/disable ). */
90
+ ($options["auto_eot_system_enabled"] == 1) ? c_ws_plugin__s2member_auto_eots::add_auto_eot_system() : c_ws_plugin__s2member_auto_eots::delete_auto_eot_system();
91
  /**/
92
+ if(($display_notices === true || in_array("success", (array)$display_notices)) && ($notice = '<strong>Options saved.'.(($request_refresh) ? ' Please <a href="'.esc_attr($_SERVER["REQUEST_URI"]).'">refresh</a>.' : '').'</strong>'))
93
+ ($enqueue_notices === true || in_array("success", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*") : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice);
94
  /**/
95
+ if(empty($_GET["page"]) || $_GET["page"] !== "ws-plugin--s2member-mms-ops") /* Do NOT display page-conflict-warnings on the Main Multisite Configuration panel. */
96
  {
97
+ if(!$options["membership_options_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>NOTE:</strong> s2Member security restrictions will NOT be enforced until you\'ve configured a Membership Options Page. See: <code>s2Member -> General Options -> Membership Options Page</code>.'))
98
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
99
  /**/
100
+ if($options["login_welcome_page"] && $options["login_welcome_page"] === $options["membership_options_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is the same as your Membership Options Page. Please correct this. See: <code>s2Member -> General Options -> Login Welcome Page</code>.'))
101
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
102
  /**/
103
+ if($options["membership_options_page"] && (string)get_option("page_on_front") === $options["membership_options_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Membership Options Page is currently configured as your Home Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Membership Options Page</code>.'))
104
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
105
  /**/
106
+ if($options["login_welcome_page"] && (string)get_option("page_on_front") === $options["login_welcome_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is currently configured as your Home Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Login Welcome Page</code>.'))
107
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
108
  /**/
109
+ if($options["membership_options_page"] && (string)get_option("page_for_posts") === $options["membership_options_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Membership Options Page is currently configured as your Posts Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Membership Options Page</code>.'))
110
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
111
  /**/
112
+ if($options["login_welcome_page"] && (string)get_option("page_for_posts") === $options["login_welcome_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is currently configured as your Posts Page ( i.e. static page ) for WordPress®. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: <code>WordPress® -> Reading Options</code>. Or change: <code>s2Member -> General Options -> Login Welcome Page</code>.'))
113
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
114
  /**/
115
+ if($options["file_download_limit_exceeded_page"] && $options["file_download_limit_exceeded_page"] === $options["membership_options_page"] && ($display_notices === true || in_array("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Download Limit Exceeded Page is the same as your Membership Options Page. Please correct this. See: <code>s2Member -> Download Options</code>.'))
116
+ ($enqueue_notices === true || in_array("page-conflict-warnings", (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, "*:*", true) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, true);
117
  }
118
  /**/
119
  $updated_all_options = true; /* Flag indicating this routine was processed successfully; and that all s2Member options have been updated successfully.*/
120
  }
121
  /**/
122
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
123
+ do_action("ws_plugin__s2member_after_update_all_options", get_defined_vars()); /* If you use this Hook, be sure to use ``wp_verify_nonce()``. */
124
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
125
  /**/
126
+ return apply_filters("ws_plugin__s2member_update_all_options", (($updated_all_options) ? true : false), get_defined_vars());
127
  }
128
  /**
129
  * Adds option menus / sub-menus.
135
  *
136
  * @return null
137
  */
138
+ public static function add_admin_options()
139
  {
140
+ do_action("ws_plugin__s2member_before_add_admin_options", get_defined_vars());
141
  /**/
142
+ add_filter("plugin_action_links", "c_ws_plugin__s2member_menu_pages::_add_settings_link", 10, 2);
143
  /**/
144
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_create_menu_items", true, get_defined_vars()))
145
  {
146
+ if((is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) || apply_filters("ws_plugin__s2member_during_add_admin_options_clear_right_side", false, get_defined_vars()))
147
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu_pages"] = array(); /* Clear right side. */
148
  /**/
149
+ $menu = apply_filters("ws_plugin__s2member_during_add_admin_options_menu_slug", "ws-plugin--s2member-start", get_defined_vars());
150
  /**/
151
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_menu_page", true, get_defined_vars()))
152
+ add_menu_page("s2Member®", "s2Member®", "create_users", $menu, "c_ws_plugin__s2member_menu_pages::start_page", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images/brand-favicon.png");
153
  /**/
154
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_start_page", true, get_defined_vars()))
155
+ add_submenu_page($menu, "s2Member Quick-Start Guide", "Quick-Start Guide", "create_users", "ws-plugin--s2member-start", "c_ws_plugin__s2member_menu_pages::start_page");
156
  /**/
157
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_divider_1", true, get_defined_vars())) /* Divider. */
158
+ add_submenu_page($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
159
  /**/
160
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_mms_ops_page", (!is_multisite() || is_main_site()), get_defined_vars()))
161
+ add_submenu_page($menu, "s2Member Multisite Configuration", "Multisite (Config)", "create_users", "ws-plugin--s2member-mms-ops", "c_ws_plugin__s2member_menu_pages::mms_ops_page");
162
  /**/
163
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_gen_ops_page", true, get_defined_vars()))
164
+ add_submenu_page($menu, "s2Member General Options", "General Options", "create_users", "ws-plugin--s2member-gen-ops", "c_ws_plugin__s2member_menu_pages::gen_ops_page");
165
  /**/
166
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_res_ops_page", true, get_defined_vars()))
167
+ add_submenu_page($menu, "s2Member Restriction Options", "Restriction Options", "create_users", "ws-plugin--s2member-res-ops", "c_ws_plugin__s2member_menu_pages::res_ops_page");
168
  /**/
169
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_down_ops_page", (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
170
+ add_submenu_page($menu, "s2Member Download Options", "Download Options", "create_users", "ws-plugin--s2member-down-ops", "c_ws_plugin__s2member_menu_pages::down_ops_page");
171
  /**/
172
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_divider_2", true, get_defined_vars())) /* Divider. */
173
+ add_submenu_page($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
174
  /**/
175
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_new_user_page", true, get_defined_vars())) /* Shortcut. */
176
+ add_submenu_page($menu, "s2Member / Add A Member", "Add A Member", "create_users", "user-new.php");
177
  /**/
178
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_browse_users_page", true, get_defined_vars())) /* Shortcut. */
179
+ add_submenu_page($menu, "s2Member / Browse Members", "Browse Members", "create_users", "users.php");
180
  /**/
181
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_divider_3", true, get_defined_vars())) /* Divider. */
182
+ add_submenu_page($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
183
  /**/
184
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_paypal_ops_page", true, get_defined_vars()))
185
+ add_submenu_page($menu, "s2Member PayPal Options", "PayPal® Options", "create_users", "ws-plugin--s2member-paypal-ops", "c_ws_plugin__s2member_menu_pages::paypal_ops_page");
186
  /**/
187
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_paypal_buttons_page", true, get_defined_vars()))
188
+ add_submenu_page($menu, "s2Member PayPal® Buttons", "PayPal® Buttons", "create_users", "ws-plugin--s2member-paypal-buttons", "c_ws_plugin__s2member_menu_pages::paypal_buttons_page");
189
  /**/
190
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_divider_4", true, get_defined_vars())) /* Divider. */
191
+ add_submenu_page($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
192
  /**/
193
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_trk_ops_page", true, get_defined_vars()))
194
+ add_submenu_page($menu, "s2Member API / Tracking", "API / Tracking", "create_users", "ws-plugin--s2member-trk-ops", "c_ws_plugin__s2member_menu_pages::trk_ops_page");
195
  /**/
196
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_els_ops_page", true, get_defined_vars()))
197
+ add_submenu_page($menu, "s2Member API / List Servers", "API / List Servers", "create_users", "ws-plugin--s2member-els-ops", "c_ws_plugin__s2member_menu_pages::els_ops_page");
198
  /**/
199
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_api_ops_page", true, get_defined_vars()))
200
+ add_submenu_page($menu, "s2Member API / Notifications", "API / Notifications", "create_users", "ws-plugin--s2member-api-ops", "c_ws_plugin__s2member_menu_pages::api_ops_page");
201
  /**/
202
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_scripting_page", true, get_defined_vars()))
203
+ add_submenu_page($menu, "s2Member API / Scripting", "API / Scripting", "create_users", "ws-plugin--s2member-scripting", "c_ws_plugin__s2member_menu_pages::scripting_page");
204
  /**/
205
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_divider_5", true, get_defined_vars())) /* Divider. */
206
+ add_submenu_page($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
207
  /**/
208
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_integrations_page", (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
209
+ add_submenu_page($menu, "s2Member / Other Integrations", "Other Integrations", "create_users", "ws-plugin--s2member-integrations", "c_ws_plugin__s2member_menu_pages::integrations_page");
210
  /**/
211
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_divider_6", true, get_defined_vars())) /* Divider. */
212
+ add_submenu_page($menu, "", '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', "create_users", "#");
213
  /**/
214
+ if(apply_filters("ws_plugin__s2member_during_add_admin_options_add_info_page", (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
215
+ add_submenu_page($menu, "s2Member Information", "s2Member Info", "create_users", "ws-plugin--s2member-info", "c_ws_plugin__s2member_menu_pages::info_page");
216
  /**/
217
+ do_action("ws_plugin__s2member_during_add_admin_options_additional_pages", get_defined_vars());
218
  }
219
  /**/
220
+ do_action("ws_plugin__s2member_after_add_admin_options", get_defined_vars());
221
  /**/
222
  return; /* Return for uniformity. */
223
  }
231
  *
232
  * @return null
233
  */
234
+ public static function add_network_admin_options()
235
  {
236
+ do_action("ws_plugin__s2member_before_add_network_admin_options", get_defined_vars());
237
  /**/
238
+ if(apply_filters("ws_plugin__s2member_during_add_network_admin_options_create_menu_items", true, get_defined_vars()))
239
  {
240
+ if((is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) || apply_filters("ws_plugin__s2member_during_add_network_admin_options_clear_right_side", false, get_defined_vars()))
241
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu_pages"] = array(); /* Clear right side. */
242
  /**/
243
  $menu = "ws-plugin--s2member-mms-ops"; /* Used below for nesting additional sub-menu pages. */
244
  /**/
245
+ add_menu_page("s2Member®", "s2Member®", "create_users", $menu, "c_ws_plugin__s2member_menu_pages::mms_ops_page", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images/brand-favicon.png");
246
  /**/
247
+ add_submenu_page($menu, "s2Member Multisite ( Configuration )", "Multisite (Config)", "create_users", "ws-plugin--s2member-mms-ops", "c_ws_plugin__s2member_menu_pages::mms_ops_page");
248
  /**/
249
+ if(apply_filters("ws_plugin__s2member_during_add_network_admin_options_add_info_page", (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
250
+ add_submenu_page($menu, "s2Member Information", "s2Member Info", "create_users", "ws-plugin--s2member-info", "c_ws_plugin__s2member_menu_pages::info_page");
251
  /**/
252
+ do_action("ws_plugin__s2member_during_add_network_admin_options_additional_pages", get_defined_vars());
253
  }
254
  /**/
255
+ do_action("ws_plugin__s2member_after_add_network_admin_options", get_defined_vars());
256
  /**/
257
  return; /* Return for uniformity. */
258
  }
268
  * @param str $plugin_file Expects path to a plugin file. We need to test against this for s2Member.
269
  * @return array An array of links, Filtered by this routine.
270
  */
271
+ public static function _add_settings_link($actions = FALSE, $plugin_file = FALSE)
272
  {
273
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
274
+ do_action("_ws_plugin__s2member_before_add_settings_link", get_defined_vars());
275
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
276
  /**/
277
+ if($plugin_file === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["plugin_basename"] && is_array($actions))
278
  {
279
+ $settings = '<a href="'.esc_attr(admin_url("/admin.php?page=ws-plugin--s2member-gen-ops")).'">Settings</a>';
280
+ array_unshift($actions, apply_filters("ws_plugin__s2member_add_settings_link", $settings, get_defined_vars()));
281
  /**/
282
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
283
+ do_action("_ws_plugin__s2member_during_add_settings_link", get_defined_vars());
284
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
285
  }
286
  /**/
287
+ return apply_filters("_ws_plugin__s2member_add_settings_link", $actions, get_defined_vars());
288
  }
289
  /**
290
  * Enqueue scripts for administrative menu pages.
296
  *
297
  * @return null
298
  */
299
+ public static function add_admin_scripts()
300
  {
301
+ do_action("ws_plugin__s2member_before_add_admin_scripts", get_defined_vars());
302
  /**/
303
+ if(!empty($_GET["page"]) && preg_match("/ws-plugin--s2member-/", $_GET["page"]))
304
  {
305
  wp_enqueue_script("jquery");
306
  wp_enqueue_script("thickbox");
307
  wp_enqueue_script("media-upload");
308
  wp_enqueue_script("jquery-ui-core");
309
+ wp_enqueue_script("jquery-sprintf", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/includes/jquery/jquery.sprintf/jquery.sprintf-min.js", array("jquery"), c_ws_plugin__s2member_utilities::ver_checksum());
310
+ wp_enqueue_script("jquery-json-ps", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/includes/jquery/jquery.json-ps/jquery.json-ps-min.js", array("jquery"), c_ws_plugin__s2member_utilities::ver_checksum());
311
+ wp_enqueue_script("jquery-ui-effects", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/includes/jquery/jquery.ui-effects/jquery.ui-effects-min.js", array("jquery", "jquery-ui-core"), c_ws_plugin__s2member_utilities::ver_checksum());
312
+ wp_enqueue_script("ws-plugin--s2member-menu-pages", site_url("/?ws_plugin__s2member_menu_pages_js=".urlencode(mt_rand())), array("jquery", "thickbox", "media-upload", "jquery-sprintf", "jquery-json-ps", "jquery-ui-core", "jquery-ui-effects", "password-strength-meter"), c_ws_plugin__s2member_utilities::ver_checksum());
313
  /**/
314
+ do_action("ws_plugin__s2member_during_add_admin_scripts", get_defined_vars());
315
  }
316
  /**/
317
+ do_action("ws_plugin__s2member_after_add_admin_scripts", get_defined_vars());
318
  /**/
319
  return; /* Return for uniformity. */
320
  }
328
  *
329
  * @return null
330
  */
331
+ public static function add_admin_styles()
332
  {
333
+ do_action("ws_plugin__s2member_before_add_admin_styles", get_defined_vars());
334
  /**/
335
+ if(!empty($_GET["page"]) && preg_match("/ws-plugin--s2member-/", $_GET["page"]))
336
  {
337
  wp_enqueue_style("thickbox");
338
+ wp_enqueue_style("ws-plugin--s2member-menu-pages", site_url("/?ws_plugin__s2member_menu_pages_css=".urlencode(mt_rand())), array("thickbox"), c_ws_plugin__s2member_utilities::ver_checksum(), "all");
339
  /**/
340
+ do_action("ws_plugin__s2member_during_add_admin_styles", get_defined_vars());
341
  }
342
  /**/
343
+ do_action("ws_plugin__s2member_after_add_admin_styles", get_defined_vars());
344
  /**/
345
  return; /* Return for uniformity. */
346
  }
352
  *
353
  * @return null
354
  */
355
+ public static function start_page()
356
  {
357
+ do_action("ws_plugin__s2member_before_start_page", get_defined_vars());
358
  /**/
359
+ include_once dirname(dirname(__FILE__))."/menu-pages/start.inc.php";
360
  /**/
361
+ do_action("ws_plugin__s2member_after_start_page", get_defined_vars());
362
  /**/
363
  return; /* Return for uniformity. */
364
  }
370
  *
371
  * @return null
372
  */
373
+ public static function mms_ops_page()
374
  {
375
+ do_action("ws_plugin__s2member_before_mms_ops_page", get_defined_vars());
376
  /**/
377
+ if(c_ws_plugin__s2member_menu_pages::update_all_options())
378
+ c_ws_plugin__s2member_mms_patches::mms_patches(true);
379
  /**/
380
+ include_once dirname(dirname(__FILE__))."/menu-pages/mms-ops.inc.php";
381
  /**/
382
+ do_action("ws_plugin__s2member_after_mms_ops_page", get_defined_vars());
383
  /**/
384
  return; /* Return for uniformity. */
385
  }
391
  *
392
  * @return null
393
  */
394
+ public static function gen_ops_page()
395
  {
396
+ do_action("ws_plugin__s2member_before_gen_ops_page", get_defined_vars());
397
  /**/
398
+ c_ws_plugin__s2member_menu_pages::update_all_options();
399
  /**/
400
+ include_once dirname(dirname(__FILE__))."/menu-pages/gen-ops.inc.php";
401
  /**/
402
+ do_action("ws_plugin__s2member_after_gen_ops_page", get_defined_vars());
403
  /**/
404
  return; /* Return for uniformity. */
405
  }
411
  *
412
  * @return null
413
  */
414
+ public static function res_ops_page()
415
  {
416
+ do_action("ws_plugin__s2member_before_res_ops_page", get_defined_vars());
417
  /**/
418
+ c_ws_plugin__s2member_menu_pages::update_all_options();
419
  /**/
420
+ include_once dirname(dirname(__FILE__))."/menu-pages/res-ops.inc.php";
421
  /**/
422
+ do_action("ws_plugin__s2member_after_res_ops_page", get_defined_vars());
423
  /**/
424
  return; /* Return for uniformity. */
425
  }
431
  *
432
  * @return null
433
  */
434
+ public static function paypal_ops_page()
435
  {
436
+ do_action("ws_plugin__s2member_before_paypal_ops_page", get_defined_vars());
437
  /**/
438
+ c_ws_plugin__s2member_menu_pages::update_all_options();
439
  /**/
440
  $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
441
  /**/
442
+ if(!is_dir($logs_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($logs_dir))))
443
+ mkdir($logs_dir, 0777, true).clearstatcache();
444
  /**/
445
+ $htaccess = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]."/.htaccess";
446
+ $htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir_htaccess"])));
447
  /**/
448
+ if(is_dir($logs_dir) && is_writable($logs_dir) && !file_exists($htaccess))
449
+ file_put_contents($htaccess, $htaccess_contents).clearstatcache();
450
  /**/
451
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) /* Logging enabled? */
452
  {
453
+ if(!is_dir($logs_dir)) /* If the security-enabled logs directory does not exist yet. */
454
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled logs directory ( <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).'</code> ) does not exist. Please create this directory manually &amp; make it writable ( chmod 777 ).', true);
455
  /**/
456
+ else if(!is_writable($logs_dir)) /* If the logs directory is not writable yet. */
457
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Permissions error. The security-enabled logs directory ( <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).'</code> ) is not writable. Please make this directory writable ( chmod 777 ).', true);
458
  /**/
459
+ if(!file_exists($htaccess)) /* If the .htaccess file has not been created yet. */
460
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file ( <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code> ) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', true);
461
  /**/
462
+ else if(!preg_match("/deny from all/i", file_get_contents($htaccess))) /* Else if the .htaccess file does not offer the required protection. */
463
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file ( <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code> ) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', true);
464
  }
465
  /**/
466
+ include_once dirname(dirname(__FILE__))."/menu-pages/paypal-ops.inc.php";
467
  /**/
468
+ do_action("ws_plugin__s2member_after_paypal_ops_page", get_defined_vars());
469
  /**/
470
  return; /* Return for uniformity. */
471
  }
477
  *
478
  * @return null
479
  */
480
+ public static function down_ops_page()
481
  {
482
+ do_action("ws_plugin__s2member_before_down_ops_page", get_defined_vars());
483
  /**/
484
+ c_ws_plugin__s2member_menu_pages::update_all_options();
485
  /**/
486
  $files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"];
487
  /**/
488
+ $htaccess = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]."/.htaccess";
489
+ $htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir_htaccess"])));
490
  /**/
491
+ $no_gzip_htaccess = /* Always located in the absolute root path for WordPress®. */ ABSPATH.".htaccess";
492
+ $no_gzip_htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_no_gzip_htaccess"])));
493
  /**/
494
+ if(!c_ws_plugin__s2member_files::no_gzip_rules_in_root_htaccess() /* If s2Member's GZIP exclusions do NOT yet exist in the root `.htaccess` file. */)
495
+ c_ws_plugin__s2member_files::write_no_gzip_into_root_htaccess(). /* Handle the root `.htaccess` file now. */clearstatcache();
496
  /**/
497
+ if(!is_dir($files_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($files_dir))))
498
+ mkdir($files_dir, 0777, true). /* Create this directory structure now. */clearstatcache();
499
  /**/
500
+ if(is_dir($files_dir) && is_writable($files_dir) && !file_exists($htaccess) /* This file does NOT exist yet? */)
501
+ file_put_contents($htaccess, $htaccess_contents). /* Create the `.htaccess` file now. */clearstatcache();
502
  /**/
503
+ if(!c_ws_plugin__s2member_files::no_gzip_rules_in_root_htaccess /* If s2Member's GZIP exclusions do NOT yet exist in the root `.htaccess` file. */())
504
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Possible GZIP conflict on server. Unable to write GZIP exclusions into root .htaccess file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($no_gzip_htaccess)).'</code>). Please read the panel below: <strong>Preventing GZIP Conflicts</strong>, and add this section yourself:<br /><pre>'.esc_html($no_gzip_htaccess_contents).'</pre>', true);
505
  /**/
506
+ if(!is_dir($files_dir)) /* If the security-enabled files directory does not exist yet. */
507
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled files directory (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($files_dir)).'</code>) does not exist. Please create this directory manually.', true);
508
+ /**/
509
+ if(!file_exists($htaccess)) /* If the `.htaccess` file has not been created yet. */
510
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', true);
511
+ /**/
512
+ else if(!preg_match("/deny from all/i", file_get_contents($htaccess))) /* Else if the `.htaccess` file does not offer the required protection. */
513
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', true);
514
+ /**/
515
+ if(!empty($_POST["ws_plugin__s2member_amazon_cf_files_auto_configure_distros"]) && ($nonce = $_POST["ws_plugin__s2member_amazon_cf_files_auto_configure_distros"]) && wp_verify_nonce($nonce, "ws-plugin--s2member-amazon-cf-files-auto-configure-distros"))
516
+ if(($amazon_cf_auto_configure_distros = c_ws_plugin__s2member_files_in::amazon_cf_auto_configure_distros()) && $amazon_cf_auto_configure_distros["success"])
517
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon® CloudFront Distributions auto-configured successfully. Please allow 30 minutes for propagation.'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) ? '<br /><em>Downloads Distribution CNAME: <code>'.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]).' &mdash;&raquo; '.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]).'</code></em>' : '').(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? '<br /><em>Streaming Distribution CNAME: <code>'.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]).' &mdash;&raquo; '.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]).'</code></em>' : ''));
518
  else /* Else there was an error. We need to report this back to the site owner so they can understand what's going on. */
519
+ (c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"] = true).c_ws_plugin__s2member_admin_notices::display_admin_notice('Unable to auto-configure Amazon® CloudFront Distributions.<br />Error code: <code>'.esc_html($amazon_cf_auto_configure_distros["code"]).'</code>. Error Message: <code>'.esc_html($amazon_cf_auto_configure_distros["message"]).'</code>', true);
520
  /**/
521
+ if(!empty($_POST["ws_plugin__s2member_amazon_s3_files_auto_configure_acls"]) && ($nonce = $_POST["ws_plugin__s2member_amazon_s3_files_auto_configure_acls"]) && wp_verify_nonce($nonce, "ws-plugin--s2member-amazon-s3-files-auto-configure-acls"))
522
+ if(($amazon_s3_auto_configure_acls = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls()) && $amazon_s3_auto_configure_acls["success"])
523
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon® S3 ACLs auto-configured successfully.');
524
  else /* Else there was an error. We need to report this back to the site owner so they can understand what's going on. */
525
+ (c_ws_plugin__s2member_menu_pages::$pre_display_errors["s3_files_auto_configure_acls"] = true).c_ws_plugin__s2member_admin_notices::display_admin_notice('Unable to auto-configure Amazon® S3 ACLs.<br />Error code: <code>'.esc_html($amazon_s3_auto_configure_acls["code"]).'</code>. Error Message: <code>'.esc_html($amazon_s3_auto_configure_acls["message"]).'</code>', true);
526
  /**/
527
+ include_once dirname(dirname(__FILE__))."/menu-pages/down-ops.inc.php";
528
  /**/
529
+ do_action("ws_plugin__s2member_after_down_ops_page", get_defined_vars());
530
  /**/
531
  return; /* Return for uniformity. */
532
  }
538
  *
539
  * @return null
540
  */
541
+ public static function trk_ops_page()
542
  {
543
+ do_action("ws_plugin__s2member_before_trk_ops_page", get_defined_vars());
544
  /**/
545
+ c_ws_plugin__s2member_menu_pages::update_all_options();
546
  /**/
547
+ include_once dirname(dirname(__FILE__))."/menu-pages/trk-ops.inc.php";
548
  /**/
549
+ do_action("ws_plugin__s2member_after_trk_ops_page", get_defined_vars());
550
  /**/
551
  return; /* Return for uniformity. */
552
  }
558
  *
559
  * @return null
560
  */
561
+ public static function els_ops_page()
562
  {
563
+ do_action("ws_plugin__s2member_before_els_ops_page", get_defined_vars());
564
  /**/
565
+ c_ws_plugin__s2member_menu_pages::update_all_options();
566
  /**/
567
+ include_once dirname(dirname(__FILE__))."/menu-pages/els-ops.inc.php";
568
  /**/
569
+ do_action("ws_plugin__s2member_after_els_ops_page", get_defined_vars());
570
  /**/
571
  return; /* Return for uniformity. */
572
  }
578
  *
579
  * @return null
580
  */
581
+ public static function api_ops_page()
582
  {
583
+ do_action("ws_plugin__s2member_before_api_ops_page", get_defined_vars());
584
  /**/
585
+ c_ws_plugin__s2member_menu_pages::update_all_options();
586
  /**/
587
+ include_once dirname(dirname(__FILE__))."/menu-pages/api-ops.inc.php";
588
  /**/
589
+ do_action("ws_plugin__s2member_after_api_ops_page", get_defined_vars());
590
  /**/
591
  return; /* Return for uniformity. */
592
  }
598
  *
599
  * @return null
600
  */
601
+ public static function paypal_buttons_page()
602
  {
603
+ do_action("ws_plugin__s2member_before_paypal_buttons_page", get_defined_vars());
604
  /**/
605
+ if(!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"] || !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_username"] || !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_password"] || !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_signature"])
606
+ c_ws_plugin__s2member_admin_notices::display_admin_notice('Please configure <code>s2Member -> PayPal® Options</code> first. Once all of your PayPal® Options are configured; including your Email Address, API Username, Password, and Signature; return to this page &amp; generate your PayPal® Button(s).', true);
607
  /**/
608
+ include_once dirname(dirname(__FILE__))."/menu-pages/paypal-buttons.inc.php";
609
  /**/
610
+ do_action("ws_plugin__s2member_after_paypal_buttons_page", get_defined_vars());
611
  /**/
612
  return; /* Return for uniformity. */
613
  }
619
  *
620
  * @return null
621
  */
622
+ public static function scripting_page()
623
  {
624
+ do_action("ws_plugin__s2member_before_scripting_page", get_defined_vars());
625
  /**/
626
+ include_once dirname(dirname(__FILE__))."/menu-pages/scripting.inc.php";
627
  /**/
628
+ do_action("ws_plugin__s2member_after_scripting_page", get_defined_vars());
629
  /**/
630
  return; /* Return for uniformity. */
631
  }
637
  *
638
  * @return null
639
  */
640
+ public static function integrations_page()
641
  {
642
+ do_action("ws_plugin__s2member_before_integrations_page", get_defined_vars());
643
  /**/
644
+ include_once dirname(dirname(__FILE__))."/menu-pages/integrations.inc.php";
645
  /**/
646
+ do_action("ws_plugin__s2member_after_integrations_page", get_defined_vars());
647
  /**/
648
  return; /* Return for uniformity. */
649
  }
655
  *
656
  * @return null
657
  */
658
+ public static function info_page()
659
  {
660
+ do_action("ws_plugin__s2member_before_info_page", get_defined_vars());
661
  /**/
662
+ include_once dirname(dirname(__FILE__))."/menu-pages/info.inc.php";
663
  /**/
664
+ do_action("ws_plugin__s2member_after_info_page", get_defined_vars());
665
  /**/
666
  return; /* Return for uniformity. */
667
  }
includes/classes/meta-box-security.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Meta_Boxes
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_meta_box_security"))
21
  {
22
  /**
23
  * Security meta box.
@@ -36,103 +36,103 @@ if (!class_exists ("c_ws_plugin__s2member_meta_box_security"))
36
  * @param obj $post Post/Page object.
37
  * @return null
38
  */
39
- public static function security_meta_box ($post = FALSE)
40
  {
41
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
42
- do_action ("ws_plugin__s2member_before_security_meta_box", get_defined_vars ());
43
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
44
  /**/
45
- if (is_object ($post) && ($post_id = $post->ID) && (($post->post_type === "page" && current_user_can ("edit_page", $post_id)) || current_user_can ("edit_post", $post_id)))
46
  {
47
- if ($post->post_type === "page" && ($page_id = $post_id)) /* OK. So we're dealing with a Page classification. */
48
  {
49
- if (!in_array ($page_id, array_merge (array ($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"]), preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"]))))
50
  {
51
- echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save" id="ws-plugin--s2member-security-meta-box-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-security-meta-box-save")) . '" />' . "\n";
52
- echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save_id" id="ws-plugin--s2member-security-meta-box-save-id" value="' . esc_attr ($page_id) . '" />' . "\n";
53
  /**/
54
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
55
- $pages[$n] = array_unique (preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_pages"]));
56
  /**/
57
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
58
- $posts[$n] = array_unique (preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_posts"]));
59
  /**/
60
- echo '<p style="margin-left:2px;"><strong>Page Level Restriction?</strong></p>' . "\n";
61
- echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-level">Add Level Restriction?</label>' . "\n";
62
- echo '<select name="ws_plugin__s2member_security_meta_box_level" id="ws-plugin--s2member-security-meta-box-level" style="width:99%;">' . "\n";
63
- echo '<option value=""></option>' . "\n"; /* By default, we allow public access to any Post/Page. */
64
  /**/
65
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
66
- echo ($pages[$n] !== array ("all")) ? /* Protecting `all` Pages, of any kind? */
67
- ((!in_array ("all-pages", $posts[$n])) /* Protecting Posts of type: `page` ( i.e. `all-pages` )? */
68
- ? '<option value="' . $n . '"' . ((in_array ($page_id, $pages[$n])) ? ' selected="selected"' : '') . '>' . (($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Require Highest Level #' . $n : 'Require Level #' . $n . ' ( or higher )') . '</option>' . "\n"/**/
69
- : '<option value="" disabled="disabled">Level #' . $n . ' ( already protects "all" Posts of this type )</option>' . "\n")/**/
70
- : '<option value="" disabled="disabled">Level #' . $n . ' ( already protects "all" Pages )</option>' . "\n";
71
  /**/
72
- echo '</select><br /><small>* see: <code>Restriction Options -> Page Level Access</code></small>' . "\n";
73
  /**/
74
- if (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ())
75
  /* ^ Will change once Custom Capabilities are compatible with a Blog Farm. */
76
  {
77
- echo '<p style="margin-top:15px; margin-left:2px;"><strong>Require Custom Capabilities?</strong></p>' . "\n";
78
- echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-ccaps">Custom Capabilities?</label>' . "\n";
79
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_security_meta_box_ccaps" id="ws-plugin--s2member-security-meta-box-ccaps" value="' . format_to_edit (trim (implode (",", (array)get_post_meta ($page_id, "s2member_ccaps_req", true)))) . '" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" style="width:99%;" />' . "\n";
80
- echo '<br /><small>* see: <code>API Scripting -> Custom Capabilities</code></small>' . "\n";
81
  }
82
  }
83
  /**/
84
- else if ($page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
85
  echo 'This Page is your:<br /><strong>Membership Options Page</strong><br />( always publicly available )';
86
  /**/
87
- else if ($page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])
88
  echo 'This Page is your:<br /><strong>Login Welcome Page</strong><br />( automatically guarded by s2Member )';
89
  /**/
90
- else if ($page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"])
91
  echo 'This Page is your:<br /><strong>Download Limit Exceeded Page</strong><br />( automatically guarded by s2Member )';
92
  /**/
93
- else if (in_array ($page_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])))
94
  echo 'This Page is a:<br /><strong>Specific Post/Page for sale</strong><br />( already guarded by s2Member )';
95
  }
96
  else /* Otherwise, we assume this is a Post, or possibly a Custom Post Type. It's NOT a Page. */
97
  {
98
- if (!in_array ($post_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])))
99
  {
100
- echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save" id="ws-plugin--s2member-security-meta-box-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-security-meta-box-save")) . '" />' . "\n";
101
- echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save_id" id="ws-plugin--s2member-security-meta-box-save-id" value="' . esc_attr ($post_id) . '" />' . "\n";
102
  /**/
103
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
104
- $posts[$n] = array_unique (preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_posts"]));
105
  /**/
106
- echo '<p style="margin-left:2px;"><strong>Post Level Restriction?</strong></p>' . "\n";
107
- echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-level">Add Level Restriction?</label>' . "\n";
108
- echo '<select name="ws_plugin__s2member_security_meta_box_level" id="ws-plugin--s2member-security-meta-box-level" style="width:99%;">' . "\n";
109
- echo '<option value=""></option>' . "\n"; /* By default, we allow public access to any Post/Page. */
110
  /**/
111
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
112
- echo ($posts[$n] !== array ("all")) ? /* Protecting `all` Posts, of any kind? */
113
- ((!in_array ("all-" . $post->post_type . "s", $posts[$n])) /* Protecting Posts `all-[of-this-type]` ( don't forget plural `s` )? */
114
- ? '<option value="' . $n . '"' . ((in_array ($post_id, $posts[$n])) ? ' selected="selected"' : '') . '>' . (($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Require Highest Level #' . $n : 'Require Level #' . $n . ' ( or higher )') . '</option>' . "\n"/**/
115
- : '<option value="" disabled="disabled">Level #' . $n . ' ( already protects "all" Posts of this type )</option>' . "\n")/**/
116
- : '<option value="" disabled="disabled">Level #' . $n . ' ( already protects "all" Posts )</option>' . "\n";
117
  /**/
118
- echo '</select><br /><small>* see: <code>Restriction Options -> Post Level Access</code></small>' . "\n";
119
  /**/
120
- if (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ())
121
  /* ^ Will change once Custom Capabilities are compatible with a Blog Farm. */
122
  {
123
- echo '<p style="margin-top:15px; margin-left:2px;"><strong>Require Custom Capabilities?</strong></p>' . "\n";
124
- echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-ccaps">Custom Capabilities?</label>' . "\n";
125
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_security_meta_box_ccaps" id="ws-plugin--s2member-security-meta-box-ccaps" value="' . format_to_edit (trim (implode (",", (array)get_post_meta ($post_id, "s2member_ccaps_req", true)))) . '" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" style="width:99%;" />' . "\n";
126
- echo '<br /><small>* see: <code>API Scripting -> Custom Capabilities</code></small>' . "\n";
127
  }
128
  }
129
  /**/
130
- else if (in_array ($post_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])))
131
  echo 'This Post is a:<br /><strong>Specific Post/Page for sale</strong><br />( already guarded by s2Member )';
132
  }
133
  }
134
  /**/
135
- do_action ("ws_plugin__s2member_after_security_meta_box", get_defined_vars ());
136
  /**/
137
  return; /* Return for uniformity. */
138
  }
14
  * @package s2Member\Meta_Boxes
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_meta_box_security"))
21
  {
22
  /**
23
  * Security meta box.
36
  * @param obj $post Post/Page object.
37
  * @return null
38
  */
39
+ public static function security_meta_box($post = FALSE)
40
  {
41
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
42
+ do_action("ws_plugin__s2member_before_security_meta_box", get_defined_vars());
43
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
44
  /**/
45
+ if(is_object($post) && ($post_id = $post->ID) && (($post->post_type === "page" && current_user_can("edit_page", $post_id)) || current_user_can("edit_post", $post_id)))
46
  {
47
+ if($post->post_type === "page" && ($page_id = $post_id)) /* OK. So we're dealing with a Page classification. */
48
  {
49
+ if(!in_array($page_id, array_merge(array($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"]), preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"]))))
50
  {
51
+ echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save" id="ws-plugin--s2member-security-meta-box-save" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-security-meta-box-save")).'" />'."\n";
52
+ echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save_id" id="ws-plugin--s2member-security-meta-box-save-id" value="'.esc_attr($page_id).'" />'."\n";
53
  /**/
54
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
55
+ $pages[$n] = array_unique(preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_pages"]));
56
  /**/
57
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
58
+ $posts[$n] = array_unique(preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_posts"]));
59
  /**/
60
+ echo '<p style="margin-left:2px;"><strong>Page Level Restriction?</strong></p>'."\n";
61
+ echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-level">Add Level Restriction?</label>'."\n";
62
+ echo '<select name="ws_plugin__s2member_security_meta_box_level" id="ws-plugin--s2member-security-meta-box-level" style="width:99%;">'."\n";
63
+ echo '<option value=""></option>'."\n"; /* By default, we allow public access to any Post/Page. */
64
  /**/
65
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
66
+ echo ($pages[$n] !== array("all")) ? /* Protecting `all` Pages, of any kind? */
67
+ ((!in_array("all-pages", $posts[$n])) /* Protecting Posts of type: `page` ( i.e. `all-pages` )? */
68
+ ? '<option value="'.$n.'"'.((in_array($page_id, $pages[$n])) ? ' selected="selected"' : '').'>'.(($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Require Highest Level #'.$n : 'Require Level #'.$n.' ( or higher )').'</option>'."\n"/**/
69
+ : '<option value="" disabled="disabled">Level #'.$n.' ( already protects "all" Posts of this type )</option>'."\n")/**/
70
+ : '<option value="" disabled="disabled">Level #'.$n.' ( already protects "all" Pages )</option>'."\n";
71
  /**/
72
+ echo '</select><br /><small>* see: <code>Restriction Options -> Pages</code></small>'."\n";
73
  /**/
74
+ if(!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site())
75
  /* ^ Will change once Custom Capabilities are compatible with a Blog Farm. */
76
  {
77
+ echo '<p style="margin-top:15px; margin-left:2px;"><strong>Require Custom Capabilities?</strong></p>'."\n";
78
+ echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-ccaps">Custom Capabilities?</label>'."\n";
79
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_security_meta_box_ccaps" id="ws-plugin--s2member-security-meta-box-ccaps" value="'.format_to_edit(trim(implode(",", (array)get_post_meta($page_id, "s2member_ccaps_req", true)))).'" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" style="width:99%;" />'."\n";
80
+ echo '<br /><small>* see: <code>API Scripting -> Custom Capabilities</code></small>'."\n";
81
  }
82
  }
83
  /**/
84
+ else if($page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
85
  echo 'This Page is your:<br /><strong>Membership Options Page</strong><br />( always publicly available )';
86
  /**/
87
+ else if($page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])
88
  echo 'This Page is your:<br /><strong>Login Welcome Page</strong><br />( automatically guarded by s2Member )';
89
  /**/
90
+ else if($page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"])
91
  echo 'This Page is your:<br /><strong>Download Limit Exceeded Page</strong><br />( automatically guarded by s2Member )';
92
  /**/
93
+ else if(in_array($page_id, preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])))
94
  echo 'This Page is a:<br /><strong>Specific Post/Page for sale</strong><br />( already guarded by s2Member )';
95
  }
96
  else /* Otherwise, we assume this is a Post, or possibly a Custom Post Type. It's NOT a Page. */
97
  {
98
+ if(!in_array($post_id, preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])))
99
  {
100
+ echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save" id="ws-plugin--s2member-security-meta-box-save" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-security-meta-box-save")).'" />'."\n";
101
+ echo '<input type="hidden" name="ws_plugin__s2member_security_meta_box_save_id" id="ws-plugin--s2member-security-meta-box-save-id" value="'.esc_attr($post_id).'" />'."\n";
102
  /**/
103
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
104
+ $posts[$n] = array_unique(preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_posts"]));
105
  /**/
106
+ echo '<p style="margin-left:2px;"><strong>Post Level Restriction?</strong></p>'."\n";
107
+ echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-level">Add Level Restriction?</label>'."\n";
108
+ echo '<select name="ws_plugin__s2member_security_meta_box_level" id="ws-plugin--s2member-security-meta-box-level" style="width:99%;">'."\n";
109
+ echo '<option value=""></option>'."\n"; /* By default, we allow public access to any Post/Page. */
110
  /**/
111
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
112
+ echo ($posts[$n] !== array("all")) ? /* Protecting `all` Posts, of any kind? */
113
+ ((!in_array("all-".$post->post_type."s", $posts[$n])) /* Protecting Posts `all-[of-this-type]` ( don't forget plural `s` )? */
114
+ ? '<option value="'.$n.'"'.((in_array($post_id, $posts[$n])) ? ' selected="selected"' : '').'>'.(($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Require Highest Level #'.$n : 'Require Level #'.$n.' ( or higher )').'</option>'."\n"/**/
115
+ : '<option value="" disabled="disabled">Level #'.$n.' ( already protects "all" Posts of this type )</option>'."\n")/**/
116
+ : '<option value="" disabled="disabled">Level #'.$n.' ( already protects "all" Posts )</option>'."\n";
117
  /**/
118
+ echo '</select><br /><small>* see: <code>Restriction Options -> Posts</code></small>'."\n";
119
  /**/
120
+ if(!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site())
121
  /* ^ Will change once Custom Capabilities are compatible with a Blog Farm. */
122
  {
123
+ echo '<p style="margin-top:15px; margin-left:2px;"><strong>Require Custom Capabilities?</strong></p>'."\n";
124
+ echo '<label class="screen-reader-text" for="ws-plugin--s2member-security-meta-box-ccaps">Custom Capabilities?</label>'."\n";
125
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_security_meta_box_ccaps" id="ws-plugin--s2member-security-meta-box-ccaps" value="'.format_to_edit(trim(implode(",", (array)get_post_meta($post_id, "s2member_ccaps_req", true)))).'" onkeyup="if(this.value.match(/[^a-z_0-9,]/)) this.value = jQuery.trim (jQuery.trim (this.value).replace (/[ \-]/g, \'_\').replace (/[^a-z_0-9,]/gi, \'\').toLowerCase ());" style="width:99%;" />'."\n";
126
+ echo '<br /><small>* see: <code>API Scripting -> Custom Capabilities</code></small>'."\n";
127
  }
128
  }
129
  /**/
130
+ else if(in_array($post_id, preg_split("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])))
131
  echo 'This Post is a:<br /><strong>Specific Post/Page for sale</strong><br />( already guarded by s2Member )';
132
  }
133
  }
134
  /**/
135
+ do_action("ws_plugin__s2member_after_security_meta_box", get_defined_vars());
136
  /**/
137
  return; /* Return for uniformity. */
138
  }
includes/classes/mo-page-in.inc.php CHANGED
@@ -44,7 +44,7 @@ if (!class_exists ("c_ws_plugin__s2member_mo_page_in"))
44
  *
45
  * @return null Or exits script execution after redirection w/ `301` status.
46
  */
47
- public static function /* Real Membership Options Page. */ membership_options_page ()
48
  {
49
  do_action ("ws_plugin__s2member_before_membership_options_page", get_defined_vars ());
50
  /**/
44
  *
45
  * @return null Or exits script execution after redirection w/ `301` status.
46
  */
47
+ public static function membership_options_page /* Real Membership Options Page. */ ()
48
  {
49
  do_action ("ws_plugin__s2member_before_membership_options_page", get_defined_vars ());
50
  /**/
includes/classes/paypal-notify-in-subscr-or-rp-eots-w-level.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\PayPal
15
  * @since 110720
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_level"))
21
  {
22
  /**
23
  * s2Member's PayPal® IPN handler ( inner processing routine ).
@@ -38,129 +38,129 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
38
  *
39
  * @todo Optimize with ``empty()`` and ``isset()``.
40
  */
41
- public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
  extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
- if (/**/(/**/(!empty ($paypal["txn_type"]) && preg_match ("/^(subscr_eot|recurring_payment_expired|recurring_payment_suspended_due_to_max_failed_payment)$/i", $paypal["txn_type"]) && ($recurring = true))/**/
46
- || (!empty ($paypal["txn_type"]) && preg_match ("/^recurring_payment_profile_cancel$/i", $paypal["txn_type"]) && !empty ($paypal["initial_payment_status"]) && preg_match ("/^failed$/i", $paypal["initial_payment_status"]) && ($recurring = true))/**/
47
- || (!empty ($paypal["txn_type"]) && preg_match ("/^new_case$/i", $paypal["txn_type"]) && !empty ($paypal["case_type"]) && preg_match ("/^chargeback$/i", $paypal["case_type"]) && !($recurring = false)) /* Seeking this for future compatibility. */
48
- || (!empty ($paypal["payment_status"]) && preg_match ("/^(refunded|reversed|reversal)$/i", $paypal["payment_status"]) && !($recurring = false))/**/) /* The `txn_type` is irrelevant in all of these payment statuses: `refunded|reversed|reversal`. */
49
- && (!empty ($paypal["subscr_id"]) || ($paypal["subscr_id"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_subscr_id ($paypal)) || (!empty ($paypal["parent_txn_id"]) && ($paypal["subscr_id"] = $paypal["parent_txn_id"]))) /* Other MUST haves. */
50
- && (!empty ($paypal["period1"]) || ($paypal["period1"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_period1 ($paypal, false)) || empty ($recurring) || ($paypal["period1"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var ("period1", false, $paypal["subscr_id"])) || ($paypal["period1"] = "0 D"))/**/
51
- && (!empty ($paypal["period3"]) || ($paypal["period3"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_period3 ($paypal, false)) || empty ($recurring) || ($paypal["period3"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var ("period3", false, $paypal["subscr_id"])) || ($paypal["period3"] = "1 D"))/**/
52
- && ((!empty ($paypal["item_number"]) || ($paypal["item_number"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_item_number ($paypal)) || ($paypal["item_number"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var ("item_number", false, $paypal["subscr_id"]))) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
53
- && (!empty ($paypal["item_name"]) || ($paypal["item_name"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_item_name ($paypal)) || ($paypal["item_name"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var ("item_name", false, $paypal["subscr_id"])) || ($paypal["item_name"] = $_SERVER["HTTP_HOST"]))/**/
54
- && (!empty ($paypal["payer_email"]) || ($paypal["payer_email"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var ("payer_email", false, $paypal["subscr_id"])) || ($paypal["payer_email"] = c_ws_plugin__s2member_utils_users::get_user_email_with ($paypal["subscr_id"])))/**/)
55
  {
56
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
57
- do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_eot", get_defined_vars ());
58
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
59
  /**/
60
- if (!get_transient ($transient_ipn = "s2m_ipn_" . md5 ("s2member_transient_" . $_paypal_s)) && set_transient ($transient_ipn, time (), 31556926 * 10))
61
  {
62
- $is_refund = (preg_match ("/^refunded$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
63
- $is_reversal = (preg_match ("/^(reversed|reversal)$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
64
- $is_reversal = (!$is_reversal) ? (preg_match ("/^new_case$/i", $paypal["txn_type"]) && preg_match ("/^chargeback$/i", $paypal["case_type"])) : $is_reversal;
65
  $is_refund_or_reversal = ($is_refund || $is_reversal); /* If either of the previous tests above evaluated to true; then it's obviously a Refund and/or a Reversal. */
66
- $is_delayed_eot = (!$is_refund_or_reversal && preg_match ("/^(subscr_eot|recurring_payment_expired)$/i", $paypal["txn_type"]) && preg_match ("/^I-/i", $paypal["subscr_id"]));
67
  /**/
68
- if ($is_refund_or_reversal)
69
- $paypal["s2member_log"][] = "s2Member `txn_type` identified as " . ($identified_as = "( `[empty or irrelevant]` ) w/ `payment_status` ( `refunded|reversed|reversal` ) - or - `new_case` w/ `case_type` ( `chargeback` )") . ".";
70
  else
71
- $paypal["s2member_log"][] = "s2Member `txn_type` identified as " . ($identified_as = "( `subscr_eot|recurring_payment_expired|recurring_payment_suspended_due_to_max_failed_payment` ) - or - `recurring_payment_profile_cancel` w/ `initial_payment_status` ( `failed` )") . ".";
72
  /**/
73
  $paypal["s2member_log"][] = "Sleeping for 5 seconds. Waiting for a possible ( `subscr_signup|subscr_modify|recurring_payment_profile_created` ).";
74
  sleep(5); /* Sleep here for a moment. PayPal® sometimes sends a subscr_eot before the subscr_signup, subscr_modify. */
75
  /* It is NOT a big deal if they do. However, s2Member goes to sleep here, just to help keep the log files in a logical order. */
76
- $paypal["s2member_log"][] = "Awake. It's " . date ("D M j, Y g:i:s a T") . ". s2Member `txn_type` identified as " . $identified_as . ".";
77
  /**/
78
- $paypal["ip"] = (preg_match ("/ip address/i", $paypal["option_name2"]) && $paypal["option_selection2"]) ? $paypal["option_selection2"] : "";
79
- $paypal["ip"] = (!$paypal["ip"] && preg_match ("/^[a-z0-9]+~[0-9\.]+$/i", $paypal["invoice"])) ? preg_replace ("/^[a-z0-9]+~/i", "", $paypal["invoice"]) : $paypal["ip"];
80
  /**/
81
- if (($user_id = c_ws_plugin__s2member_utils_users::get_user_id_with ($paypal["subscr_id"])) && is_object ($user = new WP_User ($user_id)) && !empty ($user->ID))
82
  {
83
- $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed below. */
84
- $user_reg_ip = get_user_option ("s2member_registration_ip", $user_id); /* Needed below. */
85
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"];
86
  /**/
87
- if ( /* Here we take action, BUT based on Auto EOT Behavior options; as configured by the Site Owner. */
88
- (!$is_refund_or_reversal && !$is_delayed_eot && !get_user_option ("s2member_auto_eot_time", $user_id))/**/
89
  || ($is_refund_or_reversal && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds,reversals")/**/
90
  || ($is_reversal && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "reversals")/**/
91
  || ($is_refund && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds")/**/)
92
  {
93
- if (!$user->has_cap ("administrator")) /* Do NOT process this routine on Administrators. */
94
  {
95
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"]) /* EOT enabled? */
96
  {
97
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "demote")
98
  {
99
  $processing = $during = true; /* Yes, we ARE processing this. */
100
  /**/
101
  $eot_del_type = ($is_refund_or_reversal) ? /* Set EOT/Del type. */
102
  "ipn-refund-reversal-demotion" : "ipn-cancellation-expiration-demotion";
103
  /**/
104
- $demotion_role = c_ws_plugin__s2member_option_forces::force_demotion_role ("subscriber");
105
- $existing_role = c_ws_plugin__s2member_user_access::user_access_role ($user);
106
  /**/
107
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
108
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_before_demote", get_defined_vars ());
109
- do_action ("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars (), $eot_del_type, "modification", $demotion_role);
110
- do_action ("ws_plugin__s2member_during_collective_eots", $user_id, get_defined_vars (), $eot_del_type, "modification");
111
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
112
  /**/
113
- if ($existing_role !== $demotion_role) /* Only if NOT the existing Role. */
114
- $user->set_role ($demotion_role); /* Give User the demotion Role. */
115
  /**/
116
- foreach ($user->allcaps as $cap => $cap_enabled)
117
- if (preg_match ("/^access_s2member_ccap_/", $cap))
118
- $user->remove_cap ($ccap = $cap);
119
  /**/
120
- delete_user_option ($user_id, "s2member_custom");
121
- delete_user_option ($user_id, "s2member_subscr_id");
122
- delete_user_option ($user_id, "s2member_subscr_gateway");
123
  /**/
124
- delete_user_option ($user_id, "s2member_ipn_signup_vars");
125
- if (!apply_filters ("ws_plugin__s2member_preserve_paid_registration_times", true, get_defined_vars ()))
126
- delete_user_option ($user_id, "s2member_paid_registration_times");
127
  /**/
128
- delete_user_option ($user_id, "s2member_last_status_scan");
129
- delete_user_option ($user_id, "s2member_first_payment_txn_id");
130
- delete_user_option ($user_id, "s2member_last_payment_time");
131
- delete_user_option ($user_id, "s2member_auto_eot_time");
132
  /**/
133
- delete_user_option ($user_id, "s2member_file_download_access_log");
134
  /**/
135
- c_ws_plugin__s2member_user_notes::append_user_notes ($user_id, "Demoted by s2Member: " . date ("D M j, Y g:i a T"));
136
  /**/
137
- $paypal["s2member_log"][] = "Member Level/Capabilities demoted to: " . ucwords (preg_replace ("/_/", " ", $demotion_role)) . ".";
138
  /**/
139
- if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
140
  {
141
- foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) as $url) /* Handle EOT Notifications. */
142
  /**/
143
- if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%eot_del_type%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($eot_del_type)), $url)) && ($url = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["subscr_id"])), $url)))
144
- if (($url = preg_replace ("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user->first_name)), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user->last_name)), $url)))
145
- if (($url = preg_replace ("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode (trim ($user->first_name . " " . $user->last_name))), $url)))
146
- if (($url = preg_replace ("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user->user_email)), $url)))
147
- if (($url = preg_replace ("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user->user_login)), $url)))
148
- if (($url = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user_reg_ip)), $url)))
149
- if (($url = preg_replace ("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user_id)), $url)))
150
  {
151
- if (is_array ($fields) && !empty ($fields))
152
- foreach ($fields as $var => $val) /* Custom Registration/Profile Fields. */
153
- if (!($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode (maybe_serialize ($val))), $url)))
154
  break;
155
  /**/
156
- if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
157
- c_ws_plugin__s2member_utils_urls::remote ($url);
158
  }
159
  /**/
160
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
161
  }
162
  /**/
163
- if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
164
  {
165
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
166
  $msg .= "\n\n"; /* Spacing in the message body. */
@@ -175,9 +175,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
175
  $msg .= "user_ip: %%user_ip%%\n";
176
  $msg .= "user_id: %%user_id%%\n";
177
  /**/
178
- if (is_array ($fields) && !empty ($fields))
179
- foreach ($fields as $var => $val)
180
- $msg .= $var . ": %%" . $var . "%%\n";
181
  /**/
182
  $msg .= "cv0: %%cv0%%\n";
183
  $msg .= "cv1: %%cv1%%\n";
@@ -190,34 +190,34 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
190
  $msg .= "cv8: %%cv8%%\n";
191
  $msg .= "cv9: %%cv9%%";
192
  /**/
193
- if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%eot_del_type%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($eot_del_type), $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["subscr_id"]), $msg)))
194
- if (($msg = preg_replace ("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->first_name), $msg)) && ($msg = preg_replace ("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->last_name), $msg)))
195
- if (($msg = preg_replace ("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($user->first_name . " " . $user->last_name)), $msg)))
196
- if (($msg = preg_replace ("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->user_email), $msg)))
197
- if (($msg = preg_replace ("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->user_login), $msg)))
198
- if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_reg_ip), $msg)))
199
- if (($msg = preg_replace ("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_id), $msg)))
200
  {
201
- if (is_array ($fields) && !empty ($fields))
202
- foreach ($fields as $var => $val) /* Custom Registration/Profile Fields. */
203
- if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
204
  break;
205
  /**/
206
- if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
207
  /**/
208
- foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"]) as $recipient)
209
- wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
210
  }
211
  /**/
212
  $paypal["s2member_log"][] = "EOT/Deletion Notification Emails have been processed.";
213
  }
214
  /**/
215
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
216
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_demote", get_defined_vars ());
217
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
218
  }
219
  /**/
220
- else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "delete")
221
  {
222
  $processing = $during = true; /* Yes, we ARE processing this. */
223
  /**/
@@ -225,96 +225,96 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
225
  ($is_refund_or_reversal) ? "ipn-refund-reversal-deletion" : "ipn-cancellation-expiration-deletion";
226
  /**/
227
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
228
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_before_delete", get_defined_vars ());
229
- do_action ("ws_plugin__s2member_during_collective_eots", $user_id, get_defined_vars (), $eot_del_type, "removal-deletion");
230
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
231
  /**/
232
- if (is_multisite ()) /* Multisite does NOT actually delete; ONLY removes. */
233
  {
234
- remove_user_from_blog ($user_id, $current_blog->blog_id);
235
  /* This will automatically trigger `eot_del_notification_urls` as well. */
236
- c_ws_plugin__s2member_user_deletions::handle_ms_user_deletions ($user_id, $current_blog->blog_id, "s2says");
237
  }
238
  /**/
239
  else /* Otherwise, we can actually delete them. */
240
  /* This will automatically trigger `eot_del_notification_urls` as well. */
241
  wp_delete_user($user_id); /* `c_ws_plugin__s2member_user_deletions::handle_user_deletions()` */
242
  /**/
243
- $paypal["s2member_log"][] = "This Member's account has been " . ((is_multisite ()) ? "removed" : "deleted") . ".";
244
  /**/
245
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
246
  /**/
247
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
248
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_delete", get_defined_vars ());
249
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
250
  }
251
  /**/
252
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
253
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot", get_defined_vars ());
254
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
255
  }
256
  /**/
257
  else /* Otherwise, treat this as if it were a cancellation. EOTs are currently disabled. */
258
  {
259
  $processing = $during = true; /* Yes, we ARE processing this. */
260
  /**/
261
- update_user_option ($user_id, "s2member_auto_eot_time", ($auto_eot_time = strtotime ("now")));
262
  /**/
263
  $paypal["s2member_log"][] = "Auto-EOT is currently disabled. Skipping immediate EOT ( demote|delete ), for now.";
264
- $paypal["s2member_log"][] = "Recording the Auto-EOT Time for this Member's account: " . date ("D M j, Y g:i a T", $auto_eot_time);
265
  /**/
266
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
267
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_disabled", get_defined_vars ());
268
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
269
  }
270
  }
271
  else
272
  $paypal["s2member_log"][] = "Unable to ( demote|delete ) Member. The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access.";
273
  }
274
  /**/
275
- else if ($is_delayed_eot && !get_user_option ("s2member_auto_eot_time", $user_id))
276
  {
277
- if (!$user->has_cap ("administrator")) /* Do NOT process this routine on Administrators. */
278
  {
279
  $processing = $during = true; /* Yes, we ARE processing this. */
280
  /**/
281
- $auto_eot_time = c_ws_plugin__s2member_utils_time::auto_eot_time ($user_id, $paypal["period1"], $paypal["period3"], "", time ());
282
  /* We assume the last payment was today, because this is how newer PayPal® accounts function with respect to EOT handling.
283
  Newer PayPal® accounts ( i.e. Subscription IDs starting with `I-`, will have their EOT triggered upon the last payment. */
284
- update_user_option ($user_id, "s2member_auto_eot_time", $auto_eot_time); /* s2Member will follow-up on this later. */
285
  /**/
286
- $paypal["s2member_log"][] = "Auto-EOT Time for this account ( delayed ), set to: " . date ("D M j, Y g:i a T", $auto_eot_time);
287
  /**/
288
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
289
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_delayed", get_defined_vars ());
290
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
291
  }
292
  else
293
  $paypal["s2member_log"][] = "Ignoring Delayed EOT. The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access.";
294
  }
295
  /**/
296
- else if (!$is_refund_or_reversal || $is_delayed_eot)
297
  $paypal["s2member_log"][] = "Skipping ( demote|delete ) Member, for now. An Auto-EOT Time is already set for this account. When an Auto-EOT Time has been recorded, s2Member will handle EOT ( demote|delete ) events using it's own Auto-EOT System - internally.";
298
  /**/
299
- else if ($is_reversal)
300
  $paypal["s2member_log"][] = "Skipping ( demote|delete ) Member. Your configuration dictates that s2Member should NOT take any immediate action on an EOT associated with a Chargeback Reversal. An s2Member API Notification will still be processed however.";
301
  /**/
302
- else if ($is_refund)
303
  $paypal["s2member_log"][] = "Skipping ( demote|delete ) Member. Your configuration dictates that s2Member should NOT take any immediate action on an EOT associated with a Refund. An s2Member API Notification will still be processed however.";
304
  }
305
- else if ($is_delayed_eot) /* Otherwise, we need to re-generate/store this IPN into a Transient Queue. Then re-process it on registration. */
306
  {
307
  $paypal["s2member_log"][] = "Skipping this IPN response, for now. The Subscr. ID is not associated with a registered Member.";
308
  /**/
309
- $ipn = array ("txn_type" => "subscr_eot"); /* Create a simulated IPN response for txn_type=subscr_eot. */
310
  /**/
311
- foreach ($paypal as $var => $val)
312
- if (in_array ($var, array ("subscr_gateway", "subscr_id", "custom", "invoice", "payer_email", "first_name", "last_name", "item_name", "item_number", /* Exclude; might be defaults. "period1", "period3", */ "option_name1", "option_selection1", "option_name2", "option_selection2")))
313
  $ipn[$var] = $val;
314
  /**/
315
  $paypal["s2member_log"][] = "Re-generating. This IPN will go into a Transient Queue; and be re-processed during registration.";
316
  /**/
317
- set_transient ("s2m_" . md5 ("s2member_transient_ipn_subscr_eot_" . $paypal["subscr_id"]), $ipn, 43200);
318
  }
319
  /**/
320
  else
@@ -325,38 +325,38 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
325
  Since this routine ignores the processing check, it is *possible* that Refund/Reversal Notification URLs will be contacted more than once.
326
  If you're writing scripts that depend on Refund/Reversal Notifications, please keep this in mind.
327
  */
328
- if ($is_refund_or_reversal) /* Here we access this variable that was previously assigned as a quick method of Refund/Reversal detection. */
329
  {
330
- $fields = ($user_id) ? get_user_option ("s2member_custom_fields", $user_id) : array (); /* These will be needed below. */
331
- $user_reg_ip = ($user_id) ? get_user_option ("s2member_registration_ip", $user_id) : ""; /* Needed below. */
332
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"]; /* Now merge conditionally. */
333
  /**/
334
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
335
  {
336
- foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) as $url)
337
  /**/
338
- if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["subscr_id"])), $url)) && ($url = preg_replace ("/%%parent_txn_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["parent_txn_id"])), $url)))
339
- if (($url = preg_replace ("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["item_name"])), $url)))
340
- if (($url = preg_replace ("/%%-amount%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["mc_gross"])), $url)) && ($url = preg_replace ("/%%-fee%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["mc_fee"])), $url)))
341
- if (($url = preg_replace ("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["last_name"])), $url)))
342
- if (($url = preg_replace ("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
343
- if (($url = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($paypal["payer_email"])), $url)))
344
- if (($url = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user_reg_ip)), $url)))
345
- if (($url = preg_replace ("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode ($user_id)), $url)))
346
  {
347
- if (is_array ($fields) && !empty ($fields))
348
- foreach ($fields as $var => $val) /* Custom Registration/Profile Fields. */
349
- if (!($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (urlencode (maybe_serialize ($val))), $url)))
350
  break;
351
  /**/
352
- if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
353
- c_ws_plugin__s2member_utils_urls::remote ($url);
354
  }
355
  /**/
356
  $paypal["s2member_log"][] = "Refund/Reversal Notification URLs have been processed.";
357
  }
358
  /**/
359
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
360
  {
361
  $msg = $sbj = "( s2Member / API Notification Email ) - Refund/Reversal";
362
  $msg .= "\n\n"; /* Spacing in the message body. */
@@ -374,9 +374,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
374
  $msg .= "user_ip: %%user_ip%%\n";
375
  $msg .= "user_id: %%user_id%%\n";
376
  /**/
377
- if (is_array ($fields) && !empty ($fields))
378
- foreach ($fields as $var => $val)
379
- $msg .= $var . ": %%" . $var . "%%\n";
380
  /**/
381
  $msg .= "cv0: %%cv0%%\n";
382
  $msg .= "cv1: %%cv1%%\n";
@@ -389,32 +389,32 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
389
  $msg .= "cv8: %%cv8%%\n";
390
  $msg .= "cv9: %%cv9%%";
391
  /**/
392
- if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["subscr_id"]), $msg)) && ($msg = preg_replace ("/%%parent_txn_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["parent_txn_id"]), $msg)))
393
- if (($msg = preg_replace ("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_name"]), $msg)))
394
- if (($msg = preg_replace ("/%%-amount%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["mc_gross"]), $msg)) && ($msg = preg_replace ("/%%-fee%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["mc_fee"]), $msg)))
395
- if (($msg = preg_replace ("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["last_name"]), $msg)))
396
- if (($msg = preg_replace ("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
397
- if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
398
- if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_reg_ip), $msg)))
399
- if (($msg = preg_replace ("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_id), $msg)))
400
  {
401
- if (is_array ($fields) && !empty ($fields))
402
- foreach ($fields as $var => $val) /* Custom Registration/Profile Fields. */
403
- if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
404
  break;
405
  /**/
406
- if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
407
  /**/
408
- foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"]) as $recipient)
409
- wp_mail ($recipient, apply_filters ("ws_plugin__s2member_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
410
  }
411
  /**/
412
  $paypal["s2member_log"][] = "Refund/Reversal Notification Emails have been processed.";
413
  }
414
  /**/
415
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
416
- do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_refund_reversal", get_defined_vars ());
417
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
418
  }
419
  }
420
  else /* Else, this is a duplicate IPN. Must stop here. */
@@ -425,13 +425,13 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
425
  }
426
  /**/
427
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
428
- do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_eot", get_defined_vars ());
429
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
430
  /**/
431
- return apply_filters ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_level", $paypal, get_defined_vars ());
432
  }
433
  else
434
- return apply_filters ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_level", false, get_defined_vars ());
435
  }
436
  }
437
  }
14
  * @package s2Member\PayPal
15
  * @since 110720
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_level"))
21
  {
22
  /**
23
  * s2Member's PayPal® IPN handler ( inner processing routine ).
38
  *
39
  * @todo Optimize with ``empty()`` and ``isset()``.
40
  */
41
+ public static function cp($vars = array()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
  extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
+ if(/**/(/**/(!empty($paypal["txn_type"]) && preg_match("/^(subscr_eot|recurring_payment_expired|recurring_payment_suspended_due_to_max_failed_payment)$/i", $paypal["txn_type"]) && ($recurring = true))/**/
46
+ || (!empty($paypal["txn_type"]) && preg_match("/^recurring_payment_profile_cancel$/i", $paypal["txn_type"]) && !empty($paypal["initial_payment_status"]) && preg_match("/^failed$/i", $paypal["initial_payment_status"]) && ($recurring = true))/**/
47
+ || (!empty($paypal["txn_type"]) && preg_match("/^new_case$/i", $paypal["txn_type"]) && !empty($paypal["case_type"]) && preg_match("/^chargeback$/i", $paypal["case_type"]) && !($recurring = false)) /* Seeking this for future compatibility. */
48
+ || (!empty($paypal["payment_status"]) && preg_match("/^(refunded|reversed|reversal)$/i", $paypal["payment_status"]) && !($recurring = false))/**/) /* The `txn_type` is irrelevant in all of these payment statuses: `refunded|reversed|reversal`. */
49
+ && (!empty($paypal["subscr_id"]) || ($paypal["subscr_id"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_subscr_id($paypal)) || (!empty($paypal["parent_txn_id"]) && ($paypal["subscr_id"] = $paypal["parent_txn_id"]))) /* Other MUST haves. */
50
+ && (!empty($paypal["period1"]) || ($paypal["period1"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_period1($paypal, false)) || empty($recurring) || ($paypal["period1"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var("period1", false, $paypal["subscr_id"])) || ($paypal["period1"] = "0 D"))/**/
51
+ && (!empty($paypal["period3"]) || ($paypal["period3"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_period3($paypal, false)) || empty($recurring) || ($paypal["period3"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var("period3", false, $paypal["subscr_id"])) || ($paypal["period3"] = "1 D"))/**/
52
+ && ((!empty($paypal["item_number"]) || ($paypal["item_number"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_item_number($paypal)) || ($paypal["item_number"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var("item_number", false, $paypal["subscr_id"])) || ($paypal["item_number"] = "1")) && preg_match($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
53
+ && (!empty($paypal["item_name"]) || ($paypal["item_name"] = c_ws_plugin__s2member_paypal_utilities::paypal_pro_item_name($paypal)) || ($paypal["item_name"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var("item_name", false, $paypal["subscr_id"])) || ($paypal["item_name"] = $_SERVER["HTTP_HOST"]))/**/
54
+ && (!empty($paypal["payer_email"]) || ($paypal["payer_email"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_var("payer_email", false, $paypal["subscr_id"])) || ($paypal["payer_email"] = c_ws_plugin__s2member_utils_users::get_user_email_with($paypal["subscr_id"])))/**/)
55
  {
56
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
57
+ do_action("ws_plugin__s2member_during_paypal_notify_before_subscr_eot", get_defined_vars());
58
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
59
  /**/
60
+ if(!get_transient($transient_ipn = "s2m_ipn_".md5("s2member_transient_".$_paypal_s)) && set_transient($transient_ipn, time(), 31556926 * 10))
61
  {
62
+ $is_refund = (preg_match("/^refunded$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
63
+ $is_reversal = (preg_match("/^(reversed|reversal)$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
64
+ $is_reversal = (!$is_reversal) ? (preg_match("/^new_case$/i", $paypal["txn_type"]) && preg_match("/^chargeback$/i", $paypal["case_type"])) : $is_reversal;
65
  $is_refund_or_reversal = ($is_refund || $is_reversal); /* If either of the previous tests above evaluated to true; then it's obviously a Refund and/or a Reversal. */
66
+ $is_delayed_eot = (!$is_refund_or_reversal && preg_match("/^(subscr_eot|recurring_payment_expired)$/i", $paypal["txn_type"]) && preg_match("/^I-/i", $paypal["subscr_id"]));
67
  /**/
68
+ if($is_refund_or_reversal)
69
+ $paypal["s2member_log"][] = "s2Member `txn_type` identified as ".($identified_as = "( `[empty or irrelevant]` ) w/ `payment_status` ( `refunded|reversed|reversal` ) - or - `new_case` w/ `case_type` ( `chargeback` )").".";
70
  else
71
+ $paypal["s2member_log"][] = "s2Member `txn_type` identified as ".($identified_as = "( `subscr_eot|recurring_payment_expired|recurring_payment_suspended_due_to_max_failed_payment` ) - or - `recurring_payment_profile_cancel` w/ `initial_payment_status` ( `failed` )").".";
72
  /**/
73
  $paypal["s2member_log"][] = "Sleeping for 5 seconds. Waiting for a possible ( `subscr_signup|subscr_modify|recurring_payment_profile_created` ).";
74
  sleep(5); /* Sleep here for a moment. PayPal® sometimes sends a subscr_eot before the subscr_signup, subscr_modify. */
75
  /* It is NOT a big deal if they do. However, s2Member goes to sleep here, just to help keep the log files in a logical order. */
76
+ $paypal["s2member_log"][] = "Awake. It's ".date("D M j, Y g:i:s a T").". s2Member `txn_type` identified as ".$identified_as.".";
77
  /**/
78
+ $paypal["ip"] = (preg_match("/ip address/i", $paypal["option_name2"]) && $paypal["option_selection2"]) ? $paypal["option_selection2"] : "";
79
+ $paypal["ip"] = (!$paypal["ip"] && preg_match("/^[a-z0-9]+~[0-9\.]+$/i", $paypal["invoice"])) ? preg_replace("/^[a-z0-9]+~/i", "", $paypal["invoice"]) : $paypal["ip"];
80
  /**/
81
+ if(($user_id = c_ws_plugin__s2member_utils_users::get_user_id_with($paypal["subscr_id"])) && is_object($user = new WP_User($user_id)) && !empty($user->ID))
82
  {
83
+ $fields = get_user_option("s2member_custom_fields", $user_id); /* These will be needed below. */
84
+ $user_reg_ip = get_user_option("s2member_registration_ip", $user_id); /* Needed below. */
85
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"];
86
  /**/
87
+ if( /* Here we take action, BUT based on Auto EOT Behavior options; as configured by the Site Owner. */
88
+ (!$is_refund_or_reversal && !$is_delayed_eot && !get_user_option("s2member_auto_eot_time", $user_id))/**/
89
  || ($is_refund_or_reversal && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds,reversals")/**/
90
  || ($is_reversal && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "reversals")/**/
91
  || ($is_refund && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds")/**/)
92
  {
93
+ if(!$user->has_cap("administrator")) /* Do NOT process this routine on Administrators. */
94
  {
95
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"]) /* EOT enabled? */
96
  {
97
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "demote")
98
  {
99
  $processing = $during = true; /* Yes, we ARE processing this. */
100
  /**/
101
  $eot_del_type = ($is_refund_or_reversal) ? /* Set EOT/Del type. */
102
  "ipn-refund-reversal-demotion" : "ipn-cancellation-expiration-demotion";
103
  /**/
104
+ $demotion_role = c_ws_plugin__s2member_option_forces::force_demotion_role("subscriber");
105
+ $existing_role = c_ws_plugin__s2member_user_access::user_access_role($user);
106
  /**/
107
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
108
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_before_demote", get_defined_vars());
109
+ do_action("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars(), $eot_del_type, "modification", $demotion_role);
110
+ do_action("ws_plugin__s2member_during_collective_eots", $user_id, get_defined_vars(), $eot_del_type, "modification");
111
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
112
  /**/
113
+ if($existing_role !== $demotion_role) /* Only if NOT the existing Role. */
114
+ $user->set_role($demotion_role); /* Give User the demotion Role. */
115
  /**/
116
+ foreach($user->allcaps as $cap => $cap_enabled)
117
+ if(preg_match("/^access_s2member_ccap_/", $cap))
118
+ $user->remove_cap($ccap = $cap);
119
  /**/
120
+ delete_user_option($user_id, "s2member_custom");
121
+ delete_user_option($user_id, "s2member_subscr_id");
122
+ delete_user_option($user_id, "s2member_subscr_gateway");
123
  /**/
124
+ delete_user_option($user_id, "s2member_ipn_signup_vars");
125
+ if(!apply_filters("ws_plugin__s2member_preserve_paid_registration_times", true, get_defined_vars()))
126
+ delete_user_option($user_id, "s2member_paid_registration_times");
127
  /**/
128
+ delete_user_option($user_id, "s2member_last_status_scan");
129
+ delete_user_option($user_id, "s2member_first_payment_txn_id");
130
+ delete_user_option($user_id, "s2member_last_payment_time");
131
+ delete_user_option($user_id, "s2member_auto_eot_time");
132
  /**/
133
+ delete_user_option($user_id, "s2member_file_download_access_log");
134
  /**/
135
+ c_ws_plugin__s2member_user_notes::append_user_notes($user_id, "Demoted by s2Member: ".date("D M j, Y g:i a T"));
136
  /**/
137
+ $paypal["s2member_log"][] = "Member Level/Capabilities demoted to: ".ucwords(preg_replace("/_/", " ", $demotion_role)).".";
138
  /**/
139
+ if($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"] && is_array($cv = preg_split("/\|/", $paypal["custom"])))
140
  {
141
+ foreach(preg_split("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) as $url) /* Handle EOT Notifications. */
142
  /**/
143
+ if(($url = preg_replace("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace("/%%eot_del_type%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($eot_del_type)), $url)) && ($url = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["subscr_id"])), $url)))
144
+ if(($url = preg_replace("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user->first_name)), $url)) && ($url = preg_replace("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user->last_name)), $url)))
145
+ if(($url = preg_replace("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode(trim($user->first_name." ".$user->last_name))), $url)))
146
+ if(($url = preg_replace("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user->user_email)), $url)))
147
+ if(($url = preg_replace("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user->user_login)), $url)))
148
+ if(($url = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user_reg_ip)), $url)))
149
+ if(($url = preg_replace("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user_id)), $url)))
150
  {
151
+ if(is_array($fields) && !empty($fields))
152
+ foreach($fields as $var => $val) /* Custom Registration/Profile Fields. */
153
+ if(!($url = preg_replace("/%%".preg_quote($var, "/")."%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode(maybe_serialize($val))), $url)))
154
  break;
155
  /**/
156
+ if(($url = trim(preg_replace("/%%(.+?)%%/i", "", $url))))
157
+ c_ws_plugin__s2member_utils_urls::remote($url);
158
  }
159
  /**/
160
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
161
  }
162
  /**/
163
+ if($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"] && is_array($cv = preg_split("/\|/", $paypal["custom"])))
164
  {
165
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
166
  $msg .= "\n\n"; /* Spacing in the message body. */
175
  $msg .= "user_ip: %%user_ip%%\n";
176
  $msg .= "user_id: %%user_id%%\n";
177
  /**/
178
+ if(is_array($fields) && !empty($fields))
179
+ foreach($fields as $var => $val)
180
+ $msg .= $var.": %%".$var."%%\n";
181
  /**/
182
  $msg .= "cv0: %%cv0%%\n";
183
  $msg .= "cv1: %%cv1%%\n";
190
  $msg .= "cv8: %%cv8%%\n";
191
  $msg .= "cv9: %%cv9%%";
192
  /**/
193
+ if(($msg = preg_replace("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace("/%%eot_del_type%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($eot_del_type), $msg)) && ($msg = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["subscr_id"]), $msg)))
194
+ if(($msg = preg_replace("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->first_name), $msg)) && ($msg = preg_replace("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->last_name), $msg)))
195
+ if(($msg = preg_replace("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($user->first_name." ".$user->last_name)), $msg)))
196
+ if(($msg = preg_replace("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->user_email), $msg)))
197
+ if(($msg = preg_replace("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->user_login), $msg)))
198
+ if(($msg = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_reg_ip), $msg)))
199
+ if(($msg = preg_replace("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_id), $msg)))
200
  {
201
+ if(is_array($fields) && !empty($fields))
202
+ foreach($fields as $var => $val) /* Custom Registration/Profile Fields. */
203
+ if(!($msg = preg_replace("/%%".preg_quote($var, "/")."%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(maybe_serialize($val)), $msg)))
204
  break;
205
  /**/
206
+ if($sbj && ($msg = trim(preg_replace("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
207
  /**/
208
+ foreach(c_ws_plugin__s2member_utils_strings::parse_emails($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"]) as $recipient)
209
+ wp_mail($recipient, apply_filters("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars()), apply_filters("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars()), "Content-Type: text/plain; charset=utf-8");
210
  }
211
  /**/
212
  $paypal["s2member_log"][] = "EOT/Deletion Notification Emails have been processed.";
213
  }
214
  /**/
215
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
216
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_demote", get_defined_vars());
217
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
218
  }
219
  /**/
220
+ else if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "delete")
221
  {
222
  $processing = $during = true; /* Yes, we ARE processing this. */
223
  /**/
225
  ($is_refund_or_reversal) ? "ipn-refund-reversal-deletion" : "ipn-cancellation-expiration-deletion";
226
  /**/
227
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
228
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_before_delete", get_defined_vars());
229
+ do_action("ws_plugin__s2member_during_collective_eots", $user_id, get_defined_vars(), $eot_del_type, "removal-deletion");
230
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
231
  /**/
232
+ if(is_multisite()) /* Multisite does NOT actually delete; ONLY removes. */
233
  {
234
+ remove_user_from_blog($user_id, $current_blog->blog_id);
235
  /* This will automatically trigger `eot_del_notification_urls` as well. */
236
+ c_ws_plugin__s2member_user_deletions::handle_ms_user_deletions($user_id, $current_blog->blog_id, "s2says");
237
  }
238
  /**/
239
  else /* Otherwise, we can actually delete them. */
240
  /* This will automatically trigger `eot_del_notification_urls` as well. */
241
  wp_delete_user($user_id); /* `c_ws_plugin__s2member_user_deletions::handle_user_deletions()` */
242
  /**/
243
+ $paypal["s2member_log"][] = "This Member's account has been ".((is_multisite()) ? "removed" : "deleted").".";
244
  /**/
245
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
246
  /**/
247
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
248
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_delete", get_defined_vars());
249
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
250
  }
251
  /**/
252
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
253
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot", get_defined_vars());
254
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
255
  }
256
  /**/
257
  else /* Otherwise, treat this as if it were a cancellation. EOTs are currently disabled. */
258
  {
259
  $processing = $during = true; /* Yes, we ARE processing this. */
260
  /**/
261
+ update_user_option($user_id, "s2member_auto_eot_time", ($auto_eot_time = strtotime("now")));
262
  /**/
263
  $paypal["s2member_log"][] = "Auto-EOT is currently disabled. Skipping immediate EOT ( demote|delete ), for now.";
264
+ $paypal["s2member_log"][] = "Recording the Auto-EOT Time for this Member's account: ".date("D M j, Y g:i a T", $auto_eot_time);
265
  /**/
266
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
267
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_disabled", get_defined_vars());
268
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
269
  }
270
  }
271
  else
272
  $paypal["s2member_log"][] = "Unable to ( demote|delete ) Member. The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access.";
273
  }
274
  /**/
275
+ else if($is_delayed_eot && !get_user_option("s2member_auto_eot_time", $user_id))
276
  {
277
+ if(!$user->has_cap("administrator")) /* Do NOT process this routine on Administrators. */
278
  {
279
  $processing = $during = true; /* Yes, we ARE processing this. */
280
  /**/
281
+ $auto_eot_time = c_ws_plugin__s2member_utils_time::auto_eot_time($user_id, $paypal["period1"], $paypal["period3"], "", time());
282
  /* We assume the last payment was today, because this is how newer PayPal® accounts function with respect to EOT handling.
283
  Newer PayPal® accounts ( i.e. Subscription IDs starting with `I-`, will have their EOT triggered upon the last payment. */
284
+ update_user_option($user_id, "s2member_auto_eot_time", $auto_eot_time); /* s2Member will follow-up on this later. */
285
  /**/
286
+ $paypal["s2member_log"][] = "Auto-EOT Time for this account ( delayed ), set to: ".date("D M j, Y g:i a T", $auto_eot_time);
287
  /**/
288
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
289
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_delayed", get_defined_vars());
290
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
291
  }
292
  else
293
  $paypal["s2member_log"][] = "Ignoring Delayed EOT. The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access.";
294
  }
295
  /**/
296
+ else if(!$is_refund_or_reversal || $is_delayed_eot)
297
  $paypal["s2member_log"][] = "Skipping ( demote|delete ) Member, for now. An Auto-EOT Time is already set for this account. When an Auto-EOT Time has been recorded, s2Member will handle EOT ( demote|delete ) events using it's own Auto-EOT System - internally.";
298
  /**/
299
+ else if($is_reversal)
300
  $paypal["s2member_log"][] = "Skipping ( demote|delete ) Member. Your configuration dictates that s2Member should NOT take any immediate action on an EOT associated with a Chargeback Reversal. An s2Member API Notification will still be processed however.";
301
  /**/
302
+ else if($is_refund)
303
  $paypal["s2member_log"][] = "Skipping ( demote|delete ) Member. Your configuration dictates that s2Member should NOT take any immediate action on an EOT associated with a Refund. An s2Member API Notification will still be processed however.";
304
  }
305
+ else if($is_delayed_eot) /* Otherwise, we need to re-generate/store this IPN into a Transient Queue. Then re-process it on registration. */
306
  {
307
  $paypal["s2member_log"][] = "Skipping this IPN response, for now. The Subscr. ID is not associated with a registered Member.";
308
  /**/
309
+ $ipn = array("txn_type" => "subscr_eot"); /* Create a simulated IPN response for txn_type=subscr_eot. */
310
  /**/
311
+ foreach($paypal as $var => $val)
312
+ if(in_array($var, array("subscr_gateway", "subscr_id", "custom", "invoice", "payer_email", "first_name", "last_name", "item_name", "item_number", /* Exclude; might be defaults. "period1", "period3", */ "option_name1", "option_selection1", "option_name2", "option_selection2")))
313
  $ipn[$var] = $val;
314
  /**/
315
  $paypal["s2member_log"][] = "Re-generating. This IPN will go into a Transient Queue; and be re-processed during registration.";
316
  /**/
317
+ set_transient("s2m_".md5("s2member_transient_ipn_subscr_eot_".$paypal["subscr_id"]), $ipn, 43200);
318
  }
319
  /**/
320
  else
325
  Since this routine ignores the processing check, it is *possible* that Refund/Reversal Notification URLs will be contacted more than once.
326
  If you're writing scripts that depend on Refund/Reversal Notifications, please keep this in mind.
327
  */
328
+ if($is_refund_or_reversal) /* Here we access this variable that was previously assigned as a quick method of Refund/Reversal detection. */
329
  {
330
+ $fields = ($user_id) ? get_user_option("s2member_custom_fields", $user_id) : array(); /* These will be needed below. */
331
+ $user_reg_ip = ($user_id) ? get_user_option("s2member_registration_ip", $user_id) : ""; /* Needed below. */
332
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"]; /* Now merge conditionally. */
333
  /**/
334
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"] && is_array($cv = preg_split("/\|/", $paypal["custom"])))
335
  {
336
+ foreach(preg_split("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) as $url)
337
  /**/
338
+ if(($url = preg_replace("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["subscr_id"])), $url)) && ($url = preg_replace("/%%parent_txn_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["parent_txn_id"])), $url)))
339
+ if(($url = preg_replace("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["item_number"])), $url)) && ($url = preg_replace("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["item_name"])), $url)))
340
+ if(($url = preg_replace("/%%-amount%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["mc_gross"])), $url)) && ($url = preg_replace("/%%-fee%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["mc_fee"])), $url)))
341
+ if(($url = preg_replace("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["first_name"])), $url)) && ($url = preg_replace("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["last_name"])), $url)))
342
+ if(($url = preg_replace("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode(trim($paypal["first_name"]." ".$paypal["last_name"]))), $url)))
343
+ if(($url = preg_replace("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($paypal["payer_email"])), $url)))
344
+ if(($url = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user_reg_ip)), $url)))
345
+ if(($url = preg_replace("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode($user_id)), $url)))
346
  {
347
+ if(is_array($fields) && !empty($fields))
348
+ foreach($fields as $var => $val) /* Custom Registration/Profile Fields. */
349
+ if(!($url = preg_replace("/%%".preg_quote($var, "/")."%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(urlencode(maybe_serialize($val))), $url)))
350
  break;
351
  /**/
352
+ if(($url = trim(preg_replace("/%%(.+?)%%/i", "", $url))))
353
+ c_ws_plugin__s2member_utils_urls::remote($url);
354
  }
355
  /**/
356
  $paypal["s2member_log"][] = "Refund/Reversal Notification URLs have been processed.";
357
  }
358
  /**/
359
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"] && is_array($cv = preg_split("/\|/", $paypal["custom"])))
360
  {
361
  $msg = $sbj = "( s2Member / API Notification Email ) - Refund/Reversal";
362
  $msg .= "\n\n"; /* Spacing in the message body. */
374
  $msg .= "user_ip: %%user_ip%%\n";
375
  $msg .= "user_id: %%user_id%%\n";
376
  /**/
377
+ if(is_array($fields) && !empty($fields))
378
+ foreach($fields as $var => $val)
379
+ $msg .= $var.": %%".$var."%%\n";
380
  /**/
381
  $msg .= "cv0: %%cv0%%\n";
382
  $msg .= "cv1: %%cv1%%\n";
389
  $msg .= "cv8: %%cv8%%\n";
390
  $msg .= "cv9: %%cv9%%";
391
  /**/
392
+ if(($msg = preg_replace("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["subscr_id"]), $msg)) && ($msg = preg_replace("/%%parent_txn_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["parent_txn_id"]), $msg)))
393
+ if(($msg = preg_replace("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_number"]), $msg)) && ($msg = preg_replace("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_name"]), $msg)))
394
+ if(($msg = preg_replace("/%%-amount%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["mc_gross"]), $msg)) && ($msg = preg_replace("/%%-fee%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["mc_fee"]), $msg)))
395
+ if(($msg = preg_replace("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["first_name"]), $msg)) && ($msg = preg_replace("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["last_name"]), $msg)))
396
+ if(($msg = preg_replace("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($paypal["first_name"]." ".$paypal["last_name"])), $msg)))
397
+ if(($msg = preg_replace("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["payer_email"]), $msg)))
398
+ if(($msg = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_reg_ip), $msg)))
399
+ if(($msg = preg_replace("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_id), $msg)))
400
  {
401
+ if(is_array($fields) && !empty($fields))
402
+ foreach($fields as $var => $val) /* Custom Registration/Profile Fields. */
403
+ if(!($msg = preg_replace("/%%".preg_quote($var, "/")."%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(maybe_serialize($val)), $msg)))
404
  break;
405
  /**/
406
+ if($sbj && ($msg = trim(preg_replace("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
407
  /**/
408
+ foreach(c_ws_plugin__s2member_utils_strings::parse_emails($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"]) as $recipient)
409
+ wp_mail($recipient, apply_filters("ws_plugin__s2member_ref_rev_notification_email_sbj", $sbj, get_defined_vars()), apply_filters("ws_plugin__s2member_ref_rev_notification_email_msg", $msg, get_defined_vars()), "Content-Type: text/plain; charset=utf-8");
410
  }
411
  /**/
412
  $paypal["s2member_log"][] = "Refund/Reversal Notification Emails have been processed.";
413
  }
414
  /**/
415
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
416
+ do_action("ws_plugin__s2member_during_paypal_notify_during_subscr_eot_refund_reversal", get_defined_vars());
417
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
418
  }
419
  }
420
  else /* Else, this is a duplicate IPN. Must stop here. */
425
  }
426
  /**/
427
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
428
+ do_action("ws_plugin__s2member_during_paypal_notify_after_subscr_eot", get_defined_vars());
429
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
430
  /**/
431
+ return apply_filters("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_level", $paypal, get_defined_vars());
432
  }
433
  else
434
+ return apply_filters("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_level", false, get_defined_vars());
435
  }
436
  }
437
  }
includes/classes/paypal-return-in-subscr-modify-w-level.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\PayPal
15
  * @since 110720
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level"))
21
  {
22
  /**
23
  * s2Member's PayPal® Auto-Return/PDT handler ( inner processing routine ).
@@ -38,140 +38,145 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level
38
  *
39
  * @todo Optimize with ``empty()`` and ``isset()``.
40
  */
41
- public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
  extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
- if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^subscr_modify$/i", $paypal["txn_type"]))/**/
46
- && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
47
- && (!empty ($paypal["subscr_id"]))/**/)
48
  {
49
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
50
- do_action ("ws_plugin__s2member_during_paypal_return_before_subscr_modify", get_defined_vars ());
51
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
52
  /**/
53
- if (!get_transient ($transient_rtn = "s2m_rtn_" . md5 ("s2member_transient_" . $_paypal_s)) && set_transient ($transient_rtn, time (), 31556926 * 10))
54
  {
55
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `subscr_modify` ), a Subscription Modification.";
56
  /**/
57
- list ($paypal["level"], $paypal["ccaps"]/*, $paypal["eotper"] */) = preg_split ("/\:/", $paypal["item_number"], 2);
58
  /**/
59
- $paypal["ip"] = (preg_match ("/ip address/i", $paypal["option_name2"]) && $paypal["option_selection2"]) ? $paypal["option_selection2"] : "";
60
- $paypal["ip"] = (!$paypal["ip"] && preg_match ("/^[a-z0-9]+~[0-9\.]+$/i", $paypal["invoice"])) ? preg_replace ("/^[a-z0-9]+~/i", "", $paypal["invoice"]) : $paypal["ip"];
61
  $paypal["ip"] = (!$paypal["ip"] && $_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : $paypal["ip"];
62
  /**/
63
- $paypal["period1"] = (preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
64
- $paypal["mc_amount1"] = (strlen ($paypal["mc_amount1"]) && $paypal["mc_amount1"] > 0) ? $paypal["mc_amount1"] : "0.00"; /* "0.00". */
65
  /**/
66
- if (preg_match ("/^web_accept$/i", $paypal["txn_type"])) /* Conversions for Lifetime & Fixed-Term sales. */
67
  {
68
  $paypal["period3"] = ($paypal["eotper"]) ? $paypal["eotper"] : "1 L"; /* 1 Lifetime. */
69
  $paypal["mc_amount3"] = $paypal["mc_gross"]; /* The "Buy Now" amount is the full gross. */
70
  }
71
  /**/
72
- $paypal["initial_term"] = (preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
73
- $paypal["initial"] = (strlen ($paypal["mc_amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
74
  $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the Customer. Always required by PayPal®. */
75
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
76
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
77
  /**/
78
  eval('$ipn_signup_vars = $paypal; unset($ipn_signup_vars["s2member_log"]);'); /* Create array of wouldbe IPN signup vars w/o s2member_log. */
79
  /**/
80
- if (($user_id = c_ws_plugin__s2member_utils_users::get_user_id_with ($paypal["subscr_id"])) && is_object ($user = new WP_User ($user_id)) && $user->ID)
81
  {
82
- if (!$user->has_cap ("administrator")) /* Do NOT process this routine on Administrators. */
83
  {
84
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
85
  /**/
86
- $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed in the routines below. */
87
- $user_reg_ip = get_user_option ("s2member_registration_ip", $user_id); /* Original IP during Registration. */
 
 
 
 
 
88
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"]; /* Now merge conditionally. */
89
  /**/
90
- if (is_multisite () && !is_user_member_of_blog ($user_id)) /* Must have a Role on this Blog. */
91
  {
92
- add_existing_user_to_blog(array ("user_id" => $user_id, "role" => "s2member_level" . $paypal["level"]));
93
- $user = new WP_User ($user_id); /* Now update the $user object we're using. */
94
  }
95
  /**/
96
- $current_role = c_ws_plugin__s2member_user_access::user_access_role ($user);
97
  /**/
98
- if ($current_role !== "s2member_level" . $paypal["level"]) /* Only if we need to. */
99
- $user->set_role ("s2member_level" . $paypal["level"]); /* (upgrade/downgrade) */
100
  /**/
101
- if ($paypal["ccaps"] && preg_match ("/^-all/", str_replace ("+", "", $paypal["ccaps"])))
102
- foreach ($user->allcaps as $cap => $cap_enabled)
103
- if (preg_match ("/^access_s2member_ccap_/", $cap))
104
- $user->remove_cap ($ccap = $cap);
105
  /**/
106
- if ($paypal["ccaps"] && preg_replace ("/^-all[\r\n\t\s;,]*/", "", str_replace ("+", "", $paypal["ccaps"])))
107
- foreach (preg_split ("/[\r\n\t\s;,]+/", preg_replace ("/^-all[\r\n\t\s;,]*/", "", str_replace ("+", "", $paypal["ccaps"]))) as $ccap)
108
- if (strlen ($ccap = trim (strtolower (preg_replace ("/[^a-z_0-9]/i", "", $ccap)))))
109
- $user->add_cap ("access_s2member_ccap_" . $ccap);
110
  /**/
111
- update_user_option ($user_id, "s2member_subscr_gateway", $paypal["subscr_gateway"]);
112
- update_user_option ($user_id, "s2member_subscr_id", $paypal["subscr_id"]);
113
- update_user_option ($user_id, "s2member_custom", $paypal["custom"]);
114
  /**/
115
- if (!get_user_option ("s2member_registration_ip", $user_id))
116
- update_user_option ($user_id, "s2member_registration_ip", $paypal["ip"]);
117
  /**/
118
- update_user_option ($user_id, "s2member_ipn_signup_vars", $ipn_signup_vars);
119
  /**/
120
- delete_user_option ($user_id, "s2member_file_download_access_log");
121
  /**/
122
- delete_user_option ($user_id, "s2member_auto_eot_time");
123
  /**/
124
- $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
125
- $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
126
- $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
127
- update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
128
  /**/
129
- c_ws_plugin__s2member_user_notes::clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
130
  /**/
131
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on ( `subscr_modify` ), a Subscription Modification.";
132
  /**/
133
- setcookie ("s2member_tracking", ($s2member_tracking = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["subscr_id"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_tracking", $s2member_tracking, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_tracking"] = $s2member_tracking);
134
  /**/
135
  $paypal["s2member_log"][] = "Transient Tracking Cookie set on ( `subscr_modify` ), a Subscription Modification.";
136
  /**/
137
- if ($processing && ($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_tracking_codes"]) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
138
  {
139
- if (($code = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $code)) && ($code = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["subscr_id"]), $code)))
140
- if (($code = preg_replace ("/%%initial%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["initial"]), $code)) && ($code = preg_replace ("/%%regular%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["regular"]), $code)) && ($code = preg_replace ("/%%recurring%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["recurring"]), $code)))
141
- if (($code = preg_replace ("/%%initial_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["initial_term"]), $code)) && ($code = preg_replace ("/%%regular_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["regular_term"]), $code)))
142
- if (($code = preg_replace ("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_number"]), $code)) && ($code = preg_replace ("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_name"]), $code)))
143
- if (($code = preg_replace ("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["first_name"]), $code)) && ($code = preg_replace ("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["last_name"]), $code)))
144
- if (($code = preg_replace ("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
145
- if (($code = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $code)))
146
  {
147
- if (($code = preg_replace ("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->first_name), $code)) && ($code = preg_replace ("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->last_name), $code)))
148
- if (($code = preg_replace ("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($user->first_name . " " . $user->last_name)), $code)))
149
- if (($code = preg_replace ("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->user_email), $code)))
150
- if (($code = preg_replace ("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->user_login), $code)))
151
- if (($code = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_reg_ip), $code)))
152
- if (($code = preg_replace ("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_id), $code)))
153
  {
154
- if (is_array ($fields) && !empty ($fields))
155
- foreach ($fields as $var => $val) /* Custom Registration/Profile Fields. */
156
- if (!($code = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $code)))
157
  break;
158
  /**/
159
- if (($code = trim (preg_replace ("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
160
  {
161
  $paypal["s2member_log"][] = "Storing Modification Tracking Codes into a Transient Queue. These will be processed on-site.";
162
- set_transient ("s2m_" . md5 ("s2member_transient_modification_tracking_codes_" . $paypal["subscr_id"]), $code, 43200);
163
  }
164
  }
165
  }
166
  }
167
  /**/
168
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
169
- do_action ("ws_plugin__s2member_during_paypal_return_during_subscr_modify", get_defined_vars ());
170
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
171
  /**/
172
- if (($redirection_url_after_modification = apply_filters ("ws_plugin__s2member_redirection_url_after_modification", false, get_defined_vars ())))
173
  {
174
- $paypal["s2member_log"][] = "Redirecting this Member to a custom URL after modification: " . $redirection_url_after_modification;
175
  /**/
176
  wp_redirect($redirection_url_after_modification);
177
  }
@@ -179,9 +184,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level
179
  {
180
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in.";
181
  /**/
182
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
183
- '<strong>' . _x ("Thank you! You've been updated to:", "s2member-front", "s2member") . '<br /><em>' . esc_html ($paypal["item_name"]) . '</em></strong>',/**/
184
- _x ("Please Log Back In ( Click Here )", "s2member-front", "s2member"), wp_login_url ());
185
  }
186
  }
187
  else /* Else, unable to modify Subscription. The existing User ID is associated with an Administrator. Stopping here. */
@@ -190,9 +195,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level
190
  /**/
191
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
192
  /**/
193
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
194
- _x ('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access. Please make sure that you are NOT logged in as an Administrator while testing.', "s2member-front", "s2member"),/**/
195
- _x ("Back To Home Page", "s2member-front", "s2member"), home_url ("/"));
196
  }
197
  }
198
  else /* Unable to modify Subscription. Could not get the existing User ID from the DB. */
@@ -201,9 +206,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level
201
  /**/
202
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
203
  /**/
204
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
205
- _x ('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />Could not get the existing User ID from the DB.', "s2member-front", "s2member"),/**/
206
- _x ("Back To Home Page", "s2member-front", "s2member"), home_url ("/"));
207
  }
208
  }
209
  else /* Page Expired. Duplicate Return-Data. */
@@ -212,19 +217,19 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level
212
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as `subscr_modify`.";
213
  $paypal["s2member_log"][] = "Page Expired. Redirecting Customer to the Home Page.";
214
  /**/
215
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
216
- _x ('<strong>Page Expired:</strong> Duplicate Return-Data.<br />Please contact Support if you need any assistance.', "s2member-front", "s2member"),/**/
217
- _x ("Back To Home Page", "s2member-front", "s2member"), home_url ("/"));
218
  }
219
  /**/
220
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
221
- do_action ("ws_plugin__s2member_during_paypal_return_after_subscr_modify", get_defined_vars ());
222
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
223
  /**/
224
- return apply_filters ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level", $paypal, get_defined_vars ());
225
  }
226
  else
227
- return apply_filters ("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level", false, get_defined_vars ());
228
  }
229
  }
230
  }
14
  * @package s2Member\PayPal
15
  * @since 110720
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level"))
21
  {
22
  /**
23
  * s2Member's PayPal® Auto-Return/PDT handler ( inner processing routine ).
38
  *
39
  * @todo Optimize with ``empty()`` and ``isset()``.
40
  */
41
+ public static function cp($vars = array()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
  extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
+ if(/**/(!empty($paypal["txn_type"]) && preg_match("/^subscr_modify$/i", $paypal["txn_type"]))/**/
46
+ && (!empty($paypal["item_number"]) && preg_match($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
47
+ && (!empty($paypal["subscr_id"]))/**/)
48
  {
49
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
50
+ do_action("ws_plugin__s2member_during_paypal_return_before_subscr_modify", get_defined_vars());
51
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
52
  /**/
53
+ if(!get_transient($transient_rtn = "s2m_rtn_".md5("s2member_transient_".$_paypal_s)) && set_transient($transient_rtn, time(), 31556926 * 10))
54
  {
55
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `subscr_modify` ), a Subscription Modification.";
56
  /**/
57
+ list($paypal["level"], $paypal["ccaps"]/*, $paypal["eotper"] */) = preg_split("/\:/", $paypal["item_number"], 2);
58
  /**/
59
+ $paypal["ip"] = (preg_match("/ip address/i", $paypal["option_name2"]) && $paypal["option_selection2"]) ? $paypal["option_selection2"] : "";
60
+ $paypal["ip"] = (!$paypal["ip"] && preg_match("/^[a-z0-9]+~[0-9\.]+$/i", $paypal["invoice"])) ? preg_replace("/^[a-z0-9]+~/i", "", $paypal["invoice"]) : $paypal["ip"];
61
  $paypal["ip"] = (!$paypal["ip"] && $_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : $paypal["ip"];
62
  /**/
63
+ $paypal["period1"] = (preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
64
+ $paypal["mc_amount1"] = (strlen($paypal["mc_amount1"]) && $paypal["mc_amount1"] > 0) ? $paypal["mc_amount1"] : "0.00"; /* "0.00". */
65
  /**/
66
+ if(preg_match("/^web_accept$/i", $paypal["txn_type"])) /* Conversions for Lifetime & Fixed-Term sales. */
67
  {
68
  $paypal["period3"] = ($paypal["eotper"]) ? $paypal["eotper"] : "1 L"; /* 1 Lifetime. */
69
  $paypal["mc_amount3"] = $paypal["mc_gross"]; /* The "Buy Now" amount is the full gross. */
70
  }
71
  /**/
72
+ $paypal["initial_term"] = (preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
73
+ $paypal["initial"] = (strlen($paypal["mc_amount1"]) && preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
74
  $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the Customer. Always required by PayPal®. */
75
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
76
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
77
  /**/
78
  eval('$ipn_signup_vars = $paypal; unset($ipn_signup_vars["s2member_log"]);'); /* Create array of wouldbe IPN signup vars w/o s2member_log. */
79
  /**/
80
+ if(($user_id = c_ws_plugin__s2member_utils_users::get_user_id_with($paypal["subscr_id"])) && is_object($user = new WP_User($user_id)) && $user->ID)
81
  {
82
+ if(!$user->has_cap("administrator")) /* Do NOT process this routine on Administrators. */
83
  {
84
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
85
  /**/
86
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
87
+ do_action("ws_plugin__s2member_during_paypal_return_during_before_subscr_modify", get_defined_vars());
88
+ do_action("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars(), "rtn-upgrade-downgrade", "modification", "s2member_level".$paypal["level"]);
89
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
90
+ /**/
91
+ $fields = get_user_option("s2member_custom_fields", $user_id); /* These will be needed in the routines below. */
92
+ $user_reg_ip = get_user_option("s2member_registration_ip", $user_id); /* Original IP during Registration. */
93
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"]; /* Now merge conditionally. */
94
  /**/
95
+ if(is_multisite() && !is_user_member_of_blog($user_id)) /* Must have a Role on this Blog. */
96
  {
97
+ add_existing_user_to_blog(array("user_id" => $user_id, "role" => "s2member_level".$paypal["level"]));
98
+ $user = new WP_User($user_id); /* Now update the $user object we're using. */
99
  }
100
  /**/
101
+ $current_role = c_ws_plugin__s2member_user_access::user_access_role($user);
102
  /**/
103
+ if($current_role !== "s2member_level".$paypal["level"]) /* Only if we need to. */
104
+ $user->set_role("s2member_level".$paypal["level"]); /* (upgrade/downgrade) */
105
  /**/
106
+ if($paypal["ccaps"] && preg_match("/^-all/", str_replace("+", "", $paypal["ccaps"])))
107
+ foreach($user->allcaps as $cap => $cap_enabled)
108
+ if(preg_match("/^access_s2member_ccap_/", $cap))
109
+ $user->remove_cap($ccap = $cap);
110
  /**/
111
+ if($paypal["ccaps"] && preg_replace("/^-all[\r\n\t\s;,]*/", "", str_replace("+", "", $paypal["ccaps"])))
112
+ foreach(preg_split("/[\r\n\t\s;,]+/", preg_replace("/^-all[\r\n\t\s;,]*/", "", str_replace("+", "", $paypal["ccaps"]))) as $ccap)
113
+ if(strlen($ccap = trim(strtolower(preg_replace("/[^a-z_0-9]/i", "", $ccap)))))
114
+ $user->add_cap("access_s2member_ccap_".$ccap);
115
  /**/
116
+ update_user_option($user_id, "s2member_subscr_gateway", $paypal["subscr_gateway"]);
117
+ update_user_option($user_id, "s2member_subscr_id", $paypal["subscr_id"]);
118
+ update_user_option($user_id, "s2member_custom", $paypal["custom"]);
119
  /**/
120
+ if(!get_user_option("s2member_registration_ip", $user_id))
121
+ update_user_option($user_id, "s2member_registration_ip", $paypal["ip"]);
122
  /**/
123
+ update_user_option($user_id, "s2member_ipn_signup_vars", $ipn_signup_vars);
124
  /**/
125
+ delete_user_option($user_id, "s2member_file_download_access_log");
126
  /**/
127
+ delete_user_option($user_id, "s2member_auto_eot_time");
128
  /**/
129
+ $pr_times = get_user_option("s2member_paid_registration_times", $user_id);
130
+ $pr_times["level"] = (!$pr_times["level"]) ? time() : $pr_times["level"]; /* Preserves existing. */
131
+ $pr_times["level".$paypal["level"]] = (!$pr_times["level".$paypal["level"]]) ? time() : $pr_times["level".$paypal["level"]];
132
+ update_user_option($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
133
  /**/
134
+ c_ws_plugin__s2member_user_notes::clear_user_note_lines($user_id, "/^Demoted by s2Member\:/");
135
  /**/
136
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on ( `subscr_modify` ), a Subscription Modification.";
137
  /**/
138
+ setcookie("s2member_tracking", ($s2member_tracking = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["subscr_id"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_tracking", $s2member_tracking, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_tracking"] = $s2member_tracking);
139
  /**/
140
  $paypal["s2member_log"][] = "Transient Tracking Cookie set on ( `subscr_modify` ), a Subscription Modification.";
141
  /**/
142
+ if($processing && ($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_tracking_codes"]) && is_array($cv = preg_split("/\|/", $paypal["custom"])))
143
  {
144
+ if(($code = preg_replace("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $code)) && ($code = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["subscr_id"]), $code)))
145
+ if(($code = preg_replace("/%%initial%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["initial"]), $code)) && ($code = preg_replace("/%%regular%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["regular"]), $code)) && ($code = preg_replace("/%%recurring%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["recurring"]), $code)))
146
+ if(($code = preg_replace("/%%initial_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["initial_term"]), $code)) && ($code = preg_replace("/%%regular_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["regular_term"]), $code)))
147
+ if(($code = preg_replace("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_number"]), $code)) && ($code = preg_replace("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_name"]), $code)))
148
+ if(($code = preg_replace("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["first_name"]), $code)) && ($code = preg_replace("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["last_name"]), $code)))
149
+ if(($code = preg_replace("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($paypal["first_name"]." ".$paypal["last_name"])), $code)))
150
+ if(($code = preg_replace("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["payer_email"]), $code)))
151
  {
152
+ if(($code = preg_replace("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->first_name), $code)) && ($code = preg_replace("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->last_name), $code)))
153
+ if(($code = preg_replace("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($user->first_name." ".$user->last_name)), $code)))
154
+ if(($code = preg_replace("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->user_email), $code)))
155
+ if(($code = preg_replace("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->user_login), $code)))
156
+ if(($code = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_reg_ip), $code)))
157
+ if(($code = preg_replace("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_id), $code)))
158
  {
159
+ if(is_array($fields) && !empty($fields))
160
+ foreach($fields as $var => $val) /* Custom Registration/Profile Fields. */
161
+ if(!($code = preg_replace("/%%".preg_quote($var, "/")."%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(maybe_serialize($val)), $code)))
162
  break;
163
  /**/
164
+ if(($code = trim(preg_replace("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
165
  {
166
  $paypal["s2member_log"][] = "Storing Modification Tracking Codes into a Transient Queue. These will be processed on-site.";
167
+ set_transient("s2m_".md5("s2member_transient_modification_tracking_codes_".$paypal["subscr_id"]), $code, 43200);
168
  }
169
  }
170
  }
171
  }
172
  /**/
173
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
174
+ do_action("ws_plugin__s2member_during_paypal_return_during_subscr_modify", get_defined_vars());
175
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
176
  /**/
177
+ if(($redirection_url_after_modification = apply_filters("ws_plugin__s2member_redirection_url_after_modification", false, get_defined_vars())))
178
  {
179
+ $paypal["s2member_log"][] = "Redirecting this Member to a custom URL after modification: ".$redirection_url_after_modification;
180
  /**/
181
  wp_redirect($redirection_url_after_modification);
182
  }
184
  {
185
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in.";
186
  /**/
187
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
188
+ '<strong>'._x("Thank you! You've been updated to:", "s2member-front", "s2member").'<br /><em>'.esc_html($paypal["item_name"]).'</em></strong>',/**/
189
+ _x("Please Log Back In ( Click Here )", "s2member-front", "s2member"), wp_login_url());
190
  }
191
  }
192
  else /* Else, unable to modify Subscription. The existing User ID is associated with an Administrator. Stopping here. */
195
  /**/
196
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
197
  /**/
198
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
199
+ _x('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access. Please make sure that you are NOT logged in as an Administrator while testing.', "s2member-front", "s2member"),/**/
200
+ _x("Back To Home Page", "s2member-front", "s2member"), home_url("/"));
201
  }
202
  }
203
  else /* Unable to modify Subscription. Could not get the existing User ID from the DB. */
206
  /**/
207
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
208
  /**/
209
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
210
+ _x('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />Could not get the existing User ID from the DB.', "s2member-front", "s2member"),/**/
211
+ _x("Back To Home Page", "s2member-front", "s2member"), home_url("/"));
212
  }
213
  }
214
  else /* Page Expired. Duplicate Return-Data. */
217
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as `subscr_modify`.";
218
  $paypal["s2member_log"][] = "Page Expired. Redirecting Customer to the Home Page.";
219
  /**/
220
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
221
+ _x('<strong>Page Expired:</strong> Duplicate Return-Data.<br />Please contact Support if you need any assistance.', "s2member-front", "s2member"),/**/
222
+ _x("Back To Home Page", "s2member-front", "s2member"), home_url("/"));
223
  }
224
  /**/
225
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
226
+ do_action("ws_plugin__s2member_during_paypal_return_after_subscr_modify", get_defined_vars());
227
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
228
  /**/
229
+ return apply_filters("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level", $paypal, get_defined_vars());
230
  }
231
  else
232
+ return apply_filters("c_ws_plugin__s2member_paypal_return_in_subscr_modify_w_level", false, get_defined_vars());
233
  }
234
  }
235
  }
includes/classes/paypal-return-in-subscr-or-wa-w-level.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\PayPal
15
  * @since 110720
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"))
21
  {
22
  /**
23
  * s2Member's PayPal® Auto-Return/PDT handler ( inner processing routine ).
@@ -38,67 +38,67 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
38
  *
39
  * @todo Optimize with ``empty()`` and ``isset()``.
40
  */
41
- public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
  extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
- if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^(web_accept|subscr_signup|subscr_payment)$/i", $paypal["txn_type"]))/**/
46
- && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
47
- && (!empty ($paypal["subscr_id"]) || (!empty ($paypal["txn_id"]) && ($paypal["subscr_id"] = $paypal["txn_id"])))/**/
48
- && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/)
49
  {
50
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
- do_action ("ws_plugin__s2member_during_paypal_return_before_subscr_signup", get_defined_vars ());
52
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
54
- if (!get_transient ($transient_rtn = "s2m_rtn_" . md5 ("s2member_transient_" . $_paypal_s)) && set_transient ($transient_rtn, time (), 31556926 * 10))
55
  {
56
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ).";
57
  /**/
58
- list ($paypal["level"], $paypal["ccaps"], $paypal["eotper"]) = preg_split ("/\:/", $paypal["item_number"], 3);
59
  /**/
60
- $paypal["ip"] = (preg_match ("/ip address/i", $paypal["option_name2"]) && $paypal["option_selection2"]) ? $paypal["option_selection2"] : "";
61
- $paypal["ip"] = (!$paypal["ip"] && preg_match ("/^[a-z0-9]+~[0-9\.]+$/i", $paypal["invoice"])) ? preg_replace ("/^[a-z0-9]+~/i", "", $paypal["invoice"]) : $paypal["ip"];
62
  $paypal["ip"] = (!$paypal["ip"] && $_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : $paypal["ip"];
63
  /**/
64
- if (/**/(preg_match ("/^subscr_payment$/i", $paypal["txn_type"]) && !empty ($_GET["s2member_paypal_return_tra"])) /* Decrypt/unserialize. */
65
- && (($tra = c_ws_plugin__s2member_utils_encryption::decrypt (trim (stripslashes ($_GET["s2member_paypal_return_tra"])))) && is_array ($tra = maybe_unserialize ($tra)))/**/
66
- && (count ($tra) === 11 && isset ($tra["ta"], $tra["tp"], $tra["tt"], $tra["ra"], $tra["rp"], $tra["rt"], $tra["rr"], $tra["rrt"], $tra["rra"], $tra["invoice"], $tra["checksum"]))/**/
67
- && ($tra["invoice"] === $paypal["invoice"]) && ($tra["checksum"] === md5 ($paypal["invoice"] . $paypal["ip"] . $paypal["item_number"]))/**/)
68
  {
69
  $tracking_properties = true; /* Yes, these tracking properties ARE being set here. */
70
  /**/
71
- $paypal["period1"] = ($tra["rr"] !== "BN" && $tra["tp"]) ? $tra["tp"] . " " . $tra["tt"] : "0 D";
72
- $paypal["mc_amount1"] = ($tra["rr"] !== "BN" && $tra["tp"]) ? number_format ($tra["ta"], 2, ".", "") : "0.00";
73
  /**/
74
- $paypal["period3"] = $tra["rp"] . " " . $tra["rt"];
75
  $paypal["mc_amount3"] = $tra["ra"];
76
  /**/
77
  $paypal["recurring"] = ($tra["rr"] === "1") ? "1" : "0";
78
  /**/
79
- $paypal["initial_term"] = (preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
80
- $paypal["initial"] = (strlen ($paypal["mc_amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
81
  $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the Customer. Always required by PayPal®. */
82
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
83
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
84
  /**/
85
  eval('$ipn_signup_vars = $paypal; unset($ipn_signup_vars["s2member_log"]);'); /* Create array of wouldbe IPN signup vars w/o s2member_log. */
86
  }
87
- else if (preg_match ("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]))
88
  {
89
  $tracking_properties = true; /* Yes, these tracking properties ARE being set here. */
90
  /**/
91
- $paypal["period1"] = (preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
92
- $paypal["mc_amount1"] = (strlen ($paypal["mc_amount1"]) && $paypal["mc_amount1"] > 0) ? $paypal["mc_amount1"] : "0.00"; /* "0.00". */
93
  /**/
94
- if (preg_match ("/^web_accept$/i", $paypal["txn_type"])) /* Conversions for Lifetime & Fixed-Term sales. */
95
  {
96
  $paypal["period3"] = ($paypal["eotper"]) ? $paypal["eotper"] : "1 L"; /* 1 Lifetime. */
97
  $paypal["mc_amount3"] = $paypal["mc_gross"]; /* The "Buy Now" amount is the full gross. */
98
  }
99
  /**/
100
- $paypal["initial_term"] = (preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
101
- $paypal["initial"] = (strlen ($paypal["mc_amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
102
  $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the Customer. Always required by PayPal®. */
103
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
104
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
@@ -108,119 +108,124 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
108
  /*
109
  New Subscription with advanced update vars ( option_name1, option_selection1 )? Used in Subscr. Modifications.
110
  */
111
- if (preg_match ("/(referenc|associat|updat|upgrad)/i", $paypal["option_name1"]) && $paypal["option_selection1"])
112
  {
113
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
114
- do_action ("ws_plugin__s2member_during_paypal_return_before_subscr_signup_w_update_vars", get_defined_vars ());
115
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
116
  /**/
117
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ) w/ update vars.";
118
  /**/
119
  /* Check for both the old & new subscr_id's, just in case the IPN routine already changed it. */
120
- if (($user_id = c_ws_plugin__s2member_utils_users::get_user_id_with ($paypal["subscr_id"], $paypal["option_selection1"])) && is_object ($user = new WP_User ($user_id)) && $user->ID)
121
  {
122
- if (!$user->has_cap ("administrator")) /* Do NOT process this routine on Administrators. */
123
  {
124
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
125
  /**/
126
- $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed in the routines below. */
127
- $user_reg_ip = get_user_option ("s2member_registration_ip", $user_id); /* Original IP during Registration. */
 
 
 
 
 
128
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"]; /* Now merge conditionally. */
129
  /**/
130
- if (is_multisite () && !is_user_member_of_blog ($user_id)) /* Must have a Role on this Blog. */
131
  {
132
- add_existing_user_to_blog(array ("user_id" => $user_id, "role" => "s2member_level" . $paypal["level"]));
133
- $user = new WP_User ($user_id);
134
  }
135
  /**/
136
- $current_role = c_ws_plugin__s2member_user_access::user_access_role ($user);
137
  /**/
138
- if ($current_role !== "s2member_level" . $paypal["level"]) /* Only if we need to. */
139
- $user->set_role ("s2member_level" . $paypal["level"]); /* (upgrade/downgrade) */
140
  /**/
141
- if ($paypal["ccaps"] && preg_match ("/^-all/", str_replace ("+", "", $paypal["ccaps"])))
142
- foreach ($user->allcaps as $cap => $cap_enabled)
143
- if (preg_match ("/^access_s2member_ccap_/", $cap))
144
- $user->remove_cap ($ccap = $cap);
145
  /**/
146
- if ($paypal["ccaps"] && preg_replace ("/^-all[\r\n\t\s;,]*/", "", str_replace ("+", "", $paypal["ccaps"])))
147
- foreach (preg_split ("/[\r\n\t\s;,]+/", preg_replace ("/^-all[\r\n\t\s;,]*/", "", str_replace ("+", "", $paypal["ccaps"]))) as $ccap)
148
- if (strlen ($ccap = trim (strtolower (preg_replace ("/[^a-z_0-9]/i", "", $ccap)))))
149
- $user->add_cap ("access_s2member_ccap_" . $ccap);
150
  /**/
151
- update_user_option ($user_id, "s2member_subscr_gateway", $paypal["subscr_gateway"]);
152
- update_user_option ($user_id, "s2member_subscr_id", $paypal["subscr_id"]);
153
- update_user_option ($user_id, "s2member_custom", $paypal["custom"]);
154
  /**/
155
- if (!get_user_option ("s2member_registration_ip", $user_id))
156
- update_user_option ($user_id, "s2member_registration_ip", $paypal["ip"]);
157
  /**/
158
- if ( /* We should have these from the routines above. */!empty ($ipn_signup_vars))
159
- update_user_option ($user_id, "s2member_ipn_signup_vars", $ipn_signup_vars);
160
  /**/
161
- delete_user_option ($user_id, "s2member_file_download_access_log");
162
  /**/
163
- if (preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $paypal["eotper"])
164
  {
165
  /* Don't update this in the return routine. Leave this for the IPN routine. */
166
  /* EOT Times might be extended, and we don't want the IPN routine to extend an already-extended EOT Time. */
167
- $eot_time = c_ws_plugin__s2member_utils_time::auto_eot_time ("", "", "", $paypal["eotper"], "", get_user_option ("s2member_auto_eot_time", $user_id));
168
- $paypal["s2member_log"][] = "Automatic EOT ( End Of Term ) Time will be set to: " . date ("D M j, Y g:i:s a T", $eot_time) . ".";
169
  }
170
  else /* Otherwise, we need to clear the Auto-EOT Time. */
171
- delete_user_option ($user_id, "s2member_auto_eot_time");
172
  /**/
173
- $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
174
- $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
175
- $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
176
- update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
177
  /**/
178
- c_ws_plugin__s2member_user_notes::clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
179
  /**/
180
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
181
  /**/
182
- setcookie ("s2member_tracking", ($s2member_tracking = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["subscr_id"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_tracking", $s2member_tracking, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_tracking"] = $s2member_tracking);
183
  /**/
184
  $paypal["s2member_log"][] = "Transient Tracking Cookie set on ( `web_accept|subscr_signup|subscr_payment` ) w/ update vars.";
185
  /**/
186
- if ($processing && $tracking_properties && ($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_tracking_codes"]) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
187
  {
188
- if (($code = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $code)) && ($code = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["subscr_id"]), $code)))
189
- if (($code = preg_replace ("/%%initial%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["initial"]), $code)) && ($code = preg_replace ("/%%regular%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["regular"]), $code)) && ($code = preg_replace ("/%%recurring%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["recurring"]), $code)))
190
- if (($code = preg_replace ("/%%initial_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["initial_term"]), $code)) && ($code = preg_replace ("/%%regular_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["regular_term"]), $code)))
191
- if (($code = preg_replace ("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_number"]), $code)) && ($code = preg_replace ("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_name"]), $code)))
192
- if (($code = preg_replace ("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["first_name"]), $code)) && ($code = preg_replace ("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["last_name"]), $code)))
193
- if (($code = preg_replace ("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
194
- if (($code = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $code)))
195
  {
196
- if (($code = preg_replace ("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->first_name), $code)) && ($code = preg_replace ("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->last_name), $code)))
197
- if (($code = preg_replace ("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($user->first_name . " " . $user->last_name)), $code)))
198
- if (($code = preg_replace ("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->user_email), $code)))
199
- if (($code = preg_replace ("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user->user_login), $code)))
200
- if (($code = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_reg_ip), $code)))
201
- if (($code = preg_replace ("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_id), $code)))
202
  {
203
- if (is_array ($fields) && !empty ($fields))
204
- foreach ($fields as $var => $val) /* Custom Registration/Profile Fields. */
205
- if (!($code = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $code)))
206
  break;
207
  /**/
208
- if (($code = trim (preg_replace ("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
209
  {
210
  $paypal["s2member_log"][] = "Storing Modification Tracking Codes into a Transient Queue. These will be processed on-site.";
211
- set_transient ("s2m_" . md5 ("s2member_transient_modification_tracking_codes_" . $paypal["subscr_id"]), $code, 43200);
212
  }
213
  }
214
  }
215
  }
216
  /**/
217
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
218
- do_action ("ws_plugin__s2member_during_paypal_return_during_subscr_signup_w_update_vars", get_defined_vars ());
219
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
220
  /**/
221
- if (($redirection_url_after_modification = apply_filters ("ws_plugin__s2member_redirection_url_after_modification", false, get_defined_vars ())))
222
  {
223
- $paypal["s2member_log"][] = "Redirecting Customer to a custom URL after modification: " . $redirection_url_after_modification;
224
  /**/
225
  wp_redirect($redirection_url_after_modification);
226
  }
@@ -228,9 +233,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
228
  {
229
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in.";
230
  /**/
231
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
232
- '<strong>' . _x ("Thank you! You've been updated to:", "s2member-front", "s2member") . '<br /><em>' . esc_html ($paypal["item_name"]) . '</em></strong>',/**/
233
- _x ("Please Log Back In ( Click Here )", "s2member-front", "s2member"), wp_login_url ());
234
  }
235
  }
236
  else /* Unable to modify Subscription. The existing User ID is associated with an Administrator. Stopping here. */
@@ -239,9 +244,9 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
239
  /**/
240
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
241
  /**/
242
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
243
- _x ('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access. Please make sure that you are NOT logged in as an Administrator while testing.', "s2member-front", "s2member"),/**/
244
- _x ("Back To Home Page", "s2member-front", "s2member"), home_url ("/"));
245
  }
246
  }
247
  else /* Unable to modify Subscription. Could not get the existing User ID from the DB. */
@@ -250,14 +255,14 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
250
  /**/
251
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
252
  /**/
253
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
254
- _x ('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />Could not get the existing User ID from the DB.', "s2member-front", "s2member"),/**/
255
- _x ("Back To Home Page", "s2member-front", "s2member"), home_url ("/"));
256
  }
257
  /**/
258
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
259
- do_action ("ws_plugin__s2member_during_paypal_return_after_subscr_signup_w_update_vars", get_defined_vars ());
260
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
261
  }
262
  /*
263
  New Subscription. Normal Subscription signup, we are not updating anything for a past Subscription.
@@ -265,57 +270,57 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
265
  else /* Else this is a normal Subscription signup, we are not updating an existing Subscription. */
266
  {
267
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
268
- do_action ("ws_plugin__s2member_during_paypal_return_before_subscr_signup_wo_update_vars", get_defined_vars ());
269
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
270
  /**/
271
  $processing = $during = true; /* Yes, we ARE processing this new Subscription request. */
272
  /**/
273
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ) w/o update vars.";
274
  /**/
275
- setcookie ("s2member_subscr_gateway", ($s2member_subscr_gateway = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["subscr_gateway"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_subscr_gateway", $s2member_subscr_gateway, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_subscr_gateway"] = $s2member_subscr_gateway);
276
- setcookie ("s2member_subscr_id", ($s2member_subscr_id = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["subscr_id"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_subscr_id", $s2member_subscr_id, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_subscr_id"] = $s2member_subscr_id);
277
- setcookie ("s2member_custom", ($s2member_custom = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["custom"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_custom", $s2member_custom, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_custom"] = $s2member_custom);
278
- setcookie ("s2member_item_number", ($s2member_item_number = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["item_number"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_item_number", $s2member_item_number, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_item_number"] = $s2member_item_number);
279
  /**/
280
  $paypal["s2member_log"][] = "Registration Cookies set on ( `web_accept|subscr_signup|subscr_payment` ) w/o update vars.";
281
  /**/
282
- setcookie ("s2member_tracking", ($s2member_tracking = c_ws_plugin__s2member_utils_encryption::encrypt ($paypal["subscr_id"])), time () + 31556926, COOKIEPATH, COOKIE_DOMAIN) . setcookie ("s2member_tracking", $s2member_tracking, time () + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN) . ($_COOKIE["s2member_tracking"] = $s2member_tracking);
283
  /**/
284
  $paypal["s2member_log"][] = "Transient Tracking Cookie set on ( `web_accept|subscr_signup|subscr_payment` ) w/o update vars.";
285
  /**/
286
- if ($processing && $tracking_properties && ($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_tracking_codes"]) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
287
  {
288
- if (($code = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $code)) && ($code = preg_replace ("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["subscr_id"]), $code)))
289
- if (($code = preg_replace ("/%%initial%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["initial"]), $code)) && ($code = preg_replace ("/%%regular%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["regular"]), $code)) && ($code = preg_replace ("/%%recurring%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["recurring"]), $code)))
290
- if (($code = preg_replace ("/%%initial_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["initial_term"]), $code)) && ($code = preg_replace ("/%%regular_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["regular_term"]), $code)))
291
- if (($code = preg_replace ("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_number"]), $code)) && ($code = preg_replace ("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["item_name"]), $code)))
292
- if (($code = preg_replace ("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["first_name"]), $code)) && ($code = preg_replace ("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["last_name"]), $code)))
293
- if (($code = preg_replace ("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
294
- if (($code = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $code)))
295
- if (($code = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $code)))
296
  /**/
297
- if (($code = trim (preg_replace ("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
298
  {
299
  $paypal["s2member_log"][] = "Storing Signup Tracking Codes into a Transient Queue. These will be processed on-site.";
300
- set_transient ("s2m_" . md5 ("s2member_transient_signup_tracking_codes_" . $paypal["subscr_id"]), $code, 43200);
301
  }
302
  }
303
  /**/
304
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
305
- do_action ("ws_plugin__s2member_during_paypal_return_during_subscr_signup_wo_update_vars", get_defined_vars ());
306
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
307
  /**/
308
- if (is_multisite () && c_ws_plugin__s2member_utils_conds::is_multisite_farm () && is_main_site ())
309
  {
310
- if (($redirection_url_after_mms_farm_signup = apply_filters ("ws_plugin__s2member_redirection_url_after_mms_farm_signup", false, get_defined_vars ())))
311
  {
312
- $paypal["s2member_log"][] = "Redirecting Customer to a custom URL after signup: " . $redirection_url_after_mms_farm_signup;
313
  /**/
314
  wp_redirect($redirection_url_after_mms_farm_signup);
315
  }
316
- else if ($custom_success_redirection) /* Using a custom success redirection URL? */
317
  {
318
- $paypal["s2member_log"][] = "Redirecting Customer to a custom URL on success: " . $custom_success_redirection;
319
  /**/
320
  wp_redirect($custom_success_redirection);
321
  }
@@ -323,22 +328,22 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
323
  {
324
  $paypal["s2member_log"][] = "Redirecting Customer to Signup Page. They need to Signup/Register now.";
325
  /**/
326
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
327
- _x ('<strong>Thank you! Your account has been approved.<br />The next step is to Register a Username for immediate access.</strong>', "s2member-front", "s2member"),/**/
328
- _x ("Please Register Now ( Click Here )", "s2member-front", "s2member"), c_ws_plugin__s2member_utils_urls::wp_signup_url ());
329
  }
330
  }
331
  else /* Otherwise, this is NOT a Multisite install. Or it is, but the Super Administrator is NOT selling Blog creation. */
332
  {
333
- if (($redirection_url_after_signup = apply_filters ("ws_plugin__s2member_redirection_url_after_signup", false, get_defined_vars ())))
334
  {
335
- $paypal["s2member_log"][] = "Redirecting Customer to a custom URL after signup: " . $redirection_url_after_signup;
336
  /**/
337
  wp_redirect($redirection_url_after_signup);
338
  }
339
- else if ($custom_success_redirection) /* Using a custom success redirection URL? */
340
  {
341
- $paypal["s2member_log"][] = "Redirecting Customer to a custom URL on success: " . $custom_success_redirection;
342
  /**/
343
  wp_redirect($custom_success_redirection);
344
  }
@@ -346,15 +351,15 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
346
  {
347
  $paypal["s2member_log"][] = "Redirecting Customer to Registration Page. They need to Register now.";
348
  /**/
349
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
350
- _x ('<strong>Thank you! Your account has been approved.<br />The next step is to Register a Username for immediate access.</strong>', "s2member-front", "s2member"),/**/
351
- _x ("Please Register Now ( Click Here )", "s2member-front", "s2member"), c_ws_plugin__s2member_utils_urls::wp_register_url ());
352
  }
353
  }
354
  /**/
355
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
356
- do_action ("ws_plugin__s2member_during_paypal_return_after_subscr_signup_wo_update_vars", get_defined_vars ());
357
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
358
  }
359
  }
360
  else /* Page Expired. Duplicate Return-Data. */
@@ -363,19 +368,19 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"
363
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ).";
364
  $paypal["s2member_log"][] = "Page Expired. Redirecting Customer to the Home Page.";
365
  /**/
366
- echo c_ws_plugin__s2member_return_templates::return_template ($paypal["subscr_gateway"],/**/
367
- _x ('<strong>Page Expired:</strong> Duplicate Return-Data.<br />Please contact Support if you need any assistance.', "s2member-front", "s2member"),/**/
368
- _x ("Back To Home Page", "s2member-front", "s2member"), home_url ("/"));
369
  }
370
  /**/
371
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
372
- do_action ("ws_plugin__s2member_during_paypal_return_after_subscr_signup", get_defined_vars ());
373
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
374
  /**/
375
- return apply_filters ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level", $paypal, get_defined_vars ());
376
  }
377
  else
378
- return apply_filters ("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level", false, get_defined_vars ());
379
  }
380
  }
381
  }
14
  * @package s2Member\PayPal
15
  * @since 110720
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level"))
21
  {
22
  /**
23
  * s2Member's PayPal® Auto-Return/PDT handler ( inner processing routine ).
38
  *
39
  * @todo Optimize with ``empty()`` and ``isset()``.
40
  */
41
+ public static function cp($vars = array()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
  extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
+ if(/**/(!empty($paypal["txn_type"]) && preg_match("/^(web_accept|subscr_signup|subscr_payment)$/i", $paypal["txn_type"]))/**/
46
+ && (!empty($paypal["item_number"]) && preg_match($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
47
+ && (!empty($paypal["subscr_id"]) || (!empty($paypal["txn_id"]) && ($paypal["subscr_id"] = $paypal["txn_id"])))/**/
48
+ && (empty($paypal["payment_status"]) || empty($payment_status_issues) || !preg_match($payment_status_issues, $paypal["payment_status"]))/**/)
49
  {
50
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
+ do_action("ws_plugin__s2member_during_paypal_return_before_subscr_signup", get_defined_vars());
52
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
54
+ if(!get_transient($transient_rtn = "s2m_rtn_".md5("s2member_transient_".$_paypal_s)) && set_transient($transient_rtn, time(), 31556926 * 10))
55
  {
56
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ).";
57
  /**/
58
+ list($paypal["level"], $paypal["ccaps"], $paypal["eotper"]) = preg_split("/\:/", $paypal["item_number"], 3);
59
  /**/
60
+ $paypal["ip"] = (preg_match("/ip address/i", $paypal["option_name2"]) && $paypal["option_selection2"]) ? $paypal["option_selection2"] : "";
61
+ $paypal["ip"] = (!$paypal["ip"] && preg_match("/^[a-z0-9]+~[0-9\.]+$/i", $paypal["invoice"])) ? preg_replace("/^[a-z0-9]+~/i", "", $paypal["invoice"]) : $paypal["ip"];
62
  $paypal["ip"] = (!$paypal["ip"] && $_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : $paypal["ip"];
63
  /**/
64
+ if(/**/(preg_match("/^subscr_payment$/i", $paypal["txn_type"]) && !empty($_GET["s2member_paypal_return_tra"])) /* Decrypt/unserialize. */
65
+ && (($tra = c_ws_plugin__s2member_utils_encryption::decrypt(trim(stripslashes($_GET["s2member_paypal_return_tra"])))) && is_array($tra = maybe_unserialize($tra)))/**/
66
+ && (count($tra) === 11 && isset($tra["ta"], $tra["tp"], $tra["tt"], $tra["ra"], $tra["rp"], $tra["rt"], $tra["rr"], $tra["rrt"], $tra["rra"], $tra["invoice"], $tra["checksum"]))/**/
67
+ && ($tra["invoice"] === $paypal["invoice"]) && ($tra["checksum"] === md5($paypal["invoice"].$paypal["ip"].$paypal["item_number"]))/**/)
68
  {
69
  $tracking_properties = true; /* Yes, these tracking properties ARE being set here. */
70
  /**/
71
+ $paypal["period1"] = ($tra["rr"] !== "BN" && $tra["tp"]) ? $tra["tp"]." ".$tra["tt"] : "0 D";
72
+ $paypal["mc_amount1"] = ($tra["rr"] !== "BN" && $tra["tp"]) ? number_format($tra["ta"], 2, ".", "") : "0.00";
73
  /**/
74
+ $paypal["period3"] = $tra["rp"]." ".$tra["rt"];
75
  $paypal["mc_amount3"] = $tra["ra"];
76
  /**/
77
  $paypal["recurring"] = ($tra["rr"] === "1") ? "1" : "0";
78
  /**/
79
+ $paypal["initial_term"] = (preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
80
+ $paypal["initial"] = (strlen($paypal["mc_amount1"]) && preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
81
  $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the Customer. Always required by PayPal®. */
82
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
83
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
84
  /**/
85
  eval('$ipn_signup_vars = $paypal; unset($ipn_signup_vars["s2member_log"]);'); /* Create array of wouldbe IPN signup vars w/o s2member_log. */
86
  }
87
+ else if(preg_match("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]))
88
  {
89
  $tracking_properties = true; /* Yes, these tracking properties ARE being set here. */
90
  /**/
91
+ $paypal["period1"] = (preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
92
+ $paypal["mc_amount1"] = (strlen($paypal["mc_amount1"]) && $paypal["mc_amount1"] > 0) ? $paypal["mc_amount1"] : "0.00"; /* "0.00". */
93
  /**/
94
+ if(preg_match("/^web_accept$/i", $paypal["txn_type"])) /* Conversions for Lifetime & Fixed-Term sales. */
95
  {
96
  $paypal["period3"] = ($paypal["eotper"]) ? $paypal["eotper"] : "1 L"; /* 1 Lifetime. */
97
  $paypal["mc_amount3"] = $paypal["mc_gross"]; /* The "Buy Now" amount is the full gross. */
98
  }
99
  /**/
100
+ $paypal["initial_term"] = (preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( zero days ). */
101
+ $paypal["initial"] = (strlen($paypal["mc_amount1"]) && preg_match("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
102
  $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the Customer. Always required by PayPal®. */
103
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
104
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
108
  /*
109
  New Subscription with advanced update vars ( option_name1, option_selection1 )? Used in Subscr. Modifications.
110
  */
111
+ if(preg_match("/(referenc|associat|updat|upgrad)/i", $paypal["option_name1"]) && $paypal["option_selection1"])
112
  {
113
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
114
+ do_action("ws_plugin__s2member_during_paypal_return_before_subscr_signup_w_update_vars", get_defined_vars());
115
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
116
  /**/
117
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ) w/ update vars.";
118
  /**/
119
  /* Check for both the old & new subscr_id's, just in case the IPN routine already changed it. */
120
+ if(($user_id = c_ws_plugin__s2member_utils_users::get_user_id_with($paypal["subscr_id"], $paypal["option_selection1"])) && is_object($user = new WP_User($user_id)) && $user->ID)
121
  {
122
+ if(!$user->has_cap("administrator")) /* Do NOT process this routine on Administrators. */
123
  {
124
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
125
  /**/
126
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
127
+ do_action("ws_plugin__s2member_during_paypal_return_during_before_subscr_signup_w_update_vars", get_defined_vars());
128
+ do_action("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars(), "rtn-upgrade-downgrade", "modification", "s2member_level".$paypal["level"]);
129
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
130
+ /**/
131
+ $fields = get_user_option("s2member_custom_fields", $user_id); /* These will be needed in the routines below. */
132
+ $user_reg_ip = get_user_option("s2member_registration_ip", $user_id); /* Original IP during Registration. */
133
  $user_reg_ip = $paypal["ip"] = ($user_reg_ip) ? $user_reg_ip : $paypal["ip"]; /* Now merge conditionally. */
134
  /**/
135
+ if(is_multisite() && !is_user_member_of_blog($user_id)) /* Must have a Role on this Blog. */
136
  {
137
+ add_existing_user_to_blog(array("user_id" => $user_id, "role" => "s2member_level".$paypal["level"]));
138
+ $user = new WP_User($user_id);
139
  }
140
  /**/
141
+ $current_role = c_ws_plugin__s2member_user_access::user_access_role($user);
142
  /**/
143
+ if($current_role !== "s2member_level".$paypal["level"]) /* Only if we need to. */
144
+ $user->set_role("s2member_level".$paypal["level"]); /* (upgrade/downgrade) */
145
  /**/
146
+ if($paypal["ccaps"] && preg_match("/^-all/", str_replace("+", "", $paypal["ccaps"])))
147
+ foreach($user->allcaps as $cap => $cap_enabled)
148
+ if(preg_match("/^access_s2member_ccap_/", $cap))
149
+ $user->remove_cap($ccap = $cap);
150
  /**/
151
+ if($paypal["ccaps"] && preg_replace("/^-all[\r\n\t\s;,]*/", "", str_replace("+", "", $paypal["ccaps"])))
152
+ foreach(preg_split("/[\r\n\t\s;,]+/", preg_replace("/^-all[\r\n\t\s;,]*/", "", str_replace("+", "", $paypal["ccaps"]))) as $ccap)
153
+ if(strlen($ccap = trim(strtolower(preg_replace("/[^a-z_0-9]/i", "", $ccap)))))
154
+ $user->add_cap("access_s2member_ccap_".$ccap);
155
  /**/
156
+ update_user_option($user_id, "s2member_subscr_gateway", $paypal["subscr_gateway"]);
157
+ update_user_option($user_id, "s2member_subscr_id", $paypal["subscr_id"]);
158
+ update_user_option($user_id, "s2member_custom", $paypal["custom"]);
159
  /**/
160
+ if(!get_user_option("s2member_registration_ip", $user_id))
161
+ update_user_option($user_id, "s2member_registration_ip", $paypal["ip"]);
162
  /**/
163
+ if( /* We should have these from the routines above. */!empty($ipn_signup_vars))
164
+ update_user_option($user_id, "s2member_ipn_signup_vars", $ipn_signup_vars);
165
  /**/
166
+ delete_user_option($user_id, "s2member_file_download_access_log");
167
  /**/
168
+ if(preg_match("/^web_accept$/i", $paypal["txn_type"]) && $paypal["eotper"])
169
  {
170
  /* Don't update this in the return routine. Leave this for the IPN routine. */
171
  /* EOT Times might be extended, and we don't want the IPN routine to extend an already-extended EOT Time. */
172
+ $eot_time = c_ws_plugin__s2member_utils_time::auto_eot_time("", "", "", $paypal["eotper"], "", get_user_option("s2member_auto_eot_time", $user_id));
173
+ $paypal["s2member_log"][] = "Automatic EOT ( End Of Term ) Time will be set to: ".date("D M j, Y g:i:s a T", $eot_time).".";
174
  }
175
  else /* Otherwise, we need to clear the Auto-EOT Time. */
176
+ delete_user_option($user_id, "s2member_auto_eot_time");
177
  /**/
178
+ $pr_times = get_user_option("s2member_paid_registration_times", $user_id);
179
+ $pr_times["level"] = (!$pr_times["level"]) ? time() : $pr_times["level"]; /* Preserves existing. */
180
+ $pr_times["level".$paypal["level"]] = (!$pr_times["level".$paypal["level"]]) ? time() : $pr_times["level".$paypal["level"]];
181
+ update_user_option($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
182
  /**/
183
+ c_ws_plugin__s2member_user_notes::clear_user_note_lines($user_id, "/^Demoted by s2Member\:/");
184
  /**/
185
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
186
  /**/
187
+ setcookie("s2member_tracking", ($s2member_tracking = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["subscr_id"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_tracking", $s2member_tracking, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_tracking"] = $s2member_tracking);
188
  /**/
189
  $paypal["s2member_log"][] = "Transient Tracking Cookie set on ( `web_accept|subscr_signup|subscr_payment` ) w/ update vars.";
190
  /**/
191
+ if($processing && $tracking_properties && ($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_tracking_codes"]) && is_array($cv = preg_split("/\|/", $paypal["custom"])))
192
  {
193
+ if(($code = preg_replace("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $code)) && ($code = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["subscr_id"]), $code)))
194
+ if(($code = preg_replace("/%%initial%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["initial"]), $code)) && ($code = preg_replace("/%%regular%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["regular"]), $code)) && ($code = preg_replace("/%%recurring%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["recurring"]), $code)))
195
+ if(($code = preg_replace("/%%initial_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["initial_term"]), $code)) && ($code = preg_replace("/%%regular_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["regular_term"]), $code)))
196
+ if(($code = preg_replace("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_number"]), $code)) && ($code = preg_replace("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_name"]), $code)))
197
+ if(($code = preg_replace("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["first_name"]), $code)) && ($code = preg_replace("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["last_name"]), $code)))
198
+ if(($code = preg_replace("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($paypal["first_name"]." ".$paypal["last_name"])), $code)))
199
+ if(($code = preg_replace("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["payer_email"]), $code)))
200
  {
201
+ if(($code = preg_replace("/%%user_first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->first_name), $code)) && ($code = preg_replace("/%%user_last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->last_name), $code)))
202
+ if(($code = preg_replace("/%%user_full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($user->first_name." ".$user->last_name)), $code)))
203
+ if(($code = preg_replace("/%%user_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->user_email), $code)))
204
+ if(($code = preg_replace("/%%user_login%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user->user_login), $code)))
205
+ if(($code = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_reg_ip), $code)))
206
+ if(($code = preg_replace("/%%user_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($user_id), $code)))
207
  {
208
+ if(is_array($fields) && !empty($fields))
209
+ foreach($fields as $var => $val) /* Custom Registration/Profile Fields. */
210
+ if(!($code = preg_replace("/%%".preg_quote($var, "/")."%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(maybe_serialize($val)), $code)))
211
  break;
212
  /**/
213
+ if(($code = trim(preg_replace("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
214
  {
215
  $paypal["s2member_log"][] = "Storing Modification Tracking Codes into a Transient Queue. These will be processed on-site.";
216
+ set_transient("s2m_".md5("s2member_transient_modification_tracking_codes_".$paypal["subscr_id"]), $code, 43200);
217
  }
218
  }
219
  }
220
  }
221
  /**/
222
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
223
+ do_action("ws_plugin__s2member_during_paypal_return_during_subscr_signup_w_update_vars", get_defined_vars());
224
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
225
  /**/
226
+ if(($redirection_url_after_modification = apply_filters("ws_plugin__s2member_redirection_url_after_modification", false, get_defined_vars())))
227
  {
228
+ $paypal["s2member_log"][] = "Redirecting Customer to a custom URL after modification: ".$redirection_url_after_modification;
229
  /**/
230
  wp_redirect($redirection_url_after_modification);
231
  }
233
  {
234
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in.";
235
  /**/
236
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
237
+ '<strong>'._x("Thank you! You've been updated to:", "s2member-front", "s2member").'<br /><em>'.esc_html($paypal["item_name"]).'</em></strong>',/**/
238
+ _x("Please Log Back In ( Click Here )", "s2member-front", "s2member"), wp_login_url());
239
  }
240
  }
241
  else /* Unable to modify Subscription. The existing User ID is associated with an Administrator. Stopping here. */
244
  /**/
245
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
246
  /**/
247
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
248
+ _x('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access. Please make sure that you are NOT logged in as an Administrator while testing.', "s2member-front", "s2member"),/**/
249
+ _x("Back To Home Page", "s2member-front", "s2member"), home_url("/"));
250
  }
251
  }
252
  else /* Unable to modify Subscription. Could not get the existing User ID from the DB. */
255
  /**/
256
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page, due to an error that occurred.";
257
  /**/
258
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
259
+ _x('<strong>ERROR:</strong> Unable to modify Subscription.<br />Please contact Support for assistance.<br /><br />Could not get the existing User ID from the DB.', "s2member-front", "s2member"),/**/
260
+ _x("Back To Home Page", "s2member-front", "s2member"), home_url("/"));
261
  }
262
  /**/
263
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
264
+ do_action("ws_plugin__s2member_during_paypal_return_after_subscr_signup_w_update_vars", get_defined_vars());
265
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
266
  }
267
  /*
268
  New Subscription. Normal Subscription signup, we are not updating anything for a past Subscription.
270
  else /* Else this is a normal Subscription signup, we are not updating an existing Subscription. */
271
  {
272
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
273
+ do_action("ws_plugin__s2member_during_paypal_return_before_subscr_signup_wo_update_vars", get_defined_vars());
274
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
275
  /**/
276
  $processing = $during = true; /* Yes, we ARE processing this new Subscription request. */
277
  /**/
278
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ) w/o update vars.";
279
  /**/
280
+ setcookie("s2member_subscr_gateway", ($s2member_subscr_gateway = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["subscr_gateway"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_subscr_gateway", $s2member_subscr_gateway, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_subscr_gateway"] = $s2member_subscr_gateway);
281
+ setcookie("s2member_subscr_id", ($s2member_subscr_id = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["subscr_id"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_subscr_id", $s2member_subscr_id, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_subscr_id"] = $s2member_subscr_id);
282
+ setcookie("s2member_custom", ($s2member_custom = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["custom"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_custom", $s2member_custom, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_custom"] = $s2member_custom);
283
+ setcookie("s2member_item_number", ($s2member_item_number = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["item_number"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_item_number", $s2member_item_number, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_item_number"] = $s2member_item_number);
284
  /**/
285
  $paypal["s2member_log"][] = "Registration Cookies set on ( `web_accept|subscr_signup|subscr_payment` ) w/o update vars.";
286
  /**/
287
+ setcookie("s2member_tracking", ($s2member_tracking = c_ws_plugin__s2member_utils_encryption::encrypt($paypal["subscr_id"])), time() + 31556926, COOKIEPATH, COOKIE_DOMAIN).setcookie("s2member_tracking", $s2member_tracking, time() + 31556926, SITECOOKIEPATH, COOKIE_DOMAIN).($_COOKIE["s2member_tracking"] = $s2member_tracking);
288
  /**/
289
  $paypal["s2member_log"][] = "Transient Tracking Cookie set on ( `web_accept|subscr_signup|subscr_payment` ) w/o update vars.";
290
  /**/
291
+ if($processing && $tracking_properties && ($code = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_tracking_codes"]) && is_array($cv = preg_split("/\|/", $paypal["custom"])))
292
  {
293
+ if(($code = preg_replace("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $code)) && ($code = preg_replace("/%%subscr_id%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["subscr_id"]), $code)))
294
+ if(($code = preg_replace("/%%initial%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["initial"]), $code)) && ($code = preg_replace("/%%regular%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["regular"]), $code)) && ($code = preg_replace("/%%recurring%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["recurring"]), $code)))
295
+ if(($code = preg_replace("/%%initial_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["initial_term"]), $code)) && ($code = preg_replace("/%%regular_term%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["regular_term"]), $code)))
296
+ if(($code = preg_replace("/%%item_number%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_number"]), $code)) && ($code = preg_replace("/%%item_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["item_name"]), $code)))
297
+ if(($code = preg_replace("/%%first_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["first_name"]), $code)) && ($code = preg_replace("/%%last_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["last_name"]), $code)))
298
+ if(($code = preg_replace("/%%full_name%%/i", c_ws_plugin__s2member_utils_strings::esc_ds(trim($paypal["first_name"]." ".$paypal["last_name"])), $code)))
299
+ if(($code = preg_replace("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["payer_email"]), $code)))
300
+ if(($code = preg_replace("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds($paypal["ip"]), $code)))
301
  /**/
302
+ if(($code = trim(preg_replace("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
303
  {
304
  $paypal["s2member_log"][] = "Storing Signup Tracking Codes into a Transient Queue. These will be processed on-site.";
305
+ set_transient("s2m_".md5("s2member_transient_signup_tracking_codes_".$paypal["subscr_id"]), $code, 43200);
306
  }
307
  }
308
  /**/
309
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
310
+ do_action("ws_plugin__s2member_during_paypal_return_during_subscr_signup_wo_update_vars", get_defined_vars());
311
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
312
  /**/
313
+ if(is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && is_main_site())
314
  {
315
+ if(($redirection_url_after_mms_farm_signup = apply_filters("ws_plugin__s2member_redirection_url_after_mms_farm_signup", false, get_defined_vars())))
316
  {
317
+ $paypal["s2member_log"][] = "Redirecting Customer to a custom URL after signup: ".$redirection_url_after_mms_farm_signup;
318
  /**/
319
  wp_redirect($redirection_url_after_mms_farm_signup);
320
  }
321
+ else if($custom_success_redirection) /* Using a custom success redirection URL? */
322
  {
323
+ $paypal["s2member_log"][] = "Redirecting Customer to a custom URL on success: ".$custom_success_redirection;
324
  /**/
325
  wp_redirect($custom_success_redirection);
326
  }
328
  {
329
  $paypal["s2member_log"][] = "Redirecting Customer to Signup Page. They need to Signup/Register now.";
330
  /**/
331
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
332
+ _x('<strong>Thank you! Your account has been approved.<br />The next step is to Register a Username for immediate access.</strong>', "s2member-front", "s2member"),/**/
333
+ _x("Please Register Now ( Click Here )", "s2member-front", "s2member"), c_ws_plugin__s2member_utils_urls::wp_signup_url());
334
  }
335
  }
336
  else /* Otherwise, this is NOT a Multisite install. Or it is, but the Super Administrator is NOT selling Blog creation. */
337
  {
338
+ if(($redirection_url_after_signup = apply_filters("ws_plugin__s2member_redirection_url_after_signup", false, get_defined_vars())))
339
  {
340
+ $paypal["s2member_log"][] = "Redirecting Customer to a custom URL after signup: ".$redirection_url_after_signup;
341
  /**/
342
  wp_redirect($redirection_url_after_signup);
343
  }
344
+ else if($custom_success_redirection) /* Using a custom success redirection URL? */
345
  {
346
+ $paypal["s2member_log"][] = "Redirecting Customer to a custom URL on success: ".$custom_success_redirection;
347
  /**/
348
  wp_redirect($custom_success_redirection);
349
  }
351
  {
352
  $paypal["s2member_log"][] = "Redirecting Customer to Registration Page. They need to Register now.";
353
  /**/
354
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
355
+ _x('<strong>Thank you! Your account has been approved.<br />The next step is to Register a Username for immediate access.</strong>', "s2member-front", "s2member"),/**/
356
+ _x("Please Register Now ( Click Here )", "s2member-front", "s2member"), c_ws_plugin__s2member_utils_urls::wp_register_url());
357
  }
358
  }
359
  /**/
360
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
361
+ do_action("ws_plugin__s2member_during_paypal_return_after_subscr_signup_wo_update_vars", get_defined_vars());
362
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
363
  }
364
  }
365
  else /* Page Expired. Duplicate Return-Data. */
368
  $paypal["s2member_log"][] = "s2Member `txn_type` identified as ( `web_accept|subscr_signup|subscr_payment` ).";
369
  $paypal["s2member_log"][] = "Page Expired. Redirecting Customer to the Home Page.";
370
  /**/
371
+ echo c_ws_plugin__s2member_return_templates::return_template($paypal["subscr_gateway"],/**/
372
+ _x('<strong>Page Expired:</strong> Duplicate Return-Data.<br />Please contact Support if you need any assistance.', "s2member-front", "s2member"),/**/
373
+ _x("Back To Home Page", "s2member-front", "s2member"), home_url("/"));
374
  }
375
  /**/
376
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
377
+ do_action("ws_plugin__s2member_during_paypal_return_after_subscr_signup", get_defined_vars());
378
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
379
  /**/
380
+ return apply_filters("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level", $paypal, get_defined_vars());
381
  }
382
  else
383
+ return apply_filters("c_ws_plugin__s2member_paypal_return_in_subscr_or_wa_w_level", false, get_defined_vars());
384
  }
385
  }
386
  }
includes/classes/roles-caps.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Roles_Caps
15
  * @since 110524RC
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_roles_caps"))
21
  {
22
  /**
23
  * Roles/Capabilities.
@@ -38,59 +38,59 @@ if (!class_exists ("c_ws_plugin__s2member_roles_caps"))
38
  * @todo Finalize support for unlimited Levels/Roles.
39
  * @todo Finalize support for independent Capabilities.
40
  */
41
- public static function config_roles ()
42
  {
43
- do_action ("ws_plugin__s2member_before_config_roles", get_defined_vars ());
44
  /**/
45
- if (!apply_filters ("ws_plugin__s2member_lock_roles_caps", false))
46
  {
47
- c_ws_plugin__s2member_roles_caps::unlink_roles ();
48
  /**/
49
- if (function_exists ("bbp_get_caps_for_role"))
50
- foreach (bbp_get_caps_for_role ("subscriber") as $bbp_cap)
51
  $bbp_caps[$bbp_cap] = true;
52
  /**/
53
- if (0 === 0) /* Subscriber Role is required by s2Member. */
54
  {
55
- $caps = array ("read" => true, "level_0" => true);
56
- $caps = array_merge ($caps, array ("access_s2member_level0" => true));
57
- $caps = (!empty ($bbp_caps)) ? array_merge ($caps, $bbp_caps) : $caps;
58
  /**/
59
- if (!($role = &get_role ("subscriber")))
60
  {
61
- add_role ("subscriber", "Subscriber");
62
- $role = &get_role ("subscriber");
63
  }
64
  /**/
65
- foreach (array_keys ($caps) as $cap)
66
- $role->add_cap ($cap);
67
  }
68
  /**/
69
- for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
70
  {
71
- for ($i = 0, $caps = array ("read" => true, "level_0" => true); $i <= $n; $i++)
72
- $caps = array_merge ($caps, array ("access_s2member_level" . $i => true));
73
- $caps = (!empty ($bbp_caps)) ? array_merge ($caps, $bbp_caps) : $caps;
74
  /**/
75
- if (!($role = &get_role ("s2member_level" . $n)))
76
  {
77
- add_role ("s2member_level" . $n, "s2Member Level " . $n);
78
- $role = &get_role ("s2member_level" . $n);
79
  }
80
  /**/
81
- foreach (array_keys ($caps) as $cap)
82
- $role->add_cap ($cap);
83
  }
84
  /**/
85
- foreach (array ("administrator", "editor", "author", "contributor", "bbp_moderator") as $role)
86
  {
87
- if (($role = &get_role ($role)))
88
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
89
- $role->add_cap ("access_s2member_level" . $n);
90
  }
91
  }
92
  /**/
93
- do_action ("ws_plugin__s2member_after_config_roles", get_defined_vars ());
94
  /**/
95
  return; /* Return for uniformity. */
96
  }
@@ -102,27 +102,27 @@ if (!class_exists ("c_ws_plugin__s2member_roles_caps"))
102
  *
103
  * @return null
104
  */
105
- public static function unlink_roles ()
106
  {
107
- do_action ("ws_plugin__s2member_before_unlink_roles", get_defined_vars ());
108
  /**/
109
- if (!apply_filters ("ws_plugin__s2member_lock_roles_caps", false))
110
  {
111
- if (($role = &get_role ("subscriber")))
112
- $role->remove_cap ("access_s2member_level0");
113
  /**/
114
- for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["max_levels"]; $n++)
115
- remove_role ("s2member_level" . $n);
116
  /**/
117
- foreach (array ("administrator", "editor", "author", "contributor", "bbp_moderator") as $role)
118
  {
119
- if (($role = &get_role ($role)))
120
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
121
- $role->remove_cap ("access_s2member_level" . $n);
122
  }
123
  }
124
  /**/
125
- do_action ("ws_plugin__s2member_after_unlink_roles", get_defined_vars ());
126
  /**/
127
  return; /* Return for uniformity. */
128
  }
@@ -136,30 +136,30 @@ if (!class_exists ("c_ws_plugin__s2member_roles_caps"))
136
  *
137
  * @return null Exits script execution after output for AJAX caller.
138
  */
139
- public static function update_roles_via_ajax ()
140
  {
141
- do_action ("ws_plugin__s2member_before_update_roles_via_ajax", get_defined_vars ());
142
  /**/
143
- status_header (200); /* Send a 200 OK status header. */
144
- header ("Content-Type: text/plain; charset=utf-8"); /* Content-Type with UTF-8. */
145
- eval ('while (@ob_end_clean ());'); /* End/clean all output buffers that may exist. */
146
  /**/
147
- if (current_user_can ("create_users")) /* Check priveledges. Ability to create Users? */
148
  /**/
149
- if (!empty ($_POST["ws_plugin__s2member_update_roles_via_ajax"]))
150
- if (($nonce = $_POST["ws_plugin__s2member_update_roles_via_ajax"]))
151
- if (wp_verify_nonce ($nonce, "ws-plugin--s2member-update-roles-via-ajax"))
152
  /**/
153
- if (!apply_filters ("ws_plugin__s2member_lock_roles_caps", false))
154
  {
155
- c_ws_plugin__s2member_roles_caps::config_roles ();
156
  $success = true; /* Roles updated. */
157
  }
158
  else /* Else flag as having been locked here. */
159
  $locked = true;
160
  /**/
161
- exit (apply_filters ("ws_plugin__s2member_update_roles_via_ajax", /* Also handle ``$locked`` here. */
162
- ((isset ($success) && $success) ? "1" : ((isset ($locked) && $locked) ? "l" : "0")), get_defined_vars ()));
163
  }
164
  }
165
  }
14
  * @package s2Member\Roles_Caps
15
  * @since 110524RC
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_roles_caps"))
21
  {
22
  /**
23
  * Roles/Capabilities.
38
  * @todo Finalize support for unlimited Levels/Roles.
39
  * @todo Finalize support for independent Capabilities.
40
  */
41
+ public static function config_roles()
42
  {
43
+ do_action("ws_plugin__s2member_before_config_roles", get_defined_vars());
44
  /**/
45
+ if(!apply_filters("ws_plugin__s2member_lock_roles_caps", false))
46
  {
47
+ c_ws_plugin__s2member_roles_caps::unlink_roles();
48
  /**/
49
+ if(function_exists("bbp_get_caps_for_role"))
50
+ foreach(bbp_get_caps_for_role("subscriber") as $bbp_cap)
51
  $bbp_caps[$bbp_cap] = true;
52
  /**/
53
+ if(0 === 0) /* Subscriber Role is required by s2Member. */
54
  {
55
+ $caps = array("read" => true, "level_0" => true);
56
+ $caps = array_merge($caps, array("access_s2member_level0" => true));
57
+ $caps = (!empty($bbp_caps)) ? array_merge($caps, $bbp_caps) : $caps;
58
  /**/
59
+ if(!($role = &get_role("subscriber")))
60
  {
61
+ add_role("subscriber", "Subscriber");
62
+ $role = &get_role("subscriber");
63
  }
64
  /**/
65
+ foreach(array_keys($caps) as $cap)
66
+ $role->add_cap($cap);
67
  }
68
  /**/
69
+ for($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
70
  {
71
+ for($i = 0, $caps = array("read" => true, "level_0" => true); $i <= $n; $i++)
72
+ $caps = array_merge($caps, array("access_s2member_level".$i => true));
73
+ $caps = (!empty($bbp_caps)) ? array_merge($caps, $bbp_caps) : $caps;
74
  /**/
75
+ if(!($role = &get_role("s2member_level".$n)))
76
  {
77
+ add_role("s2member_level".$n, "s2Member Level ".$n);
78
+ $role = &get_role("s2member_level".$n);
79
  }
80
  /**/
81
+ foreach(array_keys($caps) as $cap)
82
+ $role->add_cap($cap);
83
  }
84
  /**/
85
+ foreach(array("administrator", "editor", "author", "contributor", "bbp_moderator") as $role)
86
  {
87
+ if(($role = &get_role($role)))
88
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
89
+ $role->add_cap("access_s2member_level".$n);
90
  }
91
  }
92
  /**/
93
+ do_action("ws_plugin__s2member_after_config_roles", get_defined_vars());
94
  /**/
95
  return; /* Return for uniformity. */
96
  }
102
  *
103
  * @return null
104
  */
105
+ public static function unlink_roles()
106
  {
107
+ do_action("ws_plugin__s2member_before_unlink_roles", get_defined_vars());
108
  /**/
109
+ if(!apply_filters("ws_plugin__s2member_lock_roles_caps", false))
110
  {
111
+ if(($role = &get_role("subscriber")))
112
+ $role->remove_cap("access_s2member_level0");
113
  /**/
114
+ for($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["max_levels"]; $n++)
115
+ remove_role("s2member_level".$n);
116
  /**/
117
+ foreach(array("administrator", "editor", "author", "contributor", "bbp_moderator") as $role)
118
  {
119
+ if(($role = &get_role($role)))
120
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["max_levels"]; $n++)
121
+ $role->remove_cap("access_s2member_level".$n);
122
  }
123
  }
124
  /**/
125
+ do_action("ws_plugin__s2member_after_unlink_roles", get_defined_vars());
126
  /**/
127
  return; /* Return for uniformity. */
128
  }
136
  *
137
  * @return null Exits script execution after output for AJAX caller.
138
  */
139
+ public static function update_roles_via_ajax()
140
  {
141
+ do_action("ws_plugin__s2member_before_update_roles_via_ajax", get_defined_vars());
142
  /**/
143
+ status_header(200); /* Send a 200 OK status header. */
144
+ header("Content-Type: text/plain; charset=utf-8"); /* Content-Type with UTF-8. */
145
+ eval('while (@ob_end_clean ());'); /* End/clean all output buffers that may exist. */
146
  /**/
147
+ if(current_user_can("create_users")) /* Check priveledges. Ability to create Users? */
148
  /**/
149
+ if(!empty($_POST["ws_plugin__s2member_update_roles_via_ajax"]))
150
+ if(($nonce = $_POST["ws_plugin__s2member_update_roles_via_ajax"]))
151
+ if(wp_verify_nonce($nonce, "ws-plugin--s2member-update-roles-via-ajax"))
152
  /**/
153
+ if(!apply_filters("ws_plugin__s2member_lock_roles_caps", false))
154
  {
155
+ c_ws_plugin__s2member_roles_caps::config_roles();
156
  $success = true; /* Roles updated. */
157
  }
158
  else /* Else flag as having been locked here. */
159
  $locked = true;
160
  /**/
161
+ exit(apply_filters("ws_plugin__s2member_update_roles_via_ajax", /* Also handle ``$locked`` here. */
162
+ ((isset($success) && $success) ? "1" : ((isset($locked) && $locked) ? "l" : "0")), get_defined_vars()));
163
  }
164
  }
165
  }
includes/classes/ssl-in.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\SSL
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_ssl_in"))
21
  {
22
  /**
23
  * SSL routines ( inner processing routines ).
@@ -45,116 +45,118 @@ if (!class_exists ("c_ws_plugin__s2member_ssl_in"))
45
  * @todo Add `form` to the array ``$non_ssl_attr_only_tags``?
46
  * @todo Cleanup this routine and convert callback functions to static class methods?
47
  */
48
- public static function force_ssl ($vars = array ()) /* Phase 2 of ``c_ws_plugin__s2member_ssl::check_force_ssl()``. */
49
  {
50
- extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_ssl::check_force_ssl()``. */
51
  /**/
52
- $force_ssl = (!is_string ($force_ssl)) ? (string)(int)$force_ssl : $force_ssl; /* Force string. */
53
- $force_ssl = (is_numeric ($force_ssl) && $force_ssl > 1) ? $force_ssl : "yes"; /* Use `yes`. */
54
  /**/
55
- $ssl_host = preg_replace ("/\:[0-9]+$/", "", $_SERVER["HTTP_HOST"]); /* Remove port here. */
56
- $ssl_port = (is_numeric ($force_ssl) && $force_ssl > 1) ? $force_ssl : false; /* Port? */
57
- $ssl_host_port = $ssl_host . (($ssl_port) ? ":" . $ssl_port : ""); /* Use port #? */
58
  /**/
59
- if (!is_ssl () || !isset ($_GET[$s2_ssl_gv])) /* SSL must be enabled. */
60
  {
61
- $https = "https://" . $ssl_host_port . $_SERVER["REQUEST_URI"];
62
- $https_with_s2_ssl_gv = add_query_arg ($s2_ssl_gv, urlencode ($force_ssl), $https);
63
- wp_redirect($https_with_s2_ssl_gv) . exit ();
64
  }
65
  else /* Otherwise, we buffer all output, and switch all content over to `https`. */
66
  /* Assume here that other links on the site should NOT be converted to `https`. */
67
  {
68
- add_filter ("redirect_canonical", "__return_false");
69
  /**/
70
- define ("_ws_plugin__s2member_force_ssl_host", $ssl_host);
71
- define ("_ws_plugin__s2member_force_ssl_port", $ssl_port);
72
- define ("_ws_plugin__s2member_force_ssl_host_port", $ssl_host_port);
73
  /**/
74
  /* Filter these. Do NOT create a sitewide conversion to `https`. */
75
- add_filter ("home_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
76
- add_filter ("network_home_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
77
- add_filter ("site_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
78
- add_filter ("network_site_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
 
 
79
  /*
80
  These additional URLs are NOT Filtered by default; but can be if needed. Use these Filters. */
81
- if (apply_filters ("_ws_plugin__s2member_force_non_ssl_scheme_plugins_url", false, get_defined_vars ()))
82
- add_filter ("plugins_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 2);
83
  /*
84
  These additional URLs are NOT Filtered by default; but can be if needed. Use these Filters. */
85
- if (apply_filters ("_ws_plugin__s2member_force_non_ssl_scheme_content_url", false, get_defined_vars ()))
86
- add_filter ("content_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 2);
87
  /*
88
  Now we create various callback functions associated with SSL and non-SSL buffering.
89
  */
90
- if (!function_exists ("_ws_plugin__s2member_force_ssl_buffer_callback")) /* Pluggable? */
91
  {
92
- function _ws_plugin__s2member_force_ssl_buffer_callback ($m = FALSE) /* Callback function. */
93
  {
94
- $s = preg_replace ("/http\:\/\//i", "https://", $m[0]); /* Conversion to SSL mode via `https`. */
95
  /**/
96
- if (_ws_plugin__s2member_force_ssl_host && _ws_plugin__s2member_force_ssl_port && _ws_plugin__s2member_force_ssl_host_port) /* Convert port? */
97
- $s = preg_replace ("/(?:https?\:)?\/\/" . preg_quote (_ws_plugin__s2member_force_ssl_host, "/") . "(?:\:[0-9]+)?/i", "https://" . _ws_plugin__s2member_force_ssl_host_port, $s);
98
  /**/
99
- $s = (strtolower ($m[1]) === "link" && preg_match ("/['\"]alternate['\"]/i", $m[0])) ? $m[0] : $s; /* Alternates are fine to leave like they are. */
100
  /**/
101
- return $s; /* Return string with conversions. */
102
  }
103
  }
104
  /**/
105
- if (!function_exists ("_ws_plugin__s2member_force_non_ssl_buffer_callback")) /* Pluggable? */
106
  {
107
- function _ws_plugin__s2member_force_non_ssl_buffer_callback ($m = FALSE) /* Callback function. */
108
  {
109
- $s = preg_replace ("/(?:https?\:)?\/\/" . preg_quote (_ws_plugin__s2member_force_ssl_host_port, "/") . "/i", "http://" . _ws_plugin__s2member_force_ssl_host, $m[0]);
110
  /**/
111
- $s = preg_replace ("/(?:https?\:)?\/\/" . preg_quote (_ws_plugin__s2member_force_ssl_host, "/") . "/i", "http://" . _ws_plugin__s2member_force_ssl_host, $s);
112
  /**/
113
- return $s; /* Return string with conversions. */
114
  }
115
  }
116
  /**/
117
- if (!function_exists ("_ws_plugin__s2member_force_non_ssl_scheme")) /* Pluggable? */
118
  {
119
- function _ws_plugin__s2member_force_non_ssl_scheme ($url = FALSE, $path = FALSE, $scheme = FALSE)
120
  {
121
- if (!in_array ($scheme, array ("http", "https"))) /* If NOT explicitly passed through. */
122
  {
123
- if (($scheme === "login_post" || $scheme === "rpc") && (force_ssl_login () || force_ssl_admin ()))
124
  $scheme = "https";
125
  /**/
126
- else if (($scheme === "login" || $scheme === "admin") && force_ssl_admin ())
127
  $scheme = "https";
128
  /**/
129
  else /* Default to non-SSL: `http`. */
130
  $scheme = "http";
131
  }
132
- return preg_replace ("/^(?:https?\:)?\/\//i", $scheme . "://", $url);
133
  }
134
  }
135
  /**/
136
- if (!function_exists ("_ws_plugin__s2member_force_ssl_buffer")) /* Pluggable? */
137
  {
138
- function _ws_plugin__s2member_force_ssl_buffer ($buffer = FALSE) /* Output handler. */
139
  {
140
- $o_pcre = @ini_get ("pcre.backtrack_limit"); /* Record existing PCRE backtrack limit. */
141
- @ini_set ("pcre.backtrack_limit", 10000000); /* Increase PCRE backtrack limit for this routine. */
142
  /**/
143
- $ssl_entire_tags = array_unique (array_map ("strtolower", apply_filters ("_ws_plugin__s2member_force_ssl_buffer_entire_tags", array ("script", "style", "iframe", "object", "embed", "video"), get_defined_vars ())));
144
- $non_ssl_entire_tags = array_unique (array_map ("strtolower", apply_filters ("_ws_plugin__s2member_force_non_ssl_buffer_entire_tags", array (), get_defined_vars ())));
145
  /**/
146
- $ssl_attr_only_tags = array_unique ( /* Diff here. No need to re-run entire tags. */array_diff (array_map ("strtolower", apply_filters ("_ws_plugin__s2member_force_ssl_buffer_attr_only_tags", array ("link", "img", "input"), get_defined_vars ())), $ssl_entire_tags));
147
- $non_ssl_attr_only_tags = array_unique ( /* No need to re-run entire tags. */array_diff (array_map ("strtolower", apply_filters ("_ws_plugin__s2member_force_non_ssl_buffer_attr_only_tags", array ("a"), get_defined_vars ())), $non_ssl_entire_tags));
148
  /**/
149
- $buffer = ($ssl_entire_tags) ? preg_replace_callback ("/\<(" . implode ("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep ($ssl_entire_tags, "/")) . ")(?![a-z_0-9\-])[^\>]*?\>.*?\<\/\\1\>/is", "_ws_plugin__s2member_force_ssl_buffer_callback", $buffer) : $buffer;
150
- $buffer = ($ssl_attr_only_tags) ? preg_replace_callback ("/\<(" . implode ("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep ($ssl_attr_only_tags, "/")) . ")(?![a-z_0-9\-])[^\>]+?\>/i", "_ws_plugin__s2member_force_ssl_buffer_callback", $buffer) : $buffer;
151
  /**/
152
- $buffer = ($non_ssl_entire_tags) ? preg_replace_callback ("/\<(" . implode ("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep ($non_ssl_entire_tags, "/")) . ")(?![a-z_0-9\-])[^\>]*?\>.*?\<\/\\1\>/is", "_ws_plugin__s2member_force_non_ssl_buffer_callback", $buffer) : $buffer;
153
- $buffer = ($non_ssl_attr_only_tags) ? preg_replace_callback ("/\<(" . implode ("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep ($non_ssl_attr_only_tags, "/")) . ")(?![a-z_0-9\-])[^\>]+?\>/i", "_ws_plugin__s2member_force_non_ssl_buffer_callback", $buffer) : $buffer;
154
  /**/
155
- @ini_set ("pcre.backtrack_limit", $o_pcre); /* Restore original PCRE backtrack limit. This just keeps things tidy; probably NOT necessary. */
156
  /**/
157
- return apply_filters ("_ws_plugin__s2member_force_ssl_buffer", $buffer, get_defined_vars ());
158
  }
159
  }
160
  /**/
14
  * @package s2Member\SSL
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_ssl_in"))
21
  {
22
  /**
23
  * SSL routines ( inner processing routines ).
45
  * @todo Add `form` to the array ``$non_ssl_attr_only_tags``?
46
  * @todo Cleanup this routine and convert callback functions to static class methods?
47
  */
48
+ public static function force_ssl($vars = array()) /* Phase 2 of ``c_ws_plugin__s2member_ssl::check_force_ssl()``. */
49
  {
50
+ extract /* Extract all vars passed in from: ``c_ws_plugin__s2member_ssl::check_force_ssl()``. */($vars);
51
  /**/
52
+ $force_ssl = (!is_string($force_ssl)) ? /* Force string. */ (string)(int)$force_ssl : $force_ssl;
53
+ $force_ssl = (is_numeric($force_ssl) && $force_ssl > 1) ? $force_ssl : /* Use `yes`. */ "yes";
54
  /**/
55
+ $ssl_host = /* Remove port here. */ preg_replace("/\:[0-9]+$/", "", $_SERVER["HTTP_HOST"]);
56
+ $ssl_port = /* Port? */ (is_numeric($force_ssl) && $force_ssl > 1) ? $force_ssl : false;
57
+ $ssl_host_port = /* Use port #? */ $ssl_host.(($ssl_port) ? ":".$ssl_port : "");
58
  /**/
59
+ if(!is_ssl() || !isset($_GET[$s2_ssl_gv]) /* SSL must be enabled. */)
60
  {
61
+ $https = "https://".$ssl_host_port.$_SERVER["REQUEST_URI"];
62
+ $https_with_s2_ssl_gv = add_query_arg($s2_ssl_gv, urlencode($force_ssl), $https);
63
+ wp_redirect($https_with_s2_ssl_gv).exit();
64
  }
65
  else /* Otherwise, we buffer all output, and switch all content over to `https`. */
66
  /* Assume here that other links on the site should NOT be converted to `https`. */
67
  {
68
+ add_filter("redirect_canonical", "__return_false");
69
  /**/
70
+ define("_ws_plugin__s2member_force_ssl_host", $ssl_host);
71
+ define("_ws_plugin__s2member_force_ssl_port", $ssl_port);
72
+ define("_ws_plugin__s2member_force_ssl_host_port", $ssl_host_port);
73
  /**/
74
  /* Filter these. Do NOT create a sitewide conversion to `https`. */
75
+ add_filter("home_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
76
+ add_filter("network_home_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
77
+ /**/
78
+ /* Filter these. Do NOT create a sitewide conversion to `https`. */
79
+ add_filter("site_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
80
+ add_filter("network_site_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 3);
81
  /*
82
  These additional URLs are NOT Filtered by default; but can be if needed. Use these Filters. */
83
+ if(apply_filters("_ws_plugin__s2member_force_non_ssl_scheme_plugins_url", false, get_defined_vars()))
84
+ add_filter("plugins_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 2);
85
  /*
86
  These additional URLs are NOT Filtered by default; but can be if needed. Use these Filters. */
87
+ if(apply_filters("_ws_plugin__s2member_force_non_ssl_scheme_content_url", false, get_defined_vars()))
88
+ add_filter("content_url", "_ws_plugin__s2member_force_non_ssl_scheme", 10, 2);
89
  /*
90
  Now we create various callback functions associated with SSL and non-SSL buffering.
91
  */
92
+ if(!function_exists("_ws_plugin__s2member_force_ssl_buffer_callback"))
93
  {
94
+ function _ws_plugin__s2member_force_ssl_buffer_callback($m = FALSE)
95
  {
96
+ $s = /* Conversion to SSL mode via `https`. */ preg_replace("/http\:\/\//i", "https://", $m[0]);
97
  /**/
98
+ if(_ws_plugin__s2member_force_ssl_host && /* Convert port? */ _ws_plugin__s2member_force_ssl_port && _ws_plugin__s2member_force_ssl_host_port)
99
+ $s = preg_replace("/(?:https?\:)?\/\/".preg_quote(_ws_plugin__s2member_force_ssl_host, "/")."(?:\:[0-9]+)?/i", "https://"._ws_plugin__s2member_force_ssl_host_port, $s);
100
  /**/
101
+ $s = (strtolower($m[1]) === "link" && preg_match /* These are fine to leave like they are. */("/['\"](?:alternate|profile|pingback|EditURI|wlwmanifest|prev|next)['\"]/i", $m[0])) ? $m[0] : $s;
102
  /**/
103
+ return /* Return string with conversions. */ $s;
104
  }
105
  }
106
  /**/
107
+ if(!function_exists("_ws_plugin__s2member_force_non_ssl_buffer_callback"))
108
  {
109
+ function _ws_plugin__s2member_force_non_ssl_buffer_callback($m = FALSE)
110
  {
111
+ $s = preg_replace("/(?:https?\:)?\/\/".preg_quote(_ws_plugin__s2member_force_ssl_host_port, "/")."/i", "http://"._ws_plugin__s2member_force_ssl_host, $m[0]);
112
  /**/
113
+ $s = preg_replace("/(?:https?\:)?\/\/".preg_quote(_ws_plugin__s2member_force_ssl_host, "/")."/i", "http://"._ws_plugin__s2member_force_ssl_host, $s);
114
  /**/
115
+ return /* Return string with conversions. */ $s;
116
  }
117
  }
118
  /**/
119
+ if(!function_exists("_ws_plugin__s2member_force_non_ssl_scheme"))
120
  {
121
+ function _ws_plugin__s2member_force_non_ssl_scheme($url = FALSE, $path = FALSE, $scheme = FALSE)
122
  {
123
+ if(!in_array /* If NOT explicitly passed through. */($scheme, array("http", "https"), true))
124
  {
125
+ if(($scheme === "login_post" || $scheme === "rpc") && (force_ssl_login() || force_ssl_admin()))
126
  $scheme = "https";
127
  /**/
128
+ else if(($scheme === "login" || $scheme === "admin") && force_ssl_admin())
129
  $scheme = "https";
130
  /**/
131
  else /* Default to non-SSL: `http`. */
132
  $scheme = "http";
133
  }
134
+ return preg_replace("/^(?:https?\:)?\/\//i", $scheme."://", $url);
135
  }
136
  }
137
  /**/
138
+ if(!function_exists("_ws_plugin__s2member_force_ssl_buffer"))
139
  {
140
+ function _ws_plugin__s2member_force_ssl_buffer($buffer = FALSE)
141
  {
142
+ $o_pcre = /* Record existing PCRE backtrack limit. */ @ini_get("pcre.backtrack_limit");
143
+ @ini_set /* Increase PCRE backtrack limit for this routine. */("pcre.backtrack_limit", 10000000);
144
  /**/
145
+ $ssl_entire_tags = array_unique(array_map("strtolower", apply_filters("_ws_plugin__s2member_force_ssl_buffer_entire_tags", array("script", "style", "iframe", "object", "embed", "video"), get_defined_vars())));
146
+ $non_ssl_entire_tags = array_unique(array_map("strtolower", apply_filters("_ws_plugin__s2member_force_non_ssl_buffer_entire_tags", array(), get_defined_vars())));
147
  /**/
148
+ $ssl_attr_only_tags = array_unique( /* Diff here. No need to re-run entire tags. */array_diff(array_map("strtolower", apply_filters("_ws_plugin__s2member_force_ssl_buffer_attr_only_tags", array("link", "img", "input"), get_defined_vars())), $ssl_entire_tags));
149
+ $non_ssl_attr_only_tags = array_unique( /* No need to re-run entire tags. */array_diff(array_map("strtolower", apply_filters("_ws_plugin__s2member_force_non_ssl_buffer_attr_only_tags", array("a"), get_defined_vars())), $non_ssl_entire_tags));
150
  /**/
151
+ $buffer = ($ssl_entire_tags) ? preg_replace_callback("/\<(".implode("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep($ssl_entire_tags, "/")).")(?![a-z_0-9\-])[^\>]*?\>.*?\<\/\\1\>/is", "_ws_plugin__s2member_force_ssl_buffer_callback", $buffer) : $buffer;
152
+ $buffer = ($ssl_attr_only_tags) ? preg_replace_callback("/\<(".implode("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep($ssl_attr_only_tags, "/")).")(?![a-z_0-9\-])[^\>]+?\>/i", "_ws_plugin__s2member_force_ssl_buffer_callback", $buffer) : $buffer;
153
  /**/
154
+ $buffer = ($non_ssl_entire_tags) ? preg_replace_callback("/\<(".implode("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep($non_ssl_entire_tags, "/")).")(?![a-z_0-9\-])[^\>]*?\>.*?\<\/\\1\>/is", "_ws_plugin__s2member_force_non_ssl_buffer_callback", $buffer) : $buffer;
155
+ $buffer = ($non_ssl_attr_only_tags) ? preg_replace_callback("/\<(".implode("|", c_ws_plugin__s2member_utils_strings::preg_quote_deep($non_ssl_attr_only_tags, "/")).")(?![a-z_0-9\-])[^\>]+?\>/i", "_ws_plugin__s2member_force_non_ssl_buffer_callback", $buffer) : $buffer;
156
  /**/
157
+ @ini_set /* Restore original PCRE backtrack limit. This just keeps things tidy; probably NOT necessary. */("pcre.backtrack_limit", $o_pcre);
158
  /**/
159
+ return apply_filters("_ws_plugin__s2member_force_ssl_buffer", $buffer, get_defined_vars());
160
  }
161
  }
162
  /**/
includes/classes/utils-conds.inc.php CHANGED
@@ -99,9 +99,11 @@ if (!class_exists ("c_ws_plugin__s2member_utils_conds"))
99
  foreach ((array)$cats as $cat)
100
  {
101
  $descendants = get_term_children ((int)$cat, "category");
 
102
  if ($descendants && in_category ($descendants, $post_id))
103
  return true;
104
  }
 
105
  return false; /* Default return false. */
106
  }
107
  /**
@@ -123,6 +125,7 @@ if (!class_exists ("c_ws_plugin__s2member_utils_conds"))
123
  if ($parse["path"] === "/" || rtrim ($parse["path"], "/") === rtrim (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_PATH), "/"))
124
  return true;
125
  }
 
126
  return false; /* Default return false. */
127
  }
128
  /**
@@ -133,7 +136,7 @@ if (!class_exists ("c_ws_plugin__s2member_utils_conds"))
133
  *
134
  * @return bool True if we're in a localhost environment, else false.
135
  */
136
- public static function /* Checks to see if we're in a localhost environment. */ is_localhost ()
137
  {
138
  if ((defined ("LOCALHOST") && LOCALHOST) || stripos ($_SERVER["HTTP_HOST"], "localhost") !== false || strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") !== false)
139
  return true;
99
  foreach ((array)$cats as $cat)
100
  {
101
  $descendants = get_term_children ((int)$cat, "category");
102
+
103
  if ($descendants && in_category ($descendants, $post_id))
104
  return true;
105
  }
106
+
107
  return false; /* Default return false. */
108
  }
109
  /**
125
  if ($parse["path"] === "/" || rtrim ($parse["path"], "/") === rtrim (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_PATH), "/"))
126
  return true;
127
  }
128
+
129
  return false; /* Default return false. */
130
  }
131
  /**
136
  *
137
  * @return bool True if we're in a localhost environment, else false.
138
  */
139
+ public static function is_localhost ()
140
  {
141
  if ((defined ("LOCALHOST") && LOCALHOST) || stripos ($_SERVER["HTTP_HOST"], "localhost") !== false || strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") !== false)
142
  return true;
includes/classes/utils-strings.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Utilities
15
  * @since 3.5
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
21
  {
22
  /**
23
  * String utilities.
@@ -37,7 +37,7 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
37
  *
38
  * @var array
39
  */
40
- public static /* Array keys are actually regex patterns. */ $ampersand_entities = array ("&amp;" => "&amp;", "&#0*38;" => "&#38;", "&#[xX]0*26;" => "&#x26;");
41
  /**
42
  * Array of all quote entities *( and entities for quote variations )*.
43
  *
@@ -48,7 +48,7 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
48
  *
49
  * @var array
50
  */
51
- public static $quote_entities_w_variations = array ("&apos;" => "&apos;", "&#0*39;" => "&#39;", "&#[xX]0*27;" => "&#x27;", "&lsquo;" => "&lsquo;", "&#0*8216;" => "&#8216;", "&#[xX]0*2018;" => "&#x2018;", "&rsquo;" => "&rsquo;", "&#0*8217;" => "&#8217;", "&#[xX]0*2019;" => "&#x2019;", "&quot;" => "&quot;", "&#0*34;" => "&#34;", "&#[xX]0*22;" => "&#x22;", "&ldquo;" => "&ldquo;", "&#0*8220;" => "&#8220;", "&#[xX]0*201[cC];" => "&#x201C;", "&rdquo;" => "&rdquo;", "&#0*8221;" => "&#8221;", "&#[xX]0*201[dD];" => "&#x201D;");
52
  /**
53
  * Escapes double quotes.
54
  *
@@ -56,14 +56,14 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
56
  * @since 3.5
57
  *
58
  * @param str $string Input string.
59
- * @param int $times Mumber of escapes. Defaults to 1.
60
  * @return str Output string after double quotes are escaped.
61
  */
62
- public static function esc_dq ($string = FALSE, $times = FALSE)
63
  {
64
- $times = (is_numeric ($times) && $times >= 0) ? (int)$times : 1;
65
  /**/
66
- return str_replace ('"', str_repeat ("\\", $times) . '"', (string)$string);
67
  }
68
  /**
69
  * Escapes single quotes.
@@ -72,14 +72,14 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
72
  * @since 3.5
73
  *
74
  * @param str $string Input string.
75
- * @param int $times Mumber of escapes. Defaults to 1.
76
  * @return str Output string after single quotes are escaped.
77
  */
78
- public static function esc_sq ($string = FALSE, $times = FALSE)
79
  {
80
- $times = (is_numeric ($times) && $times >= 0) ? (int)$times : 1;
81
  /**/
82
- return str_replace ("'", str_repeat ("\\", $times) . "'", (string)$string);
83
  }
84
  /**
85
  * Escapes JavaScript and single quotes.
@@ -88,30 +88,49 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
88
  * @since 110901
89
  *
90
  * @param str $string Input string.
91
- * @param int $times Mumber of escapes. Defaults to 1.
92
  * @return str Output string after JavaScript and single quotes are escaped.
93
  */
94
- public static function esc_js_sq ($string = FALSE, $times = FALSE)
95
  {
96
- $times = (is_numeric ($times) && $times >= 0) ? (int)$times : 1;
97
  /**/
98
- return str_replace ("'", str_repeat ("\\", $times) . "'", str_replace (array ("\r", "\n"), array ("", '\\n'), str_replace ("\'", "'", (string)$string)));
99
  }
100
  /**
101
- * Escapes dollars signs ( for regex patterns ).
102
  *
103
  * @package s2Member\Utilities
104
  * @since 3.5
105
  *
106
  * @param str $string Input string.
107
- * @param int $times Mumber of escapes. Defaults to 1.
108
  * @return str Output string after dollar signs are escaped.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  */
110
- public static function esc_ds ($string = FALSE, $times = FALSE)
111
  {
112
- $times = (is_numeric ($times) && $times >= 0) ? (int)$times : 1;
113
  /**/
114
- return str_replace ('$', str_repeat ("\\", $times) . '$', (string)$string);
115
  }
116
  /**
117
  * Sanitizes a string; by stripping characters NOT on a standard U.S. keyboard.
@@ -122,9 +141,9 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
122
  * @param str $string Input string.
123
  * @return str Output string, after characters NOT on a standard U.S. keyboard have been stripped.
124
  */
125
- public static function strip_2_kb_chars ($string = FALSE)
126
  {
127
- return preg_replace ("/[^0-9A-Z\r\n\t\s`\=\[\]\\\;',\.\/~\!@#\$%\^&\*\(\)_\+\|\}\{\:\"\?\>\<\-]/i", "", remove_accents ((string)$string));
128
  }
129
  /**
130
  * Trims deeply; alias of ``trim_deep``.
@@ -140,9 +159,9 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
140
  * @param str|bool $extra_chars Optional. This is NOT possible with PHP alone, but here you can specify extra chars; in addition to ``$chars``.
141
  * @return str|array Either the input string, or the input array; after all data is trimmed up according to arguments passed in.
142
  */
143
- public static function trim ($value = FALSE, $chars = FALSE, $extra_chars = FALSE)
144
  {
145
- return c_ws_plugin__s2member_utils_strings::trim_deep ($value, $chars, $extra_chars);
146
  }
147
  /**
148
  * Trims deeply; or use {@link s2Member\Utilities\c_ws_plugin__s2member_utils_strings::trim()}.
@@ -158,20 +177,20 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
158
  * @param str|bool $extra_chars Optional. This is NOT possible with PHP alone, but here you can specify extra chars; in addition to ``$chars``.
159
  * @return str|array Either the input string, or the input array; after all data is trimmed up according to arguments passed in.
160
  */
161
- public static function trim_deep ($value = FALSE, $chars = FALSE, $extra_chars = FALSE)
162
  {
163
- $chars = /* List of chars to be trimmed by this routine. */ (is_string ($chars)) ? $chars : " \t\n\r\0\x0B";
164
- $chars = (is_string ($extra_chars) /* Adding additional chars? */) ? $chars . $extra_chars : $chars;
165
  /**/
166
- if (is_array ($value)) /* Handles all types of arrays.
167
- Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
168
- For further details, see: <http://php.net/manual/en/function.array-map.php>. */
169
  {
170
- foreach ($value as &$r) /* Reference. */
171
- $r = c_ws_plugin__s2member_utils_strings::trim_deep ($r, $chars);
172
  return $value; /* Return modified array. */
173
  }
174
- return trim ((string)$value, $chars);
175
  }
176
  /**
177
  * Trims double quotes deeply.
@@ -182,9 +201,9 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
182
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
183
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
184
  */
185
- public static function trim_dq_deep ($value = FALSE)
186
  {
187
- return c_ws_plugin__s2member_utils_strings::trim_deep ($value, false, '"');
188
  }
189
  /**
190
  * Trims single quotes deeply.
@@ -195,9 +214,9 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
195
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
196
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
197
  */
198
- public static function trim_sq_deep ($value = FALSE)
199
  {
200
- return c_ws_plugin__s2member_utils_strings::trim_deep ($value, false, "'");
201
  }
202
  /**
203
  * Trims double and single quotes deeply.
@@ -208,9 +227,9 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
208
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
209
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
210
  */
211
- public static function trim_dsq_deep ($value = FALSE)
212
  {
213
- return c_ws_plugin__s2member_utils_strings::trim_deep ($value, false, "'" . '"');
214
  }
215
  /**
216
  * Trims all single/double quote entity variations deeply.
@@ -223,11 +242,11 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
223
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
224
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
225
  */
226
- public static function trim_qts_deep ($value = FALSE)
227
  {
228
- $qts = implode ("|", array_keys /* Keys are regex patterns. */ (c_ws_plugin__s2member_utils_strings::$quote_entities_w_variations));
229
  /**/
230
- return is_array ($value) ? array_map ("c_ws_plugin__s2member_utils_strings::trim_qts_deep", $value) : preg_replace ("/^(?:" . $qts . ")+|(?:" . $qts . ")+$/", "", (string)$value);
231
  }
232
  /**
233
  * Wraps a string with the characters provided.
@@ -243,17 +262,17 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
243
  * @param bool $wrap_e Optional. Defaults to false. Should empty strings be wrapped too?
244
  * @return str|array Either the input string, or the input array; after all data is wrapped up.
245
  */
246
- public static function wrap_deep ($value = FALSE, $beg = FALSE, $end = FALSE, $wrap_e = FALSE)
247
  {
248
- if (is_array ($value)) /* Handles all types of arrays.
249
- Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
250
- For further details, see: <http://php.net/manual/en/function.array-map.php>. */
251
  {
252
- foreach ($value as &$r) /* Reference. */
253
- $r = c_ws_plugin__s2member_utils_strings::wrap_deep ($r, $beg, $end, $wrap_e);
254
  return $value; /* Return modified array. */
255
  }
256
- return (strlen ((string)$value) || $wrap_e) ? (string)$beg . (string)$value . (string)$end : (string)$value;
257
  }
258
  /**
259
  * Escapes meta characters with ``preg_quote()`` deeply.
@@ -265,17 +284,17 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
265
  * @param str $delimiter Optional. If a delimiting character is specified, it will also be escaped via ``preg_quote()``.
266
  * @return str|array Either the input string, or the input array; after all data is escaped with ``preg_quote()``.
267
  */
268
- public static function preg_quote_deep ($value = FALSE, $delimiter = FALSE)
269
  {
270
- if (is_array ($value)) /* Handles all types of arrays.
271
- Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
272
- For further details, see: <http://php.net/manual/en/function.array-map.php>. */
273
  {
274
- foreach ($value as &$r) /* Reference. */
275
- $r = c_ws_plugin__s2member_utils_strings::preg_quote_deep ($r, $delimiter);
276
  return $value; /* Return modified array. */
277
  }
278
- return preg_quote ((string)$value, (string)$delimiter);
279
  }
280
  /**
281
  * Generates a random string with letters/numbers/symbols.
@@ -288,16 +307,16 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
288
  * @param bool $extra_special_chars Defaults to false. If true, extra special chars are included.
289
  * @return str A randomly generated string, based on parameter configuration.
290
  */
291
- public static function random_str_gen ($length = FALSE, $special_chars = TRUE, $extra_special_chars = FALSE)
292
  {
293
- $length = (is_numeric ($length) && $length >= 0) ? (int)$length : 12;
294
  /**/
295
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
296
  $chars .= ($extra_special_chars) ? "-_ []{}<>~`+=,.;:/?|" : "";
297
  $chars .= ($special_chars) ? "!@#$%^&*()" : "";
298
  /**/
299
- for ($i = 0, $random_str = ""; $i < $length; $i++)
300
- $random_str .= substr ($chars, mt_rand (0, strlen ($chars) - 1), 1);
301
  /**/
302
  return /* Randomly generated string of chars. */ $random_str;
303
  }
@@ -310,11 +329,11 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
310
  * @param str $str Input string to be highlighted.
311
  * @return str The highlighted string.
312
  */
313
- public static function highlight_php ($string = FALSE)
314
  {
315
- $string = highlight_string ((string)$string, true); /* Start with PHP syntax, then Shortcodes. */
316
  /**/
317
- return preg_replace ("/\[\/?_*s2[a-z0-9_\-]+.*?\]/i", '<span style="color:#164A61;">$0</span>', $string);
318
  }
319
  /**
320
  * Parses email addresses from a string or array.
@@ -325,27 +344,27 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
325
  * @param str|array $value Input string or an array is also fine.
326
  * @return array Array of parsed email addresses.
327
  */
328
- public static function parse_emails ($value = FALSE)
329
  {
330
- if (is_array ($value)) /* Handles all types of arrays.
331
- Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
332
- For further details, see: <http://php.net/manual/en/function.array-map.php>. */
333
  {
334
- $emails = array (); /* Initialize array. */
335
- foreach /* Loop through array. */ ($value as $v)
336
- $emails = array_merge ($emails, c_ws_plugin__s2member_utils_strings::parse_emails ($v));
337
  return $emails; /* Return array. */
338
  }
339
- $delimiter = /* Supports semicolons or commas. */ (strpos ((string)$value, ";") !== false) ? ";" : ",";
340
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/" . preg_quote ($delimiter, "/") . "+/", (string)$value)) as $section)
341
  {
342
- if (preg_match ("/\<(.+?)\>/", $section, $m) && strpos ($m[1], "@") !== false)
343
  $emails[] = $m[1]; /* Email inside <brackets>. */
344
  /**/
345
- else if (strpos ($section, "@") !== false)
346
  $emails[] = $section;
347
  }
348
- return /* Array. */ (!empty ($emails)) ? $emails : array ();
349
  }
350
  /**
351
  * Base64 URL-safe encoding.
@@ -359,13 +378,13 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
359
  * @param str $trim_padding_chars Optional. A string of padding chars to rtrim. Defaults to: `=~.`.
360
  * @return str The base64 URL-safe encoded string.
361
  */
362
- public static function base64_url_safe_encode ($string = FALSE, $url_unsafe_chars = array ("+", "/"), $url_safe_chars = array ("-", "_"), $trim_padding_chars = "=~.")
363
  {
364
  $string = (string)$string; /* Force string values here. String MUST be a string. */
365
  $trim_padding_chars = (string)$trim_padding_chars; /* And force this one too. */
366
  /**/
367
- $base64_url_safe = str_replace ((array)$url_unsafe_chars, (array)$url_safe_chars, (string)base64_encode ($string));
368
- $base64_url_safe = (strlen ($trim_padding_chars)) ? rtrim ($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
369
  /**/
370
  return $base64_url_safe; /* Base64 encoded, with URL-safe replacements. */
371
  }
@@ -384,14 +403,14 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
384
  * @param str $trim_padding_chars Optional. A string of padding chars to rtrim. Defaults to: `=~.`.
385
  * @return str The decoded string.
386
  */
387
- public static function base64_url_safe_decode ($base64_url_safe = FALSE, $url_unsafe_chars = array ("+", "/"), $url_safe_chars = array ("-", "_"), $trim_padding_chars = "=~.")
388
  {
389
  $base64_url_safe = (string)$base64_url_safe; /* Force string values here. This MUST be a string. */
390
  $trim_padding_chars = (string)$trim_padding_chars; /* And force this one too. */
391
  /**/
392
- $string = (strlen ($trim_padding_chars)) ? rtrim ($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
393
- $string = (strlen ($trim_padding_chars)) ? str_pad ($string, strlen ($string) % 4, "=", STR_PAD_RIGHT) : $string;
394
- $string = (string)base64_decode (str_replace ((array)$url_safe_chars, (array)$url_unsafe_chars, $string));
395
  /**/
396
  return $string; /* Base64 decoded, with URL-safe replacements. */
397
  }
@@ -405,27 +424,27 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
405
  * @param str $key The secret key that will be used in this signature.
406
  * @return str|bool An RSA-SHA1 signature string, or false on failure.
407
  */
408
- public static function rsa_sha1_sign ($string = FALSE, $key = FALSE)
409
  {
410
- $key = /* Fixes key wrappers. */ c_ws_plugin__s2member_utils_strings::_rsa_sha1_key_fix_wrappers ((string)$key);
411
  /**/
412
- $signature = /* Command line. */ c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign ((string)$string, (string)$key);
413
  /**/
414
- if (empty ($signature) && stripos (PHP_OS, "win") === 0 && file_exists (($openssl = "c:\openssl-win32\bin\openssl.exe")))
415
- $signature = c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign ((string)$string, (string)$key, /* Specific location. */ $openssl);
416
  /**/
417
- if (empty ($signature) && stripos (PHP_OS, "win") === 0 && file_exists (($openssl = "c:\openssl-win64\bin\openssl.exe")))
418
- $signature = c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign ((string)$string, (string)$key, /* Specific location. */ $openssl);
419
  /**/
420
- if (empty ($signature) && function_exists ("openssl_get_privatekey") && function_exists ("openssl_sign") && is_resource ($private_key = openssl_get_privatekey ((string)$key)))
421
- openssl_sign ((string)$string, $signature, $private_key, OPENSSL_ALGO_SHA1) . openssl_free_key ($private_key);
422
  /**/
423
- if (empty ($signature)) /* Now, if we're still empty, trigger an error here. */
424
- trigger_error ("s2Member was unable to generate an RSA-SHA1 signature." .
425
- " Please make sure your installation of PHP is compiled with OpenSSL: `openssl_sign()`." .
426
  " See: http://php.net/manual/en/function.openssl-sign.php", E_USER_ERROR);
427
  /**/
428
- return (!empty ($signature)) ? $signature : false;
429
  }
430
  /**
431
  * Generates an RSA-SHA1 signature from the command line.
@@ -440,19 +459,19 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
440
  * @param str $openssl Optional. Defaults to `openssl`. Path to OpenSSL executable.
441
  * @return str|bool An RSA-SHA1 signature string, or false on failure.
442
  */
443
- public static function _rsa_sha1_shell_sign ($string = FALSE, $key = FALSE, $openssl = FALSE)
444
  {
445
- if (function_exists ("shell_exec") && ($esa = "escapeshellarg") && ($openssl = (($openssl && is_string ($openssl)) ? $openssl : "openssl")) && ($temp_dir = c_ws_plugin__s2member_utils_dirs::get_temp_dir ()))
446
  {
447
- file_put_contents (($string_file = $temp_dir . "/" . md5 (uniqid ("", true) . "rsa-sha1-string") . ".tmp"), (string)$string);
448
- file_put_contents (($private_key_file = $temp_dir . "/" . md5 (uniqid ("", true) . "rsa-sha1-private-key") . ".tmp"), (string)$key);
449
- file_put_contents (($rsa_sha1_sig_file = $temp_dir . "/" . md5 (uniqid ("", true) . "rsa-sha1-sig") . ".tmp"), "");
450
  /**/
451
- @shell_exec($esa ($openssl) . " sha1 -sign " . $esa ($private_key_file) . " -out " . $esa ($rsa_sha1_sig_file) . " " . $esa ($string_file));
452
- $signature = /* Do NOT trim here. */ file_get_contents ($rsa_sha1_sig_file); /* Was the signature was written? */
453
- unlink($rsa_sha1_sig_file) . unlink ($private_key_file) . unlink ($string_file); /* Cleanup. */
454
  }
455
- return (!empty ($signature)) ? $signature : false;
456
  }
457
  /**
458
  * Fixes incomplete private key wrappers for RSA-SHA1 signing.
@@ -467,18 +486,18 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
467
  *
468
  * @see http://www.faqs.org/qa/qa-14736.html
469
  */
470
- public static function _rsa_sha1_key_fix_wrappers ($key = FALSE)
471
  {
472
- if (($key = trim ((string)$key)) && (strpos ($key, "-----BEGIN RSA PRIVATE KEY-----") === false || strpos ($key, "-----END RSA PRIVATE KEY-----") === false))
473
  {
474
- foreach (($lines = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/[\r\n]+/", $key))) as $line => $value)
475
- if (strpos ($value, "-") === 0) /* Begins with a boundary identifying character ( a hyphen `-` )? */
476
  {
477
- $boundaries = (empty ($boundaries)) ? 1 : $boundaries + 1; /* Counter. */
478
  unset($lines[$line]); /* Remove this boundary line. We'll fix these below. */
479
  }
480
- if (empty ($boundaries) || $boundaries <= 2) /* Do NOT modify keys with more than 2 boundaries. */
481
- $key = "-----BEGIN RSA PRIVATE KEY-----\n" . implode ("\n", $lines) . "\n-----END RSA PRIVATE KEY-----";
482
  }
483
  return $key; /* Always a trimmed string here. */
484
  }
@@ -492,11 +511,11 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
492
  * @param str $key The secret key that will be used in this signature.
493
  * @return str An HMAC-SHA1 signature string.
494
  */
495
- public static function hmac_sha1_sign ($string = FALSE, $key = FALSE)
496
  {
497
- $key_64 = str_pad (((strlen ((string)$key) > 64) ? pack ('H*', sha1 ((string)$key)) : (string)$key), 64, chr (0x00));
498
  /**/
499
- return pack ('H*', sha1 (($key_64 ^ str_repeat (chr (0x5c), 64)) . pack ('H*', sha1 (($key_64 ^ str_repeat (chr (0x36), 64)) . (string)$string))));
500
  }
501
  /**
502
  * Decodes unreserved chars encoded by PHP's ``urlencode()``, deeply.
@@ -511,17 +530,17 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
511
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
512
  * @return str|array Either the input string, or the input array; after all unreserved chars are decoded properly.
513
  */
514
- public static function urldecode_ur_chars_deep ($value = array ())
515
  {
516
- if (is_array ($value)) /* Handles all types of arrays.
517
- Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
518
- For further details, see: <http://php.net/manual/en/function.array-map.php>. */
519
  {
520
- foreach ($value as &$r) /* Reference. */
521
- $r = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep ($r);
522
  return $value; /* Return modified array. */
523
  }
524
- return str_replace (array ("%2D", "%2E", "%5F", "%7E"), array ("-", ".", "_", "~"), (string)$value);
525
  }
526
  }
527
  }
14
  * @package s2Member\Utilities
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_utils_strings"))
21
  {
22
  /**
23
  * String utilities.
37
  *
38
  * @var array
39
  */
40
+ public static /* Array keys are actually regex patterns. */ $ampersand_entities = array("&amp;" => "&amp;", "&#0*38;" => "&#38;", "&#[xX]0*26;" => "&#x26;");
41
  /**
42
  * Array of all quote entities *( and entities for quote variations )*.
43
  *
48
  *
49
  * @var array
50
  */
51
+ public static $quote_entities_w_variations = array("&apos;" => "&apos;", "&#0*39;" => "&#39;", "&#[xX]0*27;" => "&#x27;", "&lsquo;" => "&lsquo;", "&#0*8216;" => "&#8216;", "&#[xX]0*2018;" => "&#x2018;", "&rsquo;" => "&rsquo;", "&#0*8217;" => "&#8217;", "&#[xX]0*2019;" => "&#x2019;", "&quot;" => "&quot;", "&#0*34;" => "&#34;", "&#[xX]0*22;" => "&#x22;", "&ldquo;" => "&ldquo;", "&#0*8220;" => "&#8220;", "&#[xX]0*201[cC];" => "&#x201C;", "&rdquo;" => "&rdquo;", "&#0*8221;" => "&#8221;", "&#[xX]0*201[dD];" => "&#x201D;");
52
  /**
53
  * Escapes double quotes.
54
  *
56
  * @since 3.5
57
  *
58
  * @param str $string Input string.
59
+ * @param int $times Number of escapes. Defaults to 1.
60
  * @return str Output string after double quotes are escaped.
61
  */
62
+ public static function esc_dq($string = FALSE, $times = FALSE)
63
  {
64
+ $times = (is_numeric($times) && $times >= 0) ? (int)$times : 1;
65
  /**/
66
+ return str_replace('"', str_repeat("\\", $times).'"', (string)$string);
67
  }
68
  /**
69
  * Escapes single quotes.
72
  * @since 3.5
73
  *
74
  * @param str $string Input string.
75
+ * @param int $times Number of escapes. Defaults to 1.
76
  * @return str Output string after single quotes are escaped.
77
  */
78
+ public static function esc_sq($string = FALSE, $times = FALSE)
79
  {
80
+ $times = (is_numeric($times) && $times >= 0) ? (int)$times : 1;
81
  /**/
82
+ return str_replace("'", str_repeat("\\", $times)."'", (string)$string);
83
  }
84
  /**
85
  * Escapes JavaScript and single quotes.
88
  * @since 110901
89
  *
90
  * @param str $string Input string.
91
+ * @param int $times Number of escapes. Defaults to 1.
92
  * @return str Output string after JavaScript and single quotes are escaped.
93
  */
94
+ public static function esc_js_sq($string = FALSE, $times = FALSE)
95
  {
96
+ $times = (is_numeric($times) && $times >= 0) ? (int)$times : 1;
97
  /**/
98
+ return str_replace("'", str_repeat("\\", $times)."'", str_replace(array("\r", "\n"), array("", '\\n'), str_replace("\'", "'", (string)$string)));
99
  }
100
  /**
101
+ * Escapes dollars signs (for regex patterns).
102
  *
103
  * @package s2Member\Utilities
104
  * @since 3.5
105
  *
106
  * @param str $string Input string.
107
+ * @param int $times Number of escapes. Defaults to 1.
108
  * @return str Output string after dollar signs are escaped.
109
+ *
110
+ * @deprecated Starting with s2Member v120103, please use:
111
+ * ``c_ws_plugin__s2member_utils_strings::esc_refs()``.
112
+ */
113
+ public static function esc_ds($string = FALSE, $times = FALSE)
114
+ {
115
+ $times = (is_numeric($times) && $times >= 0) ? (int)$times : 1;
116
+ /**/
117
+ return str_replace('$', str_repeat("\\", $times).'$', (string)$string);
118
+ }
119
+ /**
120
+ * Escapes backreferences (for regex patterns).
121
+ *
122
+ * @package s2Member\Utilities
123
+ * @since 120103
124
+ *
125
+ * @param str $string Input string.
126
+ * @param int $times Number of escapes. Defaults to 1.
127
+ * @return str Output string after backreferences are escaped.
128
  */
129
+ public static function esc_refs($string = NULL, $times = NULL)
130
  {
131
+ $times = (is_numeric($times) && $times >= 0) ? (int)$times : 1;
132
  /**/
133
+ return str_replace(array("\\", '$'), array(str_repeat("\\", $times)."\\", str_repeat("\\", $times).'$'), (string)$string);
134
  }
135
  /**
136
  * Sanitizes a string; by stripping characters NOT on a standard U.S. keyboard.
141
  * @param str $string Input string.
142
  * @return str Output string, after characters NOT on a standard U.S. keyboard have been stripped.
143
  */
144
+ public static function strip_2_kb_chars($string = FALSE)
145
  {
146
+ return preg_replace("/[^0-9A-Z\r\n\t\s`\=\[\]\\\;',\.\/~\!@#\$%\^&\*\(\)_\+\|\}\{\:\"\?\>\<\-]/i", "", remove_accents((string)$string));
147
  }
148
  /**
149
  * Trims deeply; alias of ``trim_deep``.
159
  * @param str|bool $extra_chars Optional. This is NOT possible with PHP alone, but here you can specify extra chars; in addition to ``$chars``.
160
  * @return str|array Either the input string, or the input array; after all data is trimmed up according to arguments passed in.
161
  */
162
+ public static function trim($value = FALSE, $chars = FALSE, $extra_chars = FALSE)
163
  {
164
+ return c_ws_plugin__s2member_utils_strings::trim_deep($value, $chars, $extra_chars);
165
  }
166
  /**
167
  * Trims deeply; or use {@link s2Member\Utilities\c_ws_plugin__s2member_utils_strings::trim()}.
177
  * @param str|bool $extra_chars Optional. This is NOT possible with PHP alone, but here you can specify extra chars; in addition to ``$chars``.
178
  * @return str|array Either the input string, or the input array; after all data is trimmed up according to arguments passed in.
179
  */
180
+ public static function trim_deep($value = FALSE, $chars = FALSE, $extra_chars = FALSE)
181
  {
182
+ $chars = /* List of chars to be trimmed by this routine. */ (is_string($chars)) ? $chars : " \t\n\r\0\x0B";
183
+ $chars = (is_string($extra_chars) /* Adding additional chars? */) ? $chars.$extra_chars : $chars;
184
  /**/
185
+ if(is_array($value)) /* Handles all types of arrays.
186
+ Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
187
+ For further details, see: <http://php.net/manual/en/function.array-map.php>. */
188
  {
189
+ foreach($value as &$r) /* Reference. */
190
+ $r = c_ws_plugin__s2member_utils_strings::trim_deep($r, $chars);
191
  return $value; /* Return modified array. */
192
  }
193
+ return trim((string)$value, $chars);
194
  }
195
  /**
196
  * Trims double quotes deeply.
201
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
202
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
203
  */
204
+ public static function trim_dq_deep($value = FALSE)
205
  {
206
+ return c_ws_plugin__s2member_utils_strings::trim_deep($value, false, '"');
207
  }
208
  /**
209
  * Trims single quotes deeply.
214
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
215
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
216
  */
217
+ public static function trim_sq_deep($value = FALSE)
218
  {
219
+ return c_ws_plugin__s2member_utils_strings::trim_deep($value, false, "'");
220
  }
221
  /**
222
  * Trims double and single quotes deeply.
227
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
228
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
229
  */
230
+ public static function trim_dsq_deep($value = FALSE)
231
  {
232
+ return c_ws_plugin__s2member_utils_strings::trim_deep($value, false, "'".'"');
233
  }
234
  /**
235
  * Trims all single/double quote entity variations deeply.
242
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
243
  * @return str|array Either the input string, or the input array; after all data is trimmed up.
244
  */
245
+ public static function trim_qts_deep($value = FALSE)
246
  {
247
+ $qts = implode("|", array_keys /* Keys are regex patterns. */(c_ws_plugin__s2member_utils_strings::$quote_entities_w_variations));
248
  /**/
249
+ return is_array($value) ? array_map("c_ws_plugin__s2member_utils_strings::trim_qts_deep", $value) : preg_replace("/^(?:".$qts.")+|(?:".$qts.")+$/", "", (string)$value);
250
  }
251
  /**
252
  * Wraps a string with the characters provided.
262
  * @param bool $wrap_e Optional. Defaults to false. Should empty strings be wrapped too?
263
  * @return str|array Either the input string, or the input array; after all data is wrapped up.
264
  */
265
+ public static function wrap_deep($value = FALSE, $beg = FALSE, $end = FALSE, $wrap_e = FALSE)
266
  {
267
+ if(is_array($value)) /* Handles all types of arrays.
268
+ Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
269
+ For further details, see: <http://php.net/manual/en/function.array-map.php>. */
270
  {
271
+ foreach($value as &$r) /* Reference. */
272
+ $r = c_ws_plugin__s2member_utils_strings::wrap_deep($r, $beg, $end, $wrap_e);
273
  return $value; /* Return modified array. */
274
  }
275
+ return (strlen((string)$value) || $wrap_e) ? (string)$beg.(string)$value.(string)$end : (string)$value;
276
  }
277
  /**
278
  * Escapes meta characters with ``preg_quote()`` deeply.
284
  * @param str $delimiter Optional. If a delimiting character is specified, it will also be escaped via ``preg_quote()``.
285
  * @return str|array Either the input string, or the input array; after all data is escaped with ``preg_quote()``.
286
  */
287
+ public static function preg_quote_deep($value = FALSE, $delimiter = FALSE)
288
  {
289
+ if(is_array($value)) /* Handles all types of arrays.
290
+ Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
291
+ For further details, see: <http://php.net/manual/en/function.array-map.php>. */
292
  {
293
+ foreach($value as &$r) /* Reference. */
294
+ $r = c_ws_plugin__s2member_utils_strings::preg_quote_deep($r, $delimiter);
295
  return $value; /* Return modified array. */
296
  }
297
+ return preg_quote((string)$value, (string)$delimiter);
298
  }
299
  /**
300
  * Generates a random string with letters/numbers/symbols.
307
  * @param bool $extra_special_chars Defaults to false. If true, extra special chars are included.
308
  * @return str A randomly generated string, based on parameter configuration.
309
  */
310
+ public static function random_str_gen($length = FALSE, $special_chars = TRUE, $extra_special_chars = FALSE)
311
  {
312
+ $length = (is_numeric($length) && $length >= 0) ? (int)$length : 12;
313
  /**/
314
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
315
  $chars .= ($extra_special_chars) ? "-_ []{}<>~`+=,.;:/?|" : "";
316
  $chars .= ($special_chars) ? "!@#$%^&*()" : "";
317
  /**/
318
+ for($i = 0, $random_str = ""; $i < $length; $i++)
319
+ $random_str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
320
  /**/
321
  return /* Randomly generated string of chars. */ $random_str;
322
  }
329
  * @param str $str Input string to be highlighted.
330
  * @return str The highlighted string.
331
  */
332
+ public static function highlight_php($string = FALSE)
333
  {
334
+ $string = highlight_string((string)$string, true); /* Start with PHP syntax, then Shortcodes. */
335
  /**/
336
+ return preg_replace("/\[\/?_*s2[a-z0-9_\-]+.*?\]/i", '<span style="color:#164A61;">$0</span>', $string);
337
  }
338
  /**
339
  * Parses email addresses from a string or array.
344
  * @param str|array $value Input string or an array is also fine.
345
  * @return array Array of parsed email addresses.
346
  */
347
+ public static function parse_emails($value = FALSE)
348
  {
349
+ if(is_array($value)) /* Handles all types of arrays.
350
+ Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
351
+ For further details, see: <http://php.net/manual/en/function.array-map.php>. */
352
  {
353
+ $emails = array(); /* Initialize array. */
354
+ foreach /* Loop through array. */($value as $v)
355
+ $emails = array_merge($emails, c_ws_plugin__s2member_utils_strings::parse_emails($v));
356
  return $emails; /* Return array. */
357
  }
358
+ $delimiter = /* Supports semicolons or commas. */ (strpos((string)$value, ";") !== false) ? ";" : ",";
359
+ foreach(c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/".preg_quote($delimiter, "/")."+/", (string)$value)) as $section)
360
  {
361
+ if(preg_match("/\<(.+?)\>/", $section, $m) && strpos($m[1], "@") !== false)
362
  $emails[] = $m[1]; /* Email inside <brackets>. */
363
  /**/
364
+ else if(strpos($section, "@") !== false)
365
  $emails[] = $section;
366
  }
367
+ return /* Array. */ (!empty($emails)) ? $emails : array();
368
  }
369
  /**
370
  * Base64 URL-safe encoding.
378
  * @param str $trim_padding_chars Optional. A string of padding chars to rtrim. Defaults to: `=~.`.
379
  * @return str The base64 URL-safe encoded string.
380
  */
381
+ public static function base64_url_safe_encode($string = FALSE, $url_unsafe_chars = array("+", "/"), $url_safe_chars = array("-", "_"), $trim_padding_chars = "=~.")
382
  {
383
  $string = (string)$string; /* Force string values here. String MUST be a string. */
384
  $trim_padding_chars = (string)$trim_padding_chars; /* And force this one too. */
385
  /**/
386
+ $base64_url_safe = str_replace((array)$url_unsafe_chars, (array)$url_safe_chars, (string)base64_encode($string));
387
+ $base64_url_safe = (strlen($trim_padding_chars)) ? rtrim($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
388
  /**/
389
  return $base64_url_safe; /* Base64 encoded, with URL-safe replacements. */
390
  }
403
  * @param str $trim_padding_chars Optional. A string of padding chars to rtrim. Defaults to: `=~.`.
404
  * @return str The decoded string.
405
  */
406
+ public static function base64_url_safe_decode($base64_url_safe = FALSE, $url_unsafe_chars = array("+", "/"), $url_safe_chars = array("-", "_"), $trim_padding_chars = "=~.")
407
  {
408
  $base64_url_safe = (string)$base64_url_safe; /* Force string values here. This MUST be a string. */
409
  $trim_padding_chars = (string)$trim_padding_chars; /* And force this one too. */
410
  /**/
411
+ $string = (strlen($trim_padding_chars)) ? rtrim($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
412
+ $string = (strlen($trim_padding_chars)) ? str_pad($string, strlen($string) % 4, "=", STR_PAD_RIGHT) : $string;
413
+ $string = (string)base64_decode(str_replace((array)$url_safe_chars, (array)$url_unsafe_chars, $string));
414
  /**/
415
  return $string; /* Base64 decoded, with URL-safe replacements. */
416
  }
424
  * @param str $key The secret key that will be used in this signature.
425
  * @return str|bool An RSA-SHA1 signature string, or false on failure.
426
  */
427
+ public static function rsa_sha1_sign($string = FALSE, $key = FALSE)
428
  {
429
+ $key = /* Fixes key wrappers. */ c_ws_plugin__s2member_utils_strings::_rsa_sha1_key_fix_wrappers((string)$key);
430
  /**/
431
+ $signature = /* Command line. */ c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign((string)$string, (string)$key);
432
  /**/
433
+ if(empty($signature) && stripos(PHP_OS, "win") === 0 && file_exists(($openssl = "c:\openssl-win32\bin\openssl.exe")))
434
+ $signature = c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign((string)$string, (string)$key, /* Specific location. */ $openssl);
435
  /**/
436
+ if(empty($signature) && stripos(PHP_OS, "win") === 0 && file_exists(($openssl = "c:\openssl-win64\bin\openssl.exe")))
437
+ $signature = c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign((string)$string, (string)$key, /* Specific location. */ $openssl);
438
  /**/
439
+ if(empty($signature) && function_exists("openssl_get_privatekey") && function_exists("openssl_sign") && is_resource($private_key = openssl_get_privatekey((string)$key)))
440
+ openssl_sign((string)$string, $signature, $private_key, OPENSSL_ALGO_SHA1).openssl_free_key($private_key);
441
  /**/
442
+ if(empty($signature)) /* Now, if we're still empty, trigger an error here. */
443
+ trigger_error("s2Member was unable to generate an RSA-SHA1 signature.".
444
+ " Please make sure your installation of PHP is compiled with OpenSSL: `openssl_sign()`.".
445
  " See: http://php.net/manual/en/function.openssl-sign.php", E_USER_ERROR);
446
  /**/
447
+ return (!empty($signature)) ? $signature : false;
448
  }
449
  /**
450
  * Generates an RSA-SHA1 signature from the command line.
459
  * @param str $openssl Optional. Defaults to `openssl`. Path to OpenSSL executable.
460
  * @return str|bool An RSA-SHA1 signature string, or false on failure.
461
  */
462
+ public static function _rsa_sha1_shell_sign($string = FALSE, $key = FALSE, $openssl = FALSE)
463
  {
464
+ if(function_exists("shell_exec") && ($esa = "escapeshellarg") && ($openssl = (($openssl && is_string($openssl)) ? $openssl : "openssl")) && ($temp_dir = c_ws_plugin__s2member_utils_dirs::get_temp_dir()))
465
  {
466
+ file_put_contents(($string_file = $temp_dir."/".md5(uniqid("", true)."rsa-sha1-string").".tmp"), (string)$string);
467
+ file_put_contents(($private_key_file = $temp_dir."/".md5(uniqid("", true)."rsa-sha1-private-key").".tmp"), (string)$key);
468
+ file_put_contents(($rsa_sha1_sig_file = $temp_dir."/".md5(uniqid("", true)."rsa-sha1-sig").".tmp"), "");
469
  /**/
470
+ @shell_exec($esa($openssl)." sha1 -sign ".$esa($private_key_file)." -out ".$esa($rsa_sha1_sig_file)." ".$esa($string_file));
471
+ $signature = /* Do NOT trim here. */ file_get_contents($rsa_sha1_sig_file); /* Was the signature was written? */
472
+ unlink($rsa_sha1_sig_file).unlink($private_key_file).unlink($string_file); /* Cleanup. */
473
  }
474
+ return (!empty($signature)) ? $signature : false;
475
  }
476
  /**
477
  * Fixes incomplete private key wrappers for RSA-SHA1 signing.
486
  *
487
  * @see http://www.faqs.org/qa/qa-14736.html
488
  */
489
+ public static function _rsa_sha1_key_fix_wrappers($key = FALSE)
490
  {
491
+ if(($key = trim((string)$key)) && (strpos($key, "-----BEGIN RSA PRIVATE KEY-----") === false || strpos($key, "-----END RSA PRIVATE KEY-----") === false))
492
  {
493
+ foreach(($lines = c_ws_plugin__s2member_utils_strings::trim_deep(preg_split("/[\r\n]+/", $key))) as $line => $value)
494
+ if(strpos($value, "-") === 0) /* Begins with a boundary identifying character ( a hyphen `-` )? */
495
  {
496
+ $boundaries = (empty($boundaries)) ? 1 : $boundaries + 1; /* Counter. */
497
  unset($lines[$line]); /* Remove this boundary line. We'll fix these below. */
498
  }
499
+ if(empty($boundaries) || $boundaries <= 2) /* Do NOT modify keys with more than 2 boundaries. */
500
+ $key = "-----BEGIN RSA PRIVATE KEY-----\n".implode("\n", $lines)."\n-----END RSA PRIVATE KEY-----";
501
  }
502
  return $key; /* Always a trimmed string here. */
503
  }
511
  * @param str $key The secret key that will be used in this signature.
512
  * @return str An HMAC-SHA1 signature string.
513
  */
514
+ public static function hmac_sha1_sign($string = FALSE, $key = FALSE)
515
  {
516
+ $key_64 = str_pad(((strlen((string)$key) > 64) ? pack('H*', sha1((string)$key)) : (string)$key), 64, chr(0x00));
517
  /**/
518
+ return pack('H*', sha1(($key_64 ^ str_repeat(chr(0x5c), 64)).pack('H*', sha1(($key_64 ^ str_repeat(chr(0x36), 64)).(string)$string))));
519
  }
520
  /**
521
  * Decodes unreserved chars encoded by PHP's ``urlencode()``, deeply.
530
  * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
531
  * @return str|array Either the input string, or the input array; after all unreserved chars are decoded properly.
532
  */
533
+ public static function urldecode_ur_chars_deep($value = array())
534
  {
535
+ if(is_array($value)) /* Handles all types of arrays.
536
+ Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
537
+ For further details, see: <http://php.net/manual/en/function.array-map.php>. */
538
  {
539
+ foreach($value as &$r) /* Reference. */
540
+ $r = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep($r);
541
  return $value; /* Return modified array. */
542
  }
543
+ return str_replace(array("%2D", "%2E", "%5F", "%7E"), array("-", ".", "_", "~"), (string)$value);
544
  }
545
  }
546
  }
includes/menu-pages/down-ops.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Menu_Pages
15
  * @since 3.0
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
21
  {
22
  /**
23
  * Menu page for the s2Member plugin ( File Download Options page ).
@@ -27,604 +27,627 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
27
  */
28
  class c_ws_plugin__s2member_menu_page_down_ops
29
  {
30
- public function __construct ()
31
  {
32
- echo '<div class="wrap ws-menu-page">' . "\n";
33
  /**/
34
- echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
35
- echo '<h2>s2Member® File Download Options</h2>' . "\n";
36
  /**/
37
- echo '<table class="ws-menu-page-table">' . "\n";
38
- echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
39
- echo '<tr class="ws-menu-page-table-tr">' . "\n";
40
- echo '<td class="ws-menu-page-table-l">' . "\n";
41
  /**/
42
- echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
43
- 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";
44
- echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" id="ws-plugin--s2member-amazon-cf-files-distros-auto-config-status" value="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"]) . '" />' . "\n";
45
- echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
46
  /**/
47
- do_action ("ws_plugin__s2member_during_down_ops_page_before_left_sections", get_defined_vars ());
48
  /**/
49
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_restrictions", true, get_defined_vars ()))
50
  {
51
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_restrictions", get_defined_vars ());
52
  /**/
53
- echo '<div class="ws-menu-page-group" title="Basic Download Restrictions">' . "\n";
54
  /**/
55
- echo '<div class="ws-menu-page-section ws-plugin--s2member-restrictions-section">' . "\n";
56
- echo '<h3>File Download Restrictions ( required, if providing access to protected files )</h3>' . "\n";
57
- echo '<p>If your Membership offering allows access to restricted files, you\'ll want to configure these options.</p>' . "\n";
58
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_restrictions", get_defined_vars ());
59
  /**/
60
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
61
  /**/
62
- echo '<p><strong>Upload restricted files to this security-enabled directory:</strong><br /><code>' . esc_html (c_ws_plugin__s2member_utils_dirs::doc_root_path ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '</code></p>' . "\n";
63
- echo '<p>- Now, you can link to any protected file, using this special format:<br />&nbsp;&nbsp;<code>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download</strong> = file, relative to the /' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/ directory. In other words, just the file name.</em></small></p>' . "\n";
64
- echo '<p>- Or, use: <code>[s2File download="example-file.zip" /]</code> <em>( easier Shortcode if you prefer )</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL for you, easier.</em></small></p>' . "\n";
65
  /**/
66
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
67
  /**/
68
- echo '<p>s2Member will allow access to these protected files, based on the configuration you specify below. Repeated downloads of the same exact file are NOT tabulated against the totals below. Once a file has been downloaded, future downloads of the same exact file, by the same exact Member will not be counted against them. In other words, if a Member downloads the same file three times, the system only counts that as one unique download. In addition, multiple variations of popular media formats are only counted once. This is because many site owners provide multiple download options to their Users/Members, for compatibility purposes. Files that have the same exact name, with one of these extensions, will only be counted ONE time: <code>' . esc_html (implode (",", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"])) . '</code>.</p>' . "\n";
69
- 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> or <code>s2member-files</code>. Whenever a logged-in Member clicks a link that contains <code>s2member_file_download</code> or <code>s2member-files</code>, the system will politely ask the user to confirm the download using a very intuitive JavaScript confirmation prompt, which contains specific details about your configured download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not. If you want to suppress this JavaScript confirmation prompt, you can add this to the end of your links: <code>&amp;s2member_skip_confirmation</code>. Shortcode alternative: <code>[s2File skip_confirmation="yes" /]</code>.</p>' . "\n";
70
- echo '<p><em>* The above only applies to Users who are logged in as Members. For all other visitors in the general public, the <code>?s2member_file_download</code> links will redirect them your Membership Options Page, so that new visitors can signup, in order to gain access, by becoming a Member. You may also want to have a look down below at s2Member\'s "Advanced Download Restrictions", which provides a greater degree of flexibility.</em></p>' . "\n";
71
  /**/
72
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
73
  /**/
74
- echo '<table class="form-table" style="margin-top:0;">' . "\n";
75
- echo '<tbody>' . "\n";
76
  /**/
77
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
78
  {
79
- echo '<tr>' . "\n";
80
  /**/
81
- echo '<th style="padding-top:0;">' . "\n";
82
- echo '<label for="ws-plugin--s2member-level' . $n . '-file-downloads-allowed">' . "\n";
83
- echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'File Downloads ( Highest Level #' . $n . ' ):' . "\n" : 'File Downloads ( Level #' . $n . ' Or Higher ):' . "\n";
84
- echo '</label>' . "\n";
85
- echo '</th>' . "\n";
86
  /**/
87
- echo '</tr>' . "\n";
88
- echo '<tr>' . "\n";
89
  /**/
90
- echo '<td>' . "\n";
91
- echo '<input type="text" maxlength="9" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_file_downloads_allowed" id="ws-plugin--s2member-level' . $n . '-file-downloads-allowed" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed"]) . '" style="width:200px;" /> every <input type="text" maxlength="3" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_file_downloads_allowed_days" id="ws-plugin--s2member-level' . $n . '-file-downloads-allowed-days" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_file_downloads_allowed_days"]) . '" style="width:200px;" onkeyup="if(this.value > 365){ alert(\'( 365 days is the maximum ).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> day(s).<br />' . "\n";
92
- echo 'Only this many unique downloads will be permitted every X day(s), at ' . (($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'highest Level #' . $n : 'Level #' . $n . ' or higher') . '.<br />' . "\n";
93
- echo '<em>* To allow UNLIMITED downloads, use: <code>999999999</code> ( i.e. <code>999999999</code> = unlimited ).</em>' . "\n";
94
- echo '</td>' . "\n";
95
  /**/
96
- echo '</tr>' . "\n";
97
  /**/
98
  echo ($n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? '<tr><td><div class="ws-menu-page-hr" style="margin:10px 0 10px 0;"></div></td></tr>' : '';
99
  }
100
  /**/
101
- echo '</tbody>' . "\n";
102
- echo '</table>' . "\n";
103
- echo '</div>' . "\n";
104
  /**/
105
- echo '</div>' . "\n";
106
  /**/
107
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_restrictions", get_defined_vars ());
108
  }
109
  /**/
110
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_limit_exceeded_page", true, get_defined_vars ()))
111
  {
112
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_limit_exceeded_page", get_defined_vars ());
113
  /**/
114
- echo '<div class="ws-menu-page-group" title="Download Limit Exceeded Page">' . "\n";
115
  /**/
116
- echo '<div class="ws-menu-page-section ws-plugin--s2member-limit-exceeded-page-section">' . "\n";
117
- echo '<h3>Download Limit Exceeded Page ( required, if providing access to protected files )</h3>' . "\n";
118
- echo '<p>This Page will be shown when/if a Member reaches their download limit, based on your configuration of <strong>Basic Download Restrictions</strong> above. This Page should be created by you, in WordPress®. This Page should provide an informative message to the Member, describing your file access restrictions. Just tell them a little bit about your policy on file downloads, and why they might have reached this Page.</p>' . "\n";
119
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_limit_exceeded_page", get_defined_vars ());
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-file-download-limit-exceeded-page">' . "\n";
127
- echo 'Download Limit Exceeded Page:' . "\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 '<select name="ws_plugin__s2member_file_download_limit_exceeded_page" id="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
136
- echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
137
- foreach (($ws_plugin__s2member_temp_a = array_merge ((array)get_pages ())) as $ws_plugin__s2member_temp_o)
138
- 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";
139
- echo '</select><br />' . "\n";
140
- echo 'We recommend the following title: <code>Download Limit Exceeded</code>.' . "\n";
141
- echo '</td>' . "\n";
142
  /**/
143
- echo '</tr>' . "\n";
144
- echo '</tbody>' . "\n";
145
- echo '</table>' . "\n";
146
- echo '</div>' . "\n";
147
  /**/
148
- echo '</div>' . "\n";
149
  /**/
150
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_limit_exceeded_page", get_defined_vars ());
151
  }
152
  /**/
153
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_advanced_restrictions", true, get_defined_vars ()))
154
  {
155
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_advanced_restrictions", get_defined_vars ());
156
  /**/
157
- echo '<div class="ws-menu-page-group" title="Advanced Download Restrictions">' . "\n";
158
  /**/
159
- echo '<div class="ws-menu-page-section ws-plugin--s2member-restrictions-section">' . "\n";
160
- echo '<h3>Advanced Download Restrictions ( optional, for greater flexibility )</h3>' . "\n";
161
- echo '<p>By default, s2Member uses your Basic Download Restrictions, as configured above. However, you can force s2Member to allow File Downloads, using an extra query string parameter: <code>&amp;s2member_file_download_key=[Key]</code>. A File Download `Key` is passed through this parameter; it tells s2Member to allow the download of this particular file, regardless of Membership Level; and WITHOUT checking any Basic Restrictions, that you may or may not have configured above. The creation of a File Download `Key`, requires a small PHP code snippet. In order to use PHP scripting inside your Posts/Pages, you\'ll need to install this handy plugin ( <a href="http://wordpress.org/extend/plugins/php-execution-plugin/" target="_blank" rel="external">PHP Execution</a> ). There is also a Shortcode equivalent, which does NOT require PHP at all, as seen below.</p>' . "\n";
162
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_advanced_restrictions", get_defined_vars ());
163
  /**/
164
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
165
  /**/
166
- echo '<p>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '<code>&amp;s2member_file_download_key=&lt;?php echo s2member_file_download_key("example-file.zip"); ?&gt;</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download_key</strong> = &lt;?php echo s2member_file_download_key("file, relative to the /' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/ directory"); ?&gt;</em></small></p>' . "\n";
167
  /**/
168
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
169
  /**/
170
- echo '<p>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '<code>&amp;s2member_file_download_key=[s2Key file_download="example-file.zip" /]</code><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2Key file_download="example-file.zip" /]</code></em></small></p>' . "\n";
171
  /**/
172
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
173
  /**/
174
- echo '<p><code>[s2File download="example-file.zip" download_key="true" /]</code> <em>( Key is auto-generated in this case )</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL, no need to generate a Key yourself.</em></small></p>' . "\n";
175
  /**/
176
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
177
  /**/
178
- echo '<p>The function <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_file_download_key%28%29" target="_blank" rel="external">s2member_file_download_key()</a>, is part of the s2Member API. It produces a time-sensitive File Download Key that is unique to each and every visitor. Each Key it produces <em>( at the time it is produced )</em>, will be valid for the current day, and only for a specific IP address and User-Agent string; as detected by s2Member. This makes it possible for you to create links on your site, which provide access to protected file downloads; and without having to worry about one visitor sharing their link with another. So let\'s take a quick look at what <code>s2member_file_download_key()</code> actually produces.</p>' . "\n";
179
- echo '<p><code>s2member_file_download_key("example-file.zip")</code> = a site-specific hash of: <code>date("Y-m-d").$_SERVER["REMOTE_ADDR"].$_SERVER["HTTP_USER_AGENT"].$file</code></p>' . "\n";
180
- echo '<p>When <code>s2member_file_download_key = <em>a valid Key</em></code>, it works independently from Member Level Access. That is, a visitor does NOT have to be logged in to receive access; they just need a valid Key. Using this advanced technique, you could extend s2Member\'s file protection routines, or even combine them with Specific Post/Page Access, and more. The possibilities are limitless really.</p>' . "\n";
181
  /**/
182
- echo '</div>' . "\n";
183
  /**/
184
- echo '</div>' . "\n";
185
  /**/
186
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_advanced_restrictions", get_defined_vars ());
187
  }
188
  /**/
189
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_inline_extensions", true, get_defined_vars ()))
190
  {
191
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_inline_extensions", get_defined_vars ());
192
  /**/
193
- echo '<div class="ws-menu-page-group" title="Inline File Extensions">' . "\n";
194
  /**/
195
- echo '<div class="ws-menu-page-section ws-plugin--s2member-inline-extensions-section">' . "\n";
196
- echo '<h3>Inline File Extensions ( optional, for content-disposition )</h3>' . "\n";
197
- echo '<p>There are two ways to serve files. Inline, or as an Attachment. By default, s2Member will serve all of your protected files, as downloadable attachments. Meaning, visitors will be given a file download prompt. Otherwise known as <code>Content-Disposition: attachment</code>. In some cases though, you may wish to serve files inline. For example, PDF files and images should usually be served inline. When you serve a file inline, it is displayed in your browser immediately, rather than your browser prompting you to download the file as an attachment.</p>' . "\n";
198
- echo '<p>Using the field below, you can list all of the extensions that you want s2Member to serve inline ( ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png,mp3,mp4,flv,ogg,webm</code> ). Please understand, some files just cannot be displayed inline. For instance, there is no way to display an <code>exe</code> file inline. So only specify extensions that can, and should be displayed inline by a web browser. Alternatively, if you would rather handle this on a case-by-case basis, you can simply add the following to the end of your download links: <code>&amp;s2member_file_inline=yes</code>. Shortcode alternative: <code>[s2File download="example-file.zip" inline="yes" /]</code>.</p>' . "\n";
199
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_inline_extensions", get_defined_vars ());
200
  /**/
201
- echo '<table class="form-table">' . "\n";
202
- echo '<tbody>' . "\n";
203
- echo '<tr>' . "\n";
204
  /**/
205
- echo '<th>' . "\n";
206
- echo '<label for="ws-plugin--s2member-file-download-inline-extensions">' . "\n";
207
- echo 'Default Inline File Extensions ( comma-delimited ):' . "\n";
208
- echo '</label>' . "\n";
209
- echo '</th>' . "\n";
210
  /**/
211
- echo '</tr>' . "\n";
212
- echo '<tr>' . "\n";
213
  /**/
214
- echo '<td>' . "\n";
215
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_file_download_inline_extensions" id="ws-plugin--s2member-file-download-inline-extensions" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]) . '" /><br />' . "\n";
216
- echo 'Inline extensions, comma-delimited. Ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png,mp3,mp4,flv,ogg,webm</code>' . "\n";
217
- echo '</td>' . "\n";
218
  /**/
219
- echo '</tr>' . "\n";
220
- echo '</tbody>' . "\n";
221
- echo '</table>' . "\n";
222
- echo '</div>' . "\n";
223
  /**/
224
- echo '</div>' . "\n";
225
  /**/
226
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_inline_extensions", get_defined_vars ());
227
  }
228
  /**/
229
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_remote_authorization", true, get_defined_vars ()))
230
  {
231
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_remote_authorization", get_defined_vars ());
232
  /**/
233
- echo '<div class="ws-menu-page-group" title="Remote Auth / Podcasting">' . "\n";
234
  /**/
235
- echo '<div class="ws-menu-page-section ws-plugin--s2member-remote-authorization-section">' . "\n";
236
- echo '<h3>Remote Header Authorization ( optional )</h3>' . "\n";
237
- echo '<p>This can be enabled on a case-by-case basis. Just add this to the end of your download links: <code>&amp;s2member_file_remote=yes</code>. Shortcode alternative: <code>[s2File download="example-file.zip" remote="yes" /]</code>.</p>' . "\n";
238
- echo '<p>Remote Header Authorization allows access to file downloads through an entirely different approach. Instead of asking the Member to log into your site through a browser, a Member will be prompted automatically, to log in through HTTP Header Authorization prompts; which is the same technique used in more traditional security systems via .htaccess files. In other words, Remote Header Authorization makes it possible for your Members to access files through remote applications that may NOT use a browser. This is often the case when a Member needs to access protected files through a software client like iTunes®; typical with podcasts. See <a href="http://www.primothemes.com/forums/viewtopic.php?f=4&t=837&p=28558#p28558" target="_blank" rel="external">tutorial here</a> for details about how to setup a Podcast for iTunes®.</p>' . "\n";
239
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_remote_authorization", get_defined_vars ());
240
- echo '</div>' . "\n";
241
  /**/
242
- echo '</div>' . "\n";
243
  /**/
244
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_remote_authorization", get_defined_vars ());
245
  }
246
  /**/
247
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_s3", true, get_defined_vars ()))
248
  {
249
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_s3", get_defined_vars ());
250
  /**/
251
- echo '<div class="ws-menu-page-group" title="Amazon® S3/CDN Storage Option"' . ((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' default-state="open"' : '') . '>' . "\n";
252
  /**/
253
- echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-s3-section">' . "\n";
254
- echo '<h3>Amazon® S3/CDN Storage &amp; Delivery ( optional )</h3>' . "\n";
255
- echo '<a href="http://aws.amazon.com/s3/" target="_blank"><img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/amazon-logo.png" class="ws-menu-page-right" style="width:250px; height:100px; border:0;" alt="." /></a>' . "\n";
256
- echo '<p>Please note, all of this is optional. s2Member can be configured here to ONLY use Amazon® S3 <em>( i.e. without Amazon® CloudFront )</em>. Or, s2Member can be configured to use BOTH Amazon® S3 and Amazon® CloudFront together. If you want to use Amazon® S3 Storage, but you don\'t care about Amazon® CloudFront, feel free to leave the entire Amazon® CloudFront section empty. The configuration options in the Amazon® CloudFront section are ONLY required if you are planning to use both Amazon® S3 and Amazon® CloudFront together.</p>' . "\n";
257
- echo '<p>Amazon® Simple Storage Service ( <a href="http://aws.amazon.com/s3/" target="_blank" rel="external">Amazon® S3</a> ). Amazon® S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon® S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives developers access to the same highly scalable, reliable, secure, fast, inexpensive infrastructure that Amazon® uses to run its own global network of web sites. s2Member has been integrated with Amazon® S3, so that <em>( if you wish )</em>, instead of using the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory, you can store all of your protected files inside an Amazon® S3 Bucket.</p>' . "\n";
258
- echo '<p>If you configure the options below, s2Member will assume all protected files are inside your Amazon® S3 Bucket; and the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory is no longer used at all. That being said, all other aspects of s2Member\'s File Download protection remain the same. The only thing that changes, is the location of your protected files. In other words, Basic Download Restrictions, Download Keys, Inline Extensions, Custom Capability and/or Membership Level Files will all continue to work just as before. The only difference is that s2Member will use your Amazon® S3 Bucket as a CDN <em>( i.e. Content Delivery Network )</em> instead of the local <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory.</p>' . "\n";
259
- echo '<p>s2Member assumes that you\'re creating a new Amazon® S3 Bucket, specifically for this installation; and that your Bucket is NOT available publicly. In other words, if you type this URL into your browser <em>( i.e. <code>http://your-bucket-name.s3.amazonaws.com/</code> )</em>, you should get an error that says: <code>Access Denied</code>. That\'s good, that\'s exactly what you want. You can create your Amazon® S3 Bucket using the <a href="https://console.aws.amazon.com/s3/home" target="_blank" rel="external">Amazon® interface</a>. Or, some people prefer to use this popular Firefox® extension ( <a href="http://www.s3fox.net/" target="_blank" rel="external">S3 Fox Organizer</a> ).</p>' . "\n";
260
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_amazon_s3", get_defined_vars ());
261
  /**/
262
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
263
  /**/
264
- echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Query String Authentication", provided by the Amazon® S3 API. Documented for developers <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate S3 authenticated redirect URLs ( internally ); which allow Customers temporary access to specific files inside your S3 Bucket. s2Member\'s Query String Authentication through Amazon® S3 gives a Customer 30 seconds to connect to the file inside your S3 Bucket ( i.e. the automatic redirection URL ). This connection period of 30 seconds is largely irrelevant when used in combination with s2Member. It just needs to be a low value, to further prevent any possibility of S3 authenticated link sharing. If you need to change this connection timeout of <code>30 seconds</code> for some reason ( not likely ), you can use this WordPress® Filter: <code>ws_plugin__s2member_amazon_s3_file_expires_time</code>. If you need help, please check the s2Member Forums.</em></p>' . "\n";
265
- echo '<p><em><strong>Linking To Protected Files:</strong> Nothing changes. s2Member\'s integration with Amazon® S3 serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® S3 URL, which allows them access to a particular file via Amazon® S3. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>.</em></p>' . "\n";
266
- echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> The query string parameter <code>&amp;s2member_file_inline=yes</code> DOES work for files served directly through Amazon® S3. s2Member DOES have control over the <code>Content-Type</code> and <code>Content-Disposition</code> headers for files being served through Amazon® S3. However, Amazon® CloudFront servers do NOT automatically determine the MIME type for the objects they serve. If you integrate both Amazon® S3 and CloudFront, s2Member will NOT have control over headers. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. Again, with the Amazon® S3/CloudFront combination, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>' . "\n";
267
  /**/
268
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
269
  /**/
270
- echo '<table class="form-table" style="margin-top:0;">' . "\n";
271
- echo '<tbody>' . "\n";
272
- echo '<tr>' . "\n";
273
  /**/
274
- echo '<th style="padding-top:0;">' . "\n";
275
- echo '<label for="ws-plugin--s2member-amazon-s3-files-bucket">' . "\n";
276
- echo 'Amazon® S3 File Bucket ( where protected files are ):' . "\n";
277
- echo '</label>' . "\n";
278
- echo '</th>' . "\n";
279
  /**/
280
- echo '</tr>' . "\n";
281
- echo '<tr>' . "\n";
282
  /**/
283
- echo '<td>' . "\n";
284
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_bucket" id="ws-plugin--s2member-amazon-s3-files-bucket" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]) . '" /><br />' . "\n";
285
- echo 'Your Amazon® S3 Bucket will be used, instead of the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory.' . "\n";
286
- echo '</td>' . "\n";
287
  /**/
288
- echo '</tr>' . "\n";
289
- echo '<tr>' . "\n";
290
  /**/
291
- echo '<th>' . "\n";
292
- echo '<label for="ws-plugin--s2member-amazon-s3-files-access-key">' . "\n";
293
- echo 'Amazon® Access Key ( Access Key ID ):' . "\n";
294
- echo '</label>' . "\n";
295
- echo '</th>' . "\n";
296
  /**/
297
- echo '</tr>' . "\n";
298
- echo '<tr>' . "\n";
299
  /**/
300
- echo '<td>' . "\n";
301
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_access_key" id="ws-plugin--s2member-amazon-s3-files-access-key" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]) . '" /><br />' . "\n";
302
- echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Access Credentials</code>.' . "\n";
303
- echo '</td>' . "\n";
304
  /**/
305
- echo '</tr>' . "\n";
306
- echo '<tr>' . "\n";
307
  /**/
308
- echo '<th>' . "\n";
309
- echo '<label for="ws-plugin--s2member-amazon-s3-files-secret-key">' . "\n";
310
- echo 'Amazon® Secret Key ( Secret Access Key ):' . "\n";
311
- echo '</label>' . "\n";
312
- echo '</th>' . "\n";
313
  /**/
314
- echo '</tr>' . "\n";
315
- echo '<tr>' . "\n";
316
  /**/
317
- echo '<td>' . "\n";
318
- echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_secret_key" id="ws-plugin--s2member-amazon-s3-files-secret-key" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]) . '" /><br />' . "\n";
319
- echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Access Credentials</code>.' . "\n";
320
- echo '</td>' . "\n";
321
  /**/
322
- echo '</tr>' . "\n";
323
- echo '</tbody>' . "\n";
324
- echo '</table>' . "\n";
325
- echo '</div>' . "\n";
326
  /**/
327
- echo '</div>' . "\n";
328
  /**/
329
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_s3", get_defined_vars ());
330
  }
331
  /**/
332
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_cf", true, get_defined_vars ()))
333
  {
334
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_cf", get_defined_vars ());
335
- /**/
336
- echo '<div class="ws-menu-page-group" title="Amazon® S3/CloudFront CDN Storage Option"' . ((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' default-state="open"' : '') . '>' . "\n";
337
- /**/
338
- echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-cf-section">' . "\n";
339
- echo '<h3>Amazon® S3/CloudFront CDN Storage &amp; Delivery ( optional )</h3>' . "\n";
340
- echo '<a href="http://aws.amazon.com/cloudfront/" target="_blank"><img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/amazon-logo.png" class="ws-menu-page-right" style="width:250px; height:100px; border:0;" alt="." /></a>' . "\n";
341
- echo '<p>Please note, all of this is optional. s2Member can be configured to ONLY use Amazon® S3 <em>( i.e. without Amazon® CloudFront )</em>. Or, s2Member can be configured to use BOTH Amazon® S3 and Amazon® CloudFront together. If you don\'t want to use Amazon® CloudFront, please leave this entire section empty. The configuration options in this section are ONLY required if you are planning to use both Amazon® S3 and Amazon® CloudFront together.</p>' . "\n";
342
- echo '<p>Amazon® Simple Storage Service ( <a href="http://aws.amazon.com/s3/" target="_blank" rel="external">Amazon® S3</a> ) combined with <a href="http://aws.amazon.com/cloudfront/" target="_blank" rel="external">Amazon® CloudFront</a>. Amazon® CloudFront is a web service for content delivery. It integrates with other Amazon® Web Services <em>( i.e. Amazon® S3 Storage )</em> to give developers and businesses an easy way to distribute content to end users with low latency, and with high data transfer speeds. Amazon® CloudFront delivers your static and streaming content using a global network of edge locations. Requests for your Amazon® S3 Bucket Objects <em>( i.e. your protected files )</em> are automatically routed to the nearest edge location, so content is delivered with the best possible performance. s2Member has been integrated with both Amazon® S3 and with Amazon® CloudFront. So <em>( if you wish )</em>, instead of using the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory, you can store all of your protected files inside an Amazon® S3 Bucket and serve them via Amazon® CloudFront. But again, please understand, the configuration options in this section are ONLY required if you\'re going to use both Amazon® S3 &amp; CloudFront together.</p>' . "\n";
343
- echo '<p><strong>One of the great things about Amazon® CloudFront</strong>, is its ability to <strong>stream/seek media files</strong> in the truest sense of the word. For sites delivering protected <em>FLV/MP4/OGG/WEBM</em> and other streaming audio/video file types over the <em>RTMP</em> protocol, Amazon® CloudFront is our recommendation. Once you\'ve successfully configured s2Member to use both Amazon® S3 and Amazon® CloudFront together, please review the section below regarding <code>JW Player® &amp; RTMP Protocol Examples</code>. s2Member will automatically serve your protected files over the <em>RTMP</em> protocol using an Amazon® CloudFront Streaming Distribution.</p>' . "\n";
344
- echo '<p>If you configure the options below, s2Member will assume all protected files are inside your Amazon® S3 Bucket; and the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory is no longer used at all. That being said, all other aspects of s2Member\'s File Download protection remain the same. The only thing that changes, is the location of your protected files. In other words, Basic Download Restrictions, Download Keys, Custom Capability and/or Membership Level Files will all continue to work just as before. The only difference is that s2Member will use your Amazon® S3 Bucket, automatically connecting it to both of the Amazon® CloudFront Distributions, which s2Member auto-configures for you <em>( see below )</em>. In this way, s2Member uses Amazon® CloudFront as a CDN <em>( i.e. Content Delivery Network )</em> for your protected files.</p>' . "\n";
345
- echo '<p>s2Member assumes that you\'re creating a new Amazon® S3 Bucket, specifically for this installation; and that your Bucket is NOT available publicly. In other words, if you type this URL into your browser <em>( i.e. <code>http://your-bucket-name.s3.amazonaws.com/</code> )</em>, you should get an error that says: <code>Access Denied</code>. That\'s good, that\'s exactly what you want. You can create your Amazon® S3 Bucket using the <a href="https://console.aws.amazon.com/s3/home" target="_blank" rel="external">Amazon® interface</a>. Or, some people prefer to use this popular Firefox® extension ( <a href="http://www.s3fox.net/" target="_blank" rel="external">S3 Fox Organizer</a> ). You will also need to enable CloudFront inside your Web Services account at Amazon®. Don\'t worry about creating or configuring any CloudFront Distributions, s2Member will auto-create and auto-configure those for you, allowing you to serve protected files.</p>' . "\n";
346
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_amazon_cf", get_defined_vars ());
347
- /**/
348
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
349
- /**/
350
- echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon® CloudFront (below), are designed to create &amp; configure various components on your Amazon® Web Services account, which are all requirements for you to <a href="http://docs.amazonwebservices.com/AmazonCloudFront/2010-11-01/DeveloperGuide/index.html?HowToPrivateContent.html" target="_blank" rel="external">serve protected files through the Amazon® S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon® S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy ( i.e. permissions ) on your Amazon® S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>' . "\n";
351
- echo '<p><em><strong>Linking To Protected Files:</strong> Streamed files are special, but nothing else changes. s2Member\'s integration with Amazon® S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® CloudFront URL, which allows them access to a particular file via Amazon® CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>. For streaming audio/video files, please review the section below: <code>JW Player® &amp; RTMP Protocol Examples</code>.</em></p>' . "\n";
352
- echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon® CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon® CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>' . "\n";
353
- echo (stripos (PHP_OS, "win") === 0 && c_ws_plugin__s2member_utils_conds::is_localhost ()) ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon® CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront® URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows®</a> while you\'re developing. s2Member will automatically find it here: <code>C:\OpenSSL-Win[32/64]\bin\openssl.exe</code>.' . ((file_exists ("c:\openssl-win32\bin\openssl.exe") || file_exists ("c:\openssl-win64\bin\openssl.exe")) ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] is NOT currently available )</strong>') . '</em></p>' . "\n" : '';
354
- /**/
355
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"] === "configured")
356
- echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon® CloudFront Distributions are: ( ALREADY configured! )</strong></em>' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) ? '<br /><em class="ws-menu-page-hilite">Downloads Distribution CNAME:</em> <em><code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]) . '</code></em>' : '') . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? '<br /><em class="ws-menu-page-hilite">Streaming Distribution CNAME:</em> <em><code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]) . '</code></em>' : '') . '</p>' . "\n";
357
- /**/
358
- else if (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"])
359
- echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon® CloudFront Distributions are: ( NOT yet auto-configured ).</strong></em></p>' . "\n";
360
- /**/
361
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
362
- /**/
363
- echo '<table class="form-table" style="margin-top:0;">' . "\n";
364
- echo '<tbody>' . "\n";
365
- echo '<tr>' . "\n";
366
- /**/
367
- echo '<th style="padding-top:0;">' . "\n";
368
- echo '<label for="ws-plugin--s2member-amazon-cf-files-private-key-id">' . "\n";
369
- echo 'Amazon® CloudFront Key Pair ID ( your Key Pair ID ):' . "\n";
370
- echo '</label>' . "\n";
371
- echo '</th>' . "\n";
372
- /**/
373
- echo '</tr>' . "\n";
374
- echo '<tr>' . "\n";
375
- /**/
376
- echo '<td>' . "\n";
377
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_private_key_id" id="ws-plugin--s2member-amazon-cf-files-private-key-id" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key_id"]) . '" data-s-prev-config-value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key_id"]) . '" /><br />' . "\n";
378
- echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Key Pairs</code>.' . "\n";
379
- echo '</td>' . "\n";
380
- /**/
381
- echo '</tr>' . "\n";
382
- echo '<tr>' . "\n";
383
- /**/
384
- echo '<th>' . "\n";
385
- echo '<label for="ws-plugin--s2member-amazon-cf-files-private-key-entry">' . "\n";
386
- echo 'Amazon® CloudFront Private Key ( contents of your <code>pk-[***].pem</code> file ):' . "\n";
387
- echo '</label>' . "\n";
388
- echo '</th>' . "\n";
389
- /**/
390
- echo '</tr>' . "\n";
391
- echo '<tr>' . "\n";
392
- /**/
393
- echo '<td>' . "\n";
394
- echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_private_key" id="ws-plugin--s2member-amazon-cf-files-private-key" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]) . '" data-s-prev-config-value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]) . '" />' . "\n";
395
- echo '<textarea name="ws_plugin__s2member_amazon_cf_files_private_key_entry" id="ws-plugin--s2member-amazon-cf-files-private-key-entry" rows="3" wrap="off" spellcheck="false" style="font-family:Consolas, monospace;">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]) . '</textarea><br />' . "\n";
396
- echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Key Pairs</code>.<br />' . "\n";
397
- echo '<em>* Note, s2Member needs your <strong>Private Key file</strong>, NOT your Public Key file.</em>' . "\n";
398
- echo '</td>' . "\n";
399
- /**/
400
- echo '</tr>' . "\n";
401
- echo '<tr>' . "\n";
402
- /**/
403
- echo '<th>' . "\n";
404
- echo '<label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros">' . "\n";
405
- echo 'Auto-Configure your Amazon® S3/CloudFront combination?' . "\n";
406
- echo '</label>' . "\n";
407
- echo '</th>' . "\n";
408
- /**/
409
- echo '</tr>' . "\n";
410
- echo '<tr>' . "\n";
411
- /**/
412
- echo '<td>' . "\n";
413
- echo '<input type="checkbox" name="ws_plugin__s2member_amazon_cf_files_auto_configure_distros" id="ws-plugin--s2member-amazon-cf-files-auto-configure-distros" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-amazon-cf-files-auto-configure-distros")) . '"' . ((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros"><strong>Yes</strong>, automatically configure my Amazon® CloudFront Distributions &amp; Amazon® S3 ACLs for me.</label><br />' . "\n";
414
- echo '<em>s2Member will auto-configure and/or delete &amp; re-configure your Amazon® CloudFront Distributions for you.</em>' . "\n";
415
- echo '</td>' . "\n";
416
- /**/
417
- echo '</tr>' . "\n";
418
- echo '<tr>' . "\n";
419
- /**/
420
- echo '<td>' . "\n";
421
- echo '<input type="checkbox" name="ws_plugin__s2member_amazon_cf_files_auto_configure_distros_w_cnames" id="ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames")) . '"' . ((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"] && ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"] || $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"])) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames"><strong>Yes</strong>, I want s2Member to auto-configure using custom CNAMES that I\'ll setup.</label><br />' . "\n";
422
- echo '<em>* Optional, do NOT check this box unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
423
- echo '</td>' . "\n";
424
- /**/
425
- echo '</tr>' . "\n";
426
- echo '</tbody>' . "\n";
427
- echo '</table>' . "\n";
428
- /**/
429
- echo '<div id="ws-plugin--s2member-amazon-cf-files-auto-configure-distro-cnames" style="display:none;">' . "\n";
430
- echo '<table class="form-table">' . "\n";
431
- echo '<tbody>' . "\n";
432
- echo '<tr>' . "\n";
433
- /**/
434
- echo '<th>' . "\n";
435
- echo '<label for="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname">' . "\n";
436
- echo 'Amazon® CloudFront CNAME for File Downloads ( optional ):' . "\n";
437
- echo '</label>' . "\n";
438
- echo '</th>' . "\n";
439
- /**/
440
- echo '</tr>' . "\n";
441
- echo '<tr>' . "\n";
442
- /**/
443
- echo '<td>' . "\n";
444
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . '" /><br />' . "\n";
445
- echo 'Example: <code>s2-file-downloads.' . esc_html (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_HOST)) . '</code>.<br />' . "\n";
446
- echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
447
- echo '</td>' . "\n";
448
- /**/
449
- echo '</tr>' . "\n";
450
- echo '<tr>' . "\n";
451
- /**/
452
- echo '<th>' . "\n";
453
- echo '<label for="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname">' . "\n";
454
- echo 'Amazon® CloudFront CNAME for Streaming Files ( optional ):' . "\n";
455
- echo '</label>' . "\n";
456
- echo '</th>' . "\n";
457
- /**/
458
- echo '</tr>' . "\n";
459
- echo '<tr>' . "\n";
460
- /**/
461
- echo '<td>' . "\n";
462
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . '" /><br />' . "\n";
463
- echo 'Example: <code>s2-streaming-files.' . esc_html (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_HOST)) . '</code>.<br />' . "\n";
464
- echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
465
- echo '</td>' . "\n";
466
- /**/
467
- echo '</tr>' . "\n";
468
- echo '</tbody>' . "\n";
469
- echo '</table>' . "\n";
470
- echo '</div>' . "\n";
471
- echo '</div>' . "\n";
472
- /**/
473
- echo '</div>' . "\n";
474
- /**/
475
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_cf", get_defined_vars ());
476
  }
477
  /**/
478
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_rtmp_streaming", true, get_defined_vars ()))
479
  {
480
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rtmp_streaming", get_defined_vars ());
481
  /**/
482
- echo '<div class="ws-menu-page-group" title="JW Player® &amp; RTMP Protocol Examples">' . "\n";
483
  /**/
484
- echo '<div class="ws-menu-page-section ws-plugin--s2member-rtmp-streaming-section">' . "\n";
485
- echo '<h3>JW Player® &amp; RTMP Protocol Examples</h3>' . "\n";
486
- echo '<a href="http://www.longtailvideo.com/players/" target="_blank"><img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/jwplayer-logo.png" class="ws-menu-page-right" style="width:179px; height:58px; border:0;" alt="." /></a>' . "\n";
487
- echo '<p>While it is possible to serve audio/video files protected by s2Member, without needing to integrate Amazon® S3 or CloudFront; we DO highly recommend that you integrate both Amazon® S3 and Amazon® CloudFront in order to maximize speed and compatibility across various viewing platforms. That being said, there are code samples below that will serve audio/video files both with and without Amazon® S3/CloudFront. You can also check the <a href="' . esc_attr (c_ws_plugin__s2member_readmes::parse_readme_value ("Forum URI")) . '" target="_blank" rel="external">s2Member Support Forums</a> for tips/tricks if you like.</p>' . "\n";
488
- echo '<p><strong>One of the great things about Amazon® CloudFront</strong>, is its ability to <strong>stream/seek media files</strong> in the truest sense of the word. For sites delivering protected <em>FLV/MP4/OGG/WEBM</em> and other streaming audio/video file types over the <em>RTMP</em> protocol, Amazon® CloudFront is our recommendation. Once you\'ve successfully configured s2Member to use both Amazon® S3 and Amazon® CloudFront together, please review the code samples below. s2Member can automatically serve your protected files over the <em>RTMP</em> protocol using an Amazon® CloudFront Streaming Distribution.</p>' . "\n";
489
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_rtmp_streaming", get_defined_vars ());
490
  /**/
491
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
492
  /**/
493
- echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-standard-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( MP4 file, via Rewrite URLs. Amazon® S3/CloudFront NOT required )</a></p>' . "\n";
494
- echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-standard-mp4" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This does NOT require s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <code>s2Member -> Download Options -> Advanced Mod Rewrite Linkage</code>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/jwplayer-standard-mp4.x-php")) . '</p>' . "\n";
495
  /**/
496
- echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>' . "\n";
497
- echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12455" target="_blank" rel="external">s2Member Codex -> API Functions</a>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/jwplayer-streaming-mp4.x-php")) . '</p>' . "\n";
498
  /**/
499
- echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-sca\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s JSON/Shortcode alternative )</a></p>' . "\n";
500
- echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-sca" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12455" target="_blank" rel="external">s2Member Codex -> API Functions</a>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/jwplayer-streaming-mp4-sca.x-php")) . '</p>' . "\n";
501
  /**/
502
- echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-webm\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, advanced w/ multiple HTML5 fallbacks )</a></p>' . "\n";
503
- echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-webm" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12455" target="_blank" rel="external">s2Member Codex -> API Functions</a>.<br /><br />' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/jwplayer-streaming-mp4-webm.x-php")) . '</p>' . "\n";
504
  /**/
505
- echo '</div>' . "\n";
506
  /**/
507
- echo '</div>' . "\n";
508
  /**/
509
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_rtmp_streaming", get_defined_vars ());
510
  }
511
  /**/
512
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_rewrite_linkage", true, get_defined_vars ()))
513
  {
514
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rewrite_linkage", get_defined_vars ());
515
- /**/
516
- echo '<div class="ws-menu-page-group" title="Advanced Mod-Rewrite Linkage">' . "\n";
517
- /**/
518
- echo '<div class="ws-menu-page-section ws-plugin--s2member-rewrite-linkage-section">' . "\n";
519
- echo '<h3>Advanced Mod-Rewrite Linkage</h3>' . "\n";
520
- echo '<p>s2Member automatically creates <code>mod_rewrite</code> rules inside your <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory, which provide additional flexibility in the way protected files can be served to your Customers. With s2Member\'s <code>mod_rewrite</code> rules, it is now possible to link directly to a protected file, avoiding the use of query string variables <em>( it\'s completely optional though, i.e. NOT required )</em>.</p>' . "\n";
521
- echo '<p>This new flexibility may come in handy for site owners serving files through media playback devices that have issues with query string variables. For instance, it is now possible to link to an s2Member-protected file directly, like this: <code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/example-file.zip</code> instead of <code>... /?s2member_file_download=example-file.zip</code>. Either way works, but the direct link might be easier for some.</p>' . "\n";
522
- echo '<p>It is also possible to pass query string parameters through a direct link:<br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/example-file.zip?s2member_file_inline=yes&amp;s2member_file_download_key=[key]</code>.</p>' . "\n";
523
- echo '<p>That being said, s2Member\'s <code>mod_rewrite</code> rules allow for more advanced control over s2Member-specific parameters.</p>' . "\n";
524
- echo '<p>For example, you could just do this for inline files:<br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline</strong>/example-file.zip</code></p>' . "\n";
525
- echo '<p>Or, if you really want to get advanced, you could do something like this:<br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline-[yes|no]/s2member-file-download-key-[key]</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline-yes/s2member-file-download-key-xS54df5ER4d5x</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-inline-yes/s2member-skip-confirmation</strong>/example-file.zip</code></p>' . "\n";
526
- echo '<p>Or even this, if you\'re using Remote Header Authorization:<br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-remote</strong>/example-file.zip</code></p>' . "\n";
527
- echo '<p>Specifying storage location option dynamically:<br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-storage-[local|s3|cf]</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-storage-cf</strong>/example-cloudfront-file.zip</code><br /><code>... /wp-content/plugins/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '<strong class="ws-menu-page-hilite">/s2member-file-storage-s3/s2member-file-inline</strong>/example-s3-file.html</code></p>' . "\n";
528
- echo '<p><em>* Note, the order of your s2Member-specific parameters with Advanced Mod-Rewrite Linkage is irrelevant. Feel free to add/remove, or even change the order. Everything discussed here is also Multisite compatible. Everything discussed here is also compatible when/if combined with Amazon® S3/CDN Storage. However, NONE of this will work on servers that do NOT support <code>mod_rewrite</code>. Almost all web servers do though.</em></p>' . "\n";
529
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_rewrite_linkage", get_defined_vars ());
530
- echo '</div>' . "\n";
531
- /**/
532
- echo '</div>' . "\n";
533
- /**/
534
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_rewrite_linkage", get_defined_vars ());
535
  }
536
  /**/
537
- if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_shortcode_attrs", true, get_defined_vars ()))
538
  {
539
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_shortcode_attrs", get_defined_vars ());
540
- /**/
541
- echo '<div class="ws-menu-page-group" title="Shortcode Attributes &amp; API Functions ( Explained )">' . "\n";
542
- /**/
543
- echo '<div class="ws-menu-page-section ws-plugin--s2member-shortcode-attrs-section">' . "\n";
544
- echo '<h3>Shortcode Attributes &amp; API Functions ( Explained In Full Detail )</h3>' . "\n";
545
- echo '<p>s2Member makes <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcodes</a> available to you, which allow you to generate File Download URLs and/or File Download Keys. Like most Shortcodes for WordPress®, s2Member reads Attributes in your Shortcode. Many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
546
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs", get_defined_vars ());
547
- /**/
548
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
549
- /**/
550
- echo '<h4 style="margin:0;"><code>[s2File /]</code> Shortcode Attributes:</h4>' . "\n";
551
- echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>' . "\n";
552
- echo '<table class="form-table" style="margin-top:0;">' . "\n";
553
- echo '<tbody>' . "\n";
554
- echo '<tr style="padding-top:0;">' . "\n";
555
- /**/
556
- echo '<td style="padding-top:0;">' . "\n";
557
- echo '<ul>' . "\n";
558
- echo '<li><code>download="file.zip"</code> Location of the file, relative to the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; or, relative to the root of your Amazon® S3 Bucket, when applicable.</li>' . "\n";
559
- echo '<li><code>download_key="no"</code> Defaults to <code>no</code>. If <code>download_key="1|on|yes|true|ip-forever|universal"</code>, s2Member will return a URL with an s2Member-generated File Download Key. You don\'t need to generate the File Download Key yourself, s2Member does it for you. If you set <code>download_key="ip-forever"</code>, the File Download Key that s2Member generates will last forever, for a specific IP Address; otherwise, by default, all File Download Keys expire after 24 hours automatically. If you set <code>download_key="universal"</code>, s2Member will generate a File Download Key that is good for anyone/everyone forever, with NO restrictions on who/where/when a file is accessed <em>( e.g. be careful with this one )</em>.</li>' . "\n";
560
- echo '<li><code>stream="no"</code> Defaults to <code>no</code>. If <code>stream="1|on|yes|true"</code>, s2Member will return a URL containing a parameter/directive, which forces the File Download to take place over the RTMP protocol. This ONLY works when/if s2Member is configured to run with both Amazon® S3/CloudFront. Please note however, it\'s better to use the example code provided in the section above, regarding: <code>JW Player® and the RTMP Protocol</code>. Also note, if <code>get_streamer_json="1|on|yes|true"</code>, s2Member will automatically force <code>stream="true"</code> for you.</li>' . "\n";
561
- echo '<li><code>inline=""</code> Defaults to <code>[empty]</code>. If <code>inline="1|on|yes|true"</code>, s2Member will serve the file inline, instead of as an actual File Download. If empty, s2Member will look at your <code>Inline File Extensions</code> configuration above, and serve the file inline; if, and only if, its extension matches one found in your configuration. By default, s2Member serves all files as attachments <em>( i.e. downloads )</em>. Please read the section above regarding <code>Inline File Extensions</code> for further details. Also note, this Shortcode Attribute does NOTHING for files served via Amazon® CloudFront. See the tech-notes listed in the Amazon® CloudFront section for further details and workarounds.</li>' . "\n";
562
- echo '<li><code>storage=""</code> Defaults to <code>[empty]</code>. If <code>storage="local|s3|cf"</code>, s2Member will serve the file from a specific source location, based on the value of this Shortcode Attribute. For example, if you\'ve configured Amazon® S3 and/or CloudFront; but, there are a few files that you want to upload locally to the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; you can force s2Member to serve a file from local storage by setting <code>storage="local"</code> explicitly.</li>' . "\n";
563
- echo '<li><code>remote="no"</code> Defaults to <code>no</code>. If <code>remote="1|on|yes|true"</code>, s2Member will authenticate access to the File Download via Remote Header Authorization, instead of through your web site. This is similar to <code>.htaccess</code> protection routines of yester-year</code>. Please check the <code>Remote Authorization and Podcasting</code> section for further details about how this works.</li>' . "\n";
564
- echo '<li><code>ssl=""</code> Defaults to <code>[empty]</code>. If <code>ssl="1|on|yes|true"</code>, s2Member will generate a File Download URL with an SSL protocol <em>( i.e. the URL will start with <code>https://</code> or <code>rtmpe://</code> )</em>. If empty, s2Member will only generate a File Download URL with an SSL protocol, when/if the Post/Page/URL firing the Shortcode itself, is also being viewed over SSL. Otherwise, s2Member will use a non-SSL protocol by default.</li>' . "\n";
565
- echo '<li><code>rewrite="no"</code> Defaults to <code>no</code>. If <code>rewrite="1|on|yes|true"</code>, s2Member will generate a File Download URL that takes full advantage of s2Member\'s Advanced Mod Rewrite functionality. If you\'re running an Apache web server, or another server that supports <code>mod_rewrite</code>, we highly recommend turning this on. s2Member\'s <code>mod_rewrite</code> URLs do NOT contain query string parameters, making them more portable/compatible with other software applications and/or plugins for WordPress®.</li>' . "\n";
566
- echo '<li><code>rewrite_base=""</code> Defaults to <code>[empty]</code>. If <code>rewrite_base="' . esc_attr (site_url ("/")) . '"</code>, s2Member will generate a File Download URL that takes full advantage of s2Member\'s Advanced Mod Rewrite functionality, and it will use the rewrite base URL as a prefix. This could be useful on some WordPress® installations that use advanced directory structures. It could also be useful for site owners using virtual directories that point to <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code>. Note, if <code>rewrite_base</code> is set, s2Member will automatically force <code>rewrite="yes"</code> for you.</li>' . "\n";
567
- echo '<li><code>skip_confirmation="no"</code> Defaults to <code>no</code>. If <code>skip_confirmation="1|on|yes|true"</code>, s2Member will generate a File Download URL which contains a directive, telling s2Member NOT to introduce any JavaScript confirmation prompts on your site, for this File Download URL. Please note, s2Member will automatically detect links, anywhere in your content, and/or anywhere in your theme files, that contain <code>s2member_file_download</code> or <code>s2member-files</code>. Whenever a logged-in Member clicks a link that contains <code>s2member_file_download</code> or <code>s2member-files</code>, the system will politely ask the User to confirm the download using a very intuitive JavaScript confirmation prompt, which contains specific details about your configured download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not.</li>' . "\n";
568
- echo '<li><code>url_to_storage_source="no"</code> Defaults to <code>no</code>. If <code>url_to_storage_source="1|on|yes|true"</code>, s2Member will generate a File Download URL which points directly to the storage source. This is only functional with Amazon® S3 and/or CloudFront integrations. If you create a URL that points directly to the storage source <em>( i.e. points directly to Amazon® S3 or CloudFront )</em>, s2Member will NOT be able to further authenticate the current User/Member; and, s2Member will NOT be able to count the File Download against the current User\'s account record, because the URL being generated does not pass back through s2Member at all, it points directly to the storage source. For this reason, if you set <code>url_to_storage_source="true"</code>, you should also set <code>check_user="true"</code> and <code>count_against_user="true"</code>, telling s2Member to authenticate the current User, and if authenticated, count this File Download URL against the current User\'s account record in real-time <em>( i.e. as the URL is being generated ) </em>, while it still has a chance to do so. This Shortcode Attribute is useful when you stream files over the RTMP protocol; where an <code>http://</code> URL is not feasible. It also helps in situations where a 3rd-party software application will not work as intended, with s2Member\'s internal redirection to Amazon® S3/CloudFront files. Important, when <code>check_user="true"</code> and/or <code>count_against_user="true"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>' . "\n";
569
- echo '<li><code>count_against_user="no"</code> Defaults to <code>no</code>. If <code>count_against_user="1|on|yes|true"</code>, it will automatically force <code>check_user="true"</code> as well. In other words, s2Member will authenticate the current User, and if authenticated, count this File Download URL against the current User\'s account record in real-time <em>( i.e. as the URL is being generated ) </em>. This is off by default. By default, s2Member will simply generate a File Download URL, and upon a User/Member clicking the URL, s2Member will authenticate the User/Member at that time, count the File Download against their account record, and serve the File Download. In other words, under normal circumstances, there is no reason to set <code>check_user="true"</code> and/or <code>count_against_user="true"</code> when generating the URL itself. However, this is a useful Shortcode Attribute when <code>url_to_storage_source="true"</code>. Please note, when <code>check_user="true"</code> and/or <code>count_against_user="true"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>' . "\n";
570
- echo '<li><code>check_user="no"</code> Defaults to <code>no</code>. If <code>check_user="1|on|yes|true"</code>, s2Member will authenticate the current User before allowing the File Download URL to be generated. This is off by default. By default, s2Member will simply generate a File Download URL, and upon a User/Member clicking the URL, s2Member will authenticate the User/Member at that time, and serve the File Download to the User/Member. In other words, under normal circumstances, there is no reason to set <code>check_user="true"</code> and/or <code>count_against_user="true"</code> when generating the URL itself. However, this IS a useful Shortcode Attribute when <code>url_to_storage_source="true"</code>. Please note, when <code>check_user="true"</code> and/or <code>count_against_user="true"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>' . "\n";
571
- echo '<li><code>get_streamer_json="no"</code> Defaults to <code>no</code>. If <code>get_streamer_json="1|on|yes|true"</code>, the Shortcode will return a JSON object for JavaScript notation, making it possible to integrate the <code>[s2File /]</code> Shortcode into JavaScript routines that configure streaming media players. For further details, please review the section above: <code>JW Player® &amp; RTMP Protocol Examples</code>. Note, if you set <code>get_streamer_json="true"</code>, s2Member will automatically force <code>url_to_storage_source="true"</code> and <code>stream="true"</code>. For that reason, you should carefully review the details and warning above regarding <code>url_to_storage_source</code>. If you set <code>get_streamer_json="true"</code>, you should also set <code>check_user="true"</code> and <code>count_against_user="true"</code>.</li>' . "\n";
572
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2file_lis", get_defined_vars ());
573
- echo '</ul>' . "\n";
574
- echo '</td>' . "\n";
575
- /**/
576
- echo '</tr>' . "\n";
577
- echo '</tbody>' . "\n";
578
- echo '</table>' . "\n";
579
- /**/
580
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
581
- /**/
582
- echo '<h4 style="margin:0;"><code>[s2Key /]</code> Shortcode Attributes:</h4>' . "\n";
583
- echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_file_download_key()" target="_blank" rel="external">s2member_file_download_key()</a> for PHP integration.</p>' . "\n";
584
- echo '<table class="form-table" style="margin-top:0;">' . "\n";
585
- echo '<tbody>' . "\n";
586
- echo '<tr style="padding-top:0;">' . "\n";
587
- /**/
588
- echo '<td style="padding-top:0;">' . "\n";
589
- echo '<ul>' . "\n";
590
- echo '<li><code>file_download="file.zip"</code> Location of the file, relative to the <code>/' . esc_html (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/</code> directory; or, relative to the root of your Amazon® S3 Bucket, when applicable.</li>' . "\n";
591
- echo '<li><code>directive=""</code> Defaults to <code>[empty]</code>. If <code>directive="ip-forever|universal"</code>, s2Member will return a special File Download Key. If you set <code>directive="ip-forever"</code>, the File Download Key that s2Member generates will last forever, for a specific IP Address; otherwise, by default, all File Download Keys expire after 24 hours automatically. If you set <code>directive="universal"</code>, s2Member will generate a File Download Key that is good for anyone/everyone forever, with NO restrictions on who/where/when a file is accessed <em>( e.g. be careful with this one )</em>.</li>' . "\n";
592
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2key_lis", get_defined_vars ());
593
- echo '</ul>' . "\n";
594
- echo '</td>' . "\n";
595
- /**/
596
- echo '</tr>' . "\n";
597
- echo '</tbody>' . "\n";
598
- echo '</table>' . "\n";
599
- echo '</div>' . "\n";
600
- /**/
601
- echo '</div>' . "\n";
602
- /**/
603
- do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_shortcode_attrs", get_defined_vars ());
604
  }
605
  /**/
606
- do_action ("ws_plugin__s2member_during_down_ops_page_after_left_sections", get_defined_vars ());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
607
  /**/
608
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
609
  /**/
610
- echo '<p class="submit"><input type="submit" class="button-primary" value="Save All Changes" /></p>' . "\n";
611
  /**/
612
- echo '</form>' . "\n";
613
  /**/
614
- echo '</td>' . "\n";
615
  /**/
616
- echo '<td class="ws-menu-page-table-r">' . "\n";
617
- c_ws_plugin__s2member_menu_pages_rs::display ();
618
- echo '</td>' . "\n";
619
  /**/
620
- echo '</tr>' . "\n";
621
- echo '</tbody>' . "\n";
622
- echo '</table>' . "\n";
623
  /**/
624
- echo '</div>' . "\n";
625
  }
626
  }
627
  }
628
  /**/
629
- new c_ws_plugin__s2member_menu_page_down_ops ();
630
  ?>
14
  * @package s2Member\Menu_Pages
15
  * @since 3.0
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
21
  {
22
  /**
23
  * Menu page for the s2Member plugin ( File Download Options page ).
27
  */
28
  class c_ws_plugin__s2member_menu_page_down_ops
29
  {
30
+ public function __construct()
31
  {
32
+ echo '<div class="wrap ws-menu-page">'."\n";
33
  /**/
34
+ echo '<div id="icon-plugins" class="icon32"><br /></div>'."\n";
35
+ echo '<h2>s2Member® File Download Options</h2>'."\n";
36
  /**/
37
+ echo '<table class="ws-menu-page-table">'."\n";
38
+ echo '<tbody class="ws-menu-page-table-tbody">'."\n";
39
+ echo '<tr class="ws-menu-page-table-tr">'."\n";
40
+ echo '<td class="ws-menu-page-table-l">'."\n";
41
  /**/
42
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">'."\n";
43
+ 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";
44
+ echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_distros_auto_config_status" id="ws-plugin--s2member-amazon-cf-files-distros-auto-config-status" value="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"]).'" />'."\n";
45
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />'."\n";
46
  /**/
47
+ do_action("ws_plugin__s2member_during_down_ops_page_before_left_sections", get_defined_vars());
48
  /**/
49
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_restrictions", true, get_defined_vars()))
50
  {
51
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_restrictions", get_defined_vars());
52
  /**/
53
+ echo '<div class="ws-menu-page-group" title="Basic Download Restrictions">'."\n";
54
  /**/
55
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-restrictions-section">'."\n";
56
+ echo '<h3>File Download Restrictions ( required, if providing access to protected files )</h3>'."\n";
57
+ echo '<p>If your Membership offering allows access to restricted files, you\'ll want to configure these options.</p>'."\n";
58
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_restrictions", get_defined_vars());
59
  /**/
60
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
61
  /**/
62
+ echo '<p><strong>Upload restricted files to this security-enabled directory:</strong><br /><code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'</code></p>'."\n";
63
+ echo '<p>- Now, you can link to any protected file, using this special format:<br />&nbsp;&nbsp;<code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download</strong> = file, relative to the /'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/ directory. In other words, just the file name.</em></small></p>'."\n";
64
+ echo '<p>- Or, use: <code>[s2File download="example-file.zip" /]</code> <em>( easier Shortcode if you prefer )</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL for you, easier.</em></small></p>'."\n";
65
  /**/
66
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
67
  /**/
68
+ echo '<p>s2Member will allow access to these protected files, based on the configuration you specify below. Repeated downloads of the same exact file are NOT tabulated against the totals below. Once a file has been downloaded, future downloads of the same exact file, by the same exact Member will not be counted against them. In other words, if a Member downloads the same file three times, the system only counts that as one unique download. In addition, multiple variations of popular media formats are only counted once. This is because many site owners provide multiple download options to their Users/Members, for compatibility purposes. Files that have the same exact name, with one of these extensions, will only be counted ONE time: <code>'.esc_html(implode(",", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"])).'</code>.</p>'."\n";
69
+ 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> or <code>s2member-files</code>. Whenever a logged-in Member clicks a link that contains <code>s2member_file_download</code> or <code>s2member-files</code>, the system will politely ask the user to confirm the download using a very intuitive JavaScript confirmation prompt, which contains specific details about your configured download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not. If you want to suppress this JavaScript confirmation prompt, you can add this to the end of your links: <code>&amp;s2member_skip_confirmation</code>. Shortcode alternative: <code>[s2File skip_confirmation="yes" /]</code>.</p>'."\n";
70
+ echo '<p><em>* The above only applies to Users who are logged in as Members. For all other visitors in the general public, the <code>?s2member_file_download</code> links will redirect them your Membership Options Page, so that new visitors can signup, in order to gain access, by becoming a Member. You may also want to have a look down below at s2Member\'s "Advanced Download Restrictions", which provides a greater degree of flexibility.</em></p>'."\n";
71
  /**/
72
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
73
  /**/
74
+ echo '<table class="form-table" style="margin-top:0;">'."\n";
75
+ echo '<tbody>'."\n";
76
  /**/
77
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
78
  {
79
+ echo '<tr>'."\n";
80
  /**/
81
+ echo '<th style="padding-top:0;">'."\n";
82
+ echo '<label for="ws-plugin--s2member-level'.$n.'-file-downloads-allowed">'."\n";
83
+ echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'File Downloads ( Highest Level #'.$n.' ):'."\n" : 'File Downloads ( Level #'.$n.' Or Higher ):'."\n";
84
+ echo '</label>'."\n";
85
+ echo '</th>'."\n";
86
  /**/
87
+ echo '</tr>'."\n";
88
+ echo '<tr>'."\n";
89
  /**/
90
+ echo '<td>'."\n";
91
+ echo '<input type="text" maxlength="9" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_file_downloads_allowed" id="ws-plugin--s2member-level'.$n.'-file-downloads-allowed" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed"]).'" style="width:200px;" /> every <input type="text" maxlength="3" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_file_downloads_allowed_days" id="ws-plugin--s2member-level'.$n.'-file-downloads-allowed-days" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_file_downloads_allowed_days"]).'" style="width:200px;" onkeyup="if(this.value > 365){ alert(\'( 365 days is the maximum ).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> day(s).<br />'."\n";
92
+ echo 'Only this many unique downloads will be permitted every X day(s), at '.(($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'highest Level #'.$n : 'Level #'.$n.' or higher').'.<br />'."\n";
93
+ echo '<em>* To allow UNLIMITED downloads, use: <code>999999999</code> ( i.e. <code>999999999</code> = unlimited ).</em>'."\n";
94
+ echo '</td>'."\n";
95
  /**/
96
+ echo '</tr>'."\n";
97
  /**/
98
  echo ($n < $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? '<tr><td><div class="ws-menu-page-hr" style="margin:10px 0 10px 0;"></div></td></tr>' : '';
99
  }
100
  /**/
101
+ echo '</tbody>'."\n";
102
+ echo '</table>'."\n";
103
+ echo '</div>'."\n";
104
  /**/
105
+ echo '</div>'."\n";
106
  /**/
107
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_restrictions", get_defined_vars());
108
  }
109
  /**/
110
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_limit_exceeded_page", true, get_defined_vars()))
111
  {
112
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_limit_exceeded_page", get_defined_vars());
113
  /**/
114
+ echo '<div class="ws-menu-page-group" title="Download Limit Exceeded Page">'."\n";
115
  /**/
116
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-limit-exceeded-page-section">'."\n";
117
+ echo '<h3>Download Limit Exceeded Page ( required, if providing access to protected files )</h3>'."\n";
118
+ echo '<p>This Page will be shown when/if a Member reaches their download limit, based on your configuration of <strong>Basic Download Restrictions</strong> above. This Page should be created by you, in WordPress®. This Page should provide an informative message to the Member, describing your file access restrictions. Just tell them a little bit about your policy on file downloads, and why they might have reached this Page.</p>'."\n";
119
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_limit_exceeded_page", get_defined_vars());
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-file-download-limit-exceeded-page">'."\n";
127
+ echo 'Download Limit Exceeded Page:'."\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 '<select name="ws_plugin__s2member_file_download_limit_exceeded_page" id="ws-plugin--s2member-file-download-limit-exceeded-page">'."\n";
136
+ echo '<option value="">&mdash; Select &mdash;</option>'."\n";
137
+ foreach(($ws_plugin__s2member_temp_a = array_merge((array)get_pages())) as $ws_plugin__s2member_temp_o)
138
+ 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";
139
+ echo '</select><br />'."\n";
140
+ echo 'We recommend the following title: <code>Download Limit Exceeded</code>.'."\n";
141
+ echo '</td>'."\n";
142
  /**/
143
+ echo '</tr>'."\n";
144
+ echo '</tbody>'."\n";
145
+ echo '</table>'."\n";
146
+ echo '</div>'."\n";
147
  /**/
148
+ echo '</div>'."\n";
149
  /**/
150
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_limit_exceeded_page", get_defined_vars());
151
  }
152
  /**/
153
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_advanced_restrictions", true, get_defined_vars()))
154
  {
155
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_advanced_restrictions", get_defined_vars());
156
  /**/
157
+ echo '<div class="ws-menu-page-group" title="Advanced Download Restrictions">'."\n";
158
  /**/
159
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-restrictions-section">'."\n";
160
+ echo '<h3>Advanced Download Restrictions ( optional, for greater flexibility )</h3>'."\n";
161
+ echo '<p>By default, s2Member uses your Basic Download Restrictions, as configured above. However, you can force s2Member to allow File Downloads, using an extra query string parameter: <code>&amp;s2member_file_download_key=[Key]</code>. A File Download `Key` is passed through this parameter; it tells s2Member to allow the download of this particular file, regardless of Membership Level; and WITHOUT checking any Basic Restrictions, that you may or may not have configured above. The creation of a File Download `Key`, requires a small PHP code snippet. In order to use PHP scripting inside your Posts/Pages, you\'ll need to install this handy plugin ( <a href="http://wordpress.org/extend/plugins/php-execution-plugin/" target="_blank" rel="external">PHP Execution</a> ). There is also a Shortcode equivalent, which does NOT require PHP at all, as seen below.</p>'."\n";
162
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_advanced_restrictions", get_defined_vars());
163
  /**/
164
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
165
  /**/
166
+ echo '<p>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'<code>&amp;s2member_file_download_key=&lt;?php echo s2member_file_download_key("example-file.zip"); ?&gt;</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download_key</strong> = &lt;?php echo s2member_file_download_key("file, relative to the /'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/ directory"); ?&gt;</em></small></p>'."\n";
167
  /**/
168
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
169
  /**/
170
+ echo '<p>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'<code>&amp;s2member_file_download_key=[s2Key file_download="example-file.zip" /]</code><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2Key file_download="example-file.zip" /]</code></em></small></p>'."\n";
171
  /**/
172
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
173
  /**/
174
+ echo '<p><code>[s2File download="example-file.zip" download_key="true" /]</code> <em>( Key is auto-generated in this case )</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL, no need to generate a Key yourself.</em></small></p>'."\n";
175
  /**/
176
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
177
  /**/
178
+ echo '<p>The function <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_file_download_key%28%29" target="_blank" rel="external">s2member_file_download_key()</a>, is part of the s2Member API. It produces a time-sensitive File Download Key that is unique to each and every visitor. Each Key it produces <em>( at the time it is produced )</em>, will be valid for the current day, and only for a specific IP address and User-Agent string; as detected by s2Member. This makes it possible for you to create links on your site, which provide access to protected file downloads; and without having to worry about one visitor sharing their link with another. So let\'s take a quick look at what <code>s2member_file_download_key()</code> actually produces.</p>'."\n";
179
+ echo '<p><code>s2member_file_download_key("example-file.zip")</code> = a site-specific hash of: <code>date("Y-m-d").$_SERVER["REMOTE_ADDR"].$_SERVER["HTTP_USER_AGENT"].$file</code></p>'."\n";
180
+ echo '<p>When <code>s2member_file_download_key = <em>a valid Key</em></code>, it works independently from Member Level Access. That is, a visitor does NOT have to be logged in to receive access; they just need a valid Key. Using this advanced technique, you could extend s2Member\'s file protection routines, or even combine them with Specific Post/Page Access, and more. The possibilities are limitless really.</p>'."\n";
181
  /**/
182
+ echo '</div>'."\n";
183
  /**/
184
+ echo '</div>'."\n";
185
  /**/
186
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_advanced_restrictions", get_defined_vars());
187
  }
188
  /**/
189
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_inline_extensions", true, get_defined_vars()))
190
  {
191
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_inline_extensions", get_defined_vars());
192
  /**/
193
+ echo '<div class="ws-menu-page-group" title="Inline File Extensions">'."\n";
194
  /**/
195
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-inline-extensions-section">'."\n";
196
+ echo '<h3>Inline File Extensions ( optional, for content-disposition )</h3>'."\n";
197
+ echo '<p>There are two ways to serve files. Inline, or as an Attachment. By default, s2Member will serve all of your protected files, as downloadable attachments. Meaning, visitors will be given a file download prompt. Otherwise known as <code>Content-Disposition: attachment</code>. In some cases though, you may wish to serve files inline. For example, PDF files and images should usually be served inline. When you serve a file inline, it is displayed in your browser immediately, rather than your browser prompting you to download the file as an attachment.</p>'."\n";
198
+ echo '<p>Using the field below, you can list all of the extensions that you want s2Member to serve inline ( ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png,mp3,mp4,flv,ogg,webm</code> ). Please understand, some files just cannot be displayed inline. For instance, there is no way to display an <code>exe</code> file inline. So only specify extensions that can, and should be displayed inline by a web browser. Alternatively, if you would rather handle this on a case-by-case basis, you can simply add the following to the end of your download links: <code>&amp;s2member_file_inline=yes</code>. Shortcode alternative: <code>[s2File download="example-file.zip" inline="yes" /]</code>.</p>'."\n";
199
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_inline_extensions", get_defined_vars());
200
  /**/
201
+ echo '<table class="form-table">'."\n";
202
+ echo '<tbody>'."\n";
203
+ echo '<tr>'."\n";
204
  /**/
205
+ echo '<th>'."\n";
206
+ echo '<label for="ws-plugin--s2member-file-download-inline-extensions">'."\n";
207
+ echo 'Default Inline File Extensions ( comma-delimited ):'."\n";
208
+ echo '</label>'."\n";
209
+ echo '</th>'."\n";
210
  /**/
211
+ echo '</tr>'."\n";
212
+ echo '<tr>'."\n";
213
  /**/
214
+ echo '<td>'."\n";
215
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_file_download_inline_extensions" id="ws-plugin--s2member-file-download-inline-extensions" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]).'" /><br />'."\n";
216
+ echo 'Inline extensions, comma-delimited. Ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png,mp3,mp4,flv,ogg,webm</code>'."\n";
217
+ echo '</td>'."\n";
218
  /**/
219
+ echo '</tr>'."\n";
220
+ echo '</tbody>'."\n";
221
+ echo '</table>'."\n";
222
+ echo '</div>'."\n";
223
  /**/
224
+ echo '</div>'."\n";
225
  /**/
226
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_inline_extensions", get_defined_vars());
227
  }
228
  /**/
229
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_remote_authorization", true, get_defined_vars()))
230
  {
231
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_remote_authorization", get_defined_vars());
232
  /**/
233
+ echo '<div class="ws-menu-page-group" title="Remote Auth / Podcasting">'."\n";
234
  /**/
235
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-remote-authorization-section">'."\n";
236
+ echo '<h3>Remote Header Authorization ( optional )</h3>'."\n";
237
+ echo '<p>This can be enabled on a case-by-case basis. Just add this to the end of your download links: <code>&amp;s2member_file_remote=yes</code>. Shortcode alternative: <code>[s2File download="example-file.zip" remote="yes" /]</code>.</p>'."\n";
238
+ echo '<p>Remote Header Authorization allows access to file downloads through an entirely different approach. Instead of asking the Member to log into your site through a browser, a Member will be prompted automatically, to log in through HTTP Header Authorization prompts; which is the same technique used in more traditional security systems via .htaccess files. In other words, Remote Header Authorization makes it possible for your Members to access files through remote applications that may NOT use a browser. This is often the case when a Member needs to access protected files through a software client like iTunes®; typical with podcasts. See <a href="http://www.primothemes.com/forums/viewtopic.php?f=4&t=837&p=28558#p28558" target="_blank" rel="external">tutorial here</a> for details about how to setup a Podcast for iTunes®.</p>'."\n";
239
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_remote_authorization", get_defined_vars());
240
+ echo '</div>'."\n";
241
  /**/
242
+ echo '</div>'."\n";
243
  /**/
244
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_remote_authorization", get_defined_vars());
245
  }
246
  /**/
247
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_s3", true, get_defined_vars()))
248
  {
249
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_s3", get_defined_vars());
250
  /**/
251
+ echo '<div class="ws-menu-page-group" title="Amazon® S3/CDN Storage Option"'.((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' default-state="open"' : '').'>'."\n";
252
  /**/
253
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-s3-section">'."\n";
254
+ echo '<h3>Amazon® S3/CDN Storage &amp; Delivery ( optional )</h3>'."\n";
255
+ echo '<a href="http://aws.amazon.com/s3/" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/amazon-logo.png" class="ws-menu-page-right" style="width:250px; height:100px; border:0;" alt="." /></a>'."\n";
256
+ echo '<p>Please note, all of this is optional. s2Member can be configured here to ONLY use Amazon® S3 <em>( i.e. without Amazon® CloudFront )</em>. Or, s2Member can be configured to use BOTH Amazon® S3 and Amazon® CloudFront together. If you want to use Amazon® S3 Storage, but you don\'t care about Amazon® CloudFront, feel free to leave the entire Amazon® CloudFront section empty. The configuration options in the Amazon® CloudFront section are ONLY required if you are planning to use both Amazon® S3 and Amazon® CloudFront together.</p>'."\n";
257
+ echo '<p>Amazon® Simple Storage Service ( <a href="http://aws.amazon.com/s3/" target="_blank" rel="external">Amazon® S3</a> ). Amazon® S3 is storage for the Internet. It is designed to make web-scale computing easier for developers. Amazon® S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives developers access to the same highly scalable, reliable, secure, fast, inexpensive infrastructure that Amazon® uses to run its own global network of web sites. s2Member has been integrated with Amazon® S3, so that <em>( if you wish )</em>, instead of using the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory, you can store all of your protected files inside an Amazon® S3 Bucket.</p>'."\n";
258
+ echo '<p>If you configure the options below, s2Member will assume all protected files are inside your Amazon® S3 Bucket; and the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory is no longer used at all. That being said, all other aspects of s2Member\'s File Download protection remain the same. The only thing that changes, is the location of your protected files. In other words, Basic Download Restrictions, Download Keys, Inline Extensions, Custom Capability and/or Membership Level Files will all continue to work just as before. The only difference is that s2Member will use your Amazon® S3 Bucket as a CDN <em>( i.e. Content Delivery Network )</em> instead of the local <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory.</p>'."\n";
259
+ echo '<p>s2Member assumes that you\'re creating a new Amazon® S3 Bucket, specifically for this installation; and that your Bucket is NOT available publicly. In other words, if you type this URL into your browser <em>( i.e. <code>http://your-bucket-name.s3.amazonaws.com/</code> )</em>, you should get an error that says: <code>Access Denied</code>. That\'s good, that\'s exactly what you want. You can create your Amazon® S3 Bucket using the <a href="https://console.aws.amazon.com/s3/home" target="_blank" rel="external">Amazon® interface</a>. Or, some people prefer to use this popular Firefox® extension ( <a href="http://www.s3fox.net/" target="_blank" rel="external">S3 Fox Organizer</a> ).</p>'."\n";
260
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_amazon_s3", get_defined_vars());
261
  /**/
262
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
263
  /**/
264
+ echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Query String Authentication", provided by the Amazon® S3 API. Documented for developers <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate S3 authenticated redirect URLs ( internally ); which allow Customers temporary access to specific files inside your S3 Bucket. s2Member\'s Query String Authentication through Amazon® S3 gives a Customer 30 seconds to connect to the file inside your S3 Bucket ( i.e. the automatic redirection URL ). This connection period of 30 seconds is largely irrelevant when used in combination with s2Member. It just needs to be a low value, to further prevent any possibility of S3 authenticated link sharing. If you need to change this connection timeout of <code>30 seconds</code> for some reason ( not likely ), you can use this WordPress® Filter: <code>ws_plugin__s2member_amazon_s3_file_expires_time</code>. If you need help, please check the s2Member Forums.</em></p>'."\n";
265
+ echo '<p><em><strong>Linking To Protected Files:</strong> Nothing changes. s2Member\'s integration with Amazon® S3 serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® S3 URL, which allows them access to a particular file via Amazon® S3. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>.</em></p>'."\n";
266
+ echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> The query string parameter <code>&amp;s2member_file_inline=yes</code> DOES work for files served directly through Amazon® S3. s2Member DOES have control over the <code>Content-Type</code> and <code>Content-Disposition</code> headers for files being served through Amazon® S3. However, Amazon® CloudFront servers do NOT automatically determine the MIME type for the objects they serve. If you integrate both Amazon® S3 and CloudFront, s2Member will NOT have control over headers. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. Again, with the Amazon® S3/CloudFront combination, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>'."\n";
267
  /**/
268
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
269
  /**/
270
+ echo '<table class="form-table" style="margin-top:0;">'."\n";
271
+ echo '<tbody>'."\n";
272
+ echo '<tr>'."\n";
273
  /**/
274
+ echo '<th style="padding-top:0;">'."\n";
275
+ echo '<label for="ws-plugin--s2member-amazon-s3-files-bucket">'."\n";
276
+ echo 'Amazon® S3 File Bucket ( where protected files are ):'."\n";
277
+ echo '</label>'."\n";
278
+ echo '</th>'."\n";
279
  /**/
280
+ echo '</tr>'."\n";
281
+ echo '<tr>'."\n";
282
  /**/
283
+ echo '<td>'."\n";
284
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_bucket" id="ws-plugin--s2member-amazon-s3-files-bucket" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_bucket"]).'" /><br />'."\n";
285
+ echo 'Your Amazon® S3 Bucket will be used, instead of the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory.'."\n";
286
+ echo '</td>'."\n";
287
  /**/
288
+ echo '</tr>'."\n";
289
+ echo '<tr>'."\n";
290
  /**/
291
+ echo '<th>'."\n";
292
+ echo '<label for="ws-plugin--s2member-amazon-s3-files-access-key">'."\n";
293
+ echo 'Amazon® Access Key ( Access Key ID ):'."\n";
294
+ echo '</label>'."\n";
295
+ echo '</th>'."\n";
296
  /**/
297
+ echo '</tr>'."\n";
298
+ echo '<tr>'."\n";
299
  /**/
300
+ echo '<td>'."\n";
301
+ echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_access_key" id="ws-plugin--s2member-amazon-s3-files-access-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_access_key"]).'" /><br />'."\n";
302
+ echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Access Credentials</code>.'."\n";
303
+ echo '</td>'."\n";
304
  /**/
305
+ echo '</tr>'."\n";
306
+ echo '<tr>'."\n";
307
  /**/
308
+ echo '<th>'."\n";
309
+ echo '<label for="ws-plugin--s2member-amazon-s3-files-secret-key">'."\n";
310
+ echo 'Amazon® Secret Key ( Secret Access Key ):'."\n";
311
+ echo '</label>'."\n";
312
+ echo '</th>'."\n";
313
  /**/
314
+ echo '</tr>'."\n";
315
+ echo '<tr>'."\n";
316
  /**/
317
+ echo '<td>'."\n";
318
+ echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_amazon_s3_files_secret_key" id="ws-plugin--s2member-amazon-s3-files-secret-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"]).'" /><br />'."\n";
319
+ echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Access Credentials</code>.'."\n";
320
+ echo '</td>'."\n";
321
  /**/
322
+ echo '</tr>'."\n";
323
+ echo '</tbody>'."\n";
324
+ echo '</table>'."\n";
325
+ echo '</div>'."\n";
326
  /**/
327
+ echo '</div>'."\n";
328
  /**/
329
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_s3", get_defined_vars());
330
  }
331
  /**/
332
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_amazon_cf", true, get_defined_vars()))
333
  {
334
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_amazon_cf", get_defined_vars());
335
+ /**/
336
+ echo '<div class="ws-menu-page-group" title="Amazon® S3/CloudFront CDN Storage Option"'.((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' default-state="open"' : '').'>'."\n";
337
+ /**/
338
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-amazon-cf-section">'."\n";
339
+ echo '<h3>Amazon® S3/CloudFront CDN Storage &amp; Delivery ( optional )</h3>'."\n";
340
+ echo '<a href="http://aws.amazon.com/cloudfront/" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/amazon-logo.png" class="ws-menu-page-right" style="width:250px; height:100px; border:0;" alt="." /></a>'."\n";
341
+ echo '<p>Please note, all of this is optional. s2Member can be configured to ONLY use Amazon® S3 <em>( i.e. without Amazon® CloudFront )</em>. Or, s2Member can be configured to use BOTH Amazon® S3 and Amazon® CloudFront together. If you don\'t want to use Amazon® CloudFront, please leave this entire section empty. The configuration options in this section are ONLY required if you are planning to use both Amazon® S3 and Amazon® CloudFront together.</p>'."\n";
342
+ echo '<p>Amazon® Simple Storage Service ( <a href="http://aws.amazon.com/s3/" target="_blank" rel="external">Amazon® S3</a> ) combined with <a href="http://aws.amazon.com/cloudfront/" target="_blank" rel="external">Amazon® CloudFront</a>. Amazon® CloudFront is a web service for content delivery. It integrates with other Amazon® Web Services <em>( i.e. Amazon® S3 Storage )</em> to give developers and businesses an easy way to distribute content to end users with low latency, and with high data transfer speeds. Amazon® CloudFront delivers your static and streaming content using a global network of edge locations. Requests for your Amazon® S3 Bucket Objects <em>( i.e. your protected files )</em> are automatically routed to the nearest edge location, so content is delivered with the best possible performance. s2Member has been integrated with both Amazon® S3 and with Amazon® CloudFront. So <em>( if you wish )</em>, instead of using the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory, you can store all of your protected files inside an Amazon® S3 Bucket and serve them via Amazon® CloudFront. But again, please understand, the configuration options in this section are ONLY required if you\'re going to use both Amazon® S3 &amp; CloudFront together.</p>'."\n";
343
+ echo '<p><strong>One of the great things about Amazon® CloudFront</strong>, is its ability to <strong>stream/seek media files</strong> in the truest sense of the word. For sites delivering protected <em>FLV/MP4/OGG/WEBM</em> and other streaming audio/video file types over the <em>RTMP</em> protocol, Amazon® CloudFront is our recommendation. Once you\'ve successfully configured s2Member to use both Amazon® S3 and Amazon® CloudFront together, please review the section below regarding <code>JW Player® &amp; RTMP Protocol Examples</code>. s2Member will automatically serve your protected files over the <em>RTMP</em> protocol using an Amazon® CloudFront Streaming Distribution.</p>'."\n";
344
+ echo '<p>If you configure the options below, s2Member will assume all protected files are inside your Amazon® S3 Bucket; and the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory is no longer used at all. That being said, all other aspects of s2Member\'s File Download protection remain the same. The only thing that changes, is the location of your protected files. In other words, Basic Download Restrictions, Download Keys, Custom Capability and/or Membership Level Files will all continue to work just as before. The only difference is that s2Member will use your Amazon® S3 Bucket, automatically connecting it to both of the Amazon® CloudFront Distributions, which s2Member auto-configures for you <em>( see below )</em>. In this way, s2Member uses Amazon® CloudFront as a CDN <em>( i.e. Content Delivery Network )</em> for your protected files.</p>'."\n";
345
+ echo '<p>s2Member assumes that you\'re creating a new Amazon® S3 Bucket, specifically for this installation; and that your Bucket is NOT available publicly. In other words, if you type this URL into your browser <em>( i.e. <code>http://your-bucket-name.s3.amazonaws.com/</code> )</em>, you should get an error that says: <code>Access Denied</code>. That\'s good, that\'s exactly what you want. You can create your Amazon® S3 Bucket using the <a href="https://console.aws.amazon.com/s3/home" target="_blank" rel="external">Amazon® interface</a>. Or, some people prefer to use this popular Firefox® extension ( <a href="http://www.s3fox.net/" target="_blank" rel="external">S3 Fox Organizer</a> ). You will also need to enable CloudFront inside your Web Services account at Amazon®. Don\'t worry about creating or configuring any CloudFront Distributions, s2Member will auto-create and auto-configure those for you, allowing you to serve protected files.</p>'."\n";
346
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_amazon_cf", get_defined_vars());
347
+ /**/
348
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
349
+ /**/
350
+ echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon® CloudFront (below), are designed to create &amp; configure various components on your Amazon® Web Services account, which are all requirements for you to <a href="http://docs.amazonwebservices.com/AmazonCloudFront/2010-11-01/DeveloperGuide/index.html?HowToPrivateContent.html" target="_blank" rel="external">serve protected files through the Amazon® S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon® S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy ( i.e. permissions ) on your Amazon® S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>'."\n";
351
+ echo '<p><em><strong>Linking To Protected Files:</strong> Streamed files are special, but nothing else changes. s2Member\'s integration with Amazon® S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® CloudFront URL, which allows them access to a particular file via Amazon® CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>. For streaming audio/video files, please review the section below: <code>JW Player® &amp; RTMP Protocol Examples</code>.</em></p>'."\n";
352
+ echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon® CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon® CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>'."\n";
353
+ echo (stripos(PHP_OS, "win") === 0 && c_ws_plugin__s2member_utils_conds::is_localhost()) ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon® CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront® URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows®</a> while you\'re developing. s2Member will automatically find it here: <code>C:\OpenSSL-Win[32/64]\bin\openssl.exe</code>.'.((file_exists("c:\openssl-win32\bin\openssl.exe") || file_exists("c:\openssl-win64\bin\openssl.exe")) ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] is NOT currently available )</strong>').'</em></p>'."\n" : '';
354
+ /**/
355
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"] === "configured")
356
+ echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon® CloudFront Distributions are: ( ALREADY configured! )</strong></em>'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) ? '<br /><em class="ws-menu-page-hilite">Downloads Distribution CNAME:</em> <em><code>'.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]).' &mdash;&raquo; '.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]).'</code></em>' : '').(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? '<br /><em class="ws-menu-page-hilite">Streaming Distribution CNAME:</em> <em><code>'.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]).' &mdash;&raquo; '.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]).'</code></em>' : '').'</p>'."\n";
357
+ /**/
358
+ else if(!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"])
359
+ echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon® CloudFront Distributions are: ( NOT yet auto-configured ).</strong></em></p>'."\n";
360
+ /**/
361
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
362
+ /**/
363
+ echo '<table class="form-table" style="margin-top:0;">'."\n";
364
+ echo '<tbody>'."\n";
365
+ echo '<tr>'."\n";
366
+ /**/
367
+ echo '<th style="padding-top:0;">'."\n";
368
+ echo '<label for="ws-plugin--s2member-amazon-cf-files-private-key-id">'."\n";
369
+ echo 'Amazon® CloudFront Key Pair ID ( your Key Pair ID ):'."\n";
370
+ echo '</label>'."\n";
371
+ echo '</th>'."\n";
372
+ /**/
373
+ echo '</tr>'."\n";
374
+ echo '<tr>'."\n";
375
+ /**/
376
+ echo '<td>'."\n";
377
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_private_key_id" id="ws-plugin--s2member-amazon-cf-files-private-key-id" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key_id"]).'" data-s-prev-config-value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key_id"]).'" /><br />'."\n";
378
+ echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Key Pairs</code>.'."\n";
379
+ echo '</td>'."\n";
380
+ /**/
381
+ echo '</tr>'."\n";
382
+ echo '<tr>'."\n";
383
+ /**/
384
+ echo '<th>'."\n";
385
+ echo '<label for="ws-plugin--s2member-amazon-cf-files-private-key-entry">'."\n";
386
+ echo 'Amazon® CloudFront Private Key ( contents of your <code>pk-[***].pem</code> file ):'."\n";
387
+ echo '</label>'."\n";
388
+ echo '</th>'."\n";
389
+ /**/
390
+ echo '</tr>'."\n";
391
+ echo '<tr>'."\n";
392
+ /**/
393
+ echo '<td>'."\n";
394
+ echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_private_key" id="ws-plugin--s2member-amazon-cf-files-private-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'" data-s-prev-config-value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'" />'."\n";
395
+ echo '<textarea name="ws_plugin__s2member_amazon_cf_files_private_key_entry" id="ws-plugin--s2member-amazon-cf-files-private-key-entry" rows="3" wrap="off" spellcheck="false" style="font-family:Consolas, monospace;">'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'</textarea><br />'."\n";
396
+ echo 'See: <code>Amazon® Web Services Account -> Security Credentials -> Key Pairs</code>.<br />'."\n";
397
+ echo '<em>* Note, s2Member needs your <strong>Private Key file</strong>, NOT your Public Key file.</em>'."\n";
398
+ echo '</td>'."\n";
399
+ /**/
400
+ echo '</tr>'."\n";
401
+ echo '<tr>'."\n";
402
+ /**/
403
+ echo '<th>'."\n";
404
+ echo '<label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros">'."\n";
405
+ echo 'Auto-Configure your Amazon® S3/CloudFront combination?'."\n";
406
+ echo '</label>'."\n";
407
+ echo '</th>'."\n";
408
+ /**/
409
+ echo '</tr>'."\n";
410
+ echo '<tr>'."\n";
411
+ /**/
412
+ echo '<td>'."\n";
413
+ echo '<input type="checkbox" name="ws_plugin__s2member_amazon_cf_files_auto_configure_distros" id="ws-plugin--s2member-amazon-cf-files-auto-configure-distros" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-amazon-cf-files-auto-configure-distros")).'"'.((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros"><strong>Yes</strong>, automatically configure my Amazon® CloudFront Distributions &amp; Amazon® S3 ACLs for me.</label><br />'."\n";
414
+ echo '<em>s2Member will auto-configure and/or delete &amp; re-configure your Amazon® CloudFront Distributions for you.</em>'."\n";
415
+ echo '</td>'."\n";
416
+ /**/
417
+ echo '</tr>'."\n";
418
+ echo '<tr>'."\n";
419
+ /**/
420
+ echo '<td>'."\n";
421
+ echo '<input type="checkbox" name="ws_plugin__s2member_amazon_cf_files_auto_configure_distros_w_cnames" id="ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames")).'"'.((c_ws_plugin__s2member_menu_pages::$pre_display_errors["cf_files_auto_configure_distros"] && ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"] || $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"])) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames"><strong>Yes</strong>, I want s2Member to auto-configure using custom CNAMES that I\'ll setup.</label><br />'."\n";
422
+ echo '<em>* Optional, do NOT check this box unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
423
+ echo '</td>'."\n";
424
+ /**/
425
+ echo '</tr>'."\n";
426
+ echo '</tbody>'."\n";
427
+ echo '</table>'."\n";
428
+ /**/
429
+ echo '<div id="ws-plugin--s2member-amazon-cf-files-auto-configure-distro-cnames" style="display:none;">'."\n";
430
+ echo '<table class="form-table">'."\n";
431
+ echo '<tbody>'."\n";
432
+ echo '<tr>'."\n";
433
+ /**/
434
+ echo '<th>'."\n";
435
+ echo '<label for="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname">'."\n";
436
+ echo 'Amazon® CloudFront CNAME for File Downloads ( optional ):'."\n";
437
+ echo '</label>'."\n";
438
+ echo '</th>'."\n";
439
+ /**/
440
+ echo '</tr>'."\n";
441
+ echo '<tr>'."\n";
442
+ /**/
443
+ echo '<td>'."\n";
444
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]).'" /><br />'."\n";
445
+ echo 'Example: <code>s2-file-downloads.'.esc_html(c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_HOST)).'</code>.<br />'."\n";
446
+ echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
447
+ echo '</td>'."\n";
448
+ /**/
449
+ echo '</tr>'."\n";
450
+ echo '<tr>'."\n";
451
+ /**/
452
+ echo '<th>'."\n";
453
+ echo '<label for="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname">'."\n";
454
+ echo 'Amazon® CloudFront CNAME for Streaming Files ( optional ):'."\n";
455
+ echo '</label>'."\n";
456
+ echo '</th>'."\n";
457
+ /**/
458
+ echo '</tr>'."\n";
459
+ echo '<tr>'."\n";
460
+ /**/
461
+ echo '<td>'."\n";
462
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]).'" /><br />'."\n";
463
+ echo 'Example: <code>s2-streaming-files.'.esc_html(c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_HOST)).'</code>.<br />'."\n";
464
+ echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
465
+ echo '</td>'."\n";
466
+ /**/
467
+ echo '</tr>'."\n";
468
+ echo '</tbody>'."\n";
469
+ echo '</table>'."\n";
470
+ echo '</div>'."\n";
471
+ echo '</div>'."\n";
472
+ /**/
473
+ echo '</div>'."\n";
474
+ /**/
475
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_amazon_cf", get_defined_vars());
476
  }
477
  /**/
478
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_rtmp_streaming", true, get_defined_vars()))
479
  {
480
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rtmp_streaming", get_defined_vars());
481
  /**/
482
+ echo '<div class="ws-menu-page-group" title="JW Player® &amp; RTMP Protocol Examples">'."\n";
483
  /**/
484
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-rtmp-streaming-section">'."\n";
485
+ echo '<h3>JW Player® &amp; RTMP Protocol Examples</h3>'."\n";
486
+ echo '<a href="http://www.longtailvideo.com/players/" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/jwplayer-logo.png" class="ws-menu-page-right" style="width:179px; height:58px; border:0;" alt="." /></a>'."\n";
487
+ echo '<p>While it is possible to serve audio/video files protected by s2Member, without needing to integrate Amazon® S3 or CloudFront; we DO highly recommend that you integrate both Amazon® S3 and Amazon® CloudFront in order to maximize speed and compatibility across various viewing platforms. That being said, there are code samples below that will serve audio/video files both with and without Amazon® S3/CloudFront. You can also check the <a href="'.esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Forum URI")).'" target="_blank" rel="external">s2Member Support Forums</a> for tips/tricks if you like.</p>'."\n";
488
+ echo '<p><strong>One of the great things about Amazon® CloudFront</strong>, is its ability to <strong>stream/seek media files</strong> in the truest sense of the word. For sites delivering protected <em>FLV/MP4/OGG/WEBM</em> and other streaming audio/video file types over the <em>RTMP</em> protocol, Amazon® CloudFront is our recommendation. Once you\'ve successfully configured s2Member to use both Amazon® S3 and Amazon® CloudFront together, please review the code samples below. s2Member can automatically serve your protected files over the <em>RTMP</em> protocol using an Amazon® CloudFront Streaming Distribution.</p>'."\n";
489
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_rtmp_streaming", get_defined_vars());
490
  /**/
491
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
492
  /**/
493
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-standard-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( MP4 file, via Rewrite URLs. Amazon® S3/CloudFront NOT required )</a></p>'."\n";
494
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-standard-mp4" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This does NOT require s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <code>s2Member -> Download Options -> Advanced Mod Rewrite Linkage</code>.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-standard-mp4.x-php")).'</p>'."\n";
495
  /**/
496
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>'."\n";
497
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12455" target="_blank" rel="external">s2Member Codex -> API Functions</a>.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-streaming-mp4.x-php")).'</p>'."\n";
498
  /**/
499
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-sca\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s JSON/Shortcode alternative )</a></p>'."\n";
500
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-sca" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12455" target="_blank" rel="external">s2Member Codex -> API Functions</a>.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-streaming-mp4-sca.x-php")).'</p>'."\n";
501
  /**/
502
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-webm\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, advanced w/ multiple HTML5 fallbacks )</a></p>'."\n";
503
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-streaming-mp4-webm" style="display:none;">Download <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">JW Player® here</a>, and upload <code>/jwplayer/</code> to your website\'s root directory.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br />Also see: <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12455" target="_blank" rel="external">s2Member Codex -> API Functions</a>.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-streaming-mp4-webm.x-php")).'</p>'."\n";
504
  /**/
505
+ echo '</div>'."\n";
506
  /**/
507
+ echo '</div>'."\n";
508
  /**/
509
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_rtmp_streaming", get_defined_vars());
510
  }
511
  /**/
512
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_rewrite_linkage", true, get_defined_vars()))
513
  {
514
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rewrite_linkage", get_defined_vars());
515
+ /**/
516
+ echo '<div class="ws-menu-page-group" title="Advanced Mod-Rewrite Linkage">'."\n";
517
+ /**/
518
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-rewrite-linkage-section">'."\n";
519
+ echo '<h3>Advanced Mod-Rewrite Linkage</h3>'."\n";
520
+ echo '<p>s2Member automatically creates <code>mod_rewrite</code> rules inside your <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory, which provide additional flexibility in the way protected files can be served to your Customers. With s2Member\'s <code>mod_rewrite</code> rules, it is now possible to link directly to a protected file, avoiding the use of query string variables <em>( it\'s completely optional though, i.e. NOT required )</em>.</p>'."\n";
521
+ echo '<p>This new flexibility may come in handy for site owners serving files through media playback devices that have issues with query string variables. For instance, it is now possible to link to an s2Member-protected file directly, like this: <code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/example-file.zip</code> instead of <code>... /?s2member_file_download=example-file.zip</code>. Either way works, but the direct link might be easier for some.</p>'."\n";
522
+ echo '<p>It is also possible to pass query string parameters through a direct link:<br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/example-file.zip?s2member_file_inline=yes&amp;s2member_file_download_key=[key]</code>.</p>'."\n";
523
+ echo '<p>That being said, s2Member\'s <code>mod_rewrite</code> rules allow for more advanced control over s2Member-specific parameters.</p>'."\n";
524
+ echo '<p>For example, you could just do this for inline files:<br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-inline</strong>/example-file.zip</code></p>'."\n";
525
+ echo '<p>Or, if you really want to get advanced, you could do something like this:<br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-inline-[yes|no]/s2member-file-download-key-[key]</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-inline-yes/s2member-file-download-key-xS54df5ER4d5x</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-inline-yes/s2member-skip-confirmation</strong>/example-file.zip</code></p>'."\n";
526
+ echo '<p>Or even this, if you\'re using Remote Header Authorization:<br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-remote</strong>/example-file.zip</code></p>'."\n";
527
+ echo '<p>Specifying storage location option dynamically:<br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-storage-[local|s3|cf]</strong>/example-file.zip</code><br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-storage-cf</strong>/example-cloudfront-file.zip</code><br /><code>... /wp-content/plugins/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'<strong class="ws-menu-page-hilite">/s2member-file-storage-s3/s2member-file-inline</strong>/example-s3-file.html</code></p>'."\n";
528
+ echo '<p><em>* Note, the order of your s2Member-specific parameters with Advanced Mod-Rewrite Linkage is irrelevant. Feel free to add/remove, or even change the order. Everything discussed here is also Multisite compatible. Everything discussed here is also compatible when/if combined with Amazon® S3/CDN Storage. However, NONE of this will work on servers that do NOT support <code>mod_rewrite</code>. Almost all web servers do though.</em></p>'."\n";
529
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_rewrite_linkage", get_defined_vars());
530
+ echo '</div>'."\n";
531
+ /**/
532
+ echo '</div>'."\n";
533
+ /**/
534
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_rewrite_linkage", get_defined_vars());
535
  }
536
  /**/
537
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_shortcode_attrs", true, get_defined_vars()))
538
  {
539
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_shortcode_attrs", get_defined_vars());
540
+ /**/
541
+ echo '<div class="ws-menu-page-group" title="Shortcode Attributes &amp; API Functions ( Explained )">'."\n";
542
+ /**/
543
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-shortcode-attrs-section">'."\n";
544
+ echo '<h3>Shortcode Attributes &amp; API Functions ( Explained In Full Detail )</h3>'."\n";
545
+ echo '<p>s2Member makes <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcodes</a> available to you, which allow you to generate File Download URLs and/or File Download Keys. Like most Shortcodes for WordPress®, s2Member reads Attributes in your Shortcode. Many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>'."\n";
546
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs", get_defined_vars());
547
+ /**/
548
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
549
+ /**/
550
+ echo '<h4 style="margin:0;"><code>[s2File /]</code> Shortcode Attributes:</h4>'."\n";
551
+ echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>'."\n";
552
+ echo '<table class="form-table" style="margin-top:0;">'."\n";
553
+ echo '<tbody>'."\n";
554
+ echo '<tr style="padding-top:0;">'."\n";
555
+ /**/
556
+ echo '<td style="padding-top:0;">'."\n";
557
+ echo '<ul>'."\n";
558
+ echo '<li><code>download="file.zip"</code> Location of the file, relative to the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory; or, relative to the root of your Amazon® S3 Bucket, when applicable.</li>'."\n";
559
+ echo '<li><code>download_key="no"</code> Defaults to <code>no</code>. If <code>download_key="1|on|yes|true|ip-forever|universal"</code>, s2Member will return a URL with an s2Member-generated File Download Key. You don\'t need to generate the File Download Key yourself, s2Member does it for you. If you set <code>download_key="ip-forever"</code>, the File Download Key that s2Member generates will last forever, for a specific IP Address; otherwise, by default, all File Download Keys expire after 24 hours automatically. If you set <code>download_key="universal"</code>, s2Member will generate a File Download Key that is good for anyone/everyone forever, with NO restrictions on who/where/when a file is accessed <em>( e.g. be careful with this one )</em>.</li>'."\n";
560
+ echo '<li><code>stream="no"</code> Defaults to <code>no</code>. If <code>stream="1|on|yes|true"</code>, s2Member will return a URL containing a parameter/directive, which forces the File Download to take place over the RTMP protocol. This ONLY works when/if s2Member is configured to run with both Amazon® S3/CloudFront. Please note however, it\'s better to use the example code provided in the section above, regarding: <code>JW Player® and the RTMP Protocol</code>. Also note, if <code>get_streamer_json="1|on|yes|true"</code>, s2Member will automatically force <code>stream="true"</code> for you.</li>'."\n";
561
+ echo '<li><code>inline=""</code> Defaults to <code>[empty]</code>. If <code>inline="1|on|yes|true"</code>, s2Member will serve the file inline, instead of as an actual File Download. If empty, s2Member will look at your <code>Inline File Extensions</code> configuration above, and serve the file inline; if, and only if, its extension matches one found in your configuration. By default, s2Member serves all files as attachments <em>( i.e. downloads )</em>. Please read the section above regarding <code>Inline File Extensions</code> for further details. Also note, this Shortcode Attribute does NOTHING for files served via Amazon® CloudFront. See the tech-notes listed in the Amazon® CloudFront section for further details and workarounds.</li>'."\n";
562
+ echo '<li><code>storage=""</code> Defaults to <code>[empty]</code>. If <code>storage="local|s3|cf"</code>, s2Member will serve the file from a specific source location, based on the value of this Shortcode Attribute. For example, if you\'ve configured Amazon® S3 and/or CloudFront; but, there are a few files that you want to upload locally to the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory; you can force s2Member to serve a file from local storage by setting <code>storage="local"</code> explicitly.</li>'."\n";
563
+ echo '<li><code>remote="no"</code> Defaults to <code>no</code>. If <code>remote="1|on|yes|true"</code>, s2Member will authenticate access to the File Download via Remote Header Authorization, instead of through your web site. This is similar to <code>.htaccess</code> protection routines of yester-year</code>. Please check the <code>Remote Authorization and Podcasting</code> section for further details about how this works.</li>'."\n";
564
+ echo '<li><code>ssl=""</code> Defaults to <code>[empty]</code>. If <code>ssl="1|on|yes|true"</code>, s2Member will generate a File Download URL with an SSL protocol <em>( i.e. the URL will start with <code>https://</code> or <code>rtmpe://</code> )</em>. If empty, s2Member will only generate a File Download URL with an SSL protocol, when/if the Post/Page/URL firing the Shortcode itself, is also being viewed over SSL. Otherwise, s2Member will use a non-SSL protocol by default.</li>'."\n";
565
+ echo '<li><code>rewrite="no"</code> Defaults to <code>no</code>. If <code>rewrite="1|on|yes|true"</code>, s2Member will generate a File Download URL that takes full advantage of s2Member\'s Advanced Mod Rewrite functionality. If you\'re running an Apache web server, or another server that supports <code>mod_rewrite</code>, we highly recommend turning this on. s2Member\'s <code>mod_rewrite</code> URLs do NOT contain query string parameters, making them more portable/compatible with other software applications and/or plugins for WordPress®.</li>'."\n";
566
+ echo '<li><code>rewrite_base=""</code> Defaults to <code>[empty]</code>. If <code>rewrite_base="'.esc_attr(site_url("/")).'"</code>, s2Member will generate a File Download URL that takes full advantage of s2Member\'s Advanced Mod Rewrite functionality, and it will use the rewrite base URL as a prefix. This could be useful on some WordPress® installations that use advanced directory structures. It could also be useful for site owners using virtual directories that point to <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code>. Note, if <code>rewrite_base</code> is set, s2Member will automatically force <code>rewrite="yes"</code> for you.</li>'."\n";
567
+ echo '<li><code>skip_confirmation="no"</code> Defaults to <code>no</code>. If <code>skip_confirmation="1|on|yes|true"</code>, s2Member will generate a File Download URL which contains a directive, telling s2Member NOT to introduce any JavaScript confirmation prompts on your site, for this File Download URL. Please note, s2Member will automatically detect links, anywhere in your content, and/or anywhere in your theme files, that contain <code>s2member_file_download</code> or <code>s2member-files</code>. Whenever a logged-in Member clicks a link that contains <code>s2member_file_download</code> or <code>s2member-files</code>, the system will politely ask the User to confirm the download using a very intuitive JavaScript confirmation prompt, which contains specific details about your configured download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not.</li>'."\n";
568
+ echo '<li><code>url_to_storage_source="no"</code> Defaults to <code>no</code>. If <code>url_to_storage_source="1|on|yes|true"</code>, s2Member will generate a File Download URL which points directly to the storage source. This is only functional with Amazon® S3 and/or CloudFront integrations. If you create a URL that points directly to the storage source <em>( i.e. points directly to Amazon® S3 or CloudFront )</em>, s2Member will NOT be able to further authenticate the current User/Member; and, s2Member will NOT be able to count the File Download against the current User\'s account record, because the URL being generated does not pass back through s2Member at all, it points directly to the storage source. For this reason, if you set <code>url_to_storage_source="true"</code>, you should also set <code>check_user="true"</code> and <code>count_against_user="true"</code>, telling s2Member to authenticate the current User, and if authenticated, count this File Download URL against the current User\'s account record in real-time <em>( i.e. as the URL is being generated ) </em>, while it still has a chance to do so. This Shortcode Attribute is useful when you stream files over the RTMP protocol; where an <code>http://</code> URL is not feasible. It also helps in situations where a 3rd-party software application will not work as intended, with s2Member\'s internal redirection to Amazon® S3/CloudFront files. Important, when <code>check_user="true"</code> and/or <code>count_against_user="true"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>'."\n";
569
+ echo '<li><code>count_against_user="no"</code> Defaults to <code>no</code>. If <code>count_against_user="1|on|yes|true"</code>, it will automatically force <code>check_user="true"</code> as well. In other words, s2Member will authenticate the current User, and if authenticated, count this File Download URL against the current User\'s account record in real-time <em>( i.e. as the URL is being generated ) </em>. This is off by default. By default, s2Member will simply generate a File Download URL, and upon a User/Member clicking the URL, s2Member will authenticate the User/Member at that time, count the File Download against their account record, and serve the File Download. In other words, under normal circumstances, there is no reason to set <code>check_user="true"</code> and/or <code>count_against_user="true"</code> when generating the URL itself. However, this is a useful Shortcode Attribute when <code>url_to_storage_source="true"</code>. Please note, when <code>check_user="true"</code> and/or <code>count_against_user="true"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>'."\n";
570
+ echo '<li><code>check_user="no"</code> Defaults to <code>no</code>. If <code>check_user="1|on|yes|true"</code>, s2Member will authenticate the current User before allowing the File Download URL to be generated. This is off by default. By default, s2Member will simply generate a File Download URL, and upon a User/Member clicking the URL, s2Member will authenticate the User/Member at that time, and serve the File Download to the User/Member. In other words, under normal circumstances, there is no reason to set <code>check_user="true"</code> and/or <code>count_against_user="true"</code> when generating the URL itself. However, this IS a useful Shortcode Attribute when <code>url_to_storage_source="true"</code>. Please note, when <code>check_user="true"</code> and/or <code>count_against_user="true"</code>, the Shortcode will return an empty and/or null object value in situations where the current User/Member does NOT have access to the file.</li>'."\n";
571
+ echo '<li><code>get_streamer_json="no"</code> Defaults to <code>no</code>. If <code>get_streamer_json="1|on|yes|true"</code>, the Shortcode will return a JSON object for JavaScript notation, making it possible to integrate the <code>[s2File /]</code> Shortcode into JavaScript routines that configure streaming media players. For further details, please review the section above: <code>JW Player® &amp; RTMP Protocol Examples</code>. Note, if you set <code>get_streamer_json="true"</code>, s2Member will automatically force <code>url_to_storage_source="true"</code> and <code>stream="true"</code>. For that reason, you should carefully review the details and warning above regarding <code>url_to_storage_source</code>. If you set <code>get_streamer_json="true"</code>, you should also set <code>check_user="true"</code> and <code>count_against_user="true"</code>.</li>'."\n";
572
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2file_lis", get_defined_vars());
573
+ echo '</ul>'."\n";
574
+ echo '</td>'."\n";
575
+ /**/
576
+ echo '</tr>'."\n";
577
+ echo '</tbody>'."\n";
578
+ echo '</table>'."\n";
579
+ /**/
580
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
581
+ /**/
582
+ echo '<h4 style="margin:0;"><code>[s2Key /]</code> Shortcode Attributes:</h4>'."\n";
583
+ echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.primothemes.com/forums/viewtopic.php?f=40&t=12453#src_doc_s2member_file_download_key()" target="_blank" rel="external">s2member_file_download_key()</a> for PHP integration.</p>'."\n";
584
+ echo '<table class="form-table" style="margin-top:0;">'."\n";
585
+ echo '<tbody>'."\n";
586
+ echo '<tr style="padding-top:0;">'."\n";
587
+ /**/
588
+ echo '<td style="padding-top:0;">'."\n";
589
+ echo '<ul>'."\n";
590
+ echo '<li><code>file_download="file.zip"</code> Location of the file, relative to the <code>/'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/</code> directory; or, relative to the root of your Amazon® S3 Bucket, when applicable.</li>'."\n";
591
+ echo '<li><code>directive=""</code> Defaults to <code>[empty]</code>. If <code>directive="ip-forever|universal"</code>, s2Member will return a special File Download Key. If you set <code>directive="ip-forever"</code>, the File Download Key that s2Member generates will last forever, for a specific IP Address; otherwise, by default, all File Download Keys expire after 24 hours automatically. If you set <code>directive="universal"</code>, s2Member will generate a File Download Key that is good for anyone/everyone forever, with NO restrictions on who/where/when a file is accessed <em>( e.g. be careful with this one )</em>.</li>'."\n";
592
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2key_lis", get_defined_vars());
593
+ echo '</ul>'."\n";
594
+ echo '</td>'."\n";
595
+ /**/
596
+ echo '</tr>'."\n";
597
+ echo '</tbody>'."\n";
598
+ echo '</table>'."\n";
599
+ echo '</div>'."\n";
600
+ /**/
601
+ echo '</div>'."\n";
602
+ /**/
603
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_shortcode_attrs", get_defined_vars());
604
  }
605
  /**/
606
+ if(apply_filters("ws_plugin__s2member_during_down_ops_page_during_left_sections_display_gzip_conflicts", true, get_defined_vars()))
607
+ {
608
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_gzip_conflicts", get_defined_vars());
609
+ /**/
610
+ echo '<div class="ws-menu-page-group" title="Preventing GZIP Conflicts On Server">'."\n";
611
+ /**/
612
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-gzip-conflicts-section">'."\n";
613
+ echo '<h3>Preventing GZIP Conflicts On Server ( Instructions )</h3>'."\n";
614
+ echo '<p>Protected files served by s2Member® through PHP scripts, are already compressed. Therefore, <a href="http://code.google.com/speed/articles/gzip.html" target="_blank" rel="nofollow external xlink">GZIP compression</a> is not needed during protected file delivery. Some web servers (i.e. Apache, LiteSpeed, and similar) include GZIP compression rules through server-side extensions, like <code>mod_deflate</code> for example. While s2Member® encourages the use of extensions like <code>mod_deflate</code>, it is best to disable GZIP automatically (i.e. temporarily) during s2Member\'s delivery of a protected file through a PHP script. This avoids conflicts on the server which might otherwise lead to corrupted file downloads. s2Member® makes a valiant effort to accomplish this via PHP, all on its own. However, it never hurts to add this section of code to the root <code>.htaccess</code> file for your WordPress® installation. Optional, but highly recommended.</p>'."\n";
615
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_gzip_conflicts", get_defined_vars());
616
+ /**/
617
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
618
+ echo '<p style="margin:0; font-weight:bold;">s2Member® automatically adds this to your <code>.htaccess</code> file upon activation of the plugin.</p>'."\n";
619
+ echo '<p style="margin:0;">The following <code>mod_rewrite</code> rule goes inside this file: <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path(ABSPATH.".htaccess")).'</code></p>'."\n";
620
+ echo '<pre><code>'.esc_html(trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_no_gzip_htaccess"])))).'</code></pre>';
621
+ echo '<p><strong>* Tip:</strong> this covers all types of integration with s2Member® File Downloads, even if you\'re using s2Member\'s Advanced Mod Rewrite Linkage.</p>'."\n";
622
+ echo '</div>'."\n";
623
+ /**/
624
+ echo '</div>'."\n";
625
+ /**/
626
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_after_gzip_conflicts", get_defined_vars());
627
+ }
628
+ /**/
629
+ do_action("ws_plugin__s2member_during_down_ops_page_after_left_sections", get_defined_vars());
630
  /**/
631
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
632
  /**/
633
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save All Changes" /></p>'."\n";
634
  /**/
635
+ echo '</form>'."\n";
636
  /**/
637
+ echo '</td>'."\n";
638
  /**/
639
+ echo '<td class="ws-menu-page-table-r">'."\n";
640
+ c_ws_plugin__s2member_menu_pages_rs::display();
641
+ echo '</td>'."\n";
642
  /**/
643
+ echo '</tr>'."\n";
644
+ echo '</tbody>'."\n";
645
+ echo '</table>'."\n";
646
  /**/
647
+ echo '</div>'."\n";
648
  }
649
  }
650
  }
651
  /**/
652
+ new c_ws_plugin__s2member_menu_page_down_ops();
653
  ?>
includes/menu-pages/els-ops.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Menu_Pages
15
  * @since 3.0
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_menu_page_els_ops"))
21
  {
22
  /**
23
  * Menu page for the s2Member plugin ( List Server Options page ).
@@ -27,301 +27,301 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_els_ops"))
27
  */
28
  class c_ws_plugin__s2member_menu_page_els_ops
29
  {
30
- public function __construct ()
31
  {
32
- echo '<div class="wrap ws-menu-page">' . "\n";
33
  /**/
34
- echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
35
- echo '<h2>s2Member® API / List Servers</h2>' . "\n";
36
  /**/
37
- echo '<table class="ws-menu-page-table">' . "\n";
38
- echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
39
- echo '<tr class="ws-menu-page-table-tr">' . "\n";
40
- echo '<td class="ws-menu-page-table-l">' . "\n";
41
  /**/
42
- echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
43
- 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";
44
  /**/
45
- do_action ("ws_plugin__s2member_during_els_ops_page_before_left_sections", get_defined_vars ());
46
  /**/
47
- if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_mailchimp", true, get_defined_vars ()))
48
  {
49
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_mailchimp", get_defined_vars ());
50
  /**/
51
- echo '<div class="ws-menu-page-group" title="MailChimp® Integration">' . "\n";
52
  /**/
53
- echo '<div class="ws-menu-page-section ws-plugin--s2member-mailchimp-section">' . "\n";
54
- echo '<a href="http://www.s2member.com/mailchimp" target="_blank"><img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/mailchimp-stamp.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
55
- echo '<h3>MailChimp® List Server Integration ( optional )</h3>' . "\n";
56
- echo '<p>s2Member can be integrated with MailChimp®. MailChimp® is an email marketing service. MailChimp® makes it easy to send email newsletters to your Customers, manage your MailChimp® subscriber lists, and track campaign performance. Although s2Member can be integrated with almost ANY list server, we highly recommend MailChimp®; because of their <a href="http://www.s2member.com/mailchimp-api-docs" target="_blank" rel="external">powerful API for MailChimp® services</a>. In future versions of s2Member, we plan to build additional features into s2Member that work with, and extend, MailChimp® services.</p>' . "\n";
57
- echo '<p>For now, we\'ve covered the basics. You can have your Members automatically subscribed to your MailChimp® marketing lists <em>( e.g. newsletters / auto-responders )</em>. You\'ll need a <a href="http://www.s2member.com/mailchimp" target="_blank" rel="external">MailChimp® account</a>, a <a href="http://www.s2member.com/mailchimp-api-key" target="_blank" rel="external">MailChimp® API Key</a>, and your <a href="#" onclick="alert(\'To obtain your MailChimp® List ID(s), log into your MailChimp® account and click the Lists tab. Now click the (View) button, for the List(s) you want to integrate with s2Member. Then, click the (Settings) link. At the bottom of the (Settings) page, for each list; you\\\'ll find a Unique List ID.\'); return false;">MailChimp® List IDs</a>.</p>' . "\n";
58
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_mailchimp", get_defined_vars ());
59
  /**/
60
- echo '<table class="form-table">' . "\n";
61
- echo '<tbody>' . "\n";
62
- echo '<tr>' . "\n";
63
  /**/
64
- echo '<th>' . "\n";
65
- echo '<label for="ws-plugin--s2member-mailchimp-api-key">' . "\n";
66
- echo 'MailChimp® API Key:' . "\n";
67
- echo '</label>' . "\n";
68
- echo '</th>' . "\n";
69
  /**/
70
- echo '</tr>' . "\n";
71
- echo '<tr>' . "\n";
72
  /**/
73
- echo '<td>' . "\n";
74
- echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_mailchimp_api_key" id="ws-plugin--s2member-mailchimp-api-key" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mailchimp_api_key"]) . '" /><br />' . "\n";
75
- echo 'Once you have a MailChimp® account, you\'ll need to <a href="http://www.s2member.com/mailchimp-api-key" target="_blank" rel="external">add an API Key</a>.' . "\n";
76
- echo '</td>' . "\n";
77
  /**/
78
- echo '</tr>' . "\n";
79
  /**/
80
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
81
  {
82
- echo '<tr>' . "\n";
83
  /**/
84
- echo '<th>' . "\n";
85
- echo '<label for="ws-plugin--s2member-level' . $n . '-mailchimp-list-ids">' . "\n";
86
- echo 'List ID(s) for ' . (($n === 0) ? 'Free Subscribers' : 'Level #' . $n . ' Members') . ' ( comma-delimited ):' . "\n";
87
- echo '</label>' . "\n";
88
- echo '</th>' . "\n";
89
  /**/
90
- echo '</tr>' . "\n";
91
- echo '<tr>' . "\n";
92
  /**/
93
- echo '<td>' . "\n";
94
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_mailchimp_list_ids" id="ws-plugin--s2member-level' . $n . '-mailchimp-list-ids" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_mailchimp_list_ids"]) . '" /><br />' . "\n";
95
- echo 'New ' . (($n === 0) ? 'Free Subscribers' : 'Level #' . $n . ' Members') . ' will be subscribed to these List IDs.<br />' . "\n";
96
- echo 'Ex: <code>4a44fRio5d, 434ksvviEdf, 8834jsdf923, ee9djfs4jel3</code><br />' . "\n";
97
- echo 'Or: <code>4a44fRio5d::Group Title::Group|Another Group</code>' . "\n";
98
- echo '</td>' . "\n";
99
  /**/
100
- echo '</tr>' . "\n";
101
  }
102
  /**/
103
- echo '</tbody>' . "\n";
104
- echo '</table>' . "\n";
105
- echo '</div>' . "\n";
106
  /**/
107
- echo '</div>' . "\n";
108
  /**/
109
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_mailchimp", get_defined_vars ());
110
  }
111
  /**/
112
- if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_aweber", true, get_defined_vars ()))
113
  {
114
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_aweber", get_defined_vars ());
115
  /**/
116
- echo '<div class="ws-menu-page-group" title="AWeber® Integration">' . "\n";
117
  /**/
118
- echo '<div class="ws-menu-page-section ws-plugin--s2member-aweber-section">' . "\n";
119
- echo '<a href="http://www.s2member.com/aweber" target="_blank"><img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/aweber-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
120
- echo '<h3>AWeber® List Server Integration ( optional )</h3>' . "\n";
121
- echo '<p>s2Member can be integrated with AWeber®. AWeber® is an email marketing service. Whether you\'re looking to get your first email campaign off the ground, or you\'re a seasoned veteran who wants to dig into advanced tools like detailed email web analytics, activity based segmentation, geo-targeting and broadcast split-testing, AWeber\'s got just what you need to make email marketing work for you.</p>' . "\n";
122
- echo '<p>You can have your Members automatically subscribed to your AWeber® marketing lists <em>( e.g. newsletters / auto-responders )</em>. You\'ll need an <a href="http://www.s2member.com/aweber" target="_blank" rel="external">AWeber® account</a> and your <a href="#" onclick="alert(\'To obtain your AWeber® List ID(s), log into your AWeber® account. Click on the Lists tab. On that page you\\\'ll find a Unique List ID associated with each of your lists. AWeber® sometimes refers to this as a List Name instead of a List ID.\'); return false;">AWeber® List IDs</a>. You will ALSO need to configure a <a href="http://www.primothemes.com/forums/viewtopic.php?f=36&t=15496" target="_blank" rel="external">Custom Email Parser</a> inside your AWeber® account.</p>' . "\n";
123
- echo '<p>Log into AWeber®, and go to <em>My Lists -> Email Parser</em>. If you like, choose the PayPal® Parser <em>( even if you\'re not using PayPal® as your Payment Gateway )</em>. You can safely ignore the additional instructions they provide. s2Member just needs the PayPal® box checked, and that\'s all. Or, even better, integrate <a href="http://www.primothemes.com/forums/viewtopic.php?f=36&t=15496" target="_blank" rel="external">s2Member\'s Custom Email Parser</a> for AWeber, which <strong>will improve reliability</strong> and flexibility.</p>' . "\n";
124
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_aweber", get_defined_vars ());
125
  /**/
126
- echo '<table class="form-table">' . "\n";
127
- echo '<tbody>' . "\n";
128
  /**/
129
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
130
  {
131
- echo '<tr>' . "\n";
132
  /**/
133
- echo '<th>' . "\n";
134
- echo '<label for="ws-plugin--s2member-level' . $n . '-aweber-list-ids">' . "\n";
135
- echo 'List ID(s) for ' . (($n === 0) ? 'Free Subscribers' : 'Level #' . $n . ' Members') . ' ( comma-delimited ):' . "\n";
136
- echo '</label>' . "\n";
137
- echo '</th>' . "\n";
138
  /**/
139
- echo '</tr>' . "\n";
140
- echo '<tr>' . "\n";
141
  /**/
142
- echo '<td>' . "\n";
143
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level' . $n . '_aweber_list_ids" id="ws-plugin--s2member-level' . $n . '-aweber-list-ids" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $n . "_aweber_list_ids"]) . '" /><br />' . "\n";
144
- echo 'New ' . (($n === 0) ? 'Free Subscribers' : 'Level #' . $n . ' Members') . ' will be subscribed to these List IDs.<br />' . "\n";
145
- echo 'Ex: <code>mylist, myotherlist, anotherlist</code>' . "\n";
146
- echo '</td>' . "\n";
147
  /**/
148
- echo '</tr>' . "\n";
149
  }
150
  /**/
151
- echo '</tbody>' . "\n";
152
- echo '</table>' . "\n";
153
- echo '</div>' . "\n";
154
  /**/
155
- echo '</div>' . "\n";
156
  /**/
157
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_aweber", get_defined_vars ());
158
  }
159
  /**/
160
- if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_opt_in", true, get_defined_vars ()))
161
  {
162
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_opt_in", get_defined_vars ());
163
- /**/
164
- echo '<div class="ws-menu-page-group" title="Registration / Double Opt-In Box?">' . "\n";
165
- /**/
166
- echo '<div class="ws-menu-page-section ws-plugin--s2member-opt-in-section">' . "\n";
167
- echo '<h3>Double Opt-In Checkbox Field ( optional )</h3>' . "\n";
168
- echo '<p>A Double Opt-In Checkbox will ONLY be displayed, if you\'ve integrated one <em>or more</em> List Servers.</p>' . "\n";
169
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_opt_in", get_defined_vars ());
170
- /**/
171
- echo '<table class="form-table">' . "\n";
172
- echo '<tbody>' . "\n";
173
- echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '') . '>' . "\n";
174
- /**/
175
- echo '<th>' . "\n";
176
- echo '<label for="ws-plugin--s2member-custom-reg-opt-in-label">' . "\n";
177
- echo 'Double Opt-In Checkbox Label:' . "\n";
178
- echo '</label>' . "\n";
179
- echo '</th>' . "\n";
180
- /**/
181
- echo '</tr>' . "\n";
182
- echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '') . '>' . "\n";
183
- /**/
184
- echo '<td>' . "\n";
185
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_custom_reg_opt_in_label" id="ws-plugin--s2member-custom-reg-opt-in-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"]) . '" /><br />' . "\n";
186
- echo 'Example: <code><img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? 'checked' : 'unchecked') . '.png" class="ws-plugin--s2member-custom-reg-opt-in-label-prev-img ws-menu-page-img-16" style="vertical-align:middle;" alt="" /> Your Label will appear next to a Checkbox.</code>' . "\n";
187
- echo '</td>' . "\n";
188
- /**/
189
- echo '</tr>' . "\n";
190
- echo '<tr>' . "\n";
191
- /**/
192
- echo '<th>' . "\n";
193
- echo '<label for="ws-plugin--s2member-custom-reg-opt-in">' . "\n";
194
- echo 'Require Double Opt-In Checkbox?' . "\n";
195
- echo '</label>' . "\n";
196
- echo '</th>' . "\n";
197
- /**/
198
- echo '</tr>' . "\n";
199
- echo '<tr>' . "\n";
200
- /**/
201
- echo '<td>' . "\n";
202
- echo '<select name="ws_plugin__s2member_custom_reg_opt_in" id="ws-plugin--s2member-custom-reg-opt-in">' . "\n";
203
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? ' selected="selected"' : '') . '>Yes ( the Box MUST be checked — checked by default )</option>' . "\n";
204
- echo '<option value="2"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 2) ? ' selected="selected"' : '') . '>Yes ( the Box MUST be checked — unchecked by default )</option>' . "\n";
205
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' selected="selected"' : '') . '>No ( disable — do NOT display or require the Checkbox )</option>' . "\n";
206
- echo '</select><br />' . "\n";
207
- echo 'An email confirmation will NOT be sent to the User, unless the Box is checked, or you\'ve disabled the Box; by choosing <code>No</code>.' . "\n";
208
- echo '</td>' . "\n";
209
- /**/
210
- echo '</tr>' . "\n";
211
- echo '</tbody>' . "\n";
212
- echo '</table>' . "\n";
213
- echo '</div>' . "\n";
214
- /**/
215
- echo '</div>' . "\n";
216
- /**/
217
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_opt_in", get_defined_vars ());
218
  }
219
  /**/
220
- if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_opt_out", true, get_defined_vars ()))
221
  {
222
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_opt_out", get_defined_vars ());
223
- /**/
224
- echo '<div class="ws-menu-page-group" title="Automate Un-Subscribe/Opt-Outs?">' . "\n";
225
- /**/
226
- echo '<div class="ws-menu-page-section ws-plugin--s2member-opt-out-section">' . "\n";
227
- echo '<h3>Automate Un-Subscribe/Opt-Out Removals ( optional )</h3>' . "\n";
228
- echo '<p>s2Member can automatically <em>( and silently )</em> remove Users/Members from the List Servers you\'ve configured above. s2Member is also capable of automating this, based on your own personal configuration preferences. Below, you can choose which Events you consider grounds for List Removal. It is also important to point out that s2Member will ONLY remove Users/Members from the Lists you\'ve configured at the Level the User/Member is or was at during the time of the Event. For example, if a Level #1 Member is deleted, they will ONLY be removed from the List(s) you\'ve configured at Level #1. If an account is upgraded from Level #1 to Level #2, they will ONLY be removed from the List(s) you\'ve configured at Level #1. Of course, all of this is based on the configuration below.</p>' . "\n";
229
- echo '<p><em><strong>*Regarding AWeber®*</strong> these will NOT work for AWeber® until you <a href="http://www.s2member.com/aweber-notification-email" target="_blank" rel="external">add a Notification Email</a> to your AWeber® account matching the "EMail From Address" configured in <code>s2Member -> General Options -> EMail Configuration</code>. Which is currently set to: <code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]) . '</code>. This is a required step if you want s2Member to be authenticated when it emails List Removal requests to AWeber®.</em></p>' . "\n";
230
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_opt_out", get_defined_vars ());
231
- /**/
232
- echo '<table class="form-table">' . "\n";
233
- echo '<tbody>' . "\n";
234
- echo '<tr>' . "\n";
235
- /**/
236
- echo '<th>' . "\n";
237
- echo '<label for="ws-plugin--s2member-custom-reg-auto-opt-outs">' . "\n";
238
- echo 'Process List Removals Automatically? ( choose events )' . "\n";
239
- echo '</label>' . "\n";
240
- echo '</th>' . "\n";
241
- /**/
242
- echo '</tr>' . "\n";
243
- echo '<tr>' . "\n";
244
- /**/
245
- echo '<td>' . "\n";
246
- echo '<div class="ws-menu-page-scrollbox" style="height:150px;">' . "\n";
247
- echo '<input type="hidden" name="ws_plugin__s2member_custom_reg_auto_opt_outs[]" value="update-signal" />' . "\n";
248
- foreach (array ("removal-deletion" => "<strong>Anytime a User is deleted ( including manual deletions )</strong>", "ipn-refund-reversal-deletion" => "&#9492;&#9472; Anytime s2Member deletes an account because of a Refund/Reversal.", "(ipn|auto-eot)-cancellation-expiration-deletion" => "&#9492;&#9472; Anytime s2Member deletes an account because of a Cancellation/Expiration.", "modification" => "<strong>Anytime a User's Role changes ( including manual changes )</strong>", "ipn-refund-reversal-demotion" => "&#9492;&#9472; Anytime s2Member demotes an account because of a Refund/Reversal.", "(ipn|auto-eot)-cancellation-expiration-demotion" => "&#9492;&#9472; Anytime s2Member demotes an account because of a Cancellation/Expiration.", "ipn-upgrade-downgrade" => "&#9492;&#9472; Anytime s2Member changes a User's Role after a paid Subscr. Modification.") as $ws_plugin__s2member_temp_s_value => $ws_plugin__s2member_temp_s_label)
249
- echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_auto_opt_outs[]" id="ws-plugin--s2member-custom-reg-auto-opt-outs-' . esc_attr (preg_replace ("/[^a-z0-9_\-]/", "-", $ws_plugin__s2member_temp_s_value)) . '" value="' . esc_attr ($ws_plugin__s2member_temp_s_value) . '"' . ((in_array ($ws_plugin__s2member_temp_s_value, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_outs"])) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-custom-reg-auto-opt-outs-' . esc_attr (preg_replace ("/[^a-z0-9_\-]/", "-", $ws_plugin__s2member_temp_s_value)) . '">' . $ws_plugin__s2member_temp_s_label . '</label><br />' . "\n";
250
- echo '</div>' . "\n";
251
- echo '</td>' . "\n";
252
- /**/
253
- echo '</tr>' . "\n";
254
- echo '<tr>' . "\n";
255
- /**/
256
- echo '<th>' . "\n";
257
- echo '<label for="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">' . "\n";
258
- echo 'Also Process List Transitions Automatically?' . "\n";
259
- echo '</label>' . "\n";
260
- echo '</th>' . "\n";
261
- /**/
262
- echo '</tr>' . "\n";
263
- echo '<tr>' . "\n";
264
- /**/
265
- echo '<td>' . "\n";
266
- echo '<select name="ws_plugin__s2member_custom_reg_auto_opt_out_transitions" id="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">' . "\n";
267
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"]) ? ' selected="selected"' : '') . '>No ( do NOT transition mailing list subscribers automatically )</option>' . "\n";
268
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"] === "1") ? ' selected="selected"' : '') . '>Yes ( automatically transition, if able to remove from a previous list )</option>' . "\n";
269
- echo '<option value="2"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"] === "2") ? ' selected="selected"' : '') . '>Yes ( always automatically transition, even if NOT removed from a previous list )</option>' . "\n";
270
- echo '</select><br />' . "\n";
271
- echo '<em><strong>*Transitions*</strong> When/if s2Member automatically removes a Member from Lists at their current Level# ( based on your configuration in the previous section ), this setting tells s2Member that it should <strong>also</strong> transition the Member to any Lists you\'ve configured at the new Access Level# ( i.e. Role ) they are being changed to. For example, if a Member is demoted from Level #1 to Level #0, do you want s2Member to add them to the Level #0 List(s) after it removes them from the Level #1 List(s)?</em><br /><br />' . "\n";
272
- echo '<em><strong>*If removed from a previous list, or NOT?*</strong> You can choose your preference above. When/if s2Member automatically transitions a mailing list subscriber, it will first try to remove the subscriber from a previous mailing list. If s2Member is able to remove the subscriber from a previous list before the transition takes place, s2Member will then make an attempt ( based on your configuration ) to transition the subscriber to a new/different list silently ( e.g. without a new confirmation email being sent out ). If s2Member is NOT able to remove a subscriber from a previous list, it can - ( if configured to do so ), still transition a subscriber to a new list, by sending the subscriber a new email confirmation letter ( e.g. this is NOT silent, because you absolutely NEED the subscriber\'s permission in this case ).</em><br /><br />' . "\n";
273
- echo '<em><strong>*Seamless with MailChimp®*</strong> If enabled, Automatic List Transitions work seamlessly with MailChimp®. Automatic List Transitions also work with AWeber®, but AWeber® will ALWAYS send the User/Member a new confirmation email, asking them to confirm changes to their mailing list subscription with you. Work is underway to improve this aspect of s2Member\'s integration with AWeber® in a future release. Ideally, a Customer would be transitioned silently behind the scene with AWeber® too, when appropriate.</em>' . "\n";
274
- echo '</td>' . "\n";
275
- /**/
276
- echo '</tr>' . "\n";
277
- echo '</tbody>' . "\n";
278
- echo '</table>' . "\n";
279
- echo '</div>' . "\n";
280
- /**/
281
- echo '</div>' . "\n";
282
- /**/
283
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_opt_out", get_defined_vars ());
284
  }
285
  /**/
286
- if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_other_methods", true, get_defined_vars ()))
287
  {
288
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_other_methods", get_defined_vars ());
289
  /**/
290
- echo '<div class="ws-menu-page-group" title="Other List Server Integration Methods">' . "\n";
291
  /**/
292
- echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">' . "\n";
293
- echo '<h3>Other List Server Integrations ( there\'s always a way )</h3>' . "\n";
294
- echo '<p>Check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Specific Post/Page` Notifications that are available to you through the s2Member API. These make it possible to integrate with 3rd party applications; like list servers, affiliate programs, and other back-office routines; in more advanced ways. You will probably need to get help from a web developer though. s2Member API Notifications require some light PHP scripting by someone familiar with web service connections.</p>' . "\n";
295
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_other_methods", get_defined_vars ());
296
- echo '</div>' . "\n";
297
  /**/
298
- echo '</div>' . "\n";
299
  /**/
300
- do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_other_methods", get_defined_vars ());
301
  }
302
  /**/
303
- do_action ("ws_plugin__s2member_during_els_ops_page_after_left_sections", get_defined_vars ());
304
  /**/
305
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
306
  /**/
307
- echo '<p class="submit"><input type="submit" class="button-primary" value="Save All Changes" /></p>' . "\n";
308
  /**/
309
- echo '</form>' . "\n";
310
  /**/
311
- echo '</td>' . "\n";
312
  /**/
313
- echo '<td class="ws-menu-page-table-r">' . "\n";
314
- c_ws_plugin__s2member_menu_pages_rs::display ();
315
- echo '</td>' . "\n";
316
  /**/
317
- echo '</tr>' . "\n";
318
- echo '</tbody>' . "\n";
319
- echo '</table>' . "\n";
320
  /**/
321
- echo '</div>' . "\n";
322
  }
323
  }
324
  }
325
  /**/
326
- new c_ws_plugin__s2member_menu_page_els_ops ();
327
  ?>
14
  * @package s2Member\Menu_Pages
15
  * @since 3.0
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_menu_page_els_ops"))
21
  {
22
  /**
23
  * Menu page for the s2Member plugin ( List Server Options page ).
27
  */
28
  class c_ws_plugin__s2member_menu_page_els_ops
29
  {
30
+ public function __construct()
31
  {
32
+ echo '<div class="wrap ws-menu-page">'."\n";
33
  /**/
34
+ echo '<div id="icon-plugins" class="icon32"><br /></div>'."\n";
35
+ echo '<h2>s2Member® API / List Servers</h2>'."\n";
36
  /**/
37
+ echo '<table class="ws-menu-page-table">'."\n";
38
+ echo '<tbody class="ws-menu-page-table-tbody">'."\n";
39
+ echo '<tr class="ws-menu-page-table-tr">'."\n";
40
+ echo '<td class="ws-menu-page-table-l">'."\n";
41
  /**/
42
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">'."\n";
43
+ 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";
44
  /**/
45
+ do_action("ws_plugin__s2member_during_els_ops_page_before_left_sections", get_defined_vars());
46
  /**/
47
+ if(apply_filters("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_mailchimp", true, get_defined_vars()))
48
  {
49
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_mailchimp", get_defined_vars());
50
  /**/
51
+ echo '<div class="ws-menu-page-group" title="MailChimp® Integration">'."\n";
52
  /**/
53
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-mailchimp-section">'."\n";
54
+ echo '<a href="http://www.s2member.com/mailchimp" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/mailchimp-stamp.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>'."\n";
55
+ echo '<h3>MailChimp® List Server Integration ( optional )</h3>'."\n";
56
+ echo '<p>s2Member can be integrated with MailChimp®. MailChimp® is an email marketing service. MailChimp® makes it easy to send email newsletters to your Customers, manage your MailChimp® subscriber lists, and track campaign performance. Although s2Member can be integrated with almost ANY list server, we highly recommend MailChimp®; because of their <a href="http://www.s2member.com/mailchimp-api-docs" target="_blank" rel="external">powerful API for MailChimp® services</a>. In future versions of s2Member, we plan to build additional features into s2Member that work with, and extend, MailChimp® services.</p>'."\n";
57
+ echo '<p>For now, we\'ve covered the basics. You can have your Members automatically subscribed to your MailChimp® marketing lists <em>( e.g. newsletters / auto-responders )</em>. You\'ll need a <a href="http://www.s2member.com/mailchimp" target="_blank" rel="external">MailChimp® account</a>, a <a href="http://www.s2member.com/mailchimp-api-key" target="_blank" rel="external">MailChimp® API Key</a>, and your <a href="#" onclick="alert(\'To obtain your MailChimp® List ID(s), log into your MailChimp® account and click the Lists tab. Now click the (View) button, for the List(s) you want to integrate with s2Member. Then, click the (Settings) link. At the bottom of the (Settings) page, for each list; you\\\'ll find a Unique List ID.\'); return false;">MailChimp® List IDs</a>.</p>'."\n";
58
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_mailchimp", get_defined_vars());
59
  /**/
60
+ echo '<table class="form-table">'."\n";
61
+ echo '<tbody>'."\n";
62
+ echo '<tr>'."\n";
63
  /**/
64
+ echo '<th>'."\n";
65
+ echo '<label for="ws-plugin--s2member-mailchimp-api-key">'."\n";
66
+ echo 'MailChimp® API Key:'."\n";
67
+ echo '</label>'."\n";
68
+ echo '</th>'."\n";
69
  /**/
70
+ echo '</tr>'."\n";
71
+ echo '<tr>'."\n";
72
  /**/
73
+ echo '<td>'."\n";
74
+ echo '<input type="password" autocomplete="off" name="ws_plugin__s2member_mailchimp_api_key" id="ws-plugin--s2member-mailchimp-api-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mailchimp_api_key"]).'" /><br />'."\n";
75
+ echo 'Once you have a MailChimp® account, you\'ll need to <a href="http://www.s2member.com/mailchimp-api-key" target="_blank" rel="external">add an API Key</a>.'."\n";
76
+ echo '</td>'."\n";
77
  /**/
78
+ echo '</tr>'."\n";
79
  /**/
80
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
81
  {
82
+ echo '<tr>'."\n";
83
  /**/
84
+ echo '<th>'."\n";
85
+ echo '<label for="ws-plugin--s2member-level'.$n.'-mailchimp-list-ids">'."\n";
86
+ echo 'List ID(s) for '.(($n === 0) ? 'Free Subscribers' : 'Level #'.$n.' Members').' ( comma-delimited ):'."\n";
87
+ echo '</label>'."\n";
88
+ echo '</th>'."\n";
89
  /**/
90
+ echo '</tr>'."\n";
91
+ echo '<tr>'."\n";
92
  /**/
93
+ echo '<td>'."\n";
94
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_mailchimp_list_ids" id="ws-plugin--s2member-level'.$n.'-mailchimp-list-ids" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_mailchimp_list_ids"]).'" /><br />'."\n";
95
+ echo 'New '.(($n === 0) ? 'Free Subscribers' : 'Level #'.$n.' Members').' will be subscribed to these List IDs.<br />'."\n";
96
+ echo 'Ex: <code>4a44fRio5d, 434ksvviEdf, 8834jsdf923, ee9djfs4jel3</code><br />'."\n";
97
+ echo 'Or: <code>4a44fRio5d::Group Title::Group|Another Group</code>'."\n";
98
+ echo '</td>'."\n";
99
  /**/
100
+ echo '</tr>'."\n";
101
  }
102
  /**/
103
+ echo '</tbody>'."\n";
104
+ echo '</table>'."\n";
105
+ echo '</div>'."\n";
106
  /**/
107
+ echo '</div>'."\n";
108
  /**/
109
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_mailchimp", get_defined_vars());
110
  }
111
  /**/
112
+ if(apply_filters("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_aweber", true, get_defined_vars()))
113
  {
114
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_aweber", get_defined_vars());
115
  /**/
116
+ echo '<div class="ws-menu-page-group" title="AWeber® Integration">'."\n";
117
  /**/
118
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-aweber-section">'."\n";
119
+ echo '<a href="http://www.s2member.com/aweber" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/aweber-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>'."\n";
120
+ echo '<h3>AWeber® List Server Integration ( optional )</h3>'."\n";
121
+ echo '<p>s2Member can be integrated with AWeber®. AWeber® is an email marketing service. Whether you\'re looking to get your first email campaign off the ground, or you\'re a seasoned veteran who wants to dig into advanced tools like detailed email web analytics, activity based segmentation, geo-targeting and broadcast split-testing, AWeber\'s got just what you need to make email marketing work for you.</p>'."\n";
122
+ echo '<p>You can have your Members automatically subscribed to your AWeber® marketing lists <em>( e.g. newsletters / auto-responders )</em>. You\'ll need an <a href="http://www.s2member.com/aweber" target="_blank" rel="external">AWeber® account</a> and your <a href="#" onclick="alert(\'To obtain your AWeber® List ID(s), log into your AWeber® account. Click on the Lists tab. On that page you\\\'ll find a Unique List ID associated with each of your lists. AWeber® sometimes refers to this as a List Name instead of a List ID.\'); return false;">AWeber® List IDs</a>. You will ALSO need to configure a <a href="http://www.primothemes.com/forums/viewtopic.php?f=36&t=15496" target="_blank" rel="external">Custom Email Parser</a> inside your AWeber® account.</p>'."\n";
123
+ echo '<p>Log into AWeber®, and go to <em>My Lists -> Email Parser</em>. If you like, choose the PayPal® Parser <em>( even if you\'re not using PayPal® as your Payment Gateway )</em>. You can safely ignore the additional instructions they provide. s2Member just needs the PayPal® box checked, and that\'s all. Or, even better, integrate <a href="http://www.primothemes.com/forums/viewtopic.php?f=36&t=15496" target="_blank" rel="external">s2Member\'s Custom Email Parser</a> for AWeber, which <strong>will improve reliability</strong> and flexibility.</p>'."\n";
124
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_aweber", get_defined_vars());
125
  /**/
126
+ echo '<table class="form-table">'."\n";
127
+ echo '<tbody>'."\n";
128
  /**/
129
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
130
  {
131
+ echo '<tr>'."\n";
132
  /**/
133
+ echo '<th>'."\n";
134
+ echo '<label for="ws-plugin--s2member-level'.$n.'-aweber-list-ids">'."\n";
135
+ echo 'List ID(s) for '.(($n === 0) ? 'Free Subscribers' : 'Level #'.$n.' Members').' ( comma-delimited ):'."\n";
136
+ echo '</label>'."\n";
137
+ echo '</th>'."\n";
138
  /**/
139
+ echo '</tr>'."\n";
140
+ echo '<tr>'."\n";
141
  /**/
142
+ echo '<td>'."\n";
143
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_aweber_list_ids" id="ws-plugin--s2member-level'.$n.'-aweber-list-ids" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_aweber_list_ids"]).'" /><br />'."\n";
144
+ echo 'New '.(($n === 0) ? 'Free Subscribers' : 'Level #'.$n.' Members').' will be subscribed to these List IDs.<br />'."\n";
145
+ echo 'Ex: <code>mylist, myotherlist, anotherlist</code>'."\n";
146
+ echo '</td>'."\n";
147
  /**/
148
+ echo '</tr>'."\n";
149
  }
150
  /**/
151
+ echo '</tbody>'."\n";
152
+ echo '</table>'."\n";
153
+ echo '</div>'."\n";
154
  /**/
155
+ echo '</div>'."\n";
156
  /**/
157
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_aweber", get_defined_vars());
158
  }
159
  /**/
160
+ if(apply_filters("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_opt_in", true, get_defined_vars()))
161
  {
162
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_opt_in", get_defined_vars());
163
+ /**/
164
+ echo '<div class="ws-menu-page-group" title="Registration / Double Opt-In Box?">'."\n";
165
+ /**/
166
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-opt-in-section">'."\n";
167
+ echo '<h3>Double Opt-In Checkbox Field ( optional )</h3>'."\n";
168
+ echo '<p>A Double Opt-In Checkbox will ONLY be displayed, if you\'ve integrated one <em>or more</em> List Servers.</p>'."\n";
169
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_opt_in", get_defined_vars());
170
+ /**/
171
+ echo '<table class="form-table">'."\n";
172
+ echo '<tbody>'."\n";
173
+ echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '').'>'."\n";
174
+ /**/
175
+ echo '<th>'."\n";
176
+ echo '<label for="ws-plugin--s2member-custom-reg-opt-in-label">'."\n";
177
+ echo 'Double Opt-In Checkbox Label:'."\n";
178
+ echo '</label>'."\n";
179
+ echo '</th>'."\n";
180
+ /**/
181
+ echo '</tr>'."\n";
182
+ echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '').'>'."\n";
183
+ /**/
184
+ echo '<td>'."\n";
185
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_custom_reg_opt_in_label" id="ws-plugin--s2member-custom-reg-opt-in-label" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"]).'" /><br />'."\n";
186
+ echo 'Example: <code><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? 'checked' : 'unchecked').'.png" class="ws-plugin--s2member-custom-reg-opt-in-label-prev-img ws-menu-page-img-16" style="vertical-align:middle;" alt="" /> Your Label will appear next to a Checkbox.</code>'."\n";
187
+ echo '</td>'."\n";
188
+ /**/
189
+ echo '</tr>'."\n";
190
+ echo '<tr>'."\n";
191
+ /**/
192
+ echo '<th>'."\n";
193
+ echo '<label for="ws-plugin--s2member-custom-reg-opt-in">'."\n";
194
+ echo 'Require Double Opt-In Checkbox?'."\n";
195
+ echo '</label>'."\n";
196
+ echo '</th>'."\n";
197
+ /**/
198
+ echo '</tr>'."\n";
199
+ echo '<tr>'."\n";
200
+ /**/
201
+ echo '<td>'."\n";
202
+ echo '<select name="ws_plugin__s2member_custom_reg_opt_in" id="ws-plugin--s2member-custom-reg-opt-in">'."\n";
203
+ echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? ' selected="selected"' : '').'>Yes ( the Box MUST be checked — checked by default )</option>'."\n";
204
+ echo '<option value="2"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 2) ? ' selected="selected"' : '').'>Yes ( the Box MUST be checked — unchecked by default )</option>'."\n";
205
+ echo '<option value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' selected="selected"' : '').'>No ( disable — do NOT display or require the Checkbox )</option>'."\n";
206
+ echo '</select><br />'."\n";
207
+ echo 'An email confirmation will NOT be sent to the User, unless the Box is checked, or you\'ve disabled the Box; by choosing <code>No</code>.'."\n";
208
+ echo '</td>'."\n";
209
+ /**/
210
+ echo '</tr>'."\n";
211
+ echo '</tbody>'."\n";
212
+ echo '</table>'."\n";
213
+ echo '</div>'."\n";
214
+ /**/
215
+ echo '</div>'."\n";
216
+ /**/
217
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_opt_in", get_defined_vars());
218
  }
219
  /**/
220
+ if(apply_filters("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_opt_out", true, get_defined_vars()))
221
  {
222
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_opt_out", get_defined_vars());
223
+ /**/
224
+ echo '<div class="ws-menu-page-group" title="Automate Un-Subscribe/Opt-Outs?">'."\n";
225
+ /**/
226
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-opt-out-section">'."\n";
227
+ echo '<h3>Automate Un-Subscribe/Opt-Out Removals ( optional )</h3>'."\n";
228
+ echo '<p>s2Member can automatically <em>( and silently )</em> remove Users/Members from the List Servers you\'ve configured above. s2Member is also capable of automating this, based on your own personal configuration preferences. Below, you can choose which Events you consider grounds for List Removal. It is also important to point out that s2Member will ONLY remove Users/Members from the Lists you\'ve configured at the Level the User/Member is or was at during the time of the Event. For example, if a Level #1 Member is deleted, they will ONLY be removed from the List(s) you\'ve configured at Level #1. If an account is upgraded from Level #1 to Level #2, they will ONLY be removed from the List(s) you\'ve configured at Level #1. Of course, all of this is based on the configuration below.</p>'."\n";
229
+ echo '<p><em><strong>*Regarding AWeber®*</strong> these will NOT work for AWeber® until you <a href="http://www.s2member.com/aweber-notification-email" target="_blank" rel="external">add a Notification Email</a> to your AWeber® account matching the "EMail From Address" configured in <code>s2Member -> General Options -> EMail Configuration</code>. Which is currently set to: <code>'.esc_html($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]).'</code>. This is a required step if you want s2Member to be authenticated when it emails List Removal requests to AWeber®.</em></p>'."\n";
230
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_opt_out", get_defined_vars());
231
+ /**/
232
+ echo '<table class="form-table">'."\n";
233
+ echo '<tbody>'."\n";
234
+ echo '<tr>'."\n";
235
+ /**/
236
+ echo '<th>'."\n";
237
+ echo '<label for="ws-plugin--s2member-custom-reg-auto-opt-outs">'."\n";
238
+ echo 'Process List Removals Automatically? ( choose events )'."\n";
239
+ echo '</label>'."\n";
240
+ echo '</th>'."\n";
241
+ /**/
242
+ echo '</tr>'."\n";
243
+ echo '<tr>'."\n";
244
+ /**/
245
+ echo '<td>'."\n";
246
+ echo '<div class="ws-menu-page-scrollbox" style="height:150px;">'."\n";
247
+ echo '<input type="hidden" name="ws_plugin__s2member_custom_reg_auto_opt_outs[]" value="update-signal" />'."\n";
248
+ foreach(array("removal-deletion" => "<strong>Anytime a User is deleted ( including manual deletions )</strong>", "ipn-refund-reversal-deletion" => "&#9492;&#9472; Anytime s2Member deletes an account because of a Refund/Reversal.", "(ipn|auto-eot)-cancellation-expiration-deletion" => "&#9492;&#9472; Anytime s2Member deletes an account because of a Cancellation/Expiration.", "modification" => "<strong>Anytime a User's Role changes ( including manual changes )</strong>", "ipn-refund-reversal-demotion" => "&#9492;&#9472; Anytime s2Member demotes an account because of a Refund/Reversal.", "(ipn|auto-eot)-cancellation-expiration-demotion" => "&#9492;&#9472; Anytime s2Member demotes an account because of a Cancellation/Expiration.", "(rtn|ipn)-upgrade-downgrade" => "&#9492;&#9472; Anytime s2Member changes a User's Role after a paid Subscr. Modification.") as $ws_plugin__s2member_temp_s_value => $ws_plugin__s2member_temp_s_label)
249
+ echo '<input type="checkbox" name="ws_plugin__s2member_custom_reg_auto_opt_outs[]" id="ws-plugin--s2member-custom-reg-auto-opt-outs-'.esc_attr(preg_replace("/[^a-z0-9_\-]/", "-", $ws_plugin__s2member_temp_s_value)).'" value="'.esc_attr($ws_plugin__s2member_temp_s_value).'"'.((in_array($ws_plugin__s2member_temp_s_value, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_outs"])) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-custom-reg-auto-opt-outs-'.esc_attr(preg_replace("/[^a-z0-9_\-]/", "-", $ws_plugin__s2member_temp_s_value)).'">'.$ws_plugin__s2member_temp_s_label.'</label><br />'."\n";
250
+ echo '</div>'."\n";
251
+ echo '</td>'."\n";
252
+ /**/
253
+ echo '</tr>'."\n";
254
+ echo '<tr>'."\n";
255
+ /**/
256
+ echo '<th>'."\n";
257
+ echo '<label for="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">'."\n";
258
+ echo 'Also Process List Transitions Automatically?'."\n";
259
+ echo '</label>'."\n";
260
+ echo '</th>'."\n";
261
+ /**/
262
+ echo '</tr>'."\n";
263
+ echo '<tr>'."\n";
264
+ /**/
265
+ echo '<td>'."\n";
266
+ echo '<select name="ws_plugin__s2member_custom_reg_auto_opt_out_transitions" id="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">'."\n";
267
+ echo '<option value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"]) ? ' selected="selected"' : '').'>No ( do NOT transition mailing list subscribers automatically )</option>'."\n";
268
+ echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"] === "1") ? ' selected="selected"' : '').'>Yes ( automatically transition, if able to remove from a previous list )</option>'."\n";
269
+ echo '<option value="2"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"] === "2") ? ' selected="selected"' : '').'>Yes ( always automatically transition, even if NOT removed from a previous list )</option>'."\n";
270
+ echo '</select><br />'."\n";
271
+ echo '<em><strong>*Transitions*</strong> When/if s2Member automatically removes a Member from Lists at their current Level# ( based on your configuration in the previous section ), this setting tells s2Member that it should <strong>also</strong> transition the Member to any Lists you\'ve configured at the new Access Level# ( i.e. Role ) they are being changed to. For example, if a Member is demoted from Level #1 to Level #0, do you want s2Member to add them to the Level #0 List(s) after it removes them from the Level #1 List(s)?</em><br /><br />'."\n";
272
+ echo '<em><strong>*If removed from a previous list, or NOT?*</strong> You can choose your preference above. When/if s2Member automatically transitions a mailing list subscriber, it will first try to remove the subscriber from a previous mailing list. If s2Member is able to remove the subscriber from a previous list before the transition takes place, s2Member will then make an attempt ( based on your configuration ) to transition the subscriber to a new/different list silently ( e.g. without a new confirmation email being sent out ). If s2Member is NOT able to remove a subscriber from a previous list, it can - ( if configured to do so ), still transition a subscriber to a new list, by sending the subscriber a new email confirmation letter ( e.g. this is NOT silent, because you absolutely NEED the subscriber\'s permission in this case ).</em><br /><br />'."\n";
273
+ echo '<em><strong>*Seamless with MailChimp®*</strong> If enabled, Automatic List Transitions work seamlessly with MailChimp®. Automatic List Transitions also work with AWeber®, but AWeber® will ALWAYS send the User/Member a new confirmation email, asking them to confirm changes to their mailing list subscription with you. Work is underway to improve this aspect of s2Member\'s integration with AWeber® in a future release. Ideally, a Customer would be transitioned silently behind the scene with AWeber® too, when appropriate.</em>'."\n";
274
+ echo '</td>'."\n";
275
+ /**/
276
+ echo '</tr>'."\n";
277
+ echo '</tbody>'."\n";
278
+ echo '</table>'."\n";
279
+ echo '</div>'."\n";
280
+ /**/
281
+ echo '</div>'."\n";
282
+ /**/
283
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_opt_out", get_defined_vars());
284
  }
285
  /**/
286
+ if(apply_filters("ws_plugin__s2member_during_els_ops_page_during_left_sections_display_other_methods", true, get_defined_vars()))
287
  {
288
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_before_other_methods", get_defined_vars());
289
  /**/
290
+ echo '<div class="ws-menu-page-group" title="Other List Server Integration Methods">'."\n";
291
  /**/
292
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">'."\n";
293
+ echo '<h3>Other List Server Integrations ( there\'s always a way )</h3>'."\n";
294
+ echo '<p>Check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Specific Post/Page` Notifications that are available to you through the s2Member API. These make it possible to integrate with 3rd party applications; like list servers, affiliate programs, and other back-office routines; in more advanced ways. You will probably need to get help from a web developer though. s2Member API Notifications require some light PHP scripting by someone familiar with web service connections.</p>'."\n";
295
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_other_methods", get_defined_vars());
296
+ echo '</div>'."\n";
297
  /**/
298
+ echo '</div>'."\n";
299
  /**/
300
+ do_action("ws_plugin__s2member_during_els_ops_page_during_left_sections_after_other_methods", get_defined_vars());
301
  }
302
  /**/
303
+ do_action("ws_plugin__s2member_during_els_ops_page_after_left_sections", get_defined_vars());
304
  /**/
305
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
306
  /**/
307
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save All Changes" /></p>'."\n";
308
  /**/
309
+ echo '</form>'."\n";
310
  /**/
311
+ echo '</td>'."\n";
312
  /**/
313
+ echo '<td class="ws-menu-page-table-r">'."\n";
314
+ c_ws_plugin__s2member_menu_pages_rs::display();
315
+ echo '</td>'."\n";
316
  /**/
317
+ echo '</tr>'."\n";
318
+ echo '</tbody>'."\n";
319
+ echo '</table>'."\n";
320
  /**/
321
+ echo '</div>'."\n";
322
  }
323
  }
324
  }
325
  /**/
326
+ new c_ws_plugin__s2member_menu_page_els_ops();
327
  ?>
includes/menu-pages/mms-ops.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Menu_Pages
15
  * @since 3.0
16
  */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
- if (!class_exists ("c_ws_plugin__s2member_menu_page_mms_ops"))
21
  {
22
  /**
23
  * Menu page for the s2Member plugin ( Main Multisite Options page ).
@@ -27,314 +27,314 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_mms_ops"))
27
  */
28
  class c_ws_plugin__s2member_menu_page_mms_ops
29
  {
30
- public function __construct ()
31
  {
32
- echo '<div class="wrap ws-menu-page">' . "\n";
33
  /**/
34
- echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
35
- echo '<h2>s2Member® Multisite ( Configuration )</h2>' . "\n";
36
  /**/
37
- echo '<table class="ws-menu-page-table">' . "\n";
38
- echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
39
- echo '<tr class="ws-menu-page-table-tr">' . "\n";
40
- echo '<td class="ws-menu-page-table-l">' . "\n";
41
  /**/
42
- if (is_multisite () && is_main_site ()) /* These panels will ONLY be available on the Main Site; with Multisite Networking. */
43
  {
44
- echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
45
- 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";
46
- echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
47
  /**/
48
- do_action ("ws_plugin__s2member_during_mms_ops_page_before_left_sections", get_defined_vars ());
49
  /**/
50
- if (apply_filters ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_display_mms_patches", true, get_defined_vars ()))
51
  {
52
- do_action ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_before_mms_patches", get_defined_vars ());
53
  /**/
54
- echo '<div class="ws-menu-page-group" title="Multisite WordPress® Patches" default-state="open">' . "\n";
55
  /**/
56
- echo '<div class="ws-menu-page-section ws-plugin--s2member-mms-patches-section">' . "\n";
57
- echo '<img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/small-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
58
- echo '<h3>Multisite WordPress® Patches ( required for compatiblity )</h3>' . "\n";
59
- echo '<p>In order for s2Member to function properly in a Multisite environment, you MUST implement four patches. One goes into your <code>/wp-login.php</code> file, one into <code>/wp-includes/load.php</code>, one into <code>/wp-includes/ms-functions.php</code>, and another into <code>/wp-admin/user-new.php</code>. We have TRAC tickets into WordPress® for these changes. However, until the official release of WordPress® includes these updates, you will need to use the automatic patcher below. All you do is check the box &amp; click Save.</p>' . "\n";
60
- do_action ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_during_mms_patches", get_defined_vars ());
61
  /**/
62
- echo '<table class="form-table">' . "\n";
63
- echo '<tbody>' . "\n";
64
- echo '<tr>' . "\n";
65
  /**/
66
- echo '<th>' . "\n";
67
- echo '<label for="ws-plugin--s2member-mms-auto-patch">' . "\n";
68
- echo 'Patch Automatically? ( the easiest way )' . "\n";
69
- echo '</label>' . "\n";
70
- echo '</th>' . "\n";
71
  /**/
72
- echo '</tr>' . "\n";
73
- echo '<tr>' . "\n";
74
  /**/
75
- echo '<td>' . "\n";
76
  /**/
77
- if (defined ("DISALLOW_FILE_MODS") && DISALLOW_FILE_MODS)
78
  {
79
- echo '<select name="ws_plugin__s2member_mms_auto_patch" id="ws-plugin--s2member-mms-auto-patch" disabled="disabled">' . "\n";
80
- echo '<option value="0" selected="selected">No ( I\'ll patch WordPress® myself )</option>' . "\n";
81
- echo '</select><br />' . "\n";
82
- echo '<em class="ws-menu-page-hilite">This is now locked. Your <code>/wp-config.php</code> file says: <code>DISALLOW_FILE_MODS = true</code></em>.' . "\n";
83
  }
84
  else /* Otherwise we can display these options. */
85
  {
86
- echo '<select name="ws_plugin__s2member_mms_auto_patch" id="ws-plugin--s2member-mms-auto-patch">' . "\n";
87
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_auto_patch"]) ? ' selected="selected"' : '') . '>Yes ( automatically patch WordPress® )</option>' . "\n";
88
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_auto_patch"]) ? ' selected="selected"' : '') . '>No ( I\'ll patch WordPress® myself )</option>' . "\n";
89
- echo '</select><br />' . "\n";
90
- echo '<em class="ws-menu-page-hilite">These files MUST be patched, each time you upgrade the WordPress® core. If you set this option to <code>Yes ( Patch Automatically )</code>, s2Member will patch your installation now, and also in the future, should you upgrade to newer version. That way, you won\'t need to patch manually each time WordPress® is upgraded.</em>' . "\n";
91
  }
92
  /**/
93
- echo '</td>' . "\n";
94
- /**/
95
- echo '</tr>' . "\n";
96
- echo '</tbody>' . "\n";
97
- echo '</table>' . "\n";
98
- /**/
99
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
100
- /**/
101
- echo '<div id="ws-plugin--s2member-mms-patches-details-wrapper">' . "\n";
102
- echo '<h3>Rather Do It Yourself? ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-patches-details\').toggle(); return false;" class="ws-dotted-link">manual instructions</a> )</h3>' . "\n";
103
- echo '<div id="ws-plugin--s2member-mms-patches-details" style="display:none;">' . "\n";
104
- echo '<p><strong>Patch #1</strong> ( /wp-login.php )</p>' . "\n";
105
- echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/mms-patch-wp-login.x-php")) . '</p>' . "\n";
106
- echo '<p><strong>Patch #2</strong> ( /wp-includes/load.php )</p>' . "\n";
107
- echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/mms-patch-load.x-php")) . '</p>' . "\n";
108
- echo '<p><strong>Patch #3</strong> ( /wp-admin/user-new.php )</p>' . "\n";
109
- echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/mms-patch-user-new.x-php")) . '</p>' . "\n";
110
- echo '<p><strong>Patch #4</strong> ( /wp-includes/ms-functions.php )</p>' . "\n";
111
- echo '<p>' . c_ws_plugin__s2member_utils_strings::highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/mms-patch-ms-functions.x-php")) . '</p>' . "\n";
112
- echo '<p><em class="ws-menu-page-hilite">Don\'t forget to patch these files again, each time you upgrade the WordPress® core.</em></p>' . "\n";
113
- echo '</div>' . "\n";
114
- echo '</div>' . "\n";
115
- echo '</div>' . "\n";
116
- /**/
117
- echo '</div>' . "\n";
118
- /**/
119
- do_action ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_after_mms_patches", get_defined_vars ());
120
  }
121
  /**/
122
- if (apply_filters ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_display_mms_registration", true, get_defined_vars ()))
123
  {
124
- do_action ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_before_mms_registration", get_defined_vars ());
125
- /**/
126
- echo '<div class="ws-menu-page-group" title="Multisite Registration Configuration" default-state="open">' . "\n";
127
- /**/
128
- echo '<div class="ws-menu-page-section ws-plugin--s2member-mms-registration-section">' . "\n";
129
- echo '<img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
130
- echo '<h3>Multisite Registration ( Main Site Configuration )</h3>' . "\n";
131
- echo '<p>s2Member supports Free Subscribers <em>( at Level #0 )</em>, and several Primary Roles created by the s2Member plugin (<em> i.e. s2Member Levels 1-4, or up to the number of configured Levels )</em>. If you want your visitors to be capable of registering absolutely free, you will want to "allow" Open Registration. Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0.</p>' . "\n";
132
- echo '<p><strong>Running A Multisite Blog Farm?</strong> With Multisite Networking enabled, your Main Site could ALSO offer a Customer access to create a Blog of their own <em>( optional )</em>, where a Customer becomes a "Member" of your Main Site, and also a Blog Owner/Administrator of at least one other Blog on your Network. With s2Member installed <em>( Network wide )</em>, each of your Blog Owners could offer Membership too, using a single copy of the s2Member plugin, which is a great selling point<em>!</em> We refer to this type of installation as a Multisite Blog Farm.</p>' . "\n";
133
- echo '<p>Multisite Networking makes a new Registration Form available <em>( driven by your theme )</em>; which we refer to as: <code>/wp-signup.php</code>. If, and only if, you\'re planning to offer Blogs, you MUST use <a href="' . esc_attr (c_ws_plugin__s2member_utils_urls::wp_signup_url ()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times ( for testing purposes ), regardless of configuration.' . ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">/wp-signup.php</a>, instead of using the Standard Login/Registration Form. In a Multisite installation, we refer to the Standard Login/Registration Form, as: <a href="' . esc_attr (c_ws_plugin__s2member_utils_urls::wp_register_url ()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times ( for testing purposes ), regardless of configuration.' . ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">/wp-login.php?action=register</a>. If you\'re planning to offer Membership Access only, and NOT Blogs, you can simply use the <a href="' . esc_attr (c_ws_plugin__s2member_utils_urls::wp_register_url ()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times ( for testing purposes ), regardless of configuration.' . ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">Standard Login/Registration Form</a>, which is easily customized through <code>s2Member -> General Options -> Login/Registration Design</code>.</p>' . "\n";
134
- echo '<p>In either case, s2Member Pro Forms are possible too. If you\'ve purchased s2Member Pro, you could use Pro Forms instead of these WordPress® defaults. That being said, even with s2Member Pro Forms, if you are offering Blogs, you will still need to facilitate the actual creation of each Blog through <code>/wp-signup.php</code>. In other words, Customers can register through s2Member Pro Forms, and even checkout. But when it comes time to setup a new Blog, you will need to redirect your Customer to <code>/wp-signup.php</code>, while they are logged-in. This will allow them to create a new Blog on your Network. That is, if they are allowed to <em>( based on your configuration below )</em>.</p>' . "\n";
135
- echo (c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? '<p><em><strong>BuddyPress:</strong> BuddyPress will use its own Registration Form, powered by your theme.<br />( BuddyPress can handle both Membership and Blog creation in its integration )<br />( <a href="' . esc_attr (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your BuddyPress Registration Form.\\n* However, you will probably be redirected away from this BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.\');">' . esc_html (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . '</a> )</em></p>' . "\n" : '';
136
- do_action ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_during_mms_registration", get_defined_vars ());
137
- /**/
138
- echo '<div id="ws-plugin--s2member-mms-registration-support-package-details-wrapper">' . "\n";
139
- echo '<h4 style="margin-bottom:0;">Running a Multisite Blog Farm? ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-registration-support-package-details\').toggle(); return false;" class="ws-dotted-link">click here / please read</a> )</h4>' . "\n";
140
- echo '<div id="ws-plugin--s2member-mms-registration-support-package-details" style="display:none;">' . "\n";
141
- echo '<p>The most important thing to do when setting up a Blog Farm with s2Member, is to add this line to your <code>/wp-config.php</code> file: <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"MULTISITE_FARM"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>. This will add a default layer of security, to all Blogs within your Network, with respect to s2Member. <strong>But, before you go live</strong>, please contact <a href="' . esc_attr (c_ws_plugin__s2member_readmes::parse_readme_value ("Pro Module / Prices")) . '" target="_blank" rel="external">s2Member.com</a> for full documentation. There is some additional functionality that can be enabled for security on a Blog Farm installation; and also some menus/documentation/functionality that can be disabled. You will be asked to purchase our <a href="' . esc_attr (c_ws_plugin__s2member_readmes::parse_readme_value ("Pro Module / Prices")) . '" target="_blank" rel="external">Network Support Package</a> when you need assistance in this regard.</p>' . "\n";
142
- echo '<p>Multisite Blog Farms require a site owner that fully understands the potential security risks associated with Blog Farming. s2Member\'s <a href="' . esc_attr (c_ws_plugin__s2member_readmes::parse_readme_value ("Pro Module / Prices")) . '" target="_blank" rel="external">Network Support Package</a> provides you with the information you need, and priority support for anything about s2Member that you don\'t understand. In addition, our Network Support Package includes a lengthy PDF file that details a list of things affected by <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"MULTISITE_FARM"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>, best practices, and other supplemental documentation focused on Blog Farms.</p>' . "\n";
143
- echo '<p><em><strong>Definition of a Multisite Blog Farm:</strong> If your Network is making it possible for "Members" of your Main Site, to create and/or manage Blogs (in any way), s2Member will consider your installation to be a Multisite Blog Farm. That being said, some site owners run a Multisite Network for the purpose of maintaining their own sites. The term Multisite Blog Farm does NOT apply to a Network that hosts multiple Child Blogs, all of which are operated by a single site owner and/or a single company. Again, a Multisite Blog Farm ( in the eyes of s2Member ), is any Network that is making it possible for "Members" of its Main Site, to create and/or manage Blogs; where one or more of these Child Blogs is being administered by a Customer ( e.g. if you offer both Membership and Blog creation, as configured below ).</em></p>' . "\n";
144
- echo '<p><em><strong>When NOT to run a Multisite Blog Farm:</strong> If you run a Multisite Network for the purpose of maintaining your own sites. You should NOT run a Multisite Blog Farm. You can still activate s2Member Network-wide, if you like ( optional ), but the advanced security considerations offered through s2Member\'s Multisite Blog Farm functionality are NOT needed in this case; because all of the Child Blogs in your Network belong to trusted Administrators ( i.e. your Customers are NOT going to run Child Blogs on your Network in this case ).</em></p>' . "\n";
145
- echo '</div>' . "\n";
146
- echo '</div>' . "\n";
147
- /**/
148
- echo '<div class="ws-menu-page-hr"></div>' . "\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-mms-registration-file">' . "\n";
156
- echo 'What Do You Plan To Offer? ( please choose one )' . "\n";
157
- echo '</label>' . "\n";
158
- echo '</th>' . "\n";
159
- /**/
160
- echo '</tr>' . "\n";
161
- echo '<tr>' . "\n";
162
- /**/
163
- echo '<td>' . "\n";
164
- /**/
165
- if (defined ("MULTISITE_FARM") && MULTISITE_FARM) /* Lock this down if a config option is set in /wp-config.php. */
166
  {
167
- echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file" disabled="disabled">' . "\n";
168
- echo '<option value="wp-signup" selected="selected">Blog Farm ( I plan to offer both Membership &amp; Blog creation )</option>' . "\n";
169
- echo '</select><br />' . "\n";
170
- echo '<em class="ws-menu-page-hilite">This is now locked. Your <code>/wp-config.php</code> file says: <code>MULTISITE_FARM = true</code></em>.' . "\n";
171
  }
172
  else /* Otherwise we can display these options normally. */
173
  {
174
- echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file">' . "\n";
175
- echo '<option value="wp-login"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-login") ? ' selected="selected"' : '') . '>Membership Only ( I\'m NOT offering Blogs )</option>' . "\n";
176
- echo '<option value="wp-signup"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-signup") ? ' selected="selected"' : '') . '>Blog Farm ( I plan to offer both Membership &amp; Blog creation )</option>' . "\n";
177
- echo '</select><br />' . "\n";
178
- echo 'Depending on your selection, the options below may change.' . "\n";
179
  }
180
  /**/
181
- echo '</td>' . "\n";
182
- /**/
183
- echo '</tr>' . "\n";
184
- echo '</tbody>' . "\n";
185
- echo '</table>' . "\n";
186
- /**/
187
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
188
- /**/
189
- echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-login" style="margin:0;">' . "\n";
190
- echo '<tbody>' . "\n";
191
- echo '<tr>' . "\n";
192
- /**/
193
- echo '<th style="padding-top:0;">' . "\n";
194
- echo '<label for="ws-plugin--s2member-allow-subscribers-in">' . "\n";
195
- echo 'Your Main Site / Allow Open Registration? ( via <code>wp-login.php?action=register</code> )' . "\n";
196
- echo '</label>' . "\n";
197
- echo '</th>' . "\n";
198
- /**/
199
- echo '</tr>' . "\n";
200
- echo '<tr>' . "\n";
201
- /**/
202
- echo '<td>' . "\n";
203
- echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">' . "\n";
204
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
205
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
206
- echo '</select><br />' . "\n";
207
- echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . esc_attr (c_ws_plugin__s2member_utils_urls::wp_register_url ()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times ( for testing purposes ), regardless of configuration.' . ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">wp-login.php?action=register</a> ( on your Main Site ). When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
208
- echo '</td>' . "\n";
209
- /**/
210
- echo '</tr>' . "\n";
211
- echo '</tbody>' . "\n";
212
- echo '</table>' . "\n";
213
- /**/
214
- echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup" style="margin:0;">' . "\n";
215
- echo '<tbody>' . "\n";
216
- echo '<tr>' . "\n";
217
- /**/
218
- echo '<th style="padding-top:0;">' . "\n";
219
- echo '<label for="ws-plugin--s2member-mms-registration-grants">' . "\n";
220
- echo 'Your Main Site / Allow Open Registration? ( via <code>wp-signup.php</code> )' . "\n";
221
- echo '</label>' . "\n";
222
- echo '</th>' . "\n";
223
- /**/
224
- echo '</tr>' . "\n";
225
- echo '<tr>' . "\n";
226
- /**/
227
- echo '<td style="padding-bottom:0;">' . "\n";
228
- echo '<select name="ws_plugin__s2member_mms_registration_grants" id="ws-plugin--s2member-mms-registration-grants">' . "\n";
229
- echo '<option value="none"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "none") ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
230
- echo '<option value="user"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "user") ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
231
- echo '<option value="all"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "all") ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers, with a free Blog too )</option>' . "\n";
232
- echo '</select><br />' . "\n";
233
- echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . esc_attr (c_ws_plugin__s2member_utils_urls::wp_signup_url ()) . '" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times ( for testing purposes ), regardless of configuration.' . ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( ' . c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_urls::bp_register_url ()) . ' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '') . '\');">wp-signup.php</a> ( on your Main Site ).' . "\n";
234
- echo '</td>' . "\n";
235
- /**/
236
- echo '</tr>' . "\n";
237
- echo '</tbody>' . "\n";
238
- echo '</table>' . "\n";
239
- /**/
240
- echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup ws-plugin--s2member-mms-registration-wp-signup-blogs-level0">' . "\n";
241
- echo '<tbody>' . "\n";
242
- echo '<tr>' . "\n";
243
- /**/
244
- echo '<th>' . "\n";
245
- echo '<label for="ws-plugin--s2member-mms-registration-blogs-level0">' . "\n";
246
- echo 'Level #0 ( Free Subscribers ):' . "\n";
247
- echo '</label>' . "\n";
248
- echo '</th>' . "\n";
249
- /**/
250
- echo '</tr>' . "\n";
251
- echo '<tr>' . "\n";
252
- /**/
253
- echo '<td style="padding-bottom:0;">' . "\n";
254
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_mms_registration_blogs_level0" id="ws-plugin--s2member-mms-registration-blogs-level0" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_blogs_level0"]) . '" /><br />' . "\n";
255
- echo 'How many blogs can a Free Subscriber create?' . "\n";
256
- echo '</td>' . "\n";
257
- /**/
258
- echo '</tr>' . "\n";
259
- echo '</tbody>' . "\n";
260
- echo '</table>' . "\n";
261
- /**/
262
- echo '<div class="ws-menu-page-hr ws-plugin--s2member-mms-registration-wp-signup"></div>' . "\n";
263
- /**/
264
- echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup" style="margin:0;">' . "\n";
265
- echo '<tbody>' . "\n";
266
- /**/
267
- for ($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
268
  {
269
- echo '<tr>' . "\n";
270
  /**/
271
- echo '<th style="padding-top:0;">' . "\n";
272
- echo '<label for="ws-plugin--s2member-mms-registration-blogs-level' . $n . '">' . "\n";
273
- echo 'Membership Level #' . $n . ' / Maximum Blogs Allowed:' . "\n";
274
- echo '</label>' . "\n";
275
- echo '</th>' . "\n";
276
  /**/
277
- echo '</tr>' . "\n";
278
- echo '<tr>' . "\n";
279
  /**/
280
- echo '<td>' . "\n";
281
- echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_mms_registration_blogs_level' . $n . '" id="ws-plugin--s2member-mms-registration-blogs-level' . $n . '" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_blogs_level" . $n]) . '" /><br />' . "\n";
282
- echo 'How many blogs can a Member ( at Level #' . $n . ' ) create?' . "\n";
283
- echo '</td>' . "\n";
284
  /**/
285
- echo '</tr>' . "\n";
286
  }
287
  /**/
288
- echo '</tbody>' . "\n";
289
- echo '</table>' . "\n";
290
- echo '</div>' . "\n";
291
  /**/
292
- echo '</div>' . "\n";
293
  /**/
294
- do_action ("ws_plugin__s2member_during_mms_ops_page_during_left_sections_after_mms_registration", get_defined_vars ());
295
  }
296
- do_action ("ws_plugin__s2member_during_mms_ops_page_after_left_sections", get_defined_vars ());
297
  /**/
298
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
299
  /**/
300
- echo '<p class="submit"><input type="submit" class="button-primary" value="Save All Changes" /></p>' . "\n";
301
  /**/
302
- echo '</form>' . "\n";
303
  }
304
  else /* Otherwise, we can display a simple notation; leading into Multisite Networking. */
305
  {
306
- echo '<p style="margin-top:0;"><span class="ws-menu-page-hilite">Your WordPress® installation does not have Multisite Networking enabled.<br />Which is perfectly OK :-) Multisite Networking is 100% completely optional.</span></p>' . "\n";
307
- echo '<img src="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]) . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
308
  /**/
309
- if (file_exists ($ws_plugin__s2member_temp = dirname (dirname (dirname (__FILE__))) . "/ms.txt"))
310
  {
311
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
312
  /**/
313
- if (!function_exists ("NC_Markdown"))
314
- include_once dirname (dirname (__FILE__)) . "/_xtnls/markdown/nc-markdown.inc.php";
315
  /**/
316
- $ws_plugin__s2member_temp = file_get_contents ($ws_plugin__s2member_temp);
317
- $ws_plugin__s2member_temp = preg_replace ("/(\=)( )(.+?)( )(\=)/", "<h3>$3</h3>", $ws_plugin__s2member_temp);
318
- $ws_plugin__s2member_temp = NC_Markdown ($ws_plugin__s2member_temp);
319
  /**/
320
- echo preg_replace ("/(\<a)( href)/i", "$1" . ' target="_blank" rel="nofollow external"' . "$2", $ws_plugin__s2member_temp);
321
  }
322
  }
323
  /**/
324
- echo '</td>' . "\n";
325
  /**/
326
- echo '<td class="ws-menu-page-table-r">' . "\n";
327
- c_ws_plugin__s2member_menu_pages_rs::display ();
328
- echo '</td>' . "\n";
329
  /**/
330
- echo '</tr>' . "\n";
331
- echo '</tbody>' . "\n";
332
- echo '</table>' . "\n";
333
  /**/
334
- echo '</div>' . "\n";
335
  }
336
  }
337
  }
338
  /**/
339
- new c_ws_plugin__s2member_menu_page_mms_ops ();
340
  ?>
14
  * @package s2Member\Menu_Pages
15
  * @since 3.0
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
  /**/
20
+ if(!class_exists("c_ws_plugin__s2member_menu_page_mms_ops"))
21
  {
22
  /**
23
  * Menu page for the s2Member plugin ( Main Multisite Options page ).
27
  */
28
  class c_ws_plugin__s2member_menu_page_mms_ops
29
  {
30
+ public function __construct()
31
  {
32
+ echo '<div class="wrap ws-menu-page">'."\n";
33
  /**/
34
+ echo '<div id="icon-plugins" class="icon32"><br /></div>'."\n";
35
+ echo '<h2>s2Member® Multisite ( Configuration )</h2>'."\n";
36
  /**/
37
+ echo '<table class="ws-menu-page-table">'."\n";
38
+ echo '<tbody class="ws-menu-page-table-tbody">'."\n";
39
+ echo '<tr class="ws-menu-page-table-tr">'."\n";
40
+ echo '<td class="ws-menu-page-table-l">'."\n";
41
  /**/
42
+ if(is_multisite() && is_main_site()) /* These panels will ONLY be available on the Main Site; with Multisite Networking. */
43
  {
44
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">'."\n";
45
+ 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";
46
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />'."\n";
47
  /**/
48
+ do_action("ws_plugin__s2member_during_mms_ops_page_before_left_sections", get_defined_vars());
49
  /**/
50
+ if(apply_filters("ws_plugin__s2member_during_mms_ops_page_during_left_sections_display_mms_patches", true, get_defined_vars()))
51
  {
52
+ do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_before_mms_patches", get_defined_vars());
53
  /**/
54
+ echo '<div class="ws-menu-page-group" title="Multisite WordPress® Patches" default-state="open">'."\n";
55
  /**/
56
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-mms-patches-section">'."\n";
57
+ echo '<img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/small-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />'."\n";
58
+ echo '<h3>Multisite WordPress® Patches ( required for compatiblity )</h3>'."\n";
59
+ echo '<p>In order for s2Member to function properly in a Multisite environment, you MUST implement four patches. One goes into your <code>/wp-login.php</code> file, one into <code>/wp-includes/load.php</code>, one into <code>/wp-includes/ms-functions.php</code>, and another into <code>/wp-admin/user-new.php</code>. We have TRAC tickets into WordPress® for these changes. However, until the official release of WordPress® includes these updates, you will need to use the automatic patcher below. All you do is check the box &amp; click Save.</p>'."\n";
60
+ do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_during_mms_patches", get_defined_vars());
61
  /**/
62
+ echo '<table class="form-table">'."\n";
63
+ echo '<tbody>'."\n";
64
+ echo '<tr>'."\n";
65
  /**/
66
+ echo '<th>'."\n";
67
+ echo '<label for="ws-plugin--s2member-mms-auto-patch">'."\n";
68
+ echo 'Patch Automatically? ( the easiest way )'."\n";
69
+ echo '</label>'."\n";
70
+ echo '</th>'."\n";
71
  /**/
72
+ echo '</tr>'."\n";
73
+ echo '<tr>'."\n";
74
  /**/
75
+ echo '<td>'."\n";
76
  /**/
77
+ if(defined("DISALLOW_FILE_MODS") && DISALLOW_FILE_MODS)
78
  {
79
+ echo '<select name="ws_plugin__s2member_mms_auto_patch" id="ws-plugin--s2member-mms-auto-patch" disabled="disabled">'."\n";
80
+ echo '<option value="0" selected="selected">No ( I\'ll patch WordPress® myself )</option>'."\n";
81
+ echo '</select><br />'."\n";
82
+ echo '<em class="ws-menu-page-hilite">This is now locked. Your <code>/wp-config.php</code> file says: <code>DISALLOW_FILE_MODS = true</code></em>.'."\n";
83
  }
84
  else /* Otherwise we can display these options. */
85
  {
86
+ echo '<select name="ws_plugin__s2member_mms_auto_patch" id="ws-plugin--s2member-mms-auto-patch">'."\n";
87
+ echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_auto_patch"]) ? ' selected="selected"' : '').'>Yes ( automatically patch WordPress® )</option>'."\n";
88
+ echo '<option value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_auto_patch"]) ? ' selected="selected"' : '').'>No ( I\'ll patch WordPress® myself )</option>'."\n";
89
+ echo '</select><br />'."\n";
90
+ echo '<em class="ws-menu-page-hilite">These files MUST be patched, each time you upgrade the WordPress® core. If you set this option to <code>Yes ( Patch Automatically )</code>, s2Member will patch your installation now, and also in the future, should you upgrade to newer version. That way, you won\'t need to patch manually each time WordPress® is upgraded.</em>'."\n";
91
  }
92
  /**/
93
+ echo '</td>'."\n";
94
+ /**/
95
+ echo '</tr>'."\n";
96
+ echo '</tbody>'."\n";
97
+ echo '</table>'."\n";
98
+ /**/
99
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
100
+ /**/
101
+ echo '<div id="ws-plugin--s2member-mms-patches-details-wrapper">'."\n";
102
+ echo '<h3>Rather Do It Yourself? ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-patches-details\').toggle(); return false;" class="ws-dotted-link">manual instructions</a> )</h3>'."\n";
103
+ echo '<div id="ws-plugin--s2member-mms-patches-details" style="display:none;">'."\n";
104
+ echo '<p><strong>Patch #1</strong> ( /wp-login.php )</p>'."\n";
105
+ echo '<p>'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/mms-patch-wp-login.x-php")).'</p>'."\n";
106
+ echo '<p><strong>Patch #2</strong> ( /wp-includes/load.php )</p>'."\n";
107
+ echo '<p>'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/mms-patch-load.x-php")).'</p>'."\n";
108
+ echo '<p><strong>Patch #3</strong> ( /wp-admin/user-new.php )</p>'."\n";
109
+ echo '<p>'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/mms-patch-user-new.x-php")).'</p>'."\n";
110
+ echo '<p><strong>Patch #4</strong> ( /wp-includes/ms-functions.php )</p>'."\n";
111
+ echo '<p>'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/mms-patch-ms-functions.x-php")).'</p>'."\n";
112
+ echo '<p><em class="ws-menu-page-hilite">Don\'t forget to patch these files again, each time you upgrade the WordPress® core.</em></p>'."\n";
113
+ echo '</div>'."\n";
114
+ echo '</div>'."\n";
115
+ echo '</div>'."\n";
116
+ /**/
117
+ echo '</div>'."\n";
118
+ /**/
119
+ do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_after_mms_patches", get_defined_vars());
120
  }
121
  /**/
122
+ if(apply_filters("ws_plugin__s2member_during_mms_ops_page_during_left_sections_display_mms_registration", true, get_defined_vars()))
123
  {
124
+ do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_before_mms_registration", get_defined_vars());
125
+ /**/
126
+ echo '<div class="ws-menu-page-group" title="Multisite Registration Configuration" default-state="open">'."\n";
127
+ /**/
128
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-mms-registration-section">'."\n";
129
+ echo '<img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />'."\n";
130
+ echo '<h3>Multisite Registration ( Main Site Configuration )</h3>'."\n";
131
+ echo '<p>s2Member supports Free Subscribers <em>( at Level #0 )</em>, and several Primary Roles created by the s2Member plugin (<em> i.e. s2Member Levels 1-4, or up to the number of configured Levels )</em>. If you want your visitors to be capable of registering absolutely free, you will want to "allow" Open Registration. Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0.</p>'."\n";
132
+ echo '<p><strong>Running A Multisite Blog Farm?</strong> With Multisite Networking enabled, your Main Site could ALSO offer a Customer access to create a Blog of their own <em>( optional )</em>, where a Customer becomes a "Member" of your Main Site, and also a Blog Owner/Administrator of at least one other Blog on your Network. With s2Member installed <em>( Network wide )</em>, each of your Blog Owners could offer Membership too, using a single copy of the s2Member plugin, which is a great selling point<em>!</em> We refer to this type of installation as a Multisite Blog Farm.</p>'."\n";
133
+ echo '<p>Multisite Networking makes a new Registration Form available <em>( driven by your theme )</em>; which we refer to as: <code>/wp-signup.php</code>. If, and only if, you\'re planning to offer Blogs, you MUST use <a href="'.esc_attr(c_ws_plugin__s2member_utils_urls::wp_signup_url()).'" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times ( for testing purposes ), regardless of configuration.'.((c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( '.c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()).' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '').'\');">/wp-signup.php</a>, instead of using the Standard Login/Registration Form. In a Multisite installation, we refer to the Standard Login/Registration Form, as: <a href="'.esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()).'" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times ( for testing purposes ), regardless of configuration.'.((c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( '.c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()).' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '').'\');">/wp-login.php?action=register</a>. If you\'re planning to offer Membership Access only, and NOT Blogs, you can simply use the <a href="'.esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()).'" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times ( for testing purposes ), regardless of configuration.'.((c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( '.c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()).' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '').'\');">Standard Login/Registration Form</a>, which is easily customized through <code>s2Member -> General Options -> Login/Registration Design</code>.</p>'."\n";
134
+ echo '<p>In either case, s2Member Pro Forms are possible too. If you\'ve purchased s2Member Pro, you could use Pro Forms instead of these WordPress® defaults. That being said, even with s2Member Pro Forms, if you are offering Blogs, you will still need to facilitate the actual creation of each Blog through <code>/wp-signup.php</code>. In other words, Customers can register through s2Member Pro Forms, and even checkout. But when it comes time to setup a new Blog, you will need to redirect your Customer to <code>/wp-signup.php</code>, while they are logged-in. This will allow them to create a new Blog on your Network. That is, if they are allowed to <em>( based on your configuration below )</em>.</p>'."\n";
135
+ echo (c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '<p><em><strong>BuddyPress:</strong> BuddyPress will use its own Registration Form, powered by your theme.<br />( BuddyPress can handle both Membership and Blog creation in its integration )<br />( <a href="'.esc_attr(c_ws_plugin__s2member_utils_urls::bp_register_url()).'" target="_blank" rel="external" onclick="alert(\'s2Member will now open your BuddyPress Registration Form.\\n* However, you will probably be redirected away from this BuddyPress Registration Form ( '.c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()).' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.\');">'.esc_html(c_ws_plugin__s2member_utils_urls::bp_register_url()).'</a> )</em></p>'."\n" : '';
136
+ do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_during_mms_registration", get_defined_vars());
137
+ /**/
138
+ echo '<div id="ws-plugin--s2member-mms-registration-support-package-details-wrapper">'."\n";
139
+ echo '<h4 style="margin-bottom:0;">Running a Multisite Blog Farm? ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-registration-support-package-details\').toggle(); return false;" class="ws-dotted-link">click here / please read</a> )</h4>'."\n";
140
+ echo '<div id="ws-plugin--s2member-mms-registration-support-package-details" style="display:none;">'."\n";
141
+ echo '<p>The most important thing to do when setting up a Blog Farm with s2Member, is to add this line to your <code>/wp-config.php</code> file: <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"MULTISITE_FARM"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>. This will add a default layer of security, to all Blogs within your Network, with respect to s2Member. <strong>But, before you go live</strong>, please contact <a href="'.esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")).'" target="_blank" rel="external">s2Member.com</a> for full documentation. There is some additional functionality that can be enabled for security on a Blog Farm installation; and also some menus/documentation/functionality that can be disabled. You will be asked to purchase our <a href="'.esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")).'" target="_blank" rel="external">Network Support Package</a> when you need assistance in this regard.</p>'."\n";
142
+ echo '<p>Multisite Blog Farms require a site owner that fully understands the potential security risks associated with Blog Farming. s2Member\'s <a href="'.esc_attr(c_ws_plugin__s2member_readmes::parse_readme_value("Pro Module / Prices")).'" target="_blank" rel="external">Network Support Package</a> provides you with the information you need, and priority support for anything about s2Member that you don\'t understand. In addition, our Network Support Package includes a lengthy PDF file that details a list of things affected by <code><span style="color:#0000BB;">define</span><span style="color:#007700;">(</span><span style="color:#DD0000;">"MULTISITE_FARM"</span>, <span style="color:#0000BB;">true</span><span style="color:#007700;">);</span></code>, best practices, and other supplemental documentation focused on Blog Farms.</p>'."\n";
143
+ echo '<p><em><strong>Definition of a Multisite Blog Farm:</strong> If your Network is making it possible for "Members" of your Main Site, to create and/or manage Blogs (in any way), s2Member will consider your installation to be a Multisite Blog Farm. That being said, some site owners run a Multisite Network for the purpose of maintaining their own sites. The term Multisite Blog Farm does NOT apply to a Network that hosts multiple Child Blogs, all of which are operated by a single site owner and/or a single company. Again, a Multisite Blog Farm ( in the eyes of s2Member ), is any Network that is making it possible for "Members" of its Main Site, to create and/or manage Blogs; where one or more of these Child Blogs is being administered by a Customer ( e.g. if you offer both Membership and Blog creation, as configured below ).</em></p>'."\n";
144
+ echo '<p><em><strong>When NOT to run a Multisite Blog Farm:</strong> If you run a Multisite Network for the purpose of maintaining your own sites. You should NOT run a Multisite Blog Farm. You can still activate s2Member Network-wide, if you like ( optional ), but the advanced security considerations offered through s2Member\'s Multisite Blog Farm functionality are NOT needed in this case; because all of the Child Blogs in your Network belong to trusted Administrators ( i.e. your Customers are NOT going to run Child Blogs on your Network in this case ).</em></p>'."\n";
145
+ echo '</div>'."\n";
146
+ echo '</div>'."\n";
147
+ /**/
148
+ echo '<div class="ws-menu-page-hr"></div>'."\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-mms-registration-file">'."\n";
156
+ echo 'What Do You Plan To Offer? ( please choose one )'."\n";
157
+ echo '</label>'."\n";
158
+ echo '</th>'."\n";
159
+ /**/
160
+ echo '</tr>'."\n";
161
+ echo '<tr>'."\n";
162
+ /**/
163
+ echo '<td>'."\n";
164
+ /**/
165
+ if(defined("MULTISITE_FARM") && MULTISITE_FARM) /* Lock this down if a config option is set in /wp-config.php. */
166
  {
167
+ echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file" disabled="disabled">'."\n";
168
+ echo '<option value="wp-signup" selected="selected">Blog Farm ( I plan to offer both Membership &amp; Blog creation )</option>'."\n";
169
+ echo '</select><br />'."\n";
170
+ echo '<em class="ws-menu-page-hilite">This is now locked. Your <code>/wp-config.php</code> file says: <code>MULTISITE_FARM = true</code></em>.'."\n";
171
  }
172
  else /* Otherwise we can display these options normally. */
173
  {
174
+ echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file">'."\n";
175
+ echo '<option value="wp-login"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-login") ? ' selected="selected"' : '').'>Membership Only ( I\'m NOT offering Blogs )</option>'."\n";
176
+ echo '<option value="wp-signup"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-signup") ? ' selected="selected"' : '').'>Blog Farm ( I plan to offer both Membership &amp; Blog creation )</option>'."\n";
177
+ echo '</select><br />'."\n";
178
+ echo 'Depending on your selection, the options below may change.'."\n";
179
  }
180
  /**/
181
+ echo '</td>'."\n";
182
+ /**/
183
+ echo '</tr>'."\n";
184
+ echo '</tbody>'."\n";
185
+ echo '</table>'."\n";
186
+ /**/
187
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
188
+ /**/
189
+ echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-login" style="margin:0;">'."\n";
190
+ echo '<tbody>'."\n";
191
+ echo '<tr>'."\n";
192
+ /**/
193
+ echo '<th style="padding-top:0;">'."\n";
194
+ echo '<label for="ws-plugin--s2member-allow-subscribers-in">'."\n";
195
+ echo 'Your Main Site / Allow Open Registration? ( via <code>wp-login.php?action=register</code> )'."\n";
196
+ echo '</label>'."\n";
197
+ echo '</th>'."\n";
198
+ /**/
199
+ echo '</tr>'."\n";
200
+ echo '<tr>'."\n";
201
+ /**/
202
+ echo '<td>'."\n";
203
+ echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">'."\n";
204
+ echo '<option value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '').'>No ( do NOT allow Open Registration )</option>'."\n";
205
+ echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '').'>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>'."\n";
206
+ echo '</select><br />'."\n";
207
+ echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="'.esc_attr(c_ws_plugin__s2member_utils_urls::wp_register_url()).'" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Standard Registration Form.\\n* s2Member makes this form available to logged-in Administrators, at all times ( for testing purposes ), regardless of configuration.'.((c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( '.c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()).' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '').'\');">wp-login.php?action=register</a> ( on your Main Site ). When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.'."\n";
208
+ echo '</td>'."\n";
209
+ /**/
210
+ echo '</tr>'."\n";
211
+ echo '</tbody>'."\n";
212
+ echo '</table>'."\n";
213
+ /**/
214
+ echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup" style="margin:0;">'."\n";
215
+ echo '<tbody>'."\n";
216
+ echo '<tr>'."\n";
217
+ /**/
218
+ echo '<th style="padding-top:0;">'."\n";
219
+ echo '<label for="ws-plugin--s2member-mms-registration-grants">'."\n";
220
+ echo 'Your Main Site / Allow Open Registration? ( via <code>wp-signup.php</code> )'."\n";
221
+ echo '</label>'."\n";
222
+ echo '</th>'."\n";
223
+ /**/
224
+ echo '</tr>'."\n";
225
+ echo '<tr>'."\n";
226
+ /**/
227
+ echo '<td style="padding-bottom:0;">'."\n";
228
+ echo '<select name="ws_plugin__s2member_mms_registration_grants" id="ws-plugin--s2member-mms-registration-grants">'."\n";
229
+ echo '<option value="none"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "none") ? ' selected="selected"' : '').'>No ( do NOT allow Open Registration )</option>'."\n";
230
+ echo '<option value="user"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "user") ? ' selected="selected"' : '').'>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>'."\n";
231
+ echo '<option value="all"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "all") ? ' selected="selected"' : '').'>Yes ( allow Open Registration; Free Subscribers, with a free Blog too )</option>'."\n";
232
+ echo '</select><br />'."\n";
233
+ echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="'.esc_attr(c_ws_plugin__s2member_utils_urls::wp_signup_url()).'" target="_blank" rel="external" onclick="alert(\'s2Member will now open your Multisite Registration Form.\\n* s2Member makes this form available to logged-in Super Administrators, at all times ( for testing purposes ), regardless of configuration.'.((c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '\\n\\nBuddyPress: * BuddyPress will use its own Registration Form. Please note, you will probably be redirected away from the BuddyPress Registration Form ( '.c_ws_plugin__s2member_utils_strings::esc_js_sq(c_ws_plugin__s2member_utils_urls::bp_register_url()).' ), because you\\\'re ALREADY logged-in. Please log out before testing BuddyPress registration.' : '').'\');">wp-signup.php</a> ( on your Main Site ).'."\n";
234
+ echo '</td>'."\n";
235
+ /**/
236
+ echo '</tr>'."\n";
237
+ echo '</tbody>'."\n";
238
+ echo '</table>'."\n";
239
+ /**/
240
+ echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup ws-plugin--s2member-mms-registration-wp-signup-blogs-level0">'."\n";
241
+ echo '<tbody>'."\n";
242
+ echo '<tr>'."\n";
243
+ /**/
244
+ echo '<th>'."\n";
245
+ echo '<label for="ws-plugin--s2member-mms-registration-blogs-level0">'."\n";
246
+ echo 'Level #0 ( Free Subscribers ):'."\n";
247
+ echo '</label>'."\n";
248
+ echo '</th>'."\n";
249
+ /**/
250
+ echo '</tr>'."\n";
251
+ echo '<tr>'."\n";
252
+ /**/
253
+ echo '<td style="padding-bottom:0;">'."\n";
254
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_mms_registration_blogs_level0" id="ws-plugin--s2member-mms-registration-blogs-level0" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_blogs_level0"]).'" /><br />'."\n";
255
+ echo 'How many blogs can a Free Subscriber create?'."\n";
256
+ echo '</td>'."\n";
257
+ /**/
258
+ echo '</tr>'."\n";
259
+ echo '</tbody>'."\n";
260
+ echo '</table>'."\n";
261
+ /**/
262
+ echo '<div class="ws-menu-page-hr ws-plugin--s2member-mms-registration-wp-signup"></div>'."\n";
263
+ /**/
264
+ echo '<table class="form-table ws-plugin--s2member-mms-registration-wp-signup" style="margin:0;">'."\n";
265
+ echo '<tbody>'."\n";
266
+ /**/
267
+ for($n = 1; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
268
  {
269
+ echo '<tr>'."\n";
270
  /**/
271
+ echo '<th style="padding-top:0;">'."\n";
272
+ echo '<label for="ws-plugin--s2member-mms-registration-blogs-level'.$n.'">'."\n";
273
+ echo 'Membership Level #'.$n.' / Maximum Blogs Allowed:'."\n";
274
+ echo '</label>'."\n";
275
+ echo '</th>'."\n";
276
  /**/
277
+ echo '</tr>'."\n";
278
+ echo '<tr>'."\n";
279
  /**/
280
+ echo '<td>'."\n";
281
+ echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_mms_registration_blogs_level'.$n.'" id="ws-plugin--s2member-mms-registration-blogs-level'.$n.'" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_blogs_level".$n]).'" /><br />'."\n";
282
+ echo 'How many blogs can a Member ( at Level #'.$n.' ) create?'."\n";
283
+ echo '</td>'."\n";
284
  /**/
285
+ echo '</tr>'."\n";
286
  }
287
  /**/
288
+ echo '</tbody>'."\n";
289
+ echo '</table>'."\n";
290
+ echo '</div>'."\n";
291
  /**/
292
+ echo '</div>'."\n";
293
  /**/
294
+ do_action("ws_plugin__s2member_during_mms_ops_page_during_left_sections_after_mms_registration", get_defined_vars());
295
  }
296
+ do_action("ws_plugin__s2member_during_mms_ops_page_after_left_sections", get_defined_vars());
297
  /**/
298
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
299
  /**/
300
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save All Changes" /></p>'."\n";
301
  /**/
302
+ echo '</form>'."\n";
303
  }
304
  else /* Otherwise, we can display a simple notation; leading into Multisite Networking. */
305
  {
306
+ echo '<p style="margin-top:0;"><span class="ws-menu-page-hilite">Your WordPress® installation does not have Multisite Networking enabled.<br />Which is perfectly OK :-) Multisite Networking is 100% completely optional.</span></p>'."\n";
307
+ echo '<img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/large-icon.png" title="s2Member (a Membership management system for WordPress®)" alt="" style="float:right; margin:0 0 0 25px; border:0;" />'."\n";
308
  /**/
309
+ if(file_exists($ws_plugin__s2member_temp = dirname(dirname(dirname(__FILE__)))."/readme-ms.txt"))
310
  {
311
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
312
  /**/
313
+ if(!function_exists("NC_Markdown"))
314
+ include_once dirname(dirname(__FILE__))."/_xtnls/markdown/nc-markdown.inc.php";
315
  /**/
316
+ $ws_plugin__s2member_temp = file_get_contents($ws_plugin__s2member_temp);
317
+ $ws_plugin__s2member_temp = preg_replace("/(\=)( )(.+?)( )(\=)/", "<h3>$3</h3>", $ws_plugin__s2member_temp);
318
+ $ws_plugin__s2member_temp = NC_Markdown($ws_plugin__s2member_temp);
319
  /**/
320
+ echo preg_replace("/(\<a)( href)/i", "$1".' target="_blank" rel="nofollow external"'."$2", $ws_plugin__s2member_temp);
321
  }
322
  }
323
  /**/
324
+ echo '</td>'."\n";
325
  /**/
326
+ echo '<td class="ws-menu-page-table-r">'."\n";
327
+ c_ws_plugin__s2member_menu_pages_rs::display();
328
+ echo '</td>'."\n";
329
  /**/
330
+ echo '</tr>'."\n";
331
+ echo '</tbody>'."\n";
332
+ echo '</table>'."\n";
333
  /**/
334
+ echo '</div>'."\n";
335
  }
336
  }
337
  }
338
  /**/
339
+ new c_ws_plugin__s2member_menu_page_mms_ops();
340
  ?>
includes/s2member-min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(b){ws_plugin__s2member_uniqueFilesDownloaded=[];var a='<?php echo c_ws_plugin__s2member_utils_conds::bp_is_installed ("query-active-plugins") ? "1" : ""; ?>';if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN&&S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY<S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED){b('a[href*="s2member_file_download"], a[href*="s2member-file"').click(function(){if(!this.href.match(/s2member_file_download_key\=(.+)/i)){var d='<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Confirm File Download —", "s2member-front", "s2member")); ?>\n\n';d+=b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`ve downloaded %s protected %s in the last %s.", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY,((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("file", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("files", "s2member-front", "s2member")); ?>'),((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("24 hours", "s2member-front", "s2member")); ?>':b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("%s days", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS)))+"\n\n";d+=(S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to UNLIMITED downloads though ( so, no worries ).", "s2member-front", "s2member")); ?>':b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to %s unique %s %s.", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED,((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("download", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("downloads", "s2member-front", "s2member")); ?>'),((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("each day", "s2member-front", "s2member")); ?>':b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("every %s-day period", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS)));if(this.href.match(/s2member[_\-]skip[_\-]confirmation/i)&&!this.href.match(/s2member[_\-]skip[_\-]confirmation[\=\-](0|no|false)/i)||confirm(d)){if(b.inArray(this.href,ws_plugin__s2member_uniqueFilesDownloaded)===-1){ws_plugin__s2member_uniqueFilesDownloaded.push(this.href),S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++}return true}else{return false}}else{return true}})}if(!location.href.match(/\/wp-admin(\/|\?|$)/)){b("input#ws-plugin--s2member-profile-password1, input#ws-plugin--s2member-profile-password2").keyup(function(){ws_plugin__s2member_passwordStrength(b("input#ws-plugin--s2member-profile-login"),b("input#ws-plugin--s2member-profile-password1"),b("input#ws-plugin--s2member-profile-password2"),b("div#ws-plugin--s2member-profile-password-strength"))});b("form#ws-plugin--s2member-profile").submit(function(){var e=this,d="",c="",i="";var g=b("input#ws-plugin--s2member-profile-password1",e);var f=b("input#ws-plugin--s2member-profile-password2",e);var h=b("input#ws-plugin--s2member-profile-submit",e);b(":input",e).each(function(){var j=b.trim(b(this).attr("id")).replace(/-[0-9]+$/g,"");if(j&&(d=b.trim(b('label[for="'+j+'"]',e).first().children("strong").first().text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){i+=c+"\n\n"}}});if(i=b.trim(i)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+i);return false}else{if(b.trim(g.val())&&b.trim(g.val())!==b.trim(f.val())){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Passwords do not match up. Please try again.", "s2member-front", "s2member")); ?>');return false}else{if(b.trim(g.val())&&b.trim(g.val()).length<6){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Password MUST be at least 6 characters. Please try again.", "s2member-front", "s2member")); ?>');return false}}}ws_plugin__s2member_animateProcessing(h);return true})}if(location.href.match(/\/wp-signup\.php/)){b("div#content > div.mu_register > form#setupform").submit(function(){var e=this,d="",c="",g="";b("input#user_email",e).attr("data-expected","email");var f=b('p.submit input[type="submit"]',e);b("input#user_name, input#user_email, input#blogname, input#blog_title, input#captcha_code",e).attr({"aria-required":"true"});b(":input",e).each(function(){var h=b.trim(b(this).attr("id")).replace(/-[0-9]+$/g,"");if(h&&(d=b.trim(b('label[for="'+h+'"]',e).first().text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){g+=c+"\n\n"}}});if(g=b.trim(g)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+g);return false}ws_plugin__s2member_animateProcessing(f);return true})}if(location.href.match(/\/wp-login\.php/)){b("input#ws-plugin--s2member-custom-reg-field-user-pass1, input#ws-plugin--s2member-custom-reg-field-user-pass2").keyup(function(){ws_plugin__s2member_passwordStrength(b("input#user_login"),b("input#ws-plugin--s2member-custom-reg-field-user-pass1"),b("input#ws-plugin--s2member-custom-reg-field-user-pass2"),b("div#ws-plugin--s2member-custom-reg-field-user-pass-strength"))});b("div#login > form#registerform input#wp-submit").attr("tabindex","1000");b("div#login > form#registerform").submit(function(){var e=this,d="",c="",i="";b("input#user_email",e).attr("data-expected","email");var h=b('input#ws-plugin--s2member-custom-reg-field-user-pass1[aria-required="true"]',e);var f=b("input#ws-plugin--s2member-custom-reg-field-user-pass2",e);var g=b("input#wp-submit",e);b("input#user_login, input#user_email, input#captcha_code",e).attr({"aria-required":"true"});b(":input",e).each(function(){var j=b.trim(b(this).attr("id")).replace(/-[0-9]+$/g,"");if(b.inArray(j,["user_login","user_email","captcha_code"])!==-1){if((d=b.trim(b(this).parent("label").text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){i+=c+"\n\n"}}}else{if(j&&(d=b.trim(b('label[for="'+j+'"]',e).first().children("span").first().text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){i+=c+"\n\n"}}}});if(i=b.trim(i)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+i);return false}else{if(h.length&&b.trim(h.val())!==b.trim(f.val())){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Passwords do not match up. Please try again.", "s2member-front", "s2member")); ?>');return false}else{if(h.length&&b.trim(h.val()).length<6){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Password MUST be at least 6 characters. Please try again.", "s2member-front", "s2member")); ?>');return false}}}ws_plugin__s2member_animateProcessing(g);return true})}if(location.href.match(/\/wp-admin\/(user\/)?profile\.php/)){b("form#your-profile").submit(function(){var e=this,d="",c="",f="";b("input#email",e).attr("data-expected","email");b(':input[id^="ws-plugin--s2member-profile-"]',e).each(function(){var g=b.trim(b(this).attr("id")).replace(/-[0-9]+$/g,"");if(g&&(d=b.trim(b('label[for="'+g+'"]',e).first().text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){f+=c+"\n\n"}}});if(f=b.trim(f)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+f);return false}return true})}if(a){b("body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section").closest("form").submit(function(){var e=this,d="",c="",f="";b("input#signup_email",e).attr("data-expected","email");b("input#signup_username, input#signup_email, input#signup_password, input#field_1",e).attr({"aria-required":"true"});b(":input",e).each(function(){var g=b.trim(b(this).attr("id")).replace(/-[0-9]+$/g,"");if(g&&(d=b.trim(b('label[for="'+g+'"]',e).first().text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){f+=c+"\n\n"}}});if(f=b.trim(f)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+f);return false}return true});b("body.logged-in.profile.profile-edit :input.ws-plugin--s2member-profile-field-4bp").closest("form").submit(function(){var e=this,d="",c="",f="";b("input#field_1",e).attr({"aria-required":"true"});b(":input",e).each(function(){var g=b.trim(b(this).attr("id")).replace(/-[0-9]+$/g,"");if(g&&(d=b.trim(b('label[for="'+g+'"]',e).first().text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){f+=c+"\n\n"}}});if(f=b.trim(f)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+f);return false}return true})}ws_plugin__s2member_passwordStrength=function(d,f,e,c){if(d instanceof jQuery&&f instanceof jQuery&&e instanceof jQuery&&c instanceof jQuery&&typeof passwordStrength==="function"&&typeof pwsL10n==="object"){c.removeClass("ws-plugin--s2member-password-strength-short ws-plugin--s2member-password-strength-bad ws-plugin--s2member-password-strength-good ws-plugin--s2member-password-strength-strong ws-plugin--s2member-password-strength-mismatch");switch(passwordStrength(f.val(),d.val(),e.val())){case 1:c.addClass("ws-plugin--s2member-password-strength-short").html(pwsL10n["short"]);break;case 2:c.addClass("ws-plugin--s2member-password-strength-bad").html(pwsL10n.bad);break;case 3:c.addClass("ws-plugin--s2member-password-strength-good").html(pwsL10n.good);break;case 4:c.addClass("ws-plugin--s2member-password-strength-strong").html(pwsL10n.strong);break;case 5:c.addClass("ws-plugin--s2member-password-strength-mismatch").html(pwsL10n.mismatch);break;default:c.addClass("ws-plugin--s2member-password-strength-short").html(pwsL10n["short"])}}return};ws_plugin__s2member_validationErrors=function(o,n,d,j,i){if(typeof o==="string"&&o&&typeof n==="object"&&typeof d==="object"){if(typeof n.tagName==="string"&&n.tagName.match(/^(input|textarea|select)$/i)&&!n.disabled){var q=n.tagName.toLowerCase(),m=b(n),l=b.trim(m.attr("type")).toLowerCase(),c=b.trim(m.attr("name")),p=m.val();var j=(typeof j==="boolean")?j:(m.attr("aria-required")==="true"),i=(typeof i==="string")?i:b.trim(m.attr("data-expected"));var h=('<?php echo strlen($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"]); ?>'>0)?true:false;var f=new RegExp('^(<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (implode ("|", preg_split ("/[\r\n\t ;,]+/", preg_quote ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"], "/")))); ?>)@',"i");if(q==="input"&&l==="checkbox"&&c.match(/\[\]$/)){if(typeof n.id==="string"&&n.id.match(/-0$/)){if(j&&!b('input[name="'+c.replace(/([\[\]])/g,"$1")+'"]:checked',d).length){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please check at least one of the boxes.", "s2member-front", "s2member")); ?>'}}}else{if(q==="input"&&l==="checkbox"){if(j&&!n.checked){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Required. This box must be checked.", "s2member-front", "s2member")); ?>'}}else{if(q==="input"&&l==="radio"){if(typeof n.id==="string"&&n.id.match(/-0$/)){if(j&&!b('input[name="'+c.replace(/([\[\]])/g,"$1")+'"]:checked',d).length){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please select one of the options.", "s2member-front", "s2member")); ?>'}}}else{if(q==="select"&&m.attr("multiple")){if(j&&(!(p instanceof Array)||!p.length)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please select at least one of the options.", "s2member-front", "s2member")); ?>'}}else{if(typeof p!=="string"||(j&&!(p=b.trim(p)).length)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("This is a required field, please try again.", "s2member-front", "s2member")); ?>'}else{if((p=b.trim(p)).length&&((q==="input"&&l.match(/^(text|password)$/i))||q==="textarea")&&typeof i==="string"&&i.length){if(i==="numeric-wp-commas"&&(!p.match(/^[0-9\.,]+$/)||isNaN(p.replace(/,/g,"")))){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be numeric ( with or without decimals, commas allowed ).", "s2member-front", "s2member")); ?>'}else{if(i==="numeric"&&(!p.match(/^[0-9\.]+$/)||isNaN(p))){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be numeric ( with or without decimals, no commas ).", "s2member-front", "s2member")); ?>'}else{if(i==="integer"&&(!p.match(/^[0-9]+$/)||isNaN(p))){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be an integer ( a whole number, without any decimals ).", "s2member-front", "s2member")); ?>'}else{if(i==="integer-gt-0"&&(!p.match(/^[0-9]+$/)||isNaN(p)||p<=0)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be an integer > 0 ( whole number, no decimals, greater than 0 ).", "s2member-front", "s2member")); ?>'}else{if(i==="float"&&(!p.match(/^[0-9\.]+$/)||!p.match(/[0-9]/)||!p.match(/\./)||isNaN(p))){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a float ( floating point number, decimals required ).", "s2member-front", "s2member")); ?>'}else{if(i==="float-gt-0"&&(!p.match(/^[0-9\.]+$/)||!p.match(/[0-9]/)||!p.match(/\./)||isNaN(p)||p<=0)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a float > 0 ( floating point number, decimals required, greater than 0 ).", "s2member-front", "s2member")); ?>'}else{if(i==="date"&&!p.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a date ( required date format: dd/mm/yyyy ).", "s2member-front", "s2member")); ?>'}else{if(i==="email"&&!p.match(/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a valid email address.", "s2member-front", "s2member")); ?>'}else{if(i==="email"&&h&&p.match(f)){return o+"\n"+b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use a personal email address.\nAddresses like <%s@> are problematic.", "s2member-front", "s2member")); ?>',p.split("@")[0])}else{if(i==="url"&&!p.match(/^http(s?)\:\/\/(.{5,})$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a full URL ( starting with http or https ).", "s2member-front", "s2member")); ?>'}else{if(i==="domain"&&!p.match(/^([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a domain name ( domain name only, without http ).", "s2member-front", "s2member")); ?>'}else{if(i==="phone"&&(!p.match(/^[0-9 \(\)\-]+$/)||p.replace(/[^0-9]/g,"").length!==10)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a phone # ( 10 digits w/possible hyphens,spaces,brackets ).", "s2member-front", "s2member")); ?>'}else{if(i==="uszip"&&!p.match(/^[0-9]{5}(-[0-9]{4})?$/)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a US zipcode ( 5-9 digits w/possible hyphen ).", "s2member-front", "s2member")); ?>'}else{if(i==="cazip"&&!p.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a Canadian zipcode ( 6 alpha-numerics w/possible space ).", "s2member-front", "s2member")); ?>'}else{if(i==="uczip"&&!p.match(/^[0-9]{5}(-[0-9]{4})?$/)&&!p.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a zipcode ( either a US or Canadian zipcode ).", "s2member-front", "s2member")); ?>'}else{if(i.match(/^alphanumerics-spaces-punctuation-([0-9]+)(-e)?$/)&&!p.match(/^[a-z 0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics, spaces & punctuation only.", "s2member-front", "s2member")); ?>'}else{if(i.match(/^alphanumerics-spaces-([0-9]+)(-e)?$/)&&!p.match(/^[a-z 0-9]+$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics & spaces only.", "s2member-front", "s2member")); ?>'}else{if(i.match(/^alphanumerics-punctuation-([0-9]+)(-e)?$/)&&!p.match(/^[a-z0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics & punctuation only ( no spaces ).", "s2member-front", "s2member")); ?>'}else{if(i.match(/^alphanumerics-([0-9]+)(-e)?$/)&&!p.match(/^[a-z0-9]+$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics only ( no spaces/punctuation ).", "s2member-front", "s2member")); ?>'}else{if(i.match(/^alphabetics-([0-9]+)(-e)?$/)&&!p.match(/^[a-z]+$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphabetics only ( no digits/spaces/punctuation ).", "s2member-front", "s2member")); ?>'}else{if(i.match(/^numerics-([0-9]+)(-e)?$/)&&!p.match(/^[0-9]+$/i)){return o+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use numeric digits only.", "s2member-front", "s2member")); ?>'}else{if(i.match(/^(any|alphanumerics-spaces-punctuation|alphanumerics-spaces|alphanumerics-punctuation|alphanumerics|alphabetics|numerics)-([0-9]+)(-e)?$/)){var k=i.split("-"),e=Number(k[1]),g=(k.length>2&&k[2]==="e")?true:false;if(g&&p.length!==e){return o+"\n"+b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be exactly %s %s.", "s2member-front", "s2member")); ?>',e,((k[0]==="numerics")?((e===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digit", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digits", "s2member-front", "s2member")); ?>'):((e===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("character", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("characters", "s2member-front", "s2member")); ?>')))}else{if(p.length<e){return o+"\n"+b.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be at least %s %s.", "s2member-front", "s2member")); ?>',e,((k[0]==="numerics")?((e===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digit", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digits", "s2member-front", "s2member")); ?>'):((e===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("character", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("characters", "s2member-front", "s2member")); ?>')))}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}return""};ws_plugin__s2member_animateProcessingConfig={originalText:"",interval:null,speed:100},ws_plugin__s2member_animateProcessing=function(d,c){if(d instanceof jQuery){if(c){clearInterval(ws_plugin__s2member_animateProcessingConfig.interval);if(ws_plugin__s2member_animateProcessingConfig.originalText){d.val(ws_plugin__s2member_animateProcessingConfig.originalText)}return}d.first().each(function(){var g=b(this),f=0,e="r",h=[".","..","..."];ws_plugin__s2member_animateProcessingConfig.originalText=g.val();clearInterval(ws_plugin__s2member_animateProcessingConfig.interval);ws_plugin__s2member_animateProcessingConfig.interval=setInterval(function(){if(e==="r"){if(f+1<=h.length-1){f=f+1,e="r"}else{f=f-1,e="l"}}else{if(e==="l"){if(f-1>=0){f=f-1,e="l"}else{f=f+1,e="r"}}}for(var j=h[f],i=h[f].length;i<h.length;i++){j+=" "}g.val('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Processing", "s2member-front", "s2member")); ?>'+j)},ws_plugin__s2member_animateProcessingConfig.speed)})}}});
1
+ jQuery(document).ready(function(d){var c='<?php echo c_ws_plugin__s2member_utils_conds::bp_is_installed ("query-active-plugins") ? "1" : ""; ?>';var a='<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])); ?>';var b=(typeof ws_plugin__s2member_skip_all_file_confirmations!=="undefined"&&ws_plugin__s2member_skip_all_file_confirmations)?true:false;var e=[];if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN&&S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY<S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED&&!b){d('a[href*="s2member_file_download="], a[href*="/s2member-files/"], a[href^="s2member-files/"], a[href*="/'+a.replace(/([\:\.\[\]])/g,"\\$1")+'/"], a[href^="'+a.replace(/([\:\.\[\]])/g,"\\$1")+'/"]').click(function(){if(!this.href.match(/s2member[_\-]file[_\-]download[_\-]key[\=\-].+/i)){var f='<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Confirm File Download —", "s2member-front", "s2member")); ?>\n\n';f+=d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`ve downloaded %s protected %s in the last %s.", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY,((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("file", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("files", "s2member-front", "s2member")); ?>'),((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("24 hours", "s2member-front", "s2member")); ?>':d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("%s days", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS)))+"\n\n";f+=(S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to UNLIMITED downloads though ( so, no worries ).", "s2member-front", "s2member")); ?>':d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to %s unique %s %s.", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED,((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("download", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("downloads", "s2member-front", "s2member")); ?>'),((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("each day", "s2member-front", "s2member")); ?>':d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("every %s-day period", "s2member-front", "s2member")); ?>',S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS)));if((this.href.match(/s2member[_\-]skip[_\-]confirmation/i)&&!this.href.match(/s2member[_\-]skip[_\-]confirmation[\=\-](0|no|false)/i))||confirm(f)){if(d.inArray(this.href,e)===-1){S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++,e.push(this.href)}return true}else{return false}}else{return true}})}if(!location.href.match(/\/wp-admin(\/|\?|$)/)){d("input#ws-plugin--s2member-profile-password1, input#ws-plugin--s2member-profile-password2").keyup(function(){ws_plugin__s2member_passwordStrength(d("input#ws-plugin--s2member-profile-login"),d("input#ws-plugin--s2member-profile-password1"),d("input#ws-plugin--s2member-profile-password2"),d("div#ws-plugin--s2member-profile-password-strength"))});d("form#ws-plugin--s2member-profile").submit(function(){var h=this,g="",f="",l="";var j=d("input#ws-plugin--s2member-profile-password1",h);var i=d("input#ws-plugin--s2member-profile-password2",h);var k=d("input#ws-plugin--s2member-profile-submit",h);d(":input",h).each(function(){var m=d.trim(d(this).attr("id")).replace(/-[0-9]+$/g,"");if(m&&(g=d.trim(d('label[for="'+m+'"]',h).first().children("strong").first().text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){l+=f+"\n\n"}}});if(l=d.trim(l)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+l);return false}else{if(d.trim(j.val())&&d.trim(j.val())!==d.trim(i.val())){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Passwords do not match up. Please try again.", "s2member-front", "s2member")); ?>');return false}else{if(d.trim(j.val())&&d.trim(j.val()).length<6){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Password MUST be at least 6 characters. Please try again.", "s2member-front", "s2member")); ?>');return false}}}ws_plugin__s2member_animateProcessing(k);return true})}if(location.href.match(/\/wp-signup\.php/)){d("div#content > div.mu_register > form#setupform").submit(function(){var h=this,g="",f="",j="";d("input#user_email",h).attr("data-expected","email");var i=d('p.submit input[type="submit"]',h);d("input#user_name, input#user_email, input#blogname, input#blog_title, input#captcha_code",h).attr({"aria-required":"true"});d(":input",h).each(function(){var k=d.trim(d(this).attr("id")).replace(/-[0-9]+$/g,"");if(k&&(g=d.trim(d('label[for="'+k+'"]',h).first().text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){j+=f+"\n\n"}}});if(j=d.trim(j)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+j);return false}ws_plugin__s2member_animateProcessing(i);return true})}if(location.href.match(/\/wp-login\.php/)){d("input#ws-plugin--s2member-custom-reg-field-user-pass1, input#ws-plugin--s2member-custom-reg-field-user-pass2").keyup(function(){ws_plugin__s2member_passwordStrength(d("input#user_login"),d("input#ws-plugin--s2member-custom-reg-field-user-pass1"),d("input#ws-plugin--s2member-custom-reg-field-user-pass2"),d("div#ws-plugin--s2member-custom-reg-field-user-pass-strength"))});d("div#login > form#registerform input#wp-submit").attr("tabindex","1000");d("div#login > form#registerform").submit(function(){var h=this,g="",f="",l="";d("input#user_email",h).attr("data-expected","email");var k=d('input#ws-plugin--s2member-custom-reg-field-user-pass1[aria-required="true"]',h);var i=d("input#ws-plugin--s2member-custom-reg-field-user-pass2",h);var j=d("input#wp-submit",h);d("input#user_login, input#user_email, input#captcha_code",h).attr({"aria-required":"true"});d(":input",h).each(function(){var m=d.trim(d(this).attr("id")).replace(/-[0-9]+$/g,"");if(d.inArray(m,["user_login","user_email","captcha_code"])!==-1){if((g=d.trim(d(this).parent("label").text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){l+=f+"\n\n"}}}else{if(m&&(g=d.trim(d('label[for="'+m+'"]',h).first().children("span").first().text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){l+=f+"\n\n"}}}});if(l=d.trim(l)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+l);return false}else{if(k.length&&d.trim(k.val())!==d.trim(i.val())){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Passwords do not match up. Please try again.", "s2member-front", "s2member")); ?>');return false}else{if(k.length&&d.trim(k.val()).length<6){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Password MUST be at least 6 characters. Please try again.", "s2member-front", "s2member")); ?>');return false}}}ws_plugin__s2member_animateProcessing(j);return true})}if(location.href.match(/\/wp-admin\/(user\/)?profile\.php/)){d("form#your-profile").submit(function(){var h=this,g="",f="",i="";d("input#email",h).attr("data-expected","email");d(':input[id^="ws-plugin--s2member-profile-"]',h).each(function(){var j=d.trim(d(this).attr("id")).replace(/-[0-9]+$/g,"");if(j&&(g=d.trim(d('label[for="'+j+'"]',h).first().text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){i+=f+"\n\n"}}});if(i=d.trim(i)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+i);return false}return true})}if(c){d("body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section").closest("form").submit(function(){var h=this,g="",f="",i="";d("input#signup_email",h).attr("data-expected","email");d("input#signup_username, input#signup_email, input#signup_password, input#field_1",h).attr({"aria-required":"true"});d(":input",h).each(function(){var j=d.trim(d(this).attr("id")).replace(/-[0-9]+$/g,"");if(j&&(g=d.trim(d('label[for="'+j+'"]',h).first().text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){i+=f+"\n\n"}}});if(i=d.trim(i)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+i);return false}return true});d("body.logged-in.profile.profile-edit :input.ws-plugin--s2member-profile-field-4bp").closest("form").submit(function(){var h=this,g="",f="",i="";d("input#field_1",h).attr({"aria-required":"true"});d(":input",h).each(function(){var j=d.trim(d(this).attr("id")).replace(/-[0-9]+$/g,"");if(j&&(g=d.trim(d('label[for="'+j+'"]',h).first().text().replace(/[\r\n\t]+/g," ")))){if(f=ws_plugin__s2member_validationErrors(g,this,h)){i+=f+"\n\n"}}});if(i=d.trim(i)){alert('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Oops, you missed something: —", "s2member-front", "s2member")); ?>\n\n'+i);return false}return true})}ws_plugin__s2member_passwordStrength=function(g,i,h,f){if(g instanceof jQuery&&i instanceof jQuery&&h instanceof jQuery&&f instanceof jQuery&&typeof passwordStrength==="function"&&typeof pwsL10n==="object"){f.removeClass("ws-plugin--s2member-password-strength-short ws-plugin--s2member-password-strength-bad ws-plugin--s2member-password-strength-good ws-plugin--s2member-password-strength-strong ws-plugin--s2member-password-strength-mismatch");switch(passwordStrength(i.val(),g.val(),h.val())){case 1:f.addClass("ws-plugin--s2member-password-strength-short").html(pwsL10n["short"]);break;case 2:f.addClass("ws-plugin--s2member-password-strength-bad").html(pwsL10n.bad);break;case 3:f.addClass("ws-plugin--s2member-password-strength-good").html(pwsL10n.good);break;case 4:f.addClass("ws-plugin--s2member-password-strength-strong").html(pwsL10n.strong);break;case 5:f.addClass("ws-plugin--s2member-password-strength-mismatch").html(pwsL10n.mismatch);break;default:f.addClass("ws-plugin--s2member-password-strength-short").html(pwsL10n["short"])}}return};ws_plugin__s2member_validationErrors=function(r,q,g,m,l){if(typeof r==="string"&&r&&typeof q==="object"&&typeof g==="object"){if(typeof q.tagName==="string"&&q.tagName.match(/^(input|textarea|select)$/i)&&!q.disabled){var t=q.tagName.toLowerCase(),p=d(q),o=d.trim(p.attr("type")).toLowerCase(),f=d.trim(p.attr("name")),s=p.val();var m=(typeof m==="boolean")?m:(p.attr("aria-required")==="true"),l=(typeof l==="string")?l:d.trim(p.attr("data-expected"));var k=('<?php echo strlen($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"]); ?>'>0)?true:false;var i=new RegExp('^(<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (implode ("|", preg_split ("/[\r\n\t ;,]+/", preg_quote ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"], "/")))); ?>)@',"i");if(t==="input"&&o==="checkbox"&&f.match(/\[\]$/)){if(typeof q.id==="string"&&q.id.match(/-0$/)){if(m&&!d('input[name="'+f.replace(/([\[\]])/g,"$1")+'"]:checked',g).length){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please check at least one of the boxes.", "s2member-front", "s2member")); ?>'}}}else{if(t==="input"&&o==="checkbox"){if(m&&!q.checked){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Required. This box must be checked.", "s2member-front", "s2member")); ?>'}}else{if(t==="input"&&o==="radio"){if(typeof q.id==="string"&&q.id.match(/-0$/)){if(m&&!d('input[name="'+f.replace(/([\[\]])/g,"$1")+'"]:checked',g).length){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please select one of the options.", "s2member-front", "s2member")); ?>'}}}else{if(t==="select"&&p.attr("multiple")){if(m&&(!(s instanceof Array)||!s.length)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please select at least one of the options.", "s2member-front", "s2member")); ?>'}}else{if(typeof s!=="string"||(m&&!(s=d.trim(s)).length)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("This is a required field, please try again.", "s2member-front", "s2member")); ?>'}else{if((s=d.trim(s)).length&&((t==="input"&&o.match(/^(text|password)$/i))||t==="textarea")&&typeof l==="string"&&l.length){if(l==="numeric-wp-commas"&&(!s.match(/^[0-9\.,]+$/)||isNaN(s.replace(/,/g,"")))){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be numeric ( with or without decimals, commas allowed ).", "s2member-front", "s2member")); ?>'}else{if(l==="numeric"&&(!s.match(/^[0-9\.]+$/)||isNaN(s))){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be numeric ( with or without decimals, no commas ).", "s2member-front", "s2member")); ?>'}else{if(l==="integer"&&(!s.match(/^[0-9]+$/)||isNaN(s))){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be an integer ( a whole number, without any decimals ).", "s2member-front", "s2member")); ?>'}else{if(l==="integer-gt-0"&&(!s.match(/^[0-9]+$/)||isNaN(s)||s<=0)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be an integer > 0 ( whole number, no decimals, greater than 0 ).", "s2member-front", "s2member")); ?>'}else{if(l==="float"&&(!s.match(/^[0-9\.]+$/)||!s.match(/[0-9]/)||!s.match(/\./)||isNaN(s))){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a float ( floating point number, decimals required ).", "s2member-front", "s2member")); ?>'}else{if(l==="float-gt-0"&&(!s.match(/^[0-9\.]+$/)||!s.match(/[0-9]/)||!s.match(/\./)||isNaN(s)||s<=0)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a float > 0 ( floating point number, decimals required, greater than 0 ).", "s2member-front", "s2member")); ?>'}else{if(l==="date"&&!s.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a date ( required date format: dd/mm/yyyy ).", "s2member-front", "s2member")); ?>'}else{if(l==="email"&&!s.match(/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a valid email address.", "s2member-front", "s2member")); ?>'}else{if(l==="email"&&k&&s.match(i)){return r+"\n"+d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use a personal email address.\nAddresses like <%s@> are problematic.", "s2member-front", "s2member")); ?>',s.split("@")[0])}else{if(l==="url"&&!s.match(/^http(s?)\:\/\/(.{5,})$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a full URL ( starting with http or https ).", "s2member-front", "s2member")); ?>'}else{if(l==="domain"&&!s.match(/^([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a domain name ( domain name only, without http ).", "s2member-front", "s2member")); ?>'}else{if(l==="phone"&&(!s.match(/^[0-9 \(\)\-]+$/)||s.replace(/[^0-9]/g,"").length!==10)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a phone # ( 10 digits w/possible hyphens,spaces,brackets ).", "s2member-front", "s2member")); ?>'}else{if(l==="uszip"&&!s.match(/^[0-9]{5}(-[0-9]{4})?$/)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a US zipcode ( 5-9 digits w/possible hyphen ).", "s2member-front", "s2member")); ?>'}else{if(l==="cazip"&&!s.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a Canadian zipcode ( 6 alpha-numerics w/possible space ).", "s2member-front", "s2member")); ?>'}else{if(l==="uczip"&&!s.match(/^[0-9]{5}(-[0-9]{4})?$/)&&!s.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be a zipcode ( either a US or Canadian zipcode ).", "s2member-front", "s2member")); ?>'}else{if(l.match(/^alphanumerics-spaces-punctuation-([0-9]+)(-e)?$/)&&!s.match(/^[a-z 0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics, spaces & punctuation only.", "s2member-front", "s2member")); ?>'}else{if(l.match(/^alphanumerics-spaces-([0-9]+)(-e)?$/)&&!s.match(/^[a-z 0-9]+$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics & spaces only.", "s2member-front", "s2member")); ?>'}else{if(l.match(/^alphanumerics-punctuation-([0-9]+)(-e)?$/)&&!s.match(/^[a-z0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics & punctuation only ( no spaces ).", "s2member-front", "s2member")); ?>'}else{if(l.match(/^alphanumerics-([0-9]+)(-e)?$/)&&!s.match(/^[a-z0-9]+$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphanumerics only ( no spaces/punctuation ).", "s2member-front", "s2member")); ?>'}else{if(l.match(/^alphabetics-([0-9]+)(-e)?$/)&&!s.match(/^[a-z]+$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use alphabetics only ( no digits/spaces/punctuation ).", "s2member-front", "s2member")); ?>'}else{if(l.match(/^numerics-([0-9]+)(-e)?$/)&&!s.match(/^[0-9]+$/i)){return r+'\n<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Please use numeric digits only.", "s2member-front", "s2member")); ?>'}else{if(l.match(/^(any|alphanumerics-spaces-punctuation|alphanumerics-spaces|alphanumerics-punctuation|alphanumerics|alphabetics|numerics)-([0-9]+)(-e)?$/)){var n=l.split("-"),h=Number(n[1]),j=(n.length>2&&n[2]==="e")?true:false;if(j&&s.length!==h){return r+"\n"+d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be exactly %s %s.", "s2member-front", "s2member")); ?>',h,((n[0]==="numerics")?((h===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digit", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digits", "s2member-front", "s2member")); ?>'):((h===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("character", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("characters", "s2member-front", "s2member")); ?>')))}else{if(s.length<h){return r+"\n"+d.sprintf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Must be at least %s %s.", "s2member-front", "s2member")); ?>',h,((n[0]==="numerics")?((h===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digit", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("digits", "s2member-front", "s2member")); ?>'):((h===1)?'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("character", "s2member-front", "s2member")); ?>':'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("characters", "s2member-front", "s2member")); ?>')))}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}return""};ws_plugin__s2member_animateProcessingConfig={originalText:"",interval:null,speed:100},ws_plugin__s2member_animateProcessing=function(g,f){if(g instanceof jQuery){if(f){clearInterval(ws_plugin__s2member_animateProcessingConfig.interval);if(ws_plugin__s2member_animateProcessingConfig.originalText){g.val(ws_plugin__s2member_animateProcessingConfig.originalText)}return}g.first().each(function(){var k=d(this),j=0,h="r",l=[".","..","..."];ws_plugin__s2member_animateProcessingConfig.originalText=k.val();clearInterval(ws_plugin__s2member_animateProcessingConfig.interval);ws_plugin__s2member_animateProcessingConfig.interval=setInterval(function(){if(h==="r"){if(j+1<=l.length-1){j=j+1,h="r"}else{j=j-1,h="l"}}else{if(h==="l"){if(j-1>=0){j=j-1,h="l"}else{j=j+1,h="r"}}}for(var m=l[j],i=l[j].length;i<l.length;i++){m+=" "}k.val('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("Processing", "s2member-front", "s2member")); ?>'+m)},ws_plugin__s2member_animateProcessingConfig.speed)})}}});
includes/s2member.css CHANGED
@@ -41,7 +41,7 @@ See: http://www.primothemes.com/
41
  div.ws-plugin--s2member-password-strength
42
  {
43
  padding: 3px;
44
- font-color: #000000;
45
  background-color: #EEEEEE;
46
  -moz-border-radius: 3px;
47
  -webkit-border-radius: 3px;
@@ -85,10 +85,10 @@ div#content > div.mu_register h2
85
  padding: 0; /* Get rid of padding. */
86
  width: 100%; /* Expand to 100%. */
87
  }
88
- div#content > div.mu_register > form#setupform input[type = "text"],
89
- div#content > div.mu_register > form#setupform input[type = "email"],
90
- div#content > div.mu_register > form#setupform input[type = "password"],
91
- div#content > div.mu_register > form#setupform input[type = "submit"],
92
  div#content > div.mu_register > form#setupform textarea,
93
  div#content > div.mu_register > form#setupform select
94
  {
@@ -101,13 +101,13 @@ div#content > div.mu_register > form#setupform select
101
  margin: 5px 0 5px 0;
102
  font-size: 16px;
103
  }
104
- div#content > div.mu_register > form#setupform input[type = "checkbox"],
105
- div#content > div.mu_register > form#setupform input[type = "radio"]
106
  {
107
  margin: 0 3px 0 0;
108
  vertical-align: middle;
109
  }
110
- div#content > div.mu_register > form#setupform input[type = "submit"]
111
  {
112
  width: 100% !ie<8; /* This width required in IE < 8. */
113
  }
@@ -285,9 +285,9 @@ form#ws-plugin--s2member-profile table td
285
  padding: 7px 0 7px 0;
286
  border: 0; /* Tweak 2010 theme. */
287
  }
288
- form#ws-plugin--s2member-profile input[type = "text"],
289
- form#ws-plugin--s2member-profile input[type = "password"],
290
- form#ws-plugin--s2member-profile input[type = "submit"],
291
  form#ws-plugin--s2member-profile textarea,
292
  form#ws-plugin--s2member-profile select
293
  {
@@ -299,13 +299,13 @@ form#ws-plugin--s2member-profile select
299
  -moz-box-sizing: border-box;
300
  -webkit-box-sizing: border-box;
301
  }
302
- form#ws-plugin--s2member-profile input[type = "checkbox"],
303
- form#ws-plugin--s2member-profile input[type = "radio"]
304
  {
305
  margin: 0 3px 0 0;
306
  vertical-align: middle;
307
  }
308
- form#ws-plugin--s2member-profile input[type = "submit"]
309
  {
310
  width: 100% !ie<8; /* This width required in IE < 8. */
311
  }
@@ -386,8 +386,8 @@ body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-container
386
  {
387
  margin-right: 7.5%;
388
  }
389
- body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type = "text"],
390
- body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type = "password"],
391
  body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section textarea,
392
  body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section select
393
  {
@@ -398,8 +398,8 @@ body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section sel
398
  -moz-box-sizing: border-box;
399
  -webkit-box-sizing: border-box;
400
  }
401
- body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type = "checkbox"],
402
- body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type = "radio"]
403
  {
404
  margin: 0 3px 0 0;
405
  vertical-align: middle;
@@ -442,10 +442,10 @@ If you're using a `PriMo Theme`, you can use:
442
  PriMoTheme Options -> Custom CSS
443
  See: http://www.primothemes.com/
444
  */
445
- body.logged-in.profile.profile-edit form#profile-edit-form div.editfield input[type = "text"],
446
- body.logged-in.profile.profile-edit form#profile-edit-form div.editfield input[type = "email"],
447
- body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type = "text"],
448
- body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type = "password"],
449
  body.logged-in.profile.profile-edit form textarea.ws-plugin--s2member-profile-field-4bp,
450
  body.logged-in.profile.profile-edit form select.ws-plugin--s2member-profile-field-4bp
451
  {
@@ -456,8 +456,8 @@ body.logged-in.profile.profile-edit form select.ws-plugin--s2member-profile-fiel
456
  -moz-box-sizing: border-box;
457
  -webkit-box-sizing: border-box;
458
  }
459
- body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type = "checkbox"],
460
- body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type = "radio"]
461
  {
462
  margin: 0 3px 0 0;
463
  vertical-align: middle;
41
  div.ws-plugin--s2member-password-strength
42
  {
43
  padding: 3px;
44
+ color: #000000;
45
  background-color: #EEEEEE;
46
  -moz-border-radius: 3px;
47
  -webkit-border-radius: 3px;
85
  padding: 0; /* Get rid of padding. */
86
  width: 100%; /* Expand to 100%. */
87
  }
88
+ div#content > div.mu_register > form#setupform input[type="text"],
89
+ div#content > div.mu_register > form#setupform input[type="email"],
90
+ div#content > div.mu_register > form#setupform input[type="password"],
91
+ div#content > div.mu_register > form#setupform input[type="submit"],
92
  div#content > div.mu_register > form#setupform textarea,
93
  div#content > div.mu_register > form#setupform select
94
  {
101
  margin: 5px 0 5px 0;
102
  font-size: 16px;
103
  }
104
+ div#content > div.mu_register > form#setupform input[type="checkbox"],
105
+ div#content > div.mu_register > form#setupform input[type="radio"]
106
  {
107
  margin: 0 3px 0 0;
108
  vertical-align: middle;
109
  }
110
+ div#content > div.mu_register > form#setupform input[type="submit"]
111
  {
112
  width: 100% !ie<8; /* This width required in IE < 8. */
113
  }
285
  padding: 7px 0 7px 0;
286
  border: 0; /* Tweak 2010 theme. */
287
  }
288
+ form#ws-plugin--s2member-profile input[type="text"],
289
+ form#ws-plugin--s2member-profile input[type="password"],
290
+ form#ws-plugin--s2member-profile input[type="submit"],
291
  form#ws-plugin--s2member-profile textarea,
292
  form#ws-plugin--s2member-profile select
293
  {
299
  -moz-box-sizing: border-box;
300
  -webkit-box-sizing: border-box;
301
  }
302
+ form#ws-plugin--s2member-profile input[type="checkbox"],
303
+ form#ws-plugin--s2member-profile input[type="radio"]
304
  {
305
  margin: 0 3px 0 0;
306
  vertical-align: middle;
307
  }
308
+ form#ws-plugin--s2member-profile input[type="submit"]
309
  {
310
  width: 100% !ie<8; /* This width required in IE < 8. */
311
  }
386
  {
387
  margin-right: 7.5%;
388
  }
389
+ body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type="text"],
390
+ body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type="password"],
391
  body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section textarea,
392
  body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section select
393
  {
398
  -moz-box-sizing: border-box;
399
  -webkit-box-sizing: border-box;
400
  }
401
+ body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type="checkbox"],
402
+ body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section input[type="radio"]
403
  {
404
  margin: 0 3px 0 0;
405
  vertical-align: middle;
442
  PriMoTheme Options -> Custom CSS
443
  See: http://www.primothemes.com/
444
  */
445
+ body.logged-in.profile.profile-edit form#profile-edit-form div.editfield input[type="text"],
446
+ body.logged-in.profile.profile-edit form#profile-edit-form div.editfield input[type="email"],
447
+ body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type="text"],
448
+ body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type="password"],
449
  body.logged-in.profile.profile-edit form textarea.ws-plugin--s2member-profile-field-4bp,
450
  body.logged-in.profile.profile-edit form select.ws-plugin--s2member-profile-field-4bp
451
  {
456
  -moz-box-sizing: border-box;
457
  -webkit-box-sizing: border-box;
458
  }
459
+ body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type="checkbox"],
460
+ body.logged-in.profile.profile-edit form input.ws-plugin--s2member-profile-field-4bp[type="radio"]
461
  {
462
  margin: 0 3px 0 0;
463
  vertical-align: middle;
includes/s2member.js CHANGED
@@ -18,24 +18,26 @@
18
  */
19
  jQuery(document).ready (function($)
20
  {
21
- ws_plugin__s2member_uniqueFilesDownloaded = /* Real-time counts. */ [];
22
- /**/
23
  var runningBuddyPress = '<?php echo c_ws_plugin__s2member_utils_conds::bp_is_installed ("query-active-plugins") ? "1" : ""; ?>';
 
 
 
24
  /**/
25
- if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN && S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY < S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED)
26
  {
27
- $('a[href*="s2member_file_download"], a[href*="s2member-file"').click (function()
28
  {
29
- if (!this.href.match (/s2member_file_download_key\=(.+)/i))
30
  {
31
  var c = '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Confirm File Download —", "s2member-front", "s2member")); ?>' + '\n\n';
32
  c += $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`ve downloaded %s protected %s in the last %s.", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY, ((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("file", "s2member-front", "s2member")); ?>' : '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("files", "s2member-front", "s2member")); ?>'), ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("24 hours", "s2member-front", "s2member")); ?>' : $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("%s days", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS))) + '\n\n';
33
  c += (S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to UNLIMITED downloads though ( so, no worries ).", "s2member-front", "s2member")); ?>' : $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to %s unique %s %s.", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED, ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("download", "s2member-front", "s2member")); ?>' : '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("downloads", "s2member-front", "s2member")); ?>'), ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("each day", "s2member-front", "s2member")); ?>' : $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("every %s-day period", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS)));
34
  /**/
35
- if (this.href.match (/s2member[_\-]skip[_\-]confirmation/i) && !this.href.match (/s2member[_\-]skip[_\-]confirmation[\=\-](0|no|false)/i) || confirm(c))
36
  {
37
- if ($.inArray (this.href, ws_plugin__s2member_uniqueFilesDownloaded) === -1)
38
- ws_plugin__s2member_uniqueFilesDownloaded.push (this.href), S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++;
 
39
  return /* Allow. */ true;
40
  }
41
  else /* Disallow. */
18
  */
19
  jQuery(document).ready (function($)
20
  {
 
 
21
  var runningBuddyPress = '<?php echo c_ws_plugin__s2member_utils_conds::bp_is_installed ("query-active-plugins") ? "1" : ""; ?>';
22
+ var filesBaseDir = '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (c_ws_plugin__s2member_utils_dirs::basename_dir_app_data ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])); ?>';
23
+ var skipAllFileConfirmations = ( typeof ws_plugin__s2member_skip_all_file_confirmations !== 'undefined' && ws_plugin__s2member_skip_all_file_confirmations) ? true : false;
24
+ var uniqueFilesDownloadedInPage = /* Real-time counts in a single page/instance. */ [];
25
  /**/
26
+ if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN && S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY < S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED && !skipAllFileConfirmations)
27
  {
28
+ $('a[href*="s2member_file_download="], a[href*="/s2member-files/"], a[href^="s2member-files/"], a[href*="/' + filesBaseDir.replace (/([\:\.\[\]])/g, '\\$1') + '/"], a[href^="' + filesBaseDir.replace (/([\:\.\[\]])/g, '\\$1') + '/"]').click (function()
29
  {
30
+ if (!this.href.match /* Do NOT prompt on downloads issued with a Key. */ (/s2member[_\-]file[_\-]download[_\-]key[\=\-].+/i))
31
  {
32
  var c = '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("— Confirm File Download —", "s2member-front", "s2member")); ?>' + '\n\n';
33
  c += $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`ve downloaded %s protected %s in the last %s.", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY, ((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("file", "s2member-front", "s2member")); ?>' : '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("files", "s2member-front", "s2member")); ?>'), ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("24 hours", "s2member-front", "s2member")); ?>' : $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("%s days", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS))) + '\n\n';
34
  c += (S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to UNLIMITED downloads though ( so, no worries ).", "s2member-front", "s2member")); ?>' : $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("You`re entitled to %s unique %s %s.", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED, ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("download", "s2member-front", "s2member")); ?>' : '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("downloads", "s2member-front", "s2member")); ?>'), ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS === 1) ? '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("each day", "s2member-front", "s2member")); ?>' : $.sprintf ('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (_x ("every %s-day period", "s2member-front", "s2member")); ?>', S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS)));
35
  /**/
36
+ if ((this.href.match (/s2member[_\-]skip[_\-]confirmation/i) && !this.href.match (/s2member[_\-]skip[_\-]confirmation[\=\-](0|no|false)/i)) || confirm(c))
37
  {
38
+ if ($.inArray (this.href, uniqueFilesDownloadedInPage) === -1)
39
+ S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++, uniqueFilesDownloadedInPage.push (this.href);
40
+ /**/
41
  return /* Allow. */ true;
42
  }
43
  else /* Disallow. */
includes/syscon.inc.php CHANGED
@@ -17,36 +17,36 @@
17
  * @package s2Member
18
  * @since 3.0
19
  */
20
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
21
- exit ("Do not access this file directly.");
22
  /*
23
  Determine the directory.
24
  */
25
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir"] = dirname (dirname (__FILE__));
26
  /*
27
  Determine the base directory name.
28
  */
29
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_base"] = basename (dirname (dirname (__FILE__)));
30
  /*
31
  Determine the full URL to the directory this plugin resides in.
32
  */
33
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] = (stripos (__FILE__, WP_CONTENT_DIR) !== 0) ? /* Have to assume plugins dir? */
34
- plugins_url ("/" . basename (dirname (dirname (__FILE__)))) : /* Otherwise, this gives it a chance to live anywhere in the content dir. */
35
- content_url (preg_replace ("/^(.*?)\/" . preg_quote (basename (WP_CONTENT_DIR), "/") . "/", "", str_replace (DIRECTORY_SEPARATOR, "/", dirname (dirname (__FILE__)))));
36
  /*
37
  Determine full URL to the s2Member-only file that loads WordPress® with only s2Member active.
38
  */
39
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["s2o_url"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/" . preg_replace ("/\.php$/", "-o.php", basename ($GLOBALS["WS_PLUGIN__"]["s2member"]["l"]));
40
  /*
41
  Determine correct ``plugin_basename()`` here. WordPress® has a few issues with its ``plugin_basename()`` function across different platforms.
42
  */
43
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["plugin_basename"] = basename (dirname ($GLOBALS["WS_PLUGIN__"]["s2member"]["l"])) . "/" . basename ($GLOBALS["WS_PLUGIN__"]["s2member"]["l"]);
44
  /*
45
  Configure the number of Membership Levels being used with s2Member. This is now possible. All areas of s2Member are now capable of adapting to this.
46
  */
47
  $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] = 4; /* Hard coded in at 4 Levels. This can only be extended when/if s2Member Pro is installed. */
48
  $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["min_levels"] = 1; /* A lower limit to protect the integrity of the s2Member software application. */
49
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["max_levels"] = apply_filters ("ws_plugin__s2member_max_levels", 100); /* Filterable. */
50
  /*
51
  Configure regular expression matches for Membership Access Item Numbers ( including those with only Custom Capabilities ).
52
  */
@@ -64,45 +64,46 @@ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["mb_detection_order"] = "UTF-8, ISO-885
64
  /*
65
  Configure an array of file extensions associated with streaming media file types. See: <http://www.spartanicus.utvinternet.ie/streaming.htm> Also see: <http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/12539/supported-video-and-audio-formats>
66
  */
67
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"] = array_unique (array ("avi", "wav", "mpa", "mpeg", "mpv", "mps", "m1v", "m2v", "mp4"/**/, "mp3", "m3u"/**/, "mp4", "flv", "f4v", "3gp", "3g2", "aac", "m4a"/**/, "webm"/**/, "ogg", "ogv", "pls", "m3u", "ogm", "m4u"/**/, "mov", "qtl", "mp4"/**/, "asf", "wmv", "wvx", "wma", "wax"/**/, "ra", "rm", "ram"));
68
  /*
69
  Configure directory and .htaccess for files protected by s2Member.
70
  */
71
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] = apply_filters ("ws_plugin__s2member_files_dir", dirname (dirname (__FILE__)) . "-files" . ((stripos (PHP_OS, "win") === 0 && stripos ($_SERVER["SERVER_SOFTWARE"], "apache") === false) ? "/app_data" : ""));
72
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir_htaccess"] = dirname (__FILE__) . "/templates/cfg-files/s2member-files.php";
 
73
  /*
74
  Configure the directory for logs protected by s2Member.
75
  */
76
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"] = apply_filters ("ws_plugin__s2member_logs_dir", dirname (dirname (__FILE__)) . "-logs" . ((stripos (PHP_OS, "win") === 0 && stripos ($_SERVER["SERVER_SOFTWARE"], "apache") === false) ? "/app_data" : ""));
77
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir_htaccess"] = dirname (__FILE__) . "/templates/cfg-files/s2member-logs.php";
78
  /*
79
  Configure the global reCaptcha ( www.websharks-inc.net / or any domain ). These public/private keys work on any installation.
80
  */
81
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["recaptcha"] = array ("public_key" => "6LeEOsoSAAAAALTKvUpMQMONdBOwG1UVXiFon96F", "private_key" => "6LeEOsoSAAAAAF8gycva4_0cpVr2KHlnnGzAfocd", "lang" => _x ("en", "s2member-front recaptcha-lang-code", "s2member"));
82
  /*
83
  Configure the right menu options panel for s2Member.
84
  */
85
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu_pages"] = array ("updates" => true, "upsell-pro" => true, "installation" => false, "tools" => false, "videos" => true, "support" => true, "donations" => true);
86
  /*
87
  Check if s2Member has been configured *should be set after the first config via options panel*.
88
  */
89
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"] = get_option ("ws_plugin__s2member_configured");
90
  /*
91
  This is a special option cache that holds some additional information autoloaded into WordPress®.
92
  */
93
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"] = get_option ("ws_plugin__s2member_cache");
94
  /*
95
  Configure checksum time for the syscon.inc.php file.
96
  */
97
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["checksum"] = filemtime (__FILE__);
98
  /*
99
  Configure an array of pluggable functions handled by s2Member.
100
  */
101
- $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["pluggables"] = array ();
102
  /*
103
  Configure & validate all of the s2Member options; and set their defaults.
104
  */
105
- if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"))
106
  {
107
  /**
108
  * Configures an options array for the s2Member plugin.
@@ -116,7 +117,7 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
116
  * @param array $options Optional. An array of new options, to be merged with the defaults.
117
  * @return array This merged array of options: ``$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]``
118
  */
119
- function ws_plugin__s2member_configure_options_and_their_defaults ($options = FALSE)
120
  {
121
  global $current_site, $current_blog;
122
  /**/
@@ -126,7 +127,7 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
126
  $default_options["gateway_debug_logs"] = "0";
127
  /**/
128
  $default_options["sec_encryption_key"] = "";
129
- $default_options["sec_encryption_key_history"] = array ();
130
  $default_options["s_badge_status_enabled"] = "0";
131
  /**/
132
  $default_options["max_ip_restriction"] = "5";
@@ -141,17 +142,17 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
141
  $default_options["custom_reg_password"] = "0";
142
  /**/
143
  $default_options["custom_reg_opt_in"] = "1";
144
- $default_options["custom_reg_opt_in_label"] = _x ("Yes, I want to receive updates via email.", "s2member-front", "s2member");
145
  /**/
146
- $default_options["custom_reg_auto_opt_outs"] = array ();
147
  $default_options["custom_reg_auto_opt_out_transitions"] = "0";
148
  /**/
149
- $default_options["custom_reg_fields_4bp"] = array ();
150
  $default_options["custom_reg_force_personal_emails"] = "";
151
  /**/
152
  $default_options["allow_subscribers_in"] = "0";
153
  $default_options["force_admin_lockouts"] = "0";
154
- $default_options["filter_wp_query"] = array ();
155
  /**/
156
  $default_options["default_url_shortener"] = "tiny_url";
157
  $default_options["default_custom_str_url_shortener"] = "";
@@ -159,26 +160,26 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
159
  $default_options["mms_auto_patch"] = "1";
160
  $default_options["mms_registration_file"] = "wp-login";
161
  $default_options["mms_registration_grants"] = "none";
162
- for ($n = 0, $v = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++, $v = $v + 5)
163
- $default_options["mms_registration_blogs_level" . $n] = (string)$v;
164
  /**/
165
  $default_options["login_welcome_page"] = "";
166
  $default_options["login_redirection_override"] = "";
167
  $default_options["membership_options_page"] = "";
168
  /**/
169
  $default_options["login_reg_background_color"] = "FFFFFF";
170
- $default_options["login_reg_background_image"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images/bg.png";
171
  $default_options["login_reg_background_image_repeat"] = "repeat";
172
  /**/
173
  $default_options["login_reg_background_text_color"] = "000000";
174
  $default_options["login_reg_background_text_shadow_color"] = "EEEEEE";
175
  $default_options["login_reg_background_box_shadow_color"] = "EEEEEE";
176
  /**/
177
- $default_options["login_reg_logo_src"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images/logo.png";
178
  $default_options["login_reg_logo_src_width"] = "550";
179
  $default_options["login_reg_logo_src_height"] = "100";
180
- $default_options["login_reg_logo_url"] = home_url ("/");
181
- $default_options["login_reg_logo_title"] = get_bloginfo ("name");
182
  /**/
183
  $default_options["login_reg_font_size"] = "12px";
184
  $default_options["login_reg_font_family"] = "'Verdana', 'Arial', sans-serif";
@@ -186,18 +187,18 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
186
  /**/
187
  $default_options["login_reg_footer_design"] = "";
188
  /**/
189
- $default_options["reg_email_from_name"] = get_bloginfo ("name");
190
- $default_options["reg_email_from_email"] = get_bloginfo ("admin_email");
191
- $default_options["reg_email_support_link"] = "mailto:" . get_bloginfo ("admin_email");
192
  /**/
193
  $default_options["new_user_emails_enabled"] = "0";
194
  /**/
195
- $default_options["new_user_email_subject"] = sprintf (_x ("[%s] Username/Password", "s2member-front", "s2member"), get_bloginfo ("name"));
196
- $default_options["new_user_email_message"] = sprintf (_x ("Your Username/Password for:\n%s\n\nUsername: %%%%user_login%%%%\nPassword: %%%%user_pass%%%%\n%%%%wp_login_url%%%%", "s2member-front", "s2member"), get_bloginfo ("name"));
197
  /**/
198
- $default_options["new_user_admin_email_recipients"] = get_bloginfo ("admin_email");
199
- $default_options["new_user_admin_email_subject"] = sprintf (_x ("[%s] New User Registration", "s2member-front", "s2member"), get_bloginfo ("name"));
200
- $default_options["new_user_admin_email_message"] = sprintf (_x ("New User Registration on your site:\n%s\n\nUser ID: %%%%user_id%%%%\nUsername: %%%%user_login%%%%\nEmail: %%%%user_email%%%%\nIP Address: %%%%user_ip%%%%", "s2member-front", "s2member"), get_bloginfo ("name"));
201
  /**/
202
  $default_options["paypal_sandbox"] = "0";
203
  $default_options["paypal_business"] = "";
@@ -213,20 +214,20 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
213
  $default_options["sp_tracking_codes"] = "";
214
  /**/
215
  $default_options["signup_email_recipients"] = '"%%full_name%%" <%%payer_email%%>';
216
- $default_options["signup_email_subject"] = _x ("Congratulations! ( your membership has been approved )", "s2member-front", "s2member");
217
- $default_options["signup_email_message"] = sprintf (_x ("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%s", "s2member-front", "s2member"), get_bloginfo ("name"));
218
  /**/
219
  $default_options["sp_email_recipients"] = '"%%full_name%%" <%%payer_email%%>';
220
- $default_options["sp_email_subject"] = _x ("Thank You! ( instructions for access )", "s2member-front", "s2member");
221
- $default_options["sp_email_message"] = sprintf (_x ("Thanks %%%%first_name%%%%!\n\n%%%%item_name%%%%\n\nYour order can be retrieved here:\n%%%%sp_access_url%%%%\n( link expires in %%%%sp_access_exp%%%% )\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n%s", "s2member-front", "s2member"), get_bloginfo ("name"));
222
  /**/
223
  $default_options["mailchimp_api_key"] = "";
224
  /**/
225
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
226
- $default_options["level" . $n . "_mailchimp_list_ids"] = "";
227
  /**/
228
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
229
- $default_options["level" . $n . "_aweber_list_ids"] = "";
230
  /**/
231
  $default_options["signup_notification_urls"] = "";
232
  $default_options["registration_notification_urls"] = "";
@@ -248,16 +249,16 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
248
  $default_options["sp_sale_notification_recipients"] = "";
249
  $default_options["sp_ref_rev_notification_recipients"] = "";
250
  /**/
251
- for ($n = 0, $l = array (_x ("Free Subscriber", "s2member-front", "s2member"), _x ("Bronze Member", "s2member-front", "s2member"), _x ("Silver Member", "s2member-front", "s2member"), _x ("Gold Member", "s2member-front", "s2member"), _x ("Platinum Member", "s2member-front", "s2member")); $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
252
- $default_options["level" . $n . "_label"] = (!empty ($l[$n])) ? $l[$n] : sprintf (_x ("Level %s Member", "s2member-front", "s2member"), $n);
253
  /**/
254
  $default_options["apply_label_translations"] = "0";
255
  /**/
256
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
257
- $default_options["level" . $n . "_file_downloads_allowed"] = "";
258
  /**/
259
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
260
- $default_options["level" . $n . "_file_downloads_allowed_days"] = "";
261
  /**/
262
  $default_options["file_download_limit_exceeded_page"] = "";
263
  $default_options["file_download_inline_extensions"] = "";
@@ -279,20 +280,20 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
279
  $default_options["amazon_cf_files_distro_streaming_dname"] = "";
280
  $default_options["amazon_cf_files_distros_auto_config_status"] = "";
281
  /**/
282
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
283
- $default_options["level" . $n . "_ruris"] = "";
284
  /**/
285
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
286
- $default_options["level" . $n . "_catgs"] = "";
287
  /**/
288
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
289
- $default_options["level" . $n . "_ptags"] = "";
290
  /**/
291
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
292
- $default_options["level" . $n . "_posts"] = "";
293
  /**/
294
- for ($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
295
- $default_options["level" . $n . "_pages"] = "";
296
  /**/
297
  $default_options["specific_ids"] = "";
298
  /**/
@@ -303,250 +304,250 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
303
  /**/
304
  $default_options["wp_footer_code"] = "";
305
  /**/
306
- $default_options = apply_filters ("ws_plugin__s2member_default_options", $default_options);
307
  /**/
308
- unset ($n, $v, $l); /* Unset/cleanup these working variables from the routines above. */
309
  /*
310
  Here they are merged. User options will overwrite some or all default values.
311
  */
312
- $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = array_merge ($default_options, (($options !== false) ? (array)$options : (array)get_option ("ws_plugin__s2member_options")));
313
  /**/
314
  /* Back compatibility for `filter_wp_query`. Changed in v110912 to array. */
315
- if (is_string ($_ov = &$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["filter_wp_query"]))
316
- $_ov = (!$_ov || $_ov === "none") ? $default_options["filter_wp_query"] : array_unique (preg_split ("/[;,\r\n\t\s ]+/", $_ov));
317
  /**/
318
  /* Backward compatibility for old logo image width of 500 pixels. Changed in v110604. */
319
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"] === $default_options["login_reg_logo_src"])
320
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"] = $default_options["login_reg_logo_src_width"];
321
  /**/
322
  /* Backward compatibility for PayPal® API Credentials. Starting with v3.5+, this info is stored by the free version of s2Member. */
323
- if (empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_username"]) && !empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_username"]))
324
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_username"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_username"];
325
  /**/
326
- if (empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_password"]) && !empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_password"]))
327
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_password"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_password"];
328
  /**/
329
- if (empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_signature"]) && !empty ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_signature"]))
330
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_signature"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_signature"];
331
  /*
332
  This builds an MD5 checksum for the full array of options. This also includes the config checksum and the current set of default options.
333
  */
334
- $checksum = md5 (($checksum_prefix = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["checksum"] . serialize ($default_options)) . serialize (array_merge ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"], array ("options_checksum" => 0))));
335
  /*
336
  Validate each option, possibly reverting back to the default value in some cases. This is only processed when/if the checksum is not up-to-date.
337
  */
338
- if ($options !== false || ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_checksum"] !== $checksum && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] !== $default_options))
339
  {
340
- foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $key => &$value)
341
  {
342
- if (!isset ($default_options[$key]) && !preg_match ("/^pro_/", $key))
343
- unset ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"][$key]);
344
  /**/
345
- else if ($key === "options_checksum" && (!is_string ($value) || !strlen ($value)))
346
  $value = $default_options[$key];
347
  /**/
348
- else if ($key === "options_version" && (!is_string ($value) || !is_numeric ($value)))
349
  $value = $default_options[$key];
350
  /**/
351
- else if ($key === "gateway_debug_logs" && (!is_string ($value) || !is_numeric ($value)))
352
  $value = $default_options[$key];
353
  /**/
354
- else if ($key === "sec_encryption_key" && (!is_string ($value) || !strlen ($value)))
355
  $value = $default_options[$key];
356
  /**/
357
- else if ($key === "sec_encryption_key_history" && (!is_array ($value) || empty ($value)))
358
  $value = $default_options[$key];
359
  /**/
360
- else if ($key === "s_badge_status_enabled" && (!is_string ($value) || !is_numeric ($value)))
361
  $value = $default_options[$key];
362
  /**/
363
- else if ($key === "max_ip_restriction" && (!is_string ($value) || !is_numeric ($value) || $value < 0 || $value > 100))
364
  $value = $default_options[$key];
365
  /**/
366
- else if ($key === "max_ip_restriction_time" && (!is_string ($value) || !is_numeric ($value) || $value < 900 || $value > 31556926))
367
  $value = $default_options[$key];
368
  /**/
369
- else if ($key === "max_failed_login_attempts" && (!is_string ($value) || !is_numeric ($value) || $value < 0 || $value > 100))
370
  $value = $default_options[$key];
371
  /**/
372
- else if ($key === "run_deactivation_routines" && (!is_string ($value) || !is_numeric ($value)))
373
  $value = $default_options[$key];
374
  /**/
375
- else if ($key === "custom_reg_fields" && (!is_string ($value) || !strlen ($value)))
376
  $value = $default_options[$key];
377
  /**/
378
- else if (preg_match ("/^custom_reg_(?:names|password|opt_in|auto_opt_out_transitions)$/", $key) && (!is_string ($value) || !is_numeric ($value)))
379
  $value = $default_options[$key];
380
  /**/
381
- else if ($key === "custom_reg_display_name" && (!is_string ($value) || !preg_match ("/^(?:full|first|last|login|0)$/", $value)))
382
  $value = $default_options[$key];
383
  /**/
384
- else if ($key === "custom_reg_opt_in_label" && (!is_string ($value) || !strlen ($value)))
385
  $value = $default_options[$key];
386
  /**/
387
- else if ($key === "custom_reg_auto_opt_outs" && (!is_array ($value) || empty ($value)))
388
  $value = $default_options[$key];
389
  /**/
390
- else if ($key === "custom_reg_fields_4bp" && (!is_array ($value) || empty ($value)))
391
  $value = $default_options[$key];
392
  /**/
393
- else if ($key === "custom_reg_force_personal_emails" && (!is_string ($value) || !strlen ($value = preg_replace ("/\s+/", "", $value))))
394
  $value = $default_options[$key];
395
  /**/
396
- else if ($key === "allow_subscribers_in" && (!is_string ($value) || !is_numeric ($value)))
397
  $value = $default_options[$key];
398
  /**/
399
- else if ($key === "mms_auto_patch" && (!is_string ($value) || !is_numeric ($value)))
400
  $value = $default_options[$key];
401
  /**/
402
- else if ($key === "mms_registration_file" && (!is_string ($value) || !preg_match ("/^(?:wp-login|wp-signup)$/", $value)))
403
  $value = $default_options[$key];
404
  /**/
405
- else if ($key === "mms_registration_grants" && (!is_string ($value) || !preg_match ("/^(?:none|user|all)$/", $value)))
406
  $value = $default_options[$key];
407
  /**/
408
- else if (preg_match ("/^mms_registration_blogs_level[0-9]+$/", $key) && (!is_string ($value) || !is_numeric ($value) || $value < 0))
409
  $value = $default_options[$key];
410
  /**/
411
- else if ($key === "force_admin_lockouts" && (!is_string ($value) || !is_numeric ($value)))
412
  $value = $default_options[$key];
413
  /**/
414
- else if ($key === "filter_wp_query" && !is_array ($value)) /* This array CAN be empty. */
415
  $value = $default_options[$key];
416
  /**/
417
- else if (preg_match ("/^default_(?:custom_str_)?url_shortener$/", $key) && (!is_string ($value) || !strlen ($value)))
418
  $value = $default_options[$key];
419
  /**/
420
- else if ($key === "login_welcome_page" && (!is_string ($value) || !is_numeric ($value)))
421
  $value = $default_options[$key];
422
  /**/
423
- else if ($key === "login_redirection_override" && (!is_string ($value) || !strlen ($value)))
424
  $value = $default_options[$key];
425
  /**/
426
- else if ($key === "membership_options_page" && (!is_string ($value) || !is_numeric ($value)))
427
  $value = $default_options[$key];
428
  /**/
429
- else if ($key === "login_reg_background_image" && !is_string ($value)) /* This is optional. */
430
  $value = $default_options[$key];
431
  /**/
432
- else if ($key === "login_reg_background_image_repeat" && (!is_string ($value) || !preg_match ("/^(?:repeat|repeat-x|repeat-y|no-repeat)$/", $value)))
433
  $value = $default_options[$key];
434
  /**/
435
- else if (preg_match ("/^login_reg_(?:background|logo|font|footer)_/", $key) && !preg_match ("/background_image/", $key) && (!is_string ($value) || !strlen ($value)))
436
  $value = $default_options[$key];
437
  /**/
438
- else if (preg_match ("/^reg_email_(?:from_name|from_email|support_link)$/", $key) && (!is_string ($value) || !strlen ($value)))
439
  $value = $default_options[$key];
440
  /**/
441
- else if ($key === "new_user_emails_enabled" && (!is_string ($value) || !is_numeric ($value)))
442
  $value = $default_options[$key];
443
  /**/
444
- else if (preg_match ("/^new_user_email_(?:subject|message)$/", $key) && (!is_string ($value) || !strlen ($value)))
445
  $value = $default_options[$key];
446
  /**/
447
- else if (preg_match ("/^new_user_admin_email_(?:recipients|subject|message)$/", $key) && (!is_string ($value) || !strlen ($value)))
448
  $value = $default_options[$key];
449
  /**/
450
- else if ($key === "paypal_sandbox" && (!is_string ($value) || !is_numeric ($value)))
451
  $value = $default_options[$key];
452
  /**/
453
- else if (preg_match ("/^paypal_(?:business|api_username|api_password|api_signature|identity_token)$/", $key) && (!is_string ($value) || !strlen ($value)))
454
  $value = $default_options[$key];
455
  /**/
456
- else if ($key === "paypal_btn_encryption" && (!is_string ($value) || !is_numeric ($value)))
457
  $value = $default_options[$key];
458
  /**/
459
- else if (preg_match ("/^(?:signup|modification|ccap|sp)_tracking_codes$/", $key) && (!is_string ($value) || !strlen ($value)))
460
  $value = $default_options[$key];
461
  /**/
462
- else if (preg_match ("/^(?:signup|sp)_email_recipients$/", $key) && !is_string ($value)) /* Can be empty. */
463
  $value = $default_options[$key];
464
  /**/
465
- else if (preg_match ("/^(?:signup|sp)_email_(?:subject|message)$/", $key) && (!is_string ($value) || !strlen ($value)))
466
  $value = $default_options[$key];
467
  /**/
468
- else if ($key === "mailchimp_api_key" && (!is_string ($value) || !strlen ($value)))
469
  $value = $default_options[$key];
470
  /**/
471
- else if (preg_match ("/^level[0-9]+_mailchimp_list_ids$/", $key) && (!is_string ($value) || !strlen ($value = preg_replace ("/[\r\n\t]+/", "", $value))))
472
  $value = $default_options[$key];
473
  /**/
474
- else if (preg_match ("/^level[0-9]+_aweber_list_ids$/", $key) && (!is_string ($value) || !strlen ($value = preg_replace ("/\s+/", "", $value))))
475
  $value = $default_options[$key];
476
  /**/
477
- else if (preg_match ("/^(?:signup|registration|payment|modification|cancellation|eot_del|ref_rev|sp_sale|sp_ref_rev)_notification_urls$/", $key) && (!is_string ($value) || !strlen ($value)))
478
  $value = $default_options[$key];
479
  /**/
480
- else if (preg_match ("/^(?:signup|registration|payment|modification|cancellation|eot_del|ref_rev|sp_sale|sp_ref_rev)_notification_recipients$/", $key) && (!is_string ($value) || !strlen ($value)))
481
  $value = $default_options[$key];
482
  /**/
483
- else if (preg_match ("/^level[0-9]+_label$/", $key) && (!is_string ($value) || !strlen ($value)))
484
  $value = $default_options[$key];
485
  /**/
486
- else if ($key === "apply_label_translations" && (!is_string ($value) || !is_numeric ($value)))
487
  $value = $default_options[$key];
488
  /**/
489
- else if (preg_match ("/^level[0-9]+_file_downloads_allowed$/", $key) && (!is_string ($value) || !is_numeric ($value) || $value < 0))
490
  $value = $default_options[$key];
491
  /**/
492
- else if (preg_match ("/^level[0-9]+_file_downloads_allowed_days$/", $key) && (!is_string ($value) || !is_numeric ($value) || $value < 0))
493
  $value = $default_options[$key];
494
  /**/
495
- else if ($key === "file_download_limit_exceeded_page" && (!is_string ($value) || !is_numeric ($value)))
496
  $value = $default_options[$key];
497
  /**/
498
- else if (preg_match ("/^file_download_(?:inline|stream)_extensions$/", $key) && (!is_string ($value) || !($value = strtolower (preg_replace ("/\s+/", "", $value)))))
499
  $value = $default_options[$key];
500
  /**/
501
- else if (preg_match ("/^amazon_(?:s3|cf)_files_/", $key) && (!is_string ($value) || !strlen ($value)))
502
  $value = $default_options[$key];
503
  /**/
504
- else if (preg_match ("/^level[0-9]+_ruris$/", $key) && (!is_string ($value) || !strlen ($value)))
505
  $value = $default_options[$key];
506
  /**/
507
- else if (preg_match ("/^level[0-9]+_catgs$/", $key) && (!is_string ($value) || !($value = ((strcasecmp ($value, "all") === 0) ? strtolower ($value) : trim (preg_replace ("/[^0-9,]/", "", $value), ",")))))
508
  $value = $default_options[$key];
509
  /**/
510
- else if (preg_match ("/^level[0-9]+_ptags$/", $key) && (!is_string ($value) || !($value = ((strcasecmp ($value, "all") === 0) ? strtolower ($value) : trim (preg_replace ("/ +/", " ", trim (preg_replace ("/ *, */", ",", $value))), ",")))))
511
  $value = $default_options[$key];
512
  /**/
513
- else if (preg_match ("/^level[0-9]+_posts$/", $key) && (!is_string ($value) || !($value = trim ( /* Supports `all` or `1,2,3,all-[type]s`. */preg_replace ("/[^a-z0-9_\-,]/", "", strtolower ($value)), ","))))
514
  $value = $default_options[$key];
515
  /**/
516
- else if (preg_match ("/^level[0-9]+_pages$/", $key) && (!is_string ($value) || !($value = ((strcasecmp ($value, "all") === 0) ? strtolower ($value) : trim (preg_replace ("/[^0-9,]/", "", $value), ",")))))
517
  $value = $default_options[$key];
518
  /**/
519
- else if ($key === "specific_ids" && (!is_string ($value) || !($value = trim (preg_replace ("/[^0-9,]/", "", $value), ","))))
520
  $value = $default_options[$key];
521
  /**/
522
- else if ($key === "triggers_immediate_eot" && (!is_string ($value) || !preg_match ("/^(?:none|refunds|reversals|refunds,reversals)$/", $value)))
523
  $value = $default_options[$key];
524
  /**/
525
- else if ($key === "membership_eot_behavior" && (!is_string ($value) || !preg_match ("/^(?:demote|delete)$/", $value)))
526
  $value = $default_options[$key];
527
  /**/
528
- else if ($key === "eot_time_ext_behavior" && (!is_string ($value) || !preg_match ("/^(?:extend|reset)$/", $value)))
529
  $value = $default_options[$key];
530
  /**/
531
- else if ($key === "auto_eot_system_enabled" && (!is_string ($value) || !is_numeric ($value)))
532
  $value = $default_options[$key];
533
  /**/
534
- else if ($key === "wp_footer_code" && (!is_string ($value) || !strlen ($value)))
535
  $value = $default_options[$key];
536
  }
537
  /**/
538
- if ($options !== false && is_string ($options["sec_encryption_key"]) && strlen ($options["sec_encryption_key"]) && !in_array ($options["sec_encryption_key"], $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"]))
539
  {
540
- array_unshift ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"], $options["sec_encryption_key"]);
541
- $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"] = array_slice ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"], 0, 10);
542
  }
543
  /**/
544
- $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = apply_filters_ref_array ("ws_plugin__s2member_options_before_checksum", array (&$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]));
545
  /**/
546
- $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_checksum"] = md5 ($checksum_prefix . serialize (array_merge ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"], array ("options_checksum" => 0))));
547
  }
548
  /**/
549
- return apply_filters_ref_array ("ws_plugin__s2member_options", array (&$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]));
550
  }
551
  }
552
  ?>
17
  * @package s2Member
18
  * @since 3.0
19
  */
20
+ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
21
+ exit("Do not access this file directly.");
22
  /*
23
  Determine the directory.
24
  */
25
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir"] = dirname(dirname(__FILE__));
26
  /*
27
  Determine the base directory name.
28
  */
29
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_base"] = basename(dirname(dirname(__FILE__)));
30
  /*
31
  Determine the full URL to the directory this plugin resides in.
32
  */
33
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] = (stripos(__FILE__, WP_CONTENT_DIR) !== 0) ? /* Have to assume plugins dir? */
34
+ plugins_url("/".basename(dirname(dirname(__FILE__)))) : /* Otherwise, this gives it a chance to live anywhere in the content dir. */
35
+ content_url(preg_replace("/^(.*?)\/".preg_quote(basename(WP_CONTENT_DIR), "/")."/", "", str_replace(DIRECTORY_SEPARATOR, "/", dirname(dirname(__FILE__)))));
36
  /*
37
  Determine full URL to the s2Member-only file that loads WordPress® with only s2Member active.
38
  */
39
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["s2o_url"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/".preg_replace("/\.php$/", "-o.php", basename($GLOBALS["WS_PLUGIN__"]["s2member"]["l"]));
40
  /*
41
  Determine correct ``plugin_basename()`` here. WordPress® has a few issues with its ``plugin_basename()`` function across different platforms.
42
  */
43
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["plugin_basename"] = basename(dirname($GLOBALS["WS_PLUGIN__"]["s2member"]["l"]))."/".basename($GLOBALS["WS_PLUGIN__"]["s2member"]["l"]);
44
  /*
45
  Configure the number of Membership Levels being used with s2Member. This is now possible. All areas of s2Member are now capable of adapting to this.
46
  */
47
  $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"] = 4; /* Hard coded in at 4 Levels. This can only be extended when/if s2Member Pro is installed. */
48
  $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["min_levels"] = 1; /* A lower limit to protect the integrity of the s2Member software application. */
49
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["max_levels"] = apply_filters("ws_plugin__s2member_max_levels", 100); /* Filterable. */
50
  /*
51
  Configure regular expression matches for Membership Access Item Numbers ( including those with only Custom Capabilities ).
52
  */
64
  /*
65
  Configure an array of file extensions associated with streaming media file types. See: <http://www.spartanicus.utvinternet.ie/streaming.htm> Also see: <http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/12539/supported-video-and-audio-formats>
66
  */
67
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["streaming_file_extns"] = array_unique(array("avi", "wav", "mpa", "mpeg", "mpv", "mps", "m1v", "m2v", "mp4"/**/, "mp3", "m3u"/**/, "mp4", "flv", "f4v", "3gp", "3g2", "aac", "m4a"/**/, "webm"/**/, "ogg", "ogv", "pls", "m3u", "ogm", "m4u"/**/, "mov", "qtl", "mp4"/**/, "asf", "wmv", "wvx", "wma", "wax"/**/, "ra", "rm", "ram"));
68
  /*
69
  Configure directory and .htaccess for files protected by s2Member.
70
  */
71
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] = apply_filters("ws_plugin__s2member_files_dir", dirname(dirname(__FILE__))."-files".((stripos(PHP_OS, "win") === 0 && stripos($_SERVER["SERVER_SOFTWARE"], "apache") === false) ? "/app_data" : ""));
72
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_no_gzip_htaccess"] = dirname(__FILE__)."/templates/cfg-files/s2member-files-no-gzip.php";
73
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir_htaccess"] = dirname(__FILE__)."/templates/cfg-files/s2member-files.php";
74
  /*
75
  Configure the directory for logs protected by s2Member.
76
  */
77
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"] = apply_filters("ws_plugin__s2member_logs_dir", dirname(dirname(__FILE__))."-logs".((stripos(PHP_OS, "win") === 0 && stripos($_SERVER["SERVER_SOFTWARE"], "apache") === false) ? "/app_data" : ""));
78
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir_htaccess"] = dirname(__FILE__)."/templates/cfg-files/s2member-logs.php";
79
  /*
80
  Configure the global reCaptcha ( www.websharks-inc.net / or any domain ). These public/private keys work on any installation.
81
  */
82
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["recaptcha"] = array("public_key" => "6LeEOsoSAAAAALTKvUpMQMONdBOwG1UVXiFon96F", "private_key" => "6LeEOsoSAAAAAF8gycva4_0cpVr2KHlnnGzAfocd", "lang" => _x("en", "s2member-front recaptcha-lang-code", "s2member"));
83
  /*
84
  Configure the right menu options panel for s2Member.
85
  */
86
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu_pages"] = array("updates" => true, "upsell-pro" => true, "installation" => false, "tools" => false, "videos" => true, "support" => true, "donations" => true);
87
  /*
88
  Check if s2Member has been configured *should be set after the first config via options panel*.
89
  */
90
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"] = get_option("ws_plugin__s2member_configured");
91
  /*
92
  This is a special option cache that holds some additional information autoloaded into WordPress®.
93
  */
94
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"] = get_option("ws_plugin__s2member_cache");
95
  /*
96
  Configure checksum time for the syscon.inc.php file.
97
  */
98
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["checksum"] = filemtime(__FILE__);
99
  /*
100
  Configure an array of pluggable functions handled by s2Member.
101
  */
102
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["pluggables"] = array();
103
  /*
104
  Configure & validate all of the s2Member options; and set their defaults.
105
  */
106
+ if(!function_exists("ws_plugin__s2member_configure_options_and_their_defaults"))
107
  {
108
  /**
109
  * Configures an options array for the s2Member plugin.
117
  * @param array $options Optional. An array of new options, to be merged with the defaults.
118
  * @return array This merged array of options: ``$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]``
119
  */
120
+ function ws_plugin__s2member_configure_options_and_their_defaults($options = FALSE)
121
  {
122
  global $current_site, $current_blog;
123
  /**/
127
  $default_options["gateway_debug_logs"] = "0";
128
  /**/
129
  $default_options["sec_encryption_key"] = "";
130
+ $default_options["sec_encryption_key_history"] = array();
131
  $default_options["s_badge_status_enabled"] = "0";
132
  /**/
133
  $default_options["max_ip_restriction"] = "5";
142
  $default_options["custom_reg_password"] = "0";
143
  /**/
144
  $default_options["custom_reg_opt_in"] = "1";
145
+ $default_options["custom_reg_opt_in_label"] = _x("Yes, I want to receive updates via email.", "s2member-front", "s2member");
146
  /**/
147
+ $default_options["custom_reg_auto_opt_outs"] = array();
148
  $default_options["custom_reg_auto_opt_out_transitions"] = "0";
149
  /**/
150
+ $default_options["custom_reg_fields_4bp"] = array();
151
  $default_options["custom_reg_force_personal_emails"] = "";
152
  /**/
153
  $default_options["allow_subscribers_in"] = "0";
154
  $default_options["force_admin_lockouts"] = "0";
155
+ $default_options["filter_wp_query"] = array();
156
  /**/
157
  $default_options["default_url_shortener"] = "tiny_url";
158
  $default_options["default_custom_str_url_shortener"] = "";
160
  $default_options["mms_auto_patch"] = "1";
161
  $default_options["mms_registration_file"] = "wp-login";
162
  $default_options["mms_registration_grants"] = "none";
163
+ for($n = 0, $v = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++, $v = $v + 5)
164
+ $default_options["mms_registration_blogs_level".$n] = (string)$v;
165
  /**/
166
  $default_options["login_welcome_page"] = "";
167
  $default_options["login_redirection_override"] = "";
168
  $default_options["membership_options_page"] = "";
169
  /**/
170
  $default_options["login_reg_background_color"] = "FFFFFF";
171
+ $default_options["login_reg_background_image"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images/bg.png";
172
  $default_options["login_reg_background_image_repeat"] = "repeat";
173
  /**/
174
  $default_options["login_reg_background_text_color"] = "000000";
175
  $default_options["login_reg_background_text_shadow_color"] = "EEEEEE";
176
  $default_options["login_reg_background_box_shadow_color"] = "EEEEEE";
177
  /**/
178
+ $default_options["login_reg_logo_src"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]."/images/logo.png";
179
  $default_options["login_reg_logo_src_width"] = "550";
180
  $default_options["login_reg_logo_src_height"] = "100";
181
+ $default_options["login_reg_logo_url"] = home_url("/");
182
+ $default_options["login_reg_logo_title"] = get_bloginfo("name");
183
  /**/
184
  $default_options["login_reg_font_size"] = "12px";
185
  $default_options["login_reg_font_family"] = "'Verdana', 'Arial', sans-serif";
187
  /**/
188
  $default_options["login_reg_footer_design"] = "";
189
  /**/
190
+ $default_options["reg_email_from_name"] = get_bloginfo("name");
191
+ $default_options["reg_email_from_email"] = get_bloginfo("admin_email");
192
+ $default_options["reg_email_support_link"] = "mailto:".get_bloginfo("admin_email");
193
  /**/
194
  $default_options["new_user_emails_enabled"] = "0";
195
  /**/
196
+ $default_options["new_user_email_subject"] = sprintf(_x("[%s] Username/Password", "s2member-front", "s2member"), get_bloginfo("name"));
197
+ $default_options["new_user_email_message"] = sprintf(_x("Your Username/Password for:\n%s\n\nUsername: %%%%user_login%%%%\nPassword: %%%%user_pass%%%%\n%%%%wp_login_url%%%%", "s2member-front", "s2member"), get_bloginfo("name"));
198
  /**/
199
+ $default_options["new_user_admin_email_recipients"] = get_bloginfo("admin_email");
200
+ $default_options["new_user_admin_email_subject"] = sprintf(_x("[%s] New User Registration", "s2member-front", "s2member"), get_bloginfo("name"));
201
+ $default_options["new_user_admin_email_message"] = sprintf(_x("New User Registration on your site:\n%s\n\nUser ID: %%%%user_id%%%%\nUsername: %%%%user_login%%%%\nEmail: %%%%user_email%%%%\nIP Address: %%%%user_ip%%%%", "s2member-front", "s2member"), get_bloginfo("name"));
202
  /**/
203
  $default_options["paypal_sandbox"] = "0";
204
  $default_options["paypal_business"] = "";
214
  $default_options["sp_tracking_codes"] = "";
215
  /**/
216
  $default_options["signup_email_recipients"] = '"%%full_name%%" <%%payer_email%%>';
217
+ $default_options["signup_email_subject"] = _x("Congratulations! ( your membership has been approved )", "s2member-front", "s2member");
218
+ $default_options["signup_email_message"] = sprintf(_x("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%s", "s2member-front", "s2member"), get_bloginfo("name"));
219
  /**/
220
  $default_options["sp_email_recipients"] = '"%%full_name%%" <%%payer_email%%>';
221
+ $default_options["sp_email_subject"] = _x("Thank You! ( instructions for access )", "s2member-front", "s2member");
222
+ $default_options["sp_email_message"] = sprintf(_x("Thanks %%%%first_name%%%%!\n\n%%%%item_name%%%%\n\nYour order can be retrieved here:\n%%%%sp_access_url%%%%\n( link expires in %%%%sp_access_exp%%%% )\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n%s", "s2member-front", "s2member"), get_bloginfo("name"));
223
  /**/
224
  $default_options["mailchimp_api_key"] = "";
225
  /**/
226
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
227
+ $default_options["level".$n."_mailchimp_list_ids"] = "";
228
  /**/
229
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
230
+ $default_options["level".$n."_aweber_list_ids"] = "";
231
  /**/
232
  $default_options["signup_notification_urls"] = "";
233
  $default_options["registration_notification_urls"] = "";
249
  $default_options["sp_sale_notification_recipients"] = "";
250
  $default_options["sp_ref_rev_notification_recipients"] = "";
251
  /**/
252
+ for($n = 0, $l = array(_x("Free Subscriber", "s2member-front", "s2member"), _x("Bronze Member", "s2member-front", "s2member"), _x("Silver Member", "s2member-front", "s2member"), _x("Gold Member", "s2member-front", "s2member"), _x("Platinum Member", "s2member-front", "s2member")); $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
253
+ $default_options["level".$n."_label"] = (!empty($l[$n])) ? $l[$n] : sprintf(_x("Level %s Member", "s2member-front", "s2member"), $n);
254
  /**/
255
  $default_options["apply_label_translations"] = "0";
256
  /**/
257
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
258
+ $default_options["level".$n."_file_downloads_allowed"] = "";
259
  /**/
260
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
261
+ $default_options["level".$n."_file_downloads_allowed_days"] = "";
262
  /**/
263
  $default_options["file_download_limit_exceeded_page"] = "";
264
  $default_options["file_download_inline_extensions"] = "";
280
  $default_options["amazon_cf_files_distro_streaming_dname"] = "";
281
  $default_options["amazon_cf_files_distros_auto_config_status"] = "";
282
  /**/
283
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
284
+ $default_options["level".$n."_ruris"] = "";
285
  /**/
286
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
287
+ $default_options["level".$n."_catgs"] = "";
288
  /**/
289
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
290
+ $default_options["level".$n."_ptags"] = "";
291
  /**/
292
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
293
+ $default_options["level".$n."_posts"] = "";
294
  /**/
295
+ for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
296
+ $default_options["level".$n."_pages"] = "";
297
  /**/
298
  $default_options["specific_ids"] = "";
299
  /**/
304
  /**/
305
  $default_options["wp_footer_code"] = "";
306
  /**/
307
+ $default_options = apply_filters("ws_plugin__s2member_default_options", $default_options);
308
  /**/
309
+ unset($n, $v, $l); /* Unset/cleanup these working variables from the routines above. */
310
  /*
311
  Here they are merged. User options will overwrite some or all default values.
312
  */
313
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = array_merge($default_options, (($options !== false) ? (array)$options : (array)get_option("ws_plugin__s2member_options")));
314
  /**/
315
  /* Back compatibility for `filter_wp_query`. Changed in v110912 to array. */
316
+ if(is_string($_ov = &$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["filter_wp_query"]))
317
+ $_ov = (!$_ov || $_ov === "none") ? $default_options["filter_wp_query"] : array_unique(preg_split("/[;,\r\n\t\s ]+/", $_ov));
318
  /**/
319
  /* Backward compatibility for old logo image width of 500 pixels. Changed in v110604. */
320
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"] === $default_options["login_reg_logo_src"])
321
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"] = $default_options["login_reg_logo_src_width"];
322
  /**/
323
  /* Backward compatibility for PayPal® API Credentials. Starting with v3.5+, this info is stored by the free version of s2Member. */
324
+ if(empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_username"]) && !empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_username"]))
325
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_username"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_username"];
326
  /**/
327
+ if(empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_password"]) && !empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_password"]))
328
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_password"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_password"];
329
  /**/
330
+ if(empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_signature"]) && !empty($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_signature"]))
331
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_api_signature"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_paypal_api_signature"];
332
  /*
333
  This builds an MD5 checksum for the full array of options. This also includes the config checksum and the current set of default options.
334
  */
335
+ $checksum = md5(($checksum_prefix = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["checksum"].serialize($default_options)).serialize(array_merge($GLOBALS["WS_PLUGIN__"]["s2member"]["o"], array("options_checksum" => 0))));
336
  /*
337
  Validate each option, possibly reverting back to the default value in some cases. This is only processed when/if the checksum is not up-to-date.
338
  */
339
+ if($options !== false || ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_checksum"] !== $checksum && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] !== $default_options))
340
  {
341
+ foreach($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $key => &$value)
342
  {
343
+ if(!isset($default_options[$key]) && !preg_match("/^pro_/", $key))
344
+ unset($GLOBALS["WS_PLUGIN__"]["s2member"]["o"][$key]);
345
  /**/
346
+ else if($key === "options_checksum" && (!is_string($value) || !strlen($value)))
347
  $value = $default_options[$key];
348
  /**/
349
+ else if($key === "options_version" && (!is_string($value) || !is_numeric($value)))
350
  $value = $default_options[$key];
351
  /**/
352
+ else if($key === "gateway_debug_logs" && (!is_string($value) || !is_numeric($value)))
353
  $value = $default_options[$key];
354
  /**/
355
+ else if($key === "sec_encryption_key" && (!is_string($value) || !strlen($value)))
356
  $value = $default_options[$key];
357
  /**/
358
+ else if($key === "sec_encryption_key_history" && (!is_array($value) || empty($value)))
359
  $value = $default_options[$key];
360
  /**/
361
+ else if($key === "s_badge_status_enabled" && (!is_string($value) || !is_numeric($value)))
362
  $value = $default_options[$key];
363
  /**/
364
+ else if($key === "max_ip_restriction" && (!is_string($value) || !is_numeric($value) || $value < 0 || $value > 100))
365
  $value = $default_options[$key];
366
  /**/
367
+ else if($key === "max_ip_restriction_time" && (!is_string($value) || !is_numeric($value) || $value < 900 || $value > 31556926))
368
  $value = $default_options[$key];
369
  /**/
370
+ else if($key === "max_failed_login_attempts" && (!is_string($value) || !is_numeric($value) || $value < 0 || $value > 100))
371
  $value = $default_options[$key];
372
  /**/
373
+ else if($key === "run_deactivation_routines" && (!is_string($value) || !is_numeric($value)))
374
  $value = $default_options[$key];
375
  /**/
376
+ else if($key === "custom_reg_fields" && (!is_string($value) || !strlen($value)))
377
  $value = $default_options[$key];
378
  /**/
379
+ else if(preg_match("/^custom_reg_(?:names|password|opt_in|auto_opt_out_transitions)$/", $key) && (!is_string($value) || !is_numeric($value)))
380
  $value = $default_options[$key];
381
  /**/
382
+ else if($key === "custom_reg_display_name" && (!is_string($value) || !preg_match("/^(?:full|first|last|login|0)$/", $value)))
383
  $value = $default_options[$key];
384
  /**/
385
+ else if($key === "custom_reg_opt_in_label" && (!is_string($value) || !strlen($value)))
386
  $value = $default_options[$key];
387
  /**/
388
+ else if($key === "custom_reg_auto_opt_outs" && (!is_array($value) || empty($value)))
389
  $value = $default_options[$key];
390
  /**/
391
+ else if($key === "custom_reg_fields_4bp" && (!is_array($value) || empty($value)))
392
  $value = $default_options[$key];
393
  /**/
394
+ else if($key === "custom_reg_force_personal_emails" && (!is_string($value) || !strlen($value = preg_replace("/\s+/", "", $value))))
395
  $value = $default_options[$key];
396
  /**/
397
+ else if($key === "allow_subscribers_in" && (!is_string($value) || !is_numeric($value)))
398
  $value = $default_options[$key];
399
  /**/
400
+ else if($key === "mms_auto_patch" && (!is_string($value) || !is_numeric($value)))
401
  $value = $default_options[$key];
402
  /**/
403
+ else if($key === "mms_registration_file" && (!is_string($value) || !preg_match("/^(?:wp-login|wp-signup)$/", $value)))
404
  $value = $default_options[$key];
405
  /**/
406
+ else if($key === "mms_registration_grants" && (!is_string($value) || !preg_match("/^(?:none|user|all)$/", $value)))
407
  $value = $default_options[$key];
408
  /**/
409
+ else if(preg_match("/^mms_registration_blogs_level[0-9]+$/", $key) && (!is_string($value) || !is_numeric($value) || $value < 0))
410
  $value = $default_options[$key];
411
  /**/
412
+ else if($key === "force_admin_lockouts" && (!is_string($value) || !is_numeric($value)))
413
  $value = $default_options[$key];
414
  /**/
415
+ else if($key === "filter_wp_query" && !is_array($value)) /* This array CAN be empty. */
416
  $value = $default_options[$key];
417
  /**/
418
+ else if(preg_match("/^default_(?:custom_str_)?url_shortener$/", $key) && (!is_string($value) || !strlen($value)))
419
  $value = $default_options[$key];
420
  /**/
421
+ else if($key === "login_welcome_page" && (!is_string($value) || !is_numeric($value)))
422
  $value = $default_options[$key];
423
  /**/
424
+ else if($key === "login_redirection_override" && (!is_string($value) || !strlen($value)))
425
  $value = $default_options[$key];
426
  /**/
427
+ else if($key === "membership_options_page" && (!is_string($value) || !is_numeric($value)))
428
  $value = $default_options[$key];
429
  /**/
430
+ else if($key === "login_reg_background_image" && !is_string($value)) /* This is optional. */
431
  $value = $default_options[$key];
432
  /**/
433
+ else if($key === "login_reg_background_image_repeat" && (!is_string($value) || !preg_match("/^(?:repeat|repeat-x|repeat-y|no-repeat)$/", $value)))
434
  $value = $default_options[$key];
435
  /**/
436
+ else if(preg_match("/^login_reg_(?:background|logo|font|footer)_/", $key) && !preg_match("/background_image/", $key) && (!is_string($value) || !strlen($value)))
437
  $value = $default_options[$key];
438
  /**/
439
+ else if(preg_match("/^reg_email_(?:from_name|from_email|support_link)$/", $key) && (!is_string($value) || !strlen($value)))
440
  $value = $default_options[$key];
441
  /**/
442
+ else if($key === "new_user_emails_enabled" && (!is_string($value) || !is_numeric($value)))
443
  $value = $default_options[$key];
444
  /**/
445
+ else if(preg_match("/^new_user_email_(?:subject|message)$/", $key) && (!is_string($value) || !strlen($value)))
446
  $value = $default_options[$key];
447
  /**/
448
+ else if(preg_match("/^new_user_admin_email_(?:recipients|subject|message)$/", $key) && (!is_string($value) || !strlen($value)))
449
  $value = $default_options[$key];
450
  /**/
451
+ else if($key === "paypal_sandbox" && (!is_string($value) || !is_numeric($value)))
452
  $value = $default_options[$key];
453
  /**/
454
+ else if(preg_match("/^paypal_(?:business|api_username|api_password|api_signature|identity_token)$/", $key) && (!is_string($value) || !strlen($value)))
455
  $value = $default_options[$key];
456
  /**/
457
+ else if($key === "paypal_btn_encryption" && (!is_string($value) || !is_numeric($value)))
458
  $value = $default_options[$key];
459
  /**/
460
+ else if(preg_match("/^(?:signup|modification|ccap|sp)_tracking_codes$/", $key) && (!is_string($value) || !strlen($value)))
461
  $value = $default_options[$key];
462
  /**/
463
+ else if(preg_match("/^(?:signup|sp)_email_recipients$/", $key) && !is_string($value)) /* Can be empty. */
464
  $value = $default_options[$key];
465
  /**/
466
+ else if(preg_match("/^(?:signup|sp)_email_(?:subject|message)$/", $key) && (!is_string($value) || !strlen($value)))
467
  $value = $default_options[$key];
468
  /**/
469
+ else if($key === "mailchimp_api_key" && (!is_string($value) || !strlen($value)))
470
  $value = $default_options[$key];
471
  /**/
472
+ else if(preg_match("/^level[0-9]+_mailchimp_list_ids$/", $key) && (!is_string($value) || !strlen($value = preg_replace("/[\r\n\t]+/", "", $value))))
473
  $value = $default_options[$key];
474
  /**/
475
+ else if(preg_match("/^level[0-9]+_aweber_list_ids$/", $key) && (!is_string($value) || !strlen($value = preg_replace("/\s+/", "", $value))))
476
  $value = $default_options[$key];
477
  /**/
478
+ else if(preg_match("/^(?:signup|registration|payment|modification|cancellation|eot_del|ref_rev|sp_sale|sp_ref_rev)_notification_urls$/", $key) && (!is_string($value) || !strlen($value)))
479
  $value = $default_options[$key];
480
  /**/
481
+ else if(preg_match("/^(?:signup|registration|payment|modification|cancellation|eot_del|ref_rev|sp_sale|sp_ref_rev)_notification_recipients$/", $key) && (!is_string($value) || !strlen($value)))
482
  $value = $default_options[$key];
483
  /**/
484
+ else if(preg_match("/^level[0-9]+_label$/", $key) && (!is_string($value) || !strlen($value)))
485
  $value = $default_options[$key];
486
  /**/
487
+ else if($key === "apply_label_translations" && (!is_string($value) || !is_numeric($value)))
488
  $value = $default_options[$key];
489
  /**/
490
+ else if(preg_match("/^level[0-9]+_file_downloads_allowed$/", $key) && (!is_string($value) || !is_numeric($value) || $value < 0))
491
  $value = $default_options[$key];
492
  /**/
493
+ else if(preg_match("/^level[0-9]+_file_downloads_allowed_days$/", $key) && (!is_string($value) || !is_numeric($value) || $value < 0))
494
  $value = $default_options[$key];
495
  /**/
496
+ else if($key === "file_download_limit_exceeded_page" && (!is_string($value) || !is_numeric($value)))
497
  $value = $default_options[$key];
498
  /**/
499
+ else if(preg_match("/^file_download_(?:inline|stream)_extensions$/", $key) && (!is_string($value) || !($value = strtolower(preg_replace("/\s+/", "", $value)))))
500
  $value = $default_options[$key];
501
  /**/
502
+ else if(preg_match("/^amazon_(?:s3|cf)_files_/", $key) && (!is_string($value) || !strlen($value)))
503
  $value = $default_options[$key];
504
  /**/
505
+ else if(preg_match("/^level[0-9]+_ruris$/", $key) && (!is_string($value) || !strlen($value)))
506
  $value = $default_options[$key];
507
  /**/
508
+ else if(preg_match("/^level[0-9]+_catgs$/", $key) && (!is_string($value) || !($value = ((strcasecmp($value, "all") === 0) ? strtolower($value) : trim(preg_replace("/[^0-9,]/", "", $value), ",")))))
509
  $value = $default_options[$key];
510
  /**/
511
+ else if(preg_match("/^level[0-9]+_ptags$/", $key) && (!is_string($value) || !($value = ((strcasecmp($value, "all") === 0) ? strtolower($value) : trim(preg_replace("/ +/", " ", trim(preg_replace("/ *, */", ",", $value))), ",")))))
512
  $value = $default_options[$key];
513
  /**/
514
+ else if(preg_match("/^level[0-9]+_posts$/", $key) && (!is_string($value) || !($value = trim( /* Supports `all` or `1,2,3,all-[type]s`. */preg_replace("/[^a-z0-9_\-,]/", "", strtolower($value)), ","))))
515
  $value = $default_options[$key];
516
  /**/
517
+ else if(preg_match("/^level[0-9]+_pages$/", $key) && (!is_string($value) || !($value = ((strcasecmp($value, "all") === 0) ? strtolower($value) : trim(preg_replace("/[^0-9,]/", "", $value), ",")))))
518
  $value = $default_options[$key];
519
  /**/
520
+ else if($key === "specific_ids" && (!is_string($value) || !($value = trim(preg_replace("/[^0-9,]/", "", $value), ","))))
521
  $value = $default_options[$key];
522
  /**/
523
+ else if($key === "triggers_immediate_eot" && (!is_string($value) || !preg_match("/^(?:none|refunds|reversals|refunds,reversals)$/", $value)))
524
  $value = $default_options[$key];
525
  /**/
526
+ else if($key === "membership_eot_behavior" && (!is_string($value) || !preg_match("/^(?:demote|delete)$/", $value)))
527
  $value = $default_options[$key];
528
  /**/
529
+ else if($key === "eot_time_ext_behavior" && (!is_string($value) || !preg_match("/^(?:extend|reset)$/", $value)))
530
  $value = $default_options[$key];
531
  /**/
532
+ else if($key === "auto_eot_system_enabled" && (!is_string($value) || !is_numeric($value)))
533
  $value = $default_options[$key];
534
  /**/
535
+ else if($key === "wp_footer_code" && (!is_string($value) || !strlen($value)))
536
  $value = $default_options[$key];
537
  }
538
  /**/
539
+ if($options !== false && is_string($options["sec_encryption_key"]) && strlen($options["sec_encryption_key"]) && !in_array($options["sec_encryption_key"], $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"]))
540
  {
541
+ array_unshift($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"], $options["sec_encryption_key"]);
542
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"] = array_slice($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sec_encryption_key_history"], 0, 10);
543
  }
544
  /**/
545
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = apply_filters_ref_array("ws_plugin__s2member_options_before_checksum", array(&$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]));
546
  /**/
547
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_checksum"] = md5($checksum_prefix.serialize(array_merge($GLOBALS["WS_PLUGIN__"]["s2member"]["o"], array("options_checksum" => 0))));
548
  }
549
  /**/
550
+ return apply_filters_ref_array("ws_plugin__s2member_options", array(&$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]));
551
  }
552
  }
553
  ?>
includes/templates/cfg-files/s2member-files-no-gzip.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
3
+ exit("Do not access this file directly.");
4
+
5
+ global $base; /* A Multisite ``$base`` configuration? */
6
+ $ws_plugin__s2member_temp_s_base = (!empty ($base)) ? $base : c_ws_plugin__s2member_utils_urls::parse_url (network_home_url ("/"), PHP_URL_PATH);
7
+ /* This works on Multisite installs too. The function ``network_home_url ()`` defaults to ``home_url ()`` on standard WordPress® installs. */
8
+ /* Do NOT use ``site`` URL. Must use the `home` URL here, because that's what WordPress® uses in its own `mod_rewrite` implementation. */
9
+ ?>
10
+
11
+ <IfModule mod_rewrite.c>
12
+ RewriteEngine On
13
+ RewriteBase <?php echo $ws_plugin__s2member_temp_s_base . "\n"; ?>
14
+ RewriteCond %{QUERY_STRING} (?:^|\?|&)s2member_file_download\=.+
15
+ RewriteRule .* - [E=no-gzip:1]
16
+ </IfModule>
17
+
18
+ <?php unset ($ws_plugin__s2member_temp_s_base); ?>
includes/templates/cfg-files/s2member-files.php CHANGED
@@ -10,54 +10,95 @@ $ws_plugin__s2member_temp_s_base = (!empty ($base)) ? $base : c_ws_plugin__s2mem
10
 
11
  Options +FollowSymLinks -MultiViews -Indexes
12
 
 
 
 
 
 
13
  <IfModule mod_rewrite.c>
 
14
  RewriteEngine On
15
  RewriteBase <?php echo $ws_plugin__s2member_temp_s_base . "\n"; ?>
16
 
17
- RewriteCond %{ENV:s2member_file_ms_scan} !^complete$
18
- RewriteCond %{THE_REQUEST} ^(?:GET|HEAD)(?:[\ ]+)(?:<?php echo preg_quote ($ws_plugin__s2member_temp_s_base, " "); ?>)([_0-9a-zA-Z\-]+/)(?:wp-content/)
19
- RewriteRule ^(.*)$ - [E=s2member_file_ms_scan:complete,E=s2_blog:%1]
20
 
21
- RewriteCond %{ENV:s2member_file_download_scan} !^complete$
22
- RewriteRule ^(.*)$ - [E=s2member_file_download_scan:complete,E=s2member_file_download:$1]
 
 
23
 
 
24
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-stream/)(.+)$
25
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%2,E=s2member_file_stream:&s2member_file_stream=yes]
26
 
27
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-stream-(.+?)/)(.+)$
28
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_file_stream:&s2member_file_stream=%2]
29
 
 
30
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-inline/)(.+)$
31
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%2,E=s2member_file_inline:&s2member_file_inline=yes]
32
 
33
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-inline-(.+?)/)(.+)$
34
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_file_inline:&s2member_file_inline=%2]
35
 
 
36
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-storage-(.+?)/)(.+)$
37
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_file_storage:&s2member_file_storage=%2]
38
 
 
39
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-remote/)(.+)$
40
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%2,E=s2member_file_remote:&s2member_file_remote=yes]
41
 
42
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-remote-(.+?)/)(.+)$
43
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_file_remote:&s2member_file_remote=%2]
44
 
 
45
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-ssl/)(.+)$
46
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%2,E=s2member_file_ssl:&s2member_file_ssl=yes]
47
 
48
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-ssl-(.+?)/)(.+)$
49
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_file_ssl:&s2member_file_ssl=%2]
50
 
 
51
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-download-key-(.+?)/)(.+)$
52
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_file_download_key:&s2member_file_download_key=%2]
53
 
 
54
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-skip-confirmation/)(.+)$
55
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%2,E=s2member_skip_confirmation:&s2member_skip_confirmation=yes]
56
 
57
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-skip-confirmation-(.+?)/)(.+)$
58
- RewriteRule ^(.*)$ - [N,E=s2member_file_download:%1%3,E=s2member_skip_confirmation:&s2member_skip_confirmation=%2]
59
-
60
- RewriteRule ^(.*)$ %{ENV:s2_blog}?s2member_file_download=%{ENV:s2member_file_download}%{ENV:s2member_file_stream}%{ENV:s2member_file_inline}%{ENV:s2member_file_storage}%{ENV:s2member_file_remote}%{ENV:s2member_file_ssl}%{ENV:s2member_file_download_key}%{ENV:s2member_skip_confirmation} [QSA,L]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  </IfModule>
62
 
63
  <IfModule !mod_rewrite.c>
10
 
11
  Options +FollowSymLinks -MultiViews -Indexes
12
 
13
+ <IfModule mod_env.c>
14
+ # No GZIP for script-based file downloads.
15
+ SetEnv no-gzip 1
16
+ </IfModule>
17
+
18
  <IfModule mod_rewrite.c>
19
+ # Enable rewrite and configure base.
20
  RewriteEngine On
21
  RewriteBase <?php echo $ws_plugin__s2member_temp_s_base . "\n"; ?>
22
 
23
+ # Initialize all environment variables we're using below.
24
+ RewriteCond %{ENV:s2member_file_download_setup} !^complete$
25
+ RewriteRule ^(.*)$ - [E=s2member_file_download_wp_vdir:0,E=s2member_file_download:$1,E=s2member_file_stream:0,E=s2member_file_inline:0,E=s2member_file_storage:0,E=s2member_file_remote:0,E=s2member_file_ssl:0,E=s2member_file_download_key:0,E=s2member_skip_confirmation:0,E=s2member_file_download_setup:complete]
26
 
27
+ # Handle virtual directories, common on multisite networks.
28
+ RewriteCond %{ENV:s2member_file_download_wp_vdir_check} !^complete$
29
+ RewriteCond %{THE_REQUEST} ^(?:GET|HEAD)(?:[\ ]+)(?:<?php echo preg_quote ($ws_plugin__s2member_temp_s_base, " "); ?>)([_0-9a-zA-Z\-]+/)(?:wp-content/)
30
+ RewriteRule ^(.*)$ - [E=s2member_file_download_wp_vdir:,E=s2member_file_download_wp_vdir:%1,E=s2member_file_download_wp_vdir_check:complete]
31
 
32
+ # Handle streaming download requests via the rewrite engine.
33
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-stream/)(.+)$
34
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%2,E=s2member_file_stream:,E=s2member_file_stream:&s2member_file_stream=yes]
35
 
36
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-stream-(.+?)/)(.+)$
37
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_file_stream:,E=s2member_file_stream:&s2member_file_stream=%2]
38
 
39
+ # Handle inline file requests via the rewrite engine.
40
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-inline/)(.+)$
41
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%2,E=s2member_file_inline:,E=s2member_file_inline:&s2member_file_inline=yes]
42
 
43
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-inline-(.+?)/)(.+)$
44
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_file_inline:,E=s2member_file_inline:&s2member_file_inline=%2]
45
 
46
+ # Handle storage specifications via the rewrite engine.
47
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-storage-(.+?)/)(.+)$
48
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_file_storage:,E=s2member_file_storage:&s2member_file_storage=%2]
49
 
50
+ # Handle remote authorization requests via the rewrite engine.
51
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-remote/)(.+)$
52
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%2,E=s2member_file_remote:,E=s2member_file_remote:&s2member_file_remote=yes]
53
 
54
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-remote-(.+?)/)(.+)$
55
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_file_remote:,E=s2member_file_remote:&s2member_file_remote=%2]
56
 
57
+ # Handle SSL file requests via the rewrite engine.
58
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-ssl/)(.+)$
59
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%2,E=s2member_file_ssl:,E=s2member_file_ssl:&s2member_file_ssl=yes]
60
 
61
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-ssl-(.+?)/)(.+)$
62
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_file_ssl:,E=s2member_file_ssl:&s2member_file_ssl=%2]
63
 
64
+ # Handle file download keys via the rewrite engine.
65
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-file-download-key-(.+?)/)(.+)$
66
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_file_download_key:,E=s2member_file_download_key:&s2member_file_download_key=%2]
67
 
68
+ # Handle confirmations having beek skipped via the rewrite engine.
69
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-skip-confirmation/)(.+)$
70
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%2,E=s2member_skip_confirmation:,E=s2member_skip_confirmation:&s2member_skip_confirmation=yes]
71
 
72
  RewriteCond %{ENV:s2member_file_download} ^(.*?)(?:s2member-skip-confirmation-(.+?)/)(.+)$
73
+ RewriteRule ^(.*)$ - [N,E=s2member_file_download:,E=s2member_file_download:%1%3,E=s2member_skip_confirmation:,E=s2member_skip_confirmation:&s2member_skip_confirmation=%2]
74
+
75
+ # Cleanup variables not used in this request. Looking for `0` values.
76
+ RewriteCond %{ENV:s2member_file_download_wp_vdir} ^0$
77
+ RewriteRule ^(.*)$ - [E=s2member_file_download_wp_vdir:]
78
+
79
+ RewriteCond %{ENV:s2member_file_stream} ^0$
80
+ RewriteRule ^(.*)$ - [E=s2member_file_stream:]
81
+
82
+ RewriteCond %{ENV:s2member_file_inline} ^0$
83
+ RewriteRule ^(.*)$ - [E=s2member_file_inline:]
84
+
85
+ RewriteCond %{ENV:s2member_file_storage} ^0$
86
+ RewriteRule ^(.*)$ - [E=s2member_file_storage:]
87
+
88
+ RewriteCond %{ENV:s2member_file_remote} ^0$
89
+ RewriteRule ^(.*)$ - [E=s2member_file_remote:]
90
+
91
+ RewriteCond %{ENV:s2member_file_ssl} ^0$
92
+ RewriteRule ^(.*)$ - [E=s2member_file_ssl:]
93
+
94
+ RewriteCond %{ENV:s2member_file_download_key} ^0$
95
+ RewriteRule ^(.*)$ - [E=s2member_file_download_key:]
96
+
97
+ RewriteCond %{ENV:s2member_skip_confirmation} ^0$
98
+ RewriteRule ^(.*)$ - [E=s2member_skip_confirmation:]
99
+
100
+ # Put everything together now and process the internal rewrite.
101
+ RewriteRule ^(.*)$ %{ENV:s2member_file_download_wp_vdir}?s2member_file_download=%{ENV:s2member_file_download}%{ENV:s2member_file_stream}%{ENV:s2member_file_inline}%{ENV:s2member_file_storage}%{ENV:s2member_file_remote}%{ENV:s2member_file_ssl}%{ENV:s2member_file_download_key}%{ENV:s2member_skip_confirmation} [QSA,L]
102
  </IfModule>
103
 
104
  <IfModule !mod_rewrite.c>
includes/templates/cfg-files/s2o-mu-plugins.php CHANGED
@@ -3,7 +3,18 @@ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
3
  exit("Do not access this file directly.");
4
  ?>
5
 
6
- /* s2Member-only mode. Only load special file `s2member-o.php`, exclude all others. */
7
 
8
  if (file_exists (WPMU_PLUGIN_DIR . "/s2member-o.php"))
9
- include_once WPMU_PLUGIN_DIR . "/s2member-o.php";
 
 
 
 
 
 
 
 
 
 
 
3
  exit("Do not access this file directly.");
4
  ?>
5
 
6
+ /* s2Member-only mode. Only load (o)nly/(a)ll files. */
7
 
8
  if (file_exists (WPMU_PLUGIN_DIR . "/s2member-o.php"))
9
+ include_once WPMU_PLUGIN_DIR . "/s2member-o.php";
10
+
11
+ else if (file_exists (WPMU_PLUGIN_DIR . "/s2-o.php"))
12
+ include_once WPMU_PLUGIN_DIR . "/s2-o.php";
13
+
14
+ /* -------------------------------------------------- */
15
+
16
+ if (file_exists (WPMU_PLUGIN_DIR . "/s2member-a.php"))
17
+ include_once WPMU_PLUGIN_DIR . "/s2member-a.php";
18
+
19
+ else if (file_exists (WPMU_PLUGIN_DIR . "/s2-a.php"))
20
+ include_once WPMU_PLUGIN_DIR . "/s2-a.php";
includes/translations/s2member.pot CHANGED
@@ -1,10 +1,10 @@
1
- # Copyright (C) 2010 s2Member
2
- # This file is distributed under the same license as the s2Member package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: s2Member 111220\n"
6
- "Report-Msgid-Bugs-To: http://wordpress.org/tag/.__s2member\n"
7
- "POT-Creation-Date: 2011-12-20 14:28:23+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -17,8 +17,8 @@ msgctxt "s2member-front"
17
  msgid "Max failed logins. Please wait %s and try again."
18
  msgstr ""
19
 
20
- #: s2member/includes/classes/custom-reg-fields.inc.php:337
21
- #: s2member/includes/classes/custom-reg-fields.inc.php:479
22
  #: s2member/includes/classes/profile-in.inc.php:120
23
  #: s2member/includes/classes/sc-profile-in.inc.php:136
24
  #: s2member-pro/includes/templates/forms/authnet-checkout-form.php:51
@@ -31,8 +31,8 @@ msgctxt "s2member-front"
31
  msgid "First Name"
32
  msgstr ""
33
 
34
- #: s2member/includes/classes/custom-reg-fields.inc.php:349
35
- #: s2member/includes/classes/custom-reg-fields.inc.php:494
36
  #: s2member/includes/classes/profile-in.inc.php:140
37
  #: s2member/includes/classes/sc-profile-in.inc.php:156
38
  #: s2member-pro/includes/templates/forms/authnet-checkout-form.php:57
@@ -45,8 +45,8 @@ msgctxt "s2member-front"
45
  msgid "Last Name"
46
  msgstr ""
47
 
48
- #: s2member/includes/classes/custom-reg-fields.inc.php:451
49
- #: s2member/includes/classes/custom-reg-fields.inc.php:456
50
  #: s2member/includes/classes/profile-in.inc.php:233
51
  #: s2member/includes/classes/profile-in.inc.php:239
52
  #: s2member/includes/classes/sc-profile-in.inc.php:249
@@ -55,12 +55,12 @@ msgctxt "s2member-front"
55
  msgid "Please type your Password twice to confirm."
56
  msgstr ""
57
 
58
- #: s2member/includes/classes/custom-reg-fields.inc.php:452
59
  msgctxt "s2member-front"
60
  msgid "Password ( please type it twice )"
61
  msgstr ""
62
 
63
- #: s2member/includes/classes/custom-reg-fields.inc.php:460
64
  #: s2member/includes/classes/profile-in.inc.php:243
65
  #: s2member/includes/classes/sc-profile-in.inc.php:259
66
  #: s2member-pro/includes/templates/forms/authnet-checkout-form.php:79
@@ -76,33 +76,33 @@ msgctxt "s2member-front"
76
  msgid "as a Member"
77
  msgstr ""
78
 
79
- #: s2member/includes/classes/files-in.inc.php:91
80
- #: s2member/includes/classes/files-in.inc.php:241
81
  msgctxt "s2member-front"
82
  msgid "<strong>404: Sorry, file not found.</strong> Please contact Support for assistance."
83
  msgstr ""
84
 
85
- #: s2member/includes/classes/files-in.inc.php:101
86
  msgctxt "s2member-front"
87
  msgid "<strong>503 ( Invalid Key ):</strong> Sorry, your access to this file has expired. Please contact Support for assistance."
88
  msgstr ""
89
 
90
- #: s2member/includes/classes/files-in.inc.php:121
91
  msgctxt "s2member-front"
92
  msgid "<strong>503: Basic File Downloads are NOT enabled yet.</strong> Please contact Support for assistance. If you are the site owner, please configure: <code>s2Member -> Download Options -> Basic Download Restrictions</code>."
93
  msgstr ""
94
 
95
- #: s2member/includes/classes/files-in.inc.php:390
96
  msgctxt "s2member-front"
97
  msgid "<strong>503: Access denied.</strong> Invalid File Download specs."
98
  msgstr ""
99
 
100
- #: s2member/includes/classes/files-in.inc.php:476
101
  msgctxt "s2member-front"
102
  msgid "Members Only"
103
  msgstr ""
104
 
105
- #: s2member/includes/classes/files-in.inc.php:482
106
  msgctxt "s2member-front"
107
  msgid "<strong>401:</strong> Sorry, access denied."
108
  msgstr ""
@@ -111,12 +111,12 @@ msgstr ""
111
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
112
  #. `%s` if you like.
113
 
114
- #: s2member/includes/classes/files-in.inc.php:620
115
  msgctxt "s2member-admin"
116
  msgid "Unable to update existing Amazon® S3 Cross-Domain Policy. %s"
117
  msgstr ""
118
 
119
- #: s2member/includes/classes/files-in.inc.php:623
120
  msgctxt "s2member-admin"
121
  msgid "Unable to update existing Amazon® S3 Cross-Domain Policy. Connection failed."
122
  msgstr ""
@@ -125,12 +125,12 @@ msgstr ""
125
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
126
  #. `%s` if you like.
127
 
128
- #: s2member/includes/classes/files-in.inc.php:627
129
  msgctxt "s2member-admin"
130
  msgid "Unable to update existing Amazon® S3 Bucket Policy. %s"
131
  msgstr ""
132
 
133
- #: s2member/includes/classes/files-in.inc.php:630
134
  msgctxt "s2member-admin"
135
  msgid "Unable to update existing Amazon® S3 Bucket Policy. Connection failed."
136
  msgstr ""
@@ -139,17 +139,17 @@ msgstr ""
139
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
140
  #. `%s` if you like.
141
 
142
- #: s2member/includes/classes/files-in.inc.php:634
143
  msgctxt "s2member-admin"
144
  msgid "Unable to update existing Amazon® S3 Bucket ACLs. %s"
145
  msgstr ""
146
 
147
- #: s2member/includes/classes/files-in.inc.php:637
148
  msgctxt "s2member-admin"
149
  msgid "Unable to update existing Amazon® S3 Bucket ACLs. Connection failed."
150
  msgstr ""
151
 
152
- #: s2member/includes/classes/files-in.inc.php:640
153
  msgctxt "s2member-admin"
154
  msgid "Unable to acquire/read existing Amazon® S3 Bucket ACLs. Unexpected response."
155
  msgstr ""
@@ -158,22 +158,22 @@ msgstr ""
158
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
159
  #. `%s` if you like.
160
 
161
- #: s2member/includes/classes/files-in.inc.php:644
162
  msgctxt "s2member-admin"
163
  msgid "Unable to acquire existing Amazon® S3 Bucket ACLs. %s"
164
  msgstr ""
165
 
166
- #: s2member/includes/classes/files-in.inc.php:647
167
  msgctxt "s2member-admin"
168
  msgid "Unable to acquire existing Amazon® S3 Bucket ACLs. Connection failed."
169
  msgstr ""
170
 
171
- #: s2member/includes/classes/files-in.inc.php:650
172
  msgctxt "s2member-admin"
173
  msgid "Unable to auto-configure existing Amazon® S3 Bucket ACLs. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key."
174
  msgstr ""
175
 
176
- #: s2member/includes/classes/files-in.inc.php:752
177
  msgctxt "s2member-admin"
178
  msgid "Unable to delete existing Amazon® CloudFront Downloads Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again."
179
  ms
1
+ # Copyright (C) 2010 s2Member® Framework
2
+ # This file is distributed under the same license as the s2Member® Framework package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: s2Member® Framework 120213\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/__s2member\n"
7
+ "POT-Creation-Date: 2012-02-14 02:33:18+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
17
  msgid "Max failed logins. Please wait %s and try again."
18
  msgstr ""
19
 
20
+ #: s2member/includes/classes/custom-reg-fields.inc.php:338
21
+ #: s2member/includes/classes/custom-reg-fields.inc.php:480
22
  #: s2member/includes/classes/profile-in.inc.php:120
23
  #: s2member/includes/classes/sc-profile-in.inc.php:136
24
  #: s2member-pro/includes/templates/forms/authnet-checkout-form.php:51
31
  msgid "First Name"
32
  msgstr ""
33
 
34
+ #: s2member/includes/classes/custom-reg-fields.inc.php:350
35
+ #: s2member/includes/classes/custom-reg-fields.inc.php:495
36
  #: s2member/includes/classes/profile-in.inc.php:140
37
  #: s2member/includes/classes/sc-profile-in.inc.php:156
38
  #: s2member-pro/includes/templates/forms/authnet-checkout-form.php:57
45
  msgid "Last Name"
46
  msgstr ""
47
 
48
+ #: s2member/includes/classes/custom-reg-fields.inc.php:452
49
+ #: s2member/includes/classes/custom-reg-fields.inc.php:457
50
  #: s2member/includes/classes/profile-in.inc.php:233
51
  #: s2member/includes/classes/profile-in.inc.php:239
52
  #: s2member/includes/classes/sc-profile-in.inc.php:249
55
  msgid "Please type your Password twice to confirm."
56
  msgstr ""
57
 
58
+ #: s2member/includes/classes/custom-reg-fields.inc.php:453
59
  msgctxt "s2member-front"
60
  msgid "Password ( please type it twice )"
61
  msgstr ""
62
 
63
+ #: s2member/includes/classes/custom-reg-fields.inc.php:461
64
  #: s2member/includes/classes/profile-in.inc.php:243
65
  #: s2member/includes/classes/sc-profile-in.inc.php:259
66
  #: s2member-pro/includes/templates/forms/authnet-checkout-form.php:79
76
  msgid "as a Member"
77
  msgstr ""
78
 
79
+ #: s2member/includes/classes/files-in.inc.php:92
80
+ #: s2member/includes/classes/files-in.inc.php:242
81
  msgctxt "s2member-front"
82
  msgid "<strong>404: Sorry, file not found.</strong> Please contact Support for assistance."
83
  msgstr ""
84
 
85
+ #: s2member/includes/classes/files-in.inc.php:102
86
  msgctxt "s2member-front"
87
  msgid "<strong>503 ( Invalid Key ):</strong> Sorry, your access to this file has expired. Please contact Support for assistance."
88
  msgstr ""
89
 
90
+ #: s2member/includes/classes/files-in.inc.php:122
91
  msgctxt "s2member-front"
92
  msgid "<strong>503: Basic File Downloads are NOT enabled yet.</strong> Please contact Support for assistance. If you are the site owner, please configure: <code>s2Member -> Download Options -> Basic Download Restrictions</code>."
93
  msgstr ""
94
 
95
+ #: s2member/includes/classes/files-in.inc.php:404
96
  msgctxt "s2member-front"
97
  msgid "<strong>503: Access denied.</strong> Invalid File Download specs."
98
  msgstr ""
99
 
100
+ #: s2member/includes/classes/files-in.inc.php:490
101
  msgctxt "s2member-front"
102
  msgid "Members Only"
103
  msgstr ""
104
 
105
+ #: s2member/includes/classes/files-in.inc.php:496
106
  msgctxt "s2member-front"
107
  msgid "<strong>401:</strong> Sorry, access denied."
108
  msgstr ""
111
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
112
  #. `%s` if you like.
113
 
114
+ #: s2member/includes/classes/files-in.inc.php:634
115
  msgctxt "s2member-admin"
116
  msgid "Unable to update existing Amazon® S3 Cross-Domain Policy. %s"
117
  msgstr ""
118
 
119
+ #: s2member/includes/classes/files-in.inc.php:637
120
  msgctxt "s2member-admin"
121
  msgid "Unable to update existing Amazon® S3 Cross-Domain Policy. Connection failed."
122
  msgstr ""
125
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
126
  #. `%s` if you like.
127
 
128
+ #: s2member/includes/classes/files-in.inc.php:641
129
  msgctxt "s2member-admin"
130
  msgid "Unable to update existing Amazon® S3 Bucket Policy. %s"
131
  msgstr ""
132
 
133
+ #: s2member/includes/classes/files-in.inc.php:644
134
  msgctxt "s2member-admin"
135
  msgid "Unable to update existing Amazon® S3 Bucket Policy. Connection failed."
136
  msgstr ""
139
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
140
  #. `%s` if you like.
141
 
142
+ #: s2member/includes/classes/files-in.inc.php:648
143
  msgctxt "s2member-admin"
144
  msgid "Unable to update existing Amazon® S3 Bucket ACLs. %s"
145
  msgstr ""
146
 
147
+ #: s2member/includes/classes/files-in.inc.php:651
148
  msgctxt "s2member-admin"
149
  msgid "Unable to update existing Amazon® S3 Bucket ACLs. Connection failed."
150
  msgstr ""
151
 
152
+ #: s2member/includes/classes/files-in.inc.php:654
153
  msgctxt "s2member-admin"
154
  msgid "Unable to acquire/read existing Amazon® S3 Bucket ACLs. Unexpected response."
155
  msgstr ""
158
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
159
  #. `%s` if you like.
160
 
161
+ #: s2member/includes/classes/files-in.inc.php:658
162
  msgctxt "s2member-admin"
163
  msgid "Unable to acquire existing Amazon® S3 Bucket ACLs. %s"
164
  msgstr ""
165
 
166
+ #: s2member/includes/classes/files-in.inc.php:661
167
  msgctxt "s2member-admin"
168
  msgid "Unable to acquire existing Amazon® S3 Bucket ACLs. Connection failed."
169
  msgstr ""
170
 
171
+ #: s2member/includes/classes/files-in.inc.php:664
172
  msgctxt "s2member-admin"
173
  msgid "Unable to auto-configure existing Amazon® S3 Bucket ACLs. Incomplete Amazon® S3 configuration options. Missing one of: Amazon® S3 Bucket, Access Key, or Secret Key."
174
  msgstr ""
175
 
176
+ #: s2member/includes/classes/files-in.inc.php:766
177
  msgctxt "s2member-admin"
178
  msgid "Unable to delete existing Amazon® CloudFront Downloads Distro. Still in a `pending` state. Please wait 15 minutes, then try again. There is a certain process that s2Member must strictly adhere to when re-configuring your Amazon® CloudFront Distros. You may have to tick the auto-configure checkbox again, and re-run s2Member's auto-configuration routine many times, because s2Member will likely run into several `pending` challenges, as it works to completely re-configure your Amazon® CloudFront Distros for you. Thanks for your patience. Please wait 15 minutes, then try again."
179
  ms