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

Version Description

= v130121 = Maintenance release. Upgrade immediately.

Download this release

Release Info

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

Code changes from version 130116 to 130121

checksum.txt CHANGED
@@ -1 +1 @@
1
- 655f768491a988742a812294fc044a66
1
+ 1929917d1855921a8a385f7a1198bc7b
includes/classes/files-in.inc.php CHANGED
@@ -52,6 +52,19 @@ if(!class_exists("c_ws_plugin__s2member_files_in"))
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"];
57
  $req["file_download_key"] = ($creating) ? @$create["file_download_key"] : @$_g["s2member_file_download_key"];
@@ -81,7 +94,7 @@ if(!class_exists("c_ws_plugin__s2member_files_in"))
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
  {
@@ -271,7 +284,7 @@ if(!class_exists("c_ws_plugin__s2member_files_in"))
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
- $disposition = (($inline) ? "inline" : "attachment")."; filename=\"".$basename."\"";
275
  $length = (!$using_amazon_storage && $file) ? filesize($file) : -1;
276
  /**/
277
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
@@ -331,23 +344,14 @@ if(!class_exists("c_ws_plugin__s2member_files_in"))
331
  return apply_filters("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars());
332
  }
333
  /**/
334
- else /* Else, ``if ($serving)``, use local storage. */
335
  {
336
  @set_time_limit(0);
337
  /**/
338
  @ini_set("zlib.output_compression", 0);
339
  if(function_exists("apache_setenv"))
340
  @apache_setenv("no-gzip", "1");
341
- while /* Cleans existing output buffers. */(@ob_end_clean())
342
- ;
343
- /**/
344
- $range = (string)@$_SERVER["HTTP_RANGE"];
345
- if(!$range && function_exists("apache_request_headers"))
346
- /* Note: ``apache_request_headers()`` works in FastCGI too, starting w/ PHP v5.4. */
347
- foreach((array)apache_request_headers() as $_header => $_value)
348
- if(is_string($_header) && strcasecmp($_header, "range") === 0)
349
- $range = $_value;
350
- unset($_header, $_value);
351
  /**/
352
  if /* Requesting a specific byte range? */($range)
353
  {
@@ -519,10 +523,10 @@ if(!class_exists("c_ws_plugin__s2member_files_in"))
519
  $ssl = (isset($config["file_ssl"])) ? filter_var($config["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl()) ? true : false);
520
  /**/
521
  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)))))
522
- $return = array("streamer" => $streamer, "file" => preg_replace("/^".preg_quote($streamer, "/")."\//", "", $_url), "url" => preg_replace("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
523
  /**/
524
  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)))))
525
- $return = array("streamer" => $streamer, "file" => preg_replace("/^".preg_quote($streamer, "/")."\//", "", $_url), "url" => preg_replace("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
526
  /**/
527
  else if /* If streamer, we MUST return false here; unable to acquire streamer/file. */($get_streamer_array)
528
  $return = /* We MUST return false here, unable to acquire streamer/file. */ false;
@@ -637,7 +641,7 @@ if(!class_exists("c_ws_plugin__s2member_files_in"))
637
  if(preg_match("/^amazon_s3_files_/", $option) && ($option = preg_replace("/^amazon_s3_files_/", "", $option)))
638
  $s3c[$option] = $option_value;
639
  /**/
640
- $s3c["expires"] = strtotime("+".apply_filters("ws_plugin__s2member_amazon_s3_file_expires_time", "30 seconds", get_defined_vars()));
641
  /**/
642
  $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);
643
  $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);
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
+ $serving_range = $range = /* Default values (so these variables DO get defined at all times). */ false;
56
+ if /* If we're serving, let's see if we're serving a byte-range request here. */($serving)
57
+ {
58
+ $range = (string)@$_SERVER["HTTP_RANGE"];
59
+ if(!$range && function_exists("apache_request_headers"))
60
+ /* Note: ``apache_request_headers()`` works in FastCGI too, starting w/ PHP v5.4. */
61
+ foreach((array)apache_request_headers() as $_header => $_value)
62
+ if(is_string($_header) && strcasecmp($_header, "range") === 0)
63
+ $range = $_value;
64
+ if /* Serving a range? */($range)
65
+ $serving_range = true;
66
+ unset($_header, $_value);
67
+ }
68
  /**/
69
  $req["file_download"] = ($creating) ? @$create["file_download"] : @$_g["s2member_file_download"];
70
  $req["file_download_key"] = ($creating) ? @$create["file_download_key"] : @$_g["s2member_file_download_key"];
94
  $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;
95
  $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;
96
  $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;
97
+ $updating_user_counter = ($serving_range || !$checking_user || ($creating && (!isset($req["count_against_user"]) || !filter_var($req["count_against_user"], FILTER_VALIDATE_BOOLEAN)))) ? false : true;
98
  /**/
99
  if( /* In either case, the following routines apply whenever we ARE ``$checking_user``. */($serving || $creating) && $checking_user)
100
  {
284
  /**/
285
  $pathinfo = (!$using_amazon_storage) ? pathinfo(($file = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]."/".$req["file_download"])) : array();
286
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream";
287
+ $disposition = (($inline) ? "inline" : "attachment")."; filename=\"".c_ws_plugin__s2member_utils_strings::esc_dq($basename)."\"; filename*=UTF-8''".rawurlencode($basename);
288
  $length = (!$using_amazon_storage && $file) ? filesize($file) : -1;
289
  /**/
290
  eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
344
  return apply_filters("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars());
345
  }
346
  /**/
347
+ else if /* Else, ``if ($serving)``, use local storage. */($serving)
348
  {
349
  @set_time_limit(0);
350
  /**/
351
  @ini_set("zlib.output_compression", 0);
352
  if(function_exists("apache_setenv"))
353
  @apache_setenv("no-gzip", "1");
354
+ while /* Cleans existing output buffers. */(@ob_end_clean());
 
 
 
 
 
 
 
 
 
355
  /**/
356
  if /* Requesting a specific byte range? */($range)
357
  {
523
  $ssl = (isset($config["file_ssl"])) ? filter_var($config["file_ssl"], FILTER_VALIDATE_BOOLEAN) : ((is_ssl()) ? true : false);
524
  /**/
525
  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)))))
526
+ $return = array("streamer" => $streamer, "prefix" => $extension.":", "file" => preg_replace("/^".preg_quote($streamer, "/")."\//", "", $_url), "url" => preg_replace("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
527
  /**/
528
  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)))))
529
+ $return = array("streamer" => $streamer, "prefix" => $extension.":", "file" => preg_replace("/^".preg_quote($streamer, "/")."\//", "", $_url), "url" => preg_replace("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
530
  /**/
531
  else if /* If streamer, we MUST return false here; unable to acquire streamer/file. */($get_streamer_array)
532
  $return = /* We MUST return false here, unable to acquire streamer/file. */ false;
641
  if(preg_match("/^amazon_s3_files_/", $option) && ($option = preg_replace("/^amazon_s3_files_/", "", $option)))
642
  $s3c[$option] = $option_value;
643
  /**/
644
+ $s3c["expires"] = strtotime("+".apply_filters("ws_plugin__s2member_amazon_s3_file_expires_time", "24 hours", get_defined_vars()));
645
  /**/
646
  $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);
647
  $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);
includes/classes/sc-files-in.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\s2File
15
  * @since 110926
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_sc_files_in"))
21
  {
22
  /**
23
  * Shortcode `[s2File /]` ( inner processing routines ).
@@ -40,47 +40,120 @@ if (!class_exists ("c_ws_plugin__s2member_sc_files_in"))
40
  * @param str $shortcode The actual Shortcode name itself.
41
  * @return str Value of requested File Download URL, streamer array element; or null on failure.
42
  */
43
- public static function sc_get_file ($attr = FALSE, $content = FALSE, $shortcode = FALSE)
44
  {
45
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
46
- do_action ("ws_plugin__s2member_before_sc_get_file", get_defined_vars ());
47
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
48
  /**/
49
- $attr = c_ws_plugin__s2member_utils_strings::trim_qts_deep ((array)$attr); /* Force array; trim quote entities. */
50
  /**/
51
- $attr = shortcode_atts (array ("download" => "", "download_key" => "", "stream" => "", "inline" => "", "storage" => "", "remote" => "", "ssl" => "", "rewrite" => "", "rewrite_base" => "", "skip_confirmation" => "", "url_to_storage_source" => "", "count_against_user" => "", "check_user" => "", /* Shortcode-specifics » */ "get_streamer_json" => "", "get_streamer_array" => ""), $attr);
52
  /**/
53
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
54
- do_action ("ws_plugin__s2member_before_sc_get_file_after_shortcode_atts", get_defined_vars ());
55
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
56
  /**/
57
- $get_streamer_json = filter_var ($attr["get_streamer_json"], FILTER_VALIDATE_BOOLEAN); /* Getting streamer? */
58
- $get_streamer_array = filter_var ($attr["get_streamer_array"], FILTER_VALIDATE_BOOLEAN); /* Streamer? */
59
  $get_streamer_json = $get_streamer_array = ($get_streamer_array || $get_streamer_json) ? true : false;
60
  /**/
61
- foreach ($attr as $key => $value) /* Now we need to go through and a `file_` prefix to certain Attribute keys, for compatibility. */
62
- if (strlen ($value) && in_array ($key, array ("download", "download_key", "stream", "inline", "storage", "remote", "ssl", "rewrite", "rewrite_base")))
63
- $config["file_" . $key] = $value; /* Set prefixed config parameter here so we can pass properly in ``$config`` array. */
64
- else if (strlen ($value) && !in_array ($key, array ("get_streamer_json", "get_streamer_array"))) /* Else, exclude? */
65
  $config[$key] = $value;
66
  /**/
67
- unset ($key, $value); /* Ditch these now. We don't want these bleeding into Hooks/Filters anyway. */
68
  /**/
69
- if (!empty ($config) && isset ($config["file_download"])) /* Looking for a File Download URL? */
70
  {
71
- $_get = c_ws_plugin__s2member_files::create_file_download_url ($config, $get_streamer_array);
72
  /**/
73
- if ($get_streamer_array && $get_streamer_json && is_array ($_get))
74
- $get = json_encode ($_get);
75
  /**/
76
- else if ($get_streamer_array && $get_streamer_json)
77
- $get = "null"; /* Null object value. */
78
  /**/
79
- else if (!empty ($_get)) /* Else ``$get``. */
80
- $get = $_get; /* Default return. */
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  /**/
83
- return apply_filters ("ws_plugin__s2member_sc_get_file", ((isset ($get)) ? $get : null), get_defined_vars ());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
  }
86
  }
14
  * @package s2Member\s2File
15
  * @since 110926
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_sc_files_in"))
21
  {
22
  /**
23
  * Shortcode `[s2File /]` ( inner processing routines ).
40
  * @param str $shortcode The actual Shortcode name itself.
41
  * @return str Value of requested File Download URL, streamer array element; or null on failure.
42
  */
43
+ public static function sc_get_file($attr = FALSE, $content = FALSE, $shortcode = FALSE)
44
  {
45
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
46
+ do_action("ws_plugin__s2member_before_sc_get_file", get_defined_vars());
47
+ unset /* Unset defined __refs, __v. */($__refs, $__v);
48
  /**/
49
+ $attr = /* Force array; trim quote entities. */ c_ws_plugin__s2member_utils_strings::trim_qts_deep((array)$attr);
50
  /**/
51
+ $attr = shortcode_atts(array("download" => "", "download_key" => "", "stream" => "", "inline" => "", "storage" => "", "remote" => "", "ssl" => "", "rewrite" => "", "rewrite_base" => "", "skip_confirmation" => "", "url_to_storage_source" => "", "count_against_user" => "", "check_user" => "", /* Shortcode-specifics » */ "get_streamer_json" => "", "get_streamer_array" => ""), $attr);
52
  /**/
53
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
54
+ do_action("ws_plugin__s2member_before_sc_get_file_after_shortcode_atts", get_defined_vars());
55
+ unset /* Unset defined __refs, __v. */($__refs, $__v);
56
  /**/
57
+ $get_streamer_json = filter_var($attr["get_streamer_json"], FILTER_VALIDATE_BOOLEAN);
58
+ $get_streamer_array = filter_var($attr["get_streamer_array"], FILTER_VALIDATE_BOOLEAN);
59
  $get_streamer_json = $get_streamer_array = ($get_streamer_array || $get_streamer_json) ? true : false;
60
  /**/
61
+ foreach /* Now we need to go through and a `file_` prefix to certain Attribute keys, for compatibility. */($attr as $key => $value)
62
+ if(strlen($value) && in_array($key, array("download", "download_key", "stream", "inline", "storage", "remote", "ssl", "rewrite", "rewrite_base")))
63
+ $config["file_".$key] = /* Set prefixed config parameter here so we can pass properly in ``$config`` array. */ $value;
64
+ else if(strlen($value) && !in_array($key, array("get_streamer_json", "get_streamer_array")))
65
  $config[$key] = $value;
66
  /**/
67
+ unset /* Ditch these now. We don't want these bleeding into Hooks/Filters anyway. */($key, $value);
68
  /**/
69
+ if /* Looking for a File Download URL? */(!empty($config) && isset($config["file_download"]))
70
  {
71
+ $_get = c_ws_plugin__s2member_files::create_file_download_url($config, $get_streamer_array);
72
  /**/
73
+ if($get_streamer_array && $get_streamer_json && is_array($_get))
74
+ $get = json_encode($_get);
75
  /**/
76
+ else if($get_streamer_array && $get_streamer_json)
77
+ $get = /* Null object value. */ "null";
78
  /**/
79
+ else if(!empty($_get))
80
+ $get = $_get;
81
  }
82
+ return apply_filters("ws_plugin__s2member_sc_get_file", ((isset($get)) ? $get : null), get_defined_vars());
83
+ }
84
+ /**
85
+ * Handles the Shortcode for: `[s2Stream /]`.
86
+ *
87
+ * @package s2Member\s2File
88
+ * @since 130119
89
+ *
90
+ * @attaches-to ``add_shortcode("s2Stream");``
91
+ *
92
+ * @param array $attr An array of Attributes.
93
+ * @param str $content Content inside the Shortcode.
94
+ * @param str $shortcode The actual Shortcode name itself.
95
+ * @return str HTML markup that produces an audio/video stream for a specific player.
96
+ */
97
+ public static function sc_get_stream($attr = FALSE, $content = FALSE, $shortcode = FALSE)
98
+ {
99
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
100
+ do_action("ws_plugin__s2member_before_sc_get_stream", get_defined_vars());
101
+ unset /* Unset defined __refs, __v. */($__refs, $__v);
102
+ /**/
103
+ $attr = /* Force array; trim quote entities. */ c_ws_plugin__s2member_utils_strings::trim_qts_deep((array)$attr);
104
+ /**/
105
+ $attr = shortcode_atts(array("download" => "", "download_key" => "", "stream" => "yes", "inline" => "yes", "storage" => "", "remote" => "", "ssl" => "", "rewrite" => "yes", "rewrite_base" => "", "skip_confirmation" => "", "url_to_storage_source" => "yes", "count_against_user" => "yes", "check_user" => "yes", /* Shortcode-specifics » */ "file_download" => "", "player" => "jwplayer-v6-rtmp", "player_id" => "s2-stream-".md5(uniqid("", TRUE)), "player_path" => "/jwplayer/jwplayer.js", "player_image" => "", "player_title" => "", /* Layout » */ "player_controls" => "yes", "player_height" => "270", "player_skin" => "", "player_stretching" => "uniform", "player_width" => "480", /* Playback » */ "player_autostart" => "no", "player_fallback" => "yes", "player_mute" => "no", "player_primary" => "flash", "player_repeat" => "no", "player_startparam" => ""), $attr);
106
+ $attr["download"] = (!empty($attr["file_download"])) ? $attr["file_download"] : $attr["download"];
107
+ /**/
108
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
109
+ do_action("ws_plugin__s2member_before_sc_get_stream_after_shortcode_atts", get_defined_vars());
110
+ unset /* Unset defined __refs, __v. */($__refs, $__v);
111
+ /**/
112
+ foreach /* Now we need to go through and a `file_` prefix to certain Attribute keys, for compatibility. */($attr as $key => $value)
113
+ if(strlen($value) && in_array($key, array("download", "download_key", "stream", "inline", "storage", "remote", "ssl", "rewrite", "rewrite_base")))
114
+ $config["file_".$key] = /* Set prefixed config parameter here so we can pass properly in ``$config`` array. */ $value;
115
+ else if(strlen($value) && !in_array($key, array("file_download", "player")) && strpos($key, "player_") !== 0)
116
+ $config[$key] = $value;
117
+ /**/
118
+ unset /* Ditch these now. We don't want these bleeding into Hooks/Filters anyway. */($key, $value);
119
  /**/
120
+ if /* Looking for a File Download URL? */(!empty($config) && isset($config["file_download"]))
121
+ {
122
+ $_get = c_ws_plugin__s2member_files::create_file_download_url($config, TRUE);
123
+ /**/
124
+ if(is_array($_get) && !empty($_get) && $attr["player"] && file_exists(dirname(dirname(__FILE__))."/templates/players/".$attr["player"].".php") && $attr["player_id"] && $attr["player_path"])
125
+ {
126
+ if(strpos($attr["player"], "jwplayer-v6") === 0)
127
+ {
128
+ $get = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents(dirname(dirname(__FILE__))."/templates/players/".$attr["player"].".php")));
129
+ /**/
130
+ $get = preg_replace("/%%streamer%%/", $_get["streamer"], $get);
131
+ $get = preg_replace("/%%prefix%%/", $_get["prefix"], $get);
132
+ $get = preg_replace("/%%file%%/", $_get["file"], $get);
133
+ $get = preg_replace("/%%url%%/", $_get["url"], $get);
134
+ /**/
135
+ $get = preg_replace("/%%player_id%%/", $attr["player_id"], $get);
136
+ $get = preg_replace("/%%player_path%%/", $attr["player_path"], $get);
137
+ /**/
138
+ $get = preg_replace("/%%player_image%%/", $attr["player_image"], $get);
139
+ $get = preg_replace("/%%player_title%%/", $attr["player_title"], $get);
140
+ /**/
141
+ $get = preg_replace("/%%player_controls%%/", ((filter_var($attr["player_controls"], FILTER_VALIDATE_BOOLEAN)) ? "true" : "false"), $get);
142
+ $get = preg_replace("/%%player_height%%/", (integer)$attr["player_height"], $get);
143
+ $get = preg_replace("/%%player_skin%%/", $attr["player_skin"], $get);
144
+ $get = preg_replace("/%%player_stretching%%/", $attr["player_stretching"], $get);
145
+ $get = preg_replace("/%%player_width%%/", (integer)$attr["player_width"], $get);
146
+ /**/
147
+ $get = preg_replace("/%%player_autostart%%/", ((filter_var($attr["player_autostart"], FILTER_VALIDATE_BOOLEAN)) ? "true" : "false"), $get);
148
+ $get = preg_replace("/%%player_fallback%%/", ((filter_var($attr["player_fallback"], FILTER_VALIDATE_BOOLEAN)) ? "true" : "false"), $get);
149
+ $get = preg_replace("/%%player_mute%%/", ((filter_var($attr["player_mute"], FILTER_VALIDATE_BOOLEAN)) ? "true" : "false"), $get);
150
+ $get = preg_replace("/%%player_primary%%/", $attr["player_primary"], $get);
151
+ $get = preg_replace("/%%player_repeat%%/", ((filter_var($attr["player_repeat"], FILTER_VALIDATE_BOOLEAN)) ? "true" : "false"), $get);
152
+ $get = preg_replace("/%%player_startparam%%/", $attr["player_startparam"], $get);
153
+ }
154
+ }
155
+ }
156
+ return apply_filters("ws_plugin__s2member_sc_get_stream", ((isset($get)) ? $get : null), get_defined_vars());
157
  }
158
  }
159
  }
includes/classes/sc-files.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\s2File
15
  * @since 110926
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_sc_files"))
21
  {
22
  /**
23
  * Shortcode `[s2File /]`.
@@ -40,9 +40,26 @@ if (!class_exists ("c_ws_plugin__s2member_sc_files"))
40
  * @param str $shortcode The actual Shortcode name itself.
41
  * @return str Value of the requested File Download URL, or null on failure.
42
  */
43
- public static function sc_get_file ($attr = FALSE, $content = FALSE, $shortcode = FALSE)
44
  {
45
- return c_ws_plugin__s2member_sc_files_in::sc_get_file ($attr, $content, $shortcode);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
  }
48
  }
14
  * @package s2Member\s2File
15
  * @since 110926
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_sc_files"))
21
  {
22
  /**
23
  * Shortcode `[s2File /]`.
40
  * @param str $shortcode The actual Shortcode name itself.
41
  * @return str Value of the requested File Download URL, or null on failure.
42
  */
43
+ public static function sc_get_file($attr = FALSE, $content = FALSE, $shortcode = FALSE)
44
  {
45
+ return c_ws_plugin__s2member_sc_files_in::sc_get_file($attr, $content, $shortcode);
46
+ }
47
+ /**
48
+ * Handles the Shortcode for: `[s2Stream /]`.
49
+ *
50
+ * @package s2Member\s2File
51
+ * @since 130119
52
+ *
53
+ * @attaches-to ``add_shortcode("s2Stream");``
54
+ *
55
+ * @param array $attr An array of Attributes.
56
+ * @param str $content Content inside the Shortcode.
57
+ * @param str $shortcode The actual Shortcode name itself.
58
+ * @return str HTML markup that produces an audio/video stream for a specific player.
59
+ */
60
+ public static function sc_get_stream($attr = FALSE, $content = FALSE, $shortcode = FALSE)
61
+ {
62
+ return c_ws_plugin__s2member_sc_files_in::sc_get_stream($attr, $content, $shortcode);
63
  }
64
  }
65
  }
includes/classes/users-list-in.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Users_List
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_users_list_in"))
21
  {
22
  /**
23
  * Users list ( inner processing routines ).
@@ -39,339 +39,339 @@ if (!class_exists ("c_ws_plugin__s2member_users_list_in"))
39
  * @param obj $user Expects a `WP_User` object passed in by the Action Hook.
40
  * @return null
41
  */
42
- public static function users_list_edit_cols ($user = FALSE)
43
  {
44
  global $current_site, $current_blog; /* Multisite Networking. */
45
  /**/
46
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
47
- do_action ("ws_plugin__s2member_before_users_list_edit_cols", get_defined_vars ());
48
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
49
  /**/
50
- $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false; /* Current User. */
51
  /**/
52
- if (is_object ($user) && !empty ($user->ID) && ($user_id = $user->ID) && is_object ($current_user) && !empty ($current_user->ID))
53
  {
54
- $role = c_ws_plugin__s2member_user_access::user_access_role ($user); /* This User's current WordPress® Role. */
55
- $level = c_ws_plugin__s2member_user_access::user_access_level ($user); /* User's Access Level for s2Member. */
56
  /**/
57
- if (current_user_can ("edit_users") && (!is_multisite () || is_super_admin () || is_user_member_of_blog ($user_id)))
58
  {
59
- echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
60
  /**/
61
- echo '<h3 style="position:relative;"><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="position:absolute; top:-15px; right:0; border:0;" />s2Member Configuration &amp; Profile Fields' . ((is_multisite ()) ? ' ( for this Blog )' : '') . '</h3>' . "\n";
62
  /**/
63
- echo '<table class="form-table">' . "\n";
64
  /**/
65
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
66
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before", get_defined_vars ());
67
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
68
  /**/
69
- if (is_multisite () && is_super_admin ()) /* MUST be a Super Admin. */
70
  /* On a Multisite Network, the Super Administrator can ALWAYS edit this. */
71
  {
72
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
73
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_originating_blog", get_defined_vars ());
74
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
75
  /**/
76
- echo '<tr>' . "\n";
77
- echo '<th><label for="ws-plugin--s2member-profile-s2member-originating-blog">Originating Blog ID#:</label> <a href="#" onclick="alert(\'On a Multisite Network, this is how s2Member keeps track of which Blog each User/Member originated from. So this ID#, is automatically associated with a Blog in your Network, matching the User\\\'s point of origin. ~ ONLY a Super Admin can modify this.\\n\\nOn a Multisite Blog Farm, the Originating Blog ID# for your own Customers, will ALWAYS be associated with your ( Main Site ). It is NOT likely that you\\\'ll need to modify this manually, but s2Member makes it available; just in case.\\n\\n*Tip* - If you add Users ( and/or Blogs ) with the `Super Admin` Network Administration panel inside WordPress®, then you WILL need to set everything manually. s2Member does NOT tamper with automation routines whenever YOU ( as a Super Administrator ) are working in that area.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
78
- echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_originating_blog" id="ws-plugin--s2member-profile-s2member-originating-blog" value="' . format_to_edit (get_user_meta ($user_id, "s2member_originating_blog", true)) . '" class="regular-text" /></td>' . "\n";
79
- echo '</tr>' . "\n";
80
  /**/
81
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
82
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_originating_blog", get_defined_vars ());
83
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
84
  }
85
  /**/
86
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
87
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_subscr_gateway", get_defined_vars ());
88
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
89
  /**/
90
- echo '<tr>' . "\n";
91
- echo '<th><label for="ws-plugin--s2member-profile-s2member-subscr-gateway">Paid Subscr. Gateway:</label> <a href="#" onclick="alert(\'A Payment Gateway code is associated with the Paid Subscr. ID below. A Paid Subscription ID ( or a Buy Now Transaction ID ) is only valid for paid Members. Also known as ( a Recurring Profile ID, a ClickBank® Receipt #, a Google® TID/SID ( with an s2 prefix ), an AliPay® Trade No. ). This will be filled automatically by s2Member.\\n\\nThis field will be empty for Free Subscribers, and/or anyone who is NOT paying you. This field is only editable for Customer Service purposes; just in case you ever need to update the Paid Subscr. Gateway/ID manually.\\n\\nThe value of Paid® Subscr. ID, can be a PayPal® Standard `Subscription ID`, or a PayPal® Pro `Recurring Profile ID`, or a PayPal® `Transaction ID`; depending on the type of sale. Your PayPal® account will supply this information. If you\\\'re using Google® Checkout, use the TID/SID value in the sale Description; it always starts with `s2-`. ClickBank® provides a Receipt #, ccBill® provides a Subscription ID, Authorize.Net® provides a Subscription ID, and AliPay® provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
92
- echo '<td><select name="ws_plugin__s2member_profile_s2member_subscr_gateway" id="ws-plugin--s2member-profile-s2member-subscr-gateway" style="width:25em;"><option value=""></option>' . "\n";
93
- foreach (apply_filters ("ws_plugin__s2member_profile_s2member_subscr_gateways", array ("paypal" => "PayPal® ( code: paypal )"), get_defined_vars ()) as $gateway => $gateway_name)
94
- echo '<option value="' . esc_attr ($gateway) . '"' . (($gateway === get_user_option ("s2member_subscr_gateway", $user_id)) ? ' selected="selected"' : '') . '>' . esc_html ($gateway_name) . '</option>' . "\n";
95
- echo '</select>' . "\n";
96
- echo '</td>' . "\n";
97
- echo '</tr>' . "\n";
98
  /**/
99
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
100
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_subscr_gateway", get_defined_vars ());
101
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
102
  /**/
103
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
104
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_subscr_id", get_defined_vars ());
105
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
106
  /**/
107
- echo '<tr>' . "\n";
108
- echo '<th><label for="ws-plugin--s2member-profile-s2member-subscr-id">Paid Subscr. ID:</label> <a href="#" onclick="alert(\'A Paid Subscription ID ( or a Buy Now Transaction ID ) is only valid for paid Members. Also known as ( a Recurring Profile ID, a ClickBank® Receipt #, a Google® TID/SID ( with an s2 prefix ), an AliPay® Trade No. ). This will be filled automatically by s2Member.\\n\\nThis field will be empty for Free Subscribers, and/or anyone who is NOT paying you. This field is only editable for Customer Service purposes; just in case you ever need to update the Paid Subscr. Gateway/ID manually.\\n\\nThe value of Paid® Subscr. ID, can be a PayPal® Standard `Subscription ID`, or a PayPal® Pro `Recurring Profile ID`, or a PayPal® `Transaction ID`; depending on the type of sale. Your PayPal® account will supply this information. If you\\\'re using Google® Checkout, use the TID/SID value in the sale Description; it always starts with `s2-`. ClickBank® provides a Receipt #, ccBill® provides a Subscription ID, Authorize.Net® provides a Subscription ID, and AliPay® provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
109
- echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_subscr_id" id="ws-plugin--s2member-profile-s2member-subscr-id" value="' . format_to_edit (get_user_option ("s2member_subscr_id", $user_id)) . '" class="regular-text" /></td>' . "\n";
110
- echo '</tr>' . "\n";
111
  /**/
112
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
113
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_subscr_id", get_defined_vars ());
114
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
115
  /**/
116
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
117
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_custom", get_defined_vars ());
118
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
119
  /**/
120
- echo '<tr>' . "\n";
121
- echo '<th><label for="ws-plugin--s2member-profile-s2member-custom">Custom Value:</label> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\'' . c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"]), 3) . '\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\n' . c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"]), 3) . '|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
122
- echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_custom" id="ws-plugin--s2member-profile-s2member-custom" value="' . format_to_edit (get_user_option ("s2member_custom", $user_id)) . '" class="regular-text" /></td>' . "\n";
123
- echo '</tr>' . "\n";
124
  /**/
125
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
126
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_custom", get_defined_vars ());
127
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
128
  /**/
129
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
130
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_registration_ip", get_defined_vars ());
131
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
132
  /**/
133
- echo '<tr>' . "\n";
134
- echo '<th><label for="ws-plugin--s2member-profile-s2member-registration-ip">Registration IP:</label> <a href="#" onclick="alert(\'This is the IP Address the User had at the time of registration. If you don\\\'t know the User\\\'s IP Address, just leave this blank. If this is left empty, s2Member will make attempts in the future to grab the User\\\'s IP Address.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
135
- echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_registration_ip" id="ws-plugin--s2member-profile-s2member-registration-ip" value="' . format_to_edit (get_user_option ("s2member_registration_ip", $user_id)) . '" class="regular-text" /></td>' . "\n";
136
- echo '</tr>' . "\n";
137
  /**/
138
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
139
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_registration_ip", get_defined_vars ());
140
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
141
  /**/
142
- if (!is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site ())
143
  /* ^ Will change once Custom Capabilities are compatible with a Blog Farm. */
144
  {
145
- foreach ($user->allcaps as $cap => $cap_enabled)
146
- if (preg_match ("/^access_s2member_ccap_/", $cap))
147
- $ccaps[] = preg_replace ("/^access_s2member_ccap_/", "", $cap);
148
  /**/
149
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
150
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_ccaps", get_defined_vars ());
151
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
152
  /**/
153
- echo '<tr>' . "\n";
154
- echo '<th><label for="ws-plugin--s2member-profile-s2member-ccaps">Custom Capabilities:</label> <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.' . ((is_multisite ()) ? '\\n\\nCustom Capabilities are assigned on a per-Blog basis. So having a set of Custom Capabilities for one Blog, and having NO Custom Capabilities on another Blog - is very common. This is how permissions are designed to work.' : '') . '\'); return false;" tabindex="-1">[?]</a>' . ((is_multisite ()) ? '<br /><small>( for this Blog )</small>' : '') . '</th>' . "\n";
155
- echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_ccaps" id="ws-plugin--s2member-profile-s2member-ccaps" value="' . format_to_edit (((!empty ($ccaps)) ? implode (",", $ccaps) : "")) . '" class="regular-text" 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 ());" /></td>' . "\n";
156
- echo '</tr>' . "\n";
157
  /**/
158
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
159
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_ccaps", get_defined_vars ());
160
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
161
  }
162
  /**/
163
- if (!$user->has_cap ("administrator")) /* Do NOT present these details for Administrator accounts. */
164
  {
165
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
166
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_auto_eot_time", get_defined_vars ());
167
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
168
  /**/
169
- echo '<tr>' . "\n";
170
- $auto_eot_time = get_user_option ("s2member_auto_eot_time", $user_id);
171
- $auto_eot_time = ($auto_eot_time) ? date ("D M j, Y g:i a T", $auto_eot_time) : "";
172
- echo '<th><label for="ws-plugin--s2member-profile-s2member-auto-eot-time">Automatic EOT Time:</label> <a href="#" onclick="alert(\'EOT = End Of Term. ( i.e. Account Expiration / Termination. ).\\n\\nIf you leave this empty, s2Member will configure an EOT Time automatically, based on the paid Subscription associated with this account. In other words, if a paid Subscription expires, is cancelled, terminated, refunded, reversed, or charged back to you; s2Member will deal with the EOT automatically.\\n\\nThat being said, if you would rather take control over this, you can. If you type in a date manually, s2Member will obey the Auto-EOT Time that you\\\'ve given, no matter what. In other words, you can force certain Members to expire automatically, at a time that you specify. s2Member will obey.\\n\\nValid formats for Automatic EOT Time:\\n\\nmm/dd/yyyy\\nyyyy-mm-dd\\n+1 year\\n+2 weeks\\n+2 months\\n+10 minutes\\nnext thursday\\ntomorrow\\ntoday\\n\\n* anything compatible with PHP\\\'s strtotime() function.\'); return false;" tabindex="-1">[?]</a>' . (($auto_eot_time) ? '<br /><small>( <a href="http://en.wikipedia.org/wiki/Coordinated_Universal_Time" target="_blank" rel="external">Universal Time / GMT</a> )</small>' : '') . '</th>' . "\n";
173
- echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_auto_eot_time" id="ws-plugin--s2member-profile-s2member-auto-eot-time" value="' . format_to_edit ($auto_eot_time) . '" class="regular-text" /></td>' . "\n";
174
- echo '</tr>' . "\n";
175
  /**/
176
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
177
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_auto_eot_time", get_defined_vars ());
178
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
179
  }
180
  /**/
181
- if (c_ws_plugin__s2member_list_servers::list_servers_integrated ()) /* Only if integrated with s2Member. */
182
  {
183
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
184
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_opt_in", get_defined_vars ());
185
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
186
  /**/
187
- echo '<tr>' . "\n";
188
- echo '<th><label for="ws-plugin--s2member-profile-opt-in">Re-process List Servers:</label> <a href="#" onclick="alert(\'You have at least one List Server integrated with s2Member. Would you like to re-process a confirmation request for this User? If not, just leave the box un-checked.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
189
- echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_opt_in" id="ws-plugin--s2member-profile-opt-in" value="1" /> Yes, send a mailing list confirmation email to this User.</label></td>' . "\n";
190
- echo '</tr>' . "\n";
191
  /**/
192
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
193
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_opt_in", get_defined_vars ());
194
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
195
  /**/
196
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"])
197
- if (($custom_reg_auto_op_outs = c_ws_plugin__s2member_utils_strings::wrap_deep ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_outs"], "/^", "$/i")))
198
- if (c_ws_plugin__s2member_utils_arrays::in_regex_array ("user-role-change", $custom_reg_auto_op_outs) || c_ws_plugin__s2member_utils_arrays::in_regex_array ("modification", $custom_reg_auto_op_outs))
199
  {
200
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
201
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_auto_opt_out_transitions", get_defined_vars ());
202
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
203
  /**/
204
- echo '<tr>' . "\n";
205
- echo '<th><label for="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">Allow List Transitioning:</label> <a href="#" onclick="alert(\'You\\\'ve configured s2Member with List Transitions enabled. By leaving this box checked, s2Member will Transition the User\\\'s mailing list subscription(s) automatically. For example, if a Member is demoted from Level #2, down to Level #1; s2Member will add them to the Level #1 List(s) after it removes them from the Level #2 List(s).\\n\\nHowever, the transition will ONLY occur, if s2Member IS able to successfully remove them from an existing List. In other words, if they are currently NOT subscribed to any List(s), s2Member will NOT transition them to any new Lists ( intended behavior ).\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
206
- echo '<td><label><input type="checkbox" name="ws_plugin__s2member_custom_reg_auto_opt_out_transitions" id="ws-plugin--s2member-custom-reg-auto-opt-out-transitions" value="1" checked="checked" /> Yes, automatically transition this User\'s mailing list subscription(s) when/if I change their Role.</label></td>' . "\n";
207
- echo '</tr>' . "\n";
208
  /**/
209
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
210
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_auto_opt_out_transitions", get_defined_vars ());
211
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
212
  }
213
  }
214
  /**/
215
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
216
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_ip_restrictions", get_defined_vars ());
217
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
218
  /**/
219
- echo '<tr>' . "\n";
220
- echo '<th><label for="ws-plugin--s2member-profile-ip-restrictions">Reset IP Restrictions:</label> <a href="#" onclick="alert(\'A single Username is only valid for a certain number of unique IP addresses ( as configured in your s2Member -> General Options ). Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will place a temporary ban ( preventing access ).\\n\\nIf you have spoken to a legitimate Customer that is receiving an error upon logging in ( ex: 503 / too many IP addresses ), you can remove this temporary ban by checking the box below. If the abusive behavior continues, s2Member will automatically re-instate IP Restrictions in the future. If you would like to gain further control over IP Restrictions, please check your General Options panel for s2Member.\'); return false;" tabindex="-1">[?]</a></th>' . "\n";
221
- echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_ip_restrictions" id="ws-plugin--s2member-profile-ip-restrictions" value="1" /> Yes, delete/reset IP Restrictions associated with this Username.</label>' . ((c_ws_plugin__s2member_ip_restrictions::specific_ip_restriction_breached_security (strtolower ($user->user_login))) ? '<br /><em>*Note* this User HAS breached security through existing IP Restrictions.</em>' : '<br /><em>*Note* this User is NOT currently banned by any of your IP Restrictions.</em>') . '</td>' . "\n";
222
- echo '</tr>' . "\n";
223
  /**/
224
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
225
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_ip_restrictions", get_defined_vars ());
226
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
227
  /**/
228
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) /* Only if configured. */
229
- if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level ($level, "administrative"))
230
  {
231
- echo '<tr>' . "\n";
232
- echo '<td colspan="2">' . "\n";
233
- echo '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
234
- echo '</td>' . "\n";
235
- echo '</tr>' . "\n";
236
  /**/
237
- $fields = get_user_option ("s2member_custom_fields", $user_id); /* Existing fields. */
238
  /**/
239
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
240
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_custom_fields", get_defined_vars ());
241
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
242
  /**/
243
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
244
  {
245
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
246
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_before", get_defined_vars ());
247
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
248
  /**/
249
- if (in_array ($field["id"], $fields_applicable)) /* Field applicable? */
250
  {
251
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
252
- $field_id_class = preg_replace ("/_/", "-", $field_var);
253
  /**/
254
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
255
- if (apply_filters ("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_display", true, get_defined_vars ()))
256
  {
257
- if (!empty ($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
258
- echo '<tr><td colspan="2"><div class="ws-plugin--s2member-profile-divider-section' . ((!empty ($field["sectitle"])) ? '-title' : '') . '">' . ((!empty ($field["sectitle"])) ? $field["sectitle"] : '') . '</div></td></tr>';
259
  /**/
260
- echo '<tr>' . "\n";
261
- echo '<th><label for="ws-plugin--s2member-profile-' . esc_attr ($field_id_class) . '">' . ((preg_match ("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ucwords (preg_replace ("/_/", " ", $field_var)) : $field["label"]) . ':</label></th>' . "\n";
262
- echo '<td>' . c_ws_plugin__s2member_custom_reg_fields::custom_field_gen (__FUNCTION__, $field, "ws_plugin__s2member_profile_", "ws-plugin--s2member-profile-", "", ((preg_match ("/^(text|textarea|select|selects)$/", $field["type"])) ? "width:99%;" : ""), "", "", $fields, $fields[$field_var], "administrative") . '</td>' . "\n";
263
- echo '</tr>' . "\n";
264
  }
265
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
266
  }
267
  /**/
268
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
269
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_after", get_defined_vars ());
270
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
271
  }
272
  /**/
273
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
274
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_custom_fields", get_defined_vars ());
275
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
276
  /**/
277
- echo '<tr>' . "\n";
278
- echo '<td colspan="2">' . "\n";
279
- echo '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
280
- echo '</td>' . "\n";
281
- echo '</tr>' . "\n";
282
  }
283
  /**/
284
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
285
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_notes", get_defined_vars ());
286
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
287
  /**/
288
- echo '<tr>' . "\n";
289
- echo '<th><label for="ws-plugin--s2member-profile-s2member-notes">Administrative Notes:</label> <a href="#" onclick="alert(\'This is for Administrative purposes. You can keep a list of Notations about this account. These Notations are private; Users/Members will never see these.\\n\\n*Note* The s2Member software may `append` Notes to this field occasionally, under special circumstances. For example, when/if s2Member demotes a paid Member to a Free Subscriber, s2Member will leave a Note in this field.\'); return false;" tabindex="-1">[?]</a><br /><br /><small>These Notations are private; Users/Members will never see any of these notes.</small></th>' . "\n";
290
- echo '<td><textarea name="ws_plugin__s2member_profile_s2member_notes" id="ws-plugin--s2member-profile-s2member-notes" rows="5" wrap="off" spellcheck="false" style="width:99%;">' . format_to_edit (get_user_option ("s2member_notes", $user_id)) . '</textarea></td>' . "\n";
291
- echo '</tr>' . "\n";
292
  /**/
293
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
294
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_notes", get_defined_vars ());
295
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
296
  /**/
297
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
298
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after", get_defined_vars ());
299
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
300
  /**/
301
- echo '</table>' . "\n";
302
  /**/
303
- echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
304
  }
305
  /**/
306
- else if ($current_user->ID === $user->ID) /* Otherwise, a User can always edit their own Profile. */
307
  {
308
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) /* Only if configured. */
309
- if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level ($level, "profile"))
310
  {
311
- echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
312
  /**/
313
- echo '<h3>' . _x ("Additional Profile Fields", "s2member-front", "s2member") . ((is_multisite ()) ? ' ' . _x ("( for this site )", "s2member-front", "s2member") : "") . '</h3>' . "\n";
314
  /**/
315
- echo '<table class="form-table">' . "\n";
316
  /**/
317
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
318
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before", get_defined_vars ());
319
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
320
  /**/
321
- $fields = get_user_option ("s2member_custom_fields", $user_id); /* Existing fields. */
322
  /**/
323
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
324
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_before_custom_fields", get_defined_vars ());
325
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
326
  /**/
327
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
328
  {
329
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
330
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_before", get_defined_vars ());
331
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
332
  /**/
333
- if (in_array ($field["id"], $fields_applicable)) /* Field applicable? */
334
  {
335
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
336
- $field_id_class = preg_replace ("/_/", "-", $field_var);
337
  /**/
338
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
339
- if (apply_filters ("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_display", true, get_defined_vars ()))
340
  {
341
- if (!empty ($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
342
- echo '<tr><td colspan="2"><div class="ws-plugin--s2member-profile-divider-section' . ((!empty ($field["sectitle"])) ? '-title' : '') . '">' . ((!empty ($field["sectitle"])) ? $field["sectitle"] : '') . '</div></td></tr>';
343
  /**/
344
- echo '<tr>' . "\n";
345
- echo '<th><label for="ws-plugin--s2member-profile-' . esc_attr ($field_id_class) . '">' . ((preg_match ("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ucwords (preg_replace ("/_/", " ", $field_var)) : $field["label"]) . ':</label></th>' . "\n";
346
- echo '<td>' . c_ws_plugin__s2member_custom_reg_fields::custom_field_gen (__FUNCTION__, $field, "ws_plugin__s2member_profile_", "ws-plugin--s2member-profile-", "", ((preg_match ("/^(text|textarea|select|selects)$/", $field["type"])) ? "width:99%;" : ""), "", "", $fields, $fields[$field_var], "profile") . '</td>' . "\n";
347
- echo '</tr>' . "\n";
348
  }
349
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
350
  }
351
  /**/
352
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
353
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_after", get_defined_vars ());
354
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
355
  }
356
  /**/
357
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
358
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after_custom_fields", get_defined_vars ());
359
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
360
  /**/
361
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
362
- do_action ("ws_plugin__s2member_during_users_list_edit_cols_after", get_defined_vars ());
363
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
364
  /**/
365
- echo '</table>' . "\n";
366
  /**/
367
- echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
368
  }
369
  }
370
  }
371
  /**/
372
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
373
- do_action ("ws_plugin__s2member_after_users_list_edit_cols", get_defined_vars ());
374
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
375
  /**/
376
  return; /* Return for uniformity. */
377
  }
@@ -387,174 +387,174 @@ if (!class_exists ("c_ws_plugin__s2member_users_list_in"))
387
  * @param int|str $user_id Expects a numeric WordPress® User ID passed in by the Action Hook.
388
  * @return null
389
  */
390
- public static function users_list_update_cols ($user_id = FALSE)
391
  {
392
  global $current_site, $current_blog; /* Multisite Networking. */
393
  /**/
394
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
395
- do_action ("ws_plugin__s2member_before_users_list_update_cols", get_defined_vars ());
396
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
397
  /**/
398
- $user = new WP_User ($user_id); /* We need both of these objects. $user and $current_user. */
399
- $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false; /* Current User. */
400
  /**/
401
- if (is_object ($user) && !empty ($user->ID) && ($user_id = $user->ID) && is_object ($current_user) && !empty ($current_user->ID))
402
  {
403
- if (current_user_can ("edit_users") && (!is_multisite () || is_super_admin () || is_user_member_of_blog ($user_id)))
404
  {
405
- if (!empty ($_POST) && is_array ($_p = c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep ($_POST))))
406
  {
407
- $old_user = unserialize (serialize ($user)); /* Copy existing User obj. */
408
- $old_role = c_ws_plugin__s2member_user_access::user_access_role ($old_user);
409
  /**/
410
- $role = /* Might be empty! */ (isset ($_p["role"]) && $_p["role"] !== $old_role) ? $_p["role"] : $old_role;
411
- $level = /* Might be `-1`. */ c_ws_plugin__s2member_user_access::user_access_role_to_level ($role);
412
  /**/
413
- $user->roles = (isset ($_p["role"]) && $_p["role"] !== $old_role) ? /* Might be empty! */ array ($_p["role"]): $old_user->roles;
414
- $user->user_email = (isset ($_p["email"]) && is_email ($_p["email"]) && $_p["email"] !== $old_user->user_email && !email_exists ($_p["email"])) ? $_p["email"] : $old_user->user_email;
415
- $user->first_name = (isset ($_p["first_name"]) && $_p["first_name"] !== $old_user->first_name) ? $_p["first_name"] : $old_user->first_name;
416
- $user->last_name = (isset ($_p["last_name"]) && $_p["last_name"] !== $old_user->last_name) ? $_p["last_name"] : $old_user->last_name;
417
  /**/
418
- $auto_eot_time = (!empty ($_p["ws_plugin__s2member_profile_s2member_auto_eot_time"])) ? strtotime ($_p["ws_plugin__s2member_profile_s2member_auto_eot_time"]) : "";
419
  /**/
420
- if ($role !== $old_role) /* In this case, we need to fire Hook: `ws_plugin__s2member_during_collective_mods`. */
421
- do_action ("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars (), "user-role-change", "modification", $role, $user, $old_user);
422
  /**/
423
- if (isset ($_p["ws_plugin__s2member_profile_s2member_originating_blog"]) && is_multisite () && is_super_admin ())
424
- update_user_meta ($user_id, "s2member_originating_blog", $_p["ws_plugin__s2member_profile_s2member_originating_blog"]);
425
  /**/
426
- if (isset ($_p["ws_plugin__s2member_profile_s2member_subscr_gateway"]))
427
- update_user_option ($user_id, "s2member_subscr_gateway", $_p["ws_plugin__s2member_profile_s2member_subscr_gateway"]);
428
  /**/
429
- if (isset ($_p["ws_plugin__s2member_profile_s2member_subscr_id"]))
430
- update_user_option ($user_id, "s2member_subscr_id", $_p["ws_plugin__s2member_profile_s2member_subscr_id"]);
431
  /**/
432
- if (isset ($_p["ws_plugin__s2member_profile_s2member_custom"]))
433
- update_user_option ($user_id, "s2member_custom", $_p["ws_plugin__s2member_profile_s2member_custom"]);
434
  /**/
435
- if (isset ($_p["ws_plugin__s2member_profile_s2member_registration_ip"]))
436
- update_user_option ($user_id, "s2member_registration_ip", $_p["ws_plugin__s2member_profile_s2member_registration_ip"]);
437
  /**/
438
- if (isset ($_p["ws_plugin__s2member_profile_s2member_notes"]))
439
- update_user_option ($user_id, "s2member_notes", $_p["ws_plugin__s2member_profile_s2member_notes"]);
440
  /**/
441
- if (isset ($_p["ws_plugin__s2member_profile_s2member_auto_eot_time"]) && isset ($auto_eot_time))
442
- update_user_option ($user_id, "s2member_auto_eot_time", $auto_eot_time);
443
  /**/
444
- if (isset ($_p["ws_plugin__s2member_profile_s2member_ccaps"]))
445
  {
446
- foreach ($user->allcaps as $cap => $cap_enabled)
447
- if (preg_match ("/^access_s2member_ccap_/", $cap))
448
- $user->remove_cap ($ccap = $cap);
449
  /**/
450
- if (!empty ($_p["ws_plugin__s2member_profile_s2member_ccaps"]))
451
- foreach (preg_split ("/[\r\n\t\s;,]+/", $_p["ws_plugin__s2member_profile_s2member_ccaps"]) as $ccap)
452
- if (strlen ($ccap = trim (strtolower (preg_replace ("/[^a-z_0-9]/i", "", $ccap)))))
453
- $user->add_cap ("access_s2member_ccap_" . $ccap);
454
  }
455
  /**/
456
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
457
  {
458
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
459
  {
460
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
461
- $field_id_class = preg_replace ("/_/", "-", $field_var);
462
  /**/
463
- if (isset ($_p["ws_plugin__s2member_profile_" . $field_var])) /* Field being set? */
464
  {
465
- if ((is_array ($_p["ws_plugin__s2member_profile_" . $field_var]) && !empty ($_p["ws_plugin__s2member_profile_" . $field_var])) || (is_string ($_p["ws_plugin__s2member_profile_" . $field_var]) && strlen ($_p["ws_plugin__s2member_profile_" . $field_var])))
466
- $fields[$field_var] = $_p["ws_plugin__s2member_profile_" . $field_var];
467
  else /* Else unset. */
468
- unset ($fields[$field_var]);
469
  }
470
  else /* Else ``unset()``. */
471
- unset ($fields[$field_var]);
472
  }
473
  }
474
  /**/
475
- if (!empty ($fields))
476
- update_user_option ($user_id, "s2member_custom_fields", $fields);
477
  else /* Else delete their Custom Fields? */
478
- delete_user_option ($user_id, "s2member_custom_fields");
479
  /**/
480
- if ($level > 0) /* We ONLY process this if they are higher than Level #0. */
481
  {
482
- $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
483
- $pr_times["level"] = (empty ($pr_times["level"])) ? time () : $pr_times["level"];
484
- $pr_times["level" . $level] = (empty ($pr_times["level" . $level])) ? time () : $pr_times["level" . $level];
485
- update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
486
  }
487
  /**/
488
- if (!empty ($_p["ws_plugin__s2member_profile_opt_in"]) && !empty ($role) && $level >= 0) /* Should we process List Servers? */
489
- c_ws_plugin__s2member_list_servers::process_list_servers ($role, $level, $user->user_login, ((!empty ($_p["pass1"])) ? $_p["pass1"] : ""), $user->user_email, $user->first_name, $user->last_name, false, true, true, $user_id);
490
  /**/
491
- if (!empty ($_p["ws_plugin__s2member_profile_ip_restrictions"])) /* Delete/reset IP Restrictions? */
492
- c_ws_plugin__s2member_ip_restrictions::delete_reset_specific_ip_restrictions (strtolower ($user->user_login));
493
  /**/
494
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
495
- do_action ("ws_plugin__s2member_during_users_list_update_cols", get_defined_vars ());
496
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
497
  }
498
  }
499
  /**/
500
- else if ($current_user->ID === $user->ID) /* Otherwise, a User can always edit their own Profile. */
501
  {
502
- if (!empty ($_POST) && is_array ($_p = c_ws_plugin__s2member_utils_strings::trim_deep (stripslashes_deep ($_POST))))
503
  {
504
- $role = /* Role is NOT changing here. */ c_ws_plugin__s2member_user_access::user_access_role ($user);
505
- $level = c_ws_plugin__s2member_user_access::user_access_role_to_level ($role);
506
  /**/
507
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
508
- if ($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level ($level, "profile"))
509
  {
510
- $_existing_fields = get_user_option ("s2member_custom_fields", $user_id);
511
  /**/
512
- foreach (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
513
  {
514
- $field_var = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field["id"]));
515
- $field_id_class = preg_replace ("/_/", "-", $field_var);
516
  /**/
517
- if (!in_array ($field["id"], $fields_applicable) || strpos ($field["editable"], "no") === 0)
518
  {
519
- if (isset ($_existing_fields[$field_var]) && ((is_array ($_existing_fields[$field_var]) && !empty ($_existing_fields[$field_var])) || (is_string ($_existing_fields[$field_var]) && strlen ($_existing_fields[$field_var]))))
520
  $fields[$field_var] = $_existing_fields[$field_var];
521
  else /* Else ``unset()``. */
522
- unset ($fields[$field_var]);
523
  }
524
- else if ($field["required"] === "yes" && (!isset ($_p["ws_plugin__s2member_profile_" . $field_var]) || (!is_array ($_p["ws_plugin__s2member_profile_" . $field_var]) && !is_string ($_p["ws_plugin__s2member_profile_" . $field_var])) || (is_array ($_p["ws_plugin__s2member_profile_" . $field_var]) && empty ($_p["ws_plugin__s2member_profile_" . $field_var])) || (is_string ($_p["ws_plugin__s2member_profile_" . $field_var]) && !strlen ($_p["ws_plugin__s2member_profile_" . $field_var]))))
525
  {
526
- if (isset ($_existing_fields[$field_var]) && ((is_array ($_existing_fields[$field_var]) && !empty ($_existing_fields[$field_var])) || (is_string ($_existing_fields[$field_var]) && strlen ($_existing_fields[$field_var]))))
527
  $fields[$field_var] = $_existing_fields[$field_var];
528
  else /* Else ``unset()``. */
529
- unset ($fields[$field_var]);
530
  }
531
- else if (isset ($_p["ws_plugin__s2member_profile_" . $field_var]))
532
  {
533
- if ((is_array ($_p["ws_plugin__s2member_profile_" . $field_var]) && !empty ($_p["ws_plugin__s2member_profile_" . $field_var])) || (is_string ($_p["ws_plugin__s2member_profile_" . $field_var]) && strlen ($_p["ws_plugin__s2member_profile_" . $field_var])))
534
- $fields[$field_var] = $_p["ws_plugin__s2member_profile_" . $field_var];
535
  else /* Else ``unset()``. */
536
- unset ($fields[$field_var]);
537
  }
538
  else /* Else ``unset()``. */
539
- unset ($fields[$field_var]);
540
  }
541
  /**/
542
- if (!empty ($fields))
543
- update_user_option ($user_id, "s2member_custom_fields", $fields);
544
  else /* Else delete their Custom Fields? */
545
- delete_user_option ($user_id, "s2member_custom_fields");
546
  }
547
  /**/
548
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
549
- do_action ("ws_plugin__s2member_during_users_list_update_cols", get_defined_vars ());
550
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
551
  }
552
  }
553
  }
554
  /**/
555
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
556
- do_action ("ws_plugin__s2member_after_users_list_update_cols", get_defined_vars ());
557
- unset ($__refs, $__v); /* Unset defined __refs, __v. */
558
  /**/
559
  return; /* Return for uniformity. */
560
  }
14
  * @package s2Member\Users_List
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_users_list_in"))
21
  {
22
  /**
23
  * Users list ( inner processing routines ).
39
  * @param obj $user Expects a `WP_User` object passed in by the Action Hook.
40
  * @return null
41
  */
42
+ public static function users_list_edit_cols($user = FALSE)
43
  {
44
  global $current_site, $current_blog; /* Multisite Networking. */
45
  /**/
46
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
47
+ do_action("ws_plugin__s2member_before_users_list_edit_cols", get_defined_vars());
48
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
49
  /**/
50
+ $current_user = (is_user_logged_in()) ? wp_get_current_user() : false; /* Current User. */
51
  /**/
52
+ if(is_object($user) && !empty($user->ID) && ($user_id = $user->ID) && is_object($current_user) && !empty($current_user->ID))
53
  {
54
+ $role = c_ws_plugin__s2member_user_access::user_access_role($user); /* This User's current WordPress® Role. */
55
+ $level = c_ws_plugin__s2member_user_access::user_access_level($user); /* User's Access Level for s2Member. */
56
  /**/
57
+ if(current_user_can("edit_users") && (!is_multisite() || is_super_admin() || is_user_member_of_blog($user_id)))
58
  {
59
+ echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>'."\n";
60
  /**/
61
+ echo '<h3 style="position:relative;"><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="position:absolute; top:-15px; right:0; border:0;" />s2Member Configuration &amp; Profile Fields'.((is_multisite()) ? ' ( for this Blog )' : '').'</h3>'."\n";
62
  /**/
63
+ echo '<table class="form-table">'."\n";
64
  /**/
65
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
66
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before", get_defined_vars());
67
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
68
  /**/
69
+ if(is_multisite() && is_super_admin()) /* MUST be a Super Admin. */
70
  /* On a Multisite Network, the Super Administrator can ALWAYS edit this. */
71
  {
72
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
73
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_originating_blog", get_defined_vars());
74
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
75
  /**/
76
+ echo '<tr>'."\n";
77
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-originating-blog">Originating Blog ID#:</label> <a href="#" onclick="alert(\'On a Multisite Network, this is how s2Member keeps track of which Blog each User/Member originated from. So this ID#, is automatically associated with a Blog in your Network, matching the User\\\'s point of origin. ~ ONLY a Super Admin can modify this.\\n\\nOn a Multisite Blog Farm, the Originating Blog ID# for your own Customers, will ALWAYS be associated with your ( Main Site ). It is NOT likely that you\\\'ll need to modify this manually, but s2Member makes it available; just in case.\\n\\n*Tip* - If you add Users ( and/or Blogs ) with the `Super Admin` Network Administration panel inside WordPress®, then you WILL need to set everything manually. s2Member does NOT tamper with automation routines whenever YOU ( as a Super Administrator ) are working in that area.\'); return false;" tabindex="-1">[?]</a></th>'."\n";
78
+ echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_originating_blog" id="ws-plugin--s2member-profile-s2member-originating-blog" value="'.format_to_edit(get_user_meta($user_id, "s2member_originating_blog", true)).'" class="regular-text" /></td>'."\n";
79
+ echo '</tr>'."\n";
80
  /**/
81
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
82
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_originating_blog", get_defined_vars());
83
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
84
  }
85
  /**/
86
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
87
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_subscr_gateway", get_defined_vars());
88
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
89
  /**/
90
+ echo '<tr>'."\n";
91
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-subscr-gateway">Paid Subscr. Gateway:</label> <a href="#" onclick="alert(\'A Payment Gateway code is associated with the Paid Subscr. ID below. A Paid Subscription ID ( or a Buy Now Transaction ID ) is only valid for paid Members. Also known as ( a Recurring Profile ID, a ClickBank® Receipt #, a Google® TID/SID ( with an s2 prefix ), an AliPay® Trade No. ). This will be filled automatically by s2Member.\\n\\nThis field will be empty for Free Subscribers, and/or anyone who is NOT paying you. This field is only editable for Customer Service purposes; just in case you ever need to update the Paid Subscr. Gateway/ID manually.\\n\\nThe value of Paid® Subscr. ID, can be a PayPal® Standard `Subscription ID`, or a PayPal® Pro `Recurring Profile ID`, or a PayPal® `Transaction ID`; depending on the type of sale. Your PayPal® account will supply this information. If you\\\'re using Google® Checkout, use the TID/SID value in the sale Description; it always starts with `s2-`. ClickBank® provides a Receipt #, ccBill® provides a Subscription ID, Authorize.Net® provides a Subscription ID, and AliPay® provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>'."\n";
92
+ echo '<td><select name="ws_plugin__s2member_profile_s2member_subscr_gateway" id="ws-plugin--s2member-profile-s2member-subscr-gateway" style="width:25em;"><option value=""></option>'."\n";
93
+ foreach(apply_filters("ws_plugin__s2member_profile_s2member_subscr_gateways", array("paypal" => "PayPal® ( code: paypal )"), get_defined_vars()) as $gateway => $gateway_name)
94
+ echo '<option value="'.esc_attr($gateway).'"'.(($gateway === get_user_option("s2member_subscr_gateway", $user_id)) ? ' selected="selected"' : '').'>'.esc_html($gateway_name).'</option>'."\n";
95
+ echo '</select>'."\n";
96
+ echo '</td>'."\n";
97
+ echo '</tr>'."\n";
98
  /**/
99
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
100
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_subscr_gateway", get_defined_vars());
101
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
102
  /**/
103
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
104
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_subscr_id", get_defined_vars());
105
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
106
  /**/
107
+ echo '<tr>'."\n";
108
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-subscr-id">Paid Subscr. ID:</label> <a href="#" onclick="alert(\'A Paid Subscription ID ( or a Buy Now Transaction ID ) is only valid for paid Members. Also known as ( a Recurring Profile ID, a ClickBank® Receipt #, a Google® TID/SID ( with an s2 prefix ), an AliPay® Trade No. ). This will be filled automatically by s2Member.\\n\\nThis field will be empty for Free Subscribers, and/or anyone who is NOT paying you. This field is only editable for Customer Service purposes; just in case you ever need to update the Paid Subscr. Gateway/ID manually.\\n\\nThe value of Paid® Subscr. ID, can be a PayPal® Standard `Subscription ID`, or a PayPal® Pro `Recurring Profile ID`, or a PayPal® `Transaction ID`; depending on the type of sale. Your PayPal® account will supply this information. If you\\\'re using Google® Checkout, use the TID/SID value in the sale Description; it always starts with `s2-`. ClickBank® provides a Receipt #, ccBill® provides a Subscription ID, Authorize.Net® provides a Subscription ID, and AliPay® provides a Transaction ID. The general rule is... IF there\\\'s a Subscription ID, use that! If there\\\'s NOT, use the Transaction ID.\'); return false;" tabindex="-1">[?]</a></th>'."\n";
109
+ echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_subscr_id" id="ws-plugin--s2member-profile-s2member-subscr-id" value="'.format_to_edit(get_user_option("s2member_subscr_id", $user_id)).'" class="regular-text" /></td>'."\n";
110
+ echo '</tr>'."\n";
111
  /**/
112
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
113
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_subscr_id", get_defined_vars());
114
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
115
  /**/
116
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
117
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_custom", get_defined_vars());
118
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
119
  /**/
120
+ echo '<tr>'."\n";
121
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-custom">Custom Value:</label> <a href="#" onclick="alert(\'A Paid Subscription is always associated with a Custom String that is passed through the custom=\\\'\\\''.c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3).'\\\'\\\' attribute of your Shortcode. This Custom Value, MUST always start with your domain name. However, you can also pipe delimit additional values after your domain, if you need to.\\n\\nFor example:\n'.c_ws_plugin__s2member_utils_strings::esc_js_sq(esc_attr($_SERVER["HTTP_HOST"]), 3).'|cv1|cv2|cv3\'); return false;" tabindex="-1">[?]</a></th>'."\n";
122
+ echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_custom" id="ws-plugin--s2member-profile-s2member-custom" value="'.format_to_edit(get_user_option("s2member_custom", $user_id)).'" class="regular-text" /></td>'."\n";
123
+ echo '</tr>'."\n";
124
  /**/
125
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
126
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_custom", get_defined_vars());
127
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
128
  /**/
129
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
130
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_registration_ip", get_defined_vars());
131
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
132
  /**/
133
+ echo '<tr>'."\n";
134
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-registration-ip">Registration IP:</label> <a href="#" onclick="alert(\'This is the IP Address the User had at the time of registration. If you don\\\'t know the User\\\'s IP Address, just leave this blank. If this is left empty, s2Member will make attempts in the future to grab the User\\\'s IP Address.\'); return false;" tabindex="-1">[?]</a></th>'."\n";
135
+ echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_registration_ip" id="ws-plugin--s2member-profile-s2member-registration-ip" value="'.format_to_edit(get_user_option("s2member_registration_ip", $user_id)).'" class="regular-text" /></td>'."\n";
136
+ echo '</tr>'."\n";
137
  /**/
138
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
139
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_registration_ip", get_defined_vars());
140
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
141
  /**/
142
+ if(!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site())
143
  /* ^ Will change once Custom Capabilities are compatible with a Blog Farm. */
144
  {
145
+ foreach($user->allcaps as $cap => $cap_enabled)
146
+ if(preg_match("/^access_s2member_ccap_/", $cap))
147
+ $ccaps[] = preg_replace("/^access_s2member_ccap_/", "", $cap);
148
  /**/
149
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
150
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_ccaps", get_defined_vars());
151
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
152
  /**/
153
+ echo '<tr>'."\n";
154
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-ccaps">Custom Capabilities:</label> <a href="#" onclick="alert(\'Optional. This is VERY advanced.\\nSee: s2Member -> API Scripting -> Custom Capabilities.'.((is_multisite()) ? '\\n\\nCustom Capabilities are assigned on a per-Blog basis. So having a set of Custom Capabilities for one Blog, and having NO Custom Capabilities on another Blog - is very common. This is how permissions are designed to work.' : '').'\'); return false;" tabindex="-1">[?]</a>'.((is_multisite()) ? '<br /><small>( for this Blog )</small>' : '').'</th>'."\n";
155
+ echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_ccaps" id="ws-plugin--s2member-profile-s2member-ccaps" value="'.format_to_edit(((!empty($ccaps)) ? implode(",", $ccaps) : "")).'" class="regular-text" 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 ());" /></td>'."\n";
156
+ echo '</tr>'."\n";
157
  /**/
158
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
159
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_ccaps", get_defined_vars());
160
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
161
  }
162
  /**/
163
+ if(!$user->has_cap("administrator")) /* Do NOT present these details for Administrator accounts. */
164
  {
165
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
166
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_auto_eot_time", get_defined_vars());
167
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
168
  /**/
169
+ echo '<tr>'."\n";
170
+ $auto_eot_time = get_user_option("s2member_auto_eot_time", $user_id);
171
+ $auto_eot_time = ($auto_eot_time) ? date("D M j, Y g:i a T", $auto_eot_time) : "";
172
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-auto-eot-time">Automatic EOT Time:</label> <a href="#" onclick="alert(\'EOT = End Of Term. ( i.e. Account Expiration / Termination. ).\\n\\nIf you leave this empty, s2Member will configure an EOT Time automatically, based on the paid Subscription associated with this account. In other words, if a paid Subscription expires, is cancelled, terminated, refunded, reversed, or charged back to you; s2Member will deal with the EOT automatically.\\n\\nThat being said, if you would rather take control over this, you can. If you type in a date manually, s2Member will obey the Auto-EOT Time that you\\\'ve given, no matter what. In other words, you can force certain Members to expire automatically, at a time that you specify. s2Member will obey.\\n\\nValid formats for Automatic EOT Time:\\n\\nmm/dd/yyyy\\nyyyy-mm-dd\\n+1 year\\n+2 weeks\\n+2 months\\n+10 minutes\\nnext thursday\\ntomorrow\\ntoday\\n\\n* anything compatible with PHP\\\'s strtotime() function.\'); return false;" tabindex="-1">[?]</a>'.(($auto_eot_time) ? '<br /><small>( <a href="http://en.wikipedia.org/wiki/Coordinated_Universal_Time" target="_blank" rel="external">Universal Time / GMT</a> )</small>' : '').'</th>'."\n";
173
+ echo '<td><input type="text" autocomplete="off" name="ws_plugin__s2member_profile_s2member_auto_eot_time" id="ws-plugin--s2member-profile-s2member-auto-eot-time" value="'.format_to_edit($auto_eot_time).'" class="regular-text" /></td>'."\n";
174
+ echo '</tr>'."\n";
175
  /**/
176
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
177
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_auto_eot_time", get_defined_vars());
178
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
179
  }
180
  /**/
181
+ if(c_ws_plugin__s2member_list_servers::list_servers_integrated()) /* Only if integrated with s2Member. */
182
  {
183
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
184
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_opt_in", get_defined_vars());
185
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
186
  /**/
187
+ echo '<tr>'."\n";
188
+ echo '<th><label for="ws-plugin--s2member-profile-opt-in">Re-process List Servers:</label> <a href="#" onclick="alert(\'You have at least one List Server integrated with s2Member. Would you like to re-process a confirmation request for this User? If not, just leave the box un-checked.\'); return false;" tabindex="-1">[?]</a></th>'."\n";
189
+ echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_opt_in" id="ws-plugin--s2member-profile-opt-in" value="1" /> Yes, send a mailing list confirmation email to this User.</label></td>'."\n";
190
+ echo '</tr>'."\n";
191
  /**/
192
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
193
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_opt_in", get_defined_vars());
194
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
195
  /**/
196
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_out_transitions"])
197
+ if(($custom_reg_auto_op_outs = c_ws_plugin__s2member_utils_strings::wrap_deep($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_auto_opt_outs"], "/^", "$/i")))
198
+ if(c_ws_plugin__s2member_utils_arrays::in_regex_array("user-role-change", $custom_reg_auto_op_outs) || c_ws_plugin__s2member_utils_arrays::in_regex_array("modification", $custom_reg_auto_op_outs))
199
  {
200
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
201
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_auto_opt_out_transitions", get_defined_vars());
202
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
203
  /**/
204
+ echo '<tr>'."\n";
205
+ echo '<th><label for="ws-plugin--s2member-custom-reg-auto-opt-out-transitions">Allow List Transitioning:</label> <a href="#" onclick="alert(\'You\\\'ve configured s2Member with List Transitions enabled. By leaving this box checked, s2Member will Transition the User\\\'s mailing list subscription(s) automatically. For example, if a Member is demoted from Level #2, down to Level #1; s2Member will add them to the Level #1 List(s) after it removes them from the Level #2 List(s).\\n\\nHowever, the transition will ONLY occur, if s2Member IS able to successfully remove them from an existing List. In other words, if they are currently NOT subscribed to any List(s), s2Member will NOT transition them to any new Lists ( intended behavior ).\'); return false;" tabindex="-1">[?]</a></th>'."\n";
206
+ echo '<td><label><input type="checkbox" name="ws_plugin__s2member_custom_reg_auto_opt_out_transitions" id="ws-plugin--s2member-custom-reg-auto-opt-out-transitions" value="1" checked="checked" /> Yes, automatically transition this User\'s mailing list subscription(s) when/if I change their Role.</label></td>'."\n";
207
+ echo '</tr>'."\n";
208
  /**/
209
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
210
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_auto_opt_out_transitions", get_defined_vars());
211
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
212
  }
213
  }
214
  /**/
215
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
216
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_ip_restrictions", get_defined_vars());
217
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
218
  /**/
219
+ echo '<tr>'."\n";
220
+ echo '<th><label for="ws-plugin--s2member-profile-ip-restrictions">Reset IP Restrictions:</label> <a href="#" onclick="alert(\'A single Username is only valid for a certain number of unique IP addresses ( as configured in your s2Member -> General Options ). Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will place a temporary ban ( preventing access ).\\n\\nIf you have spoken to a legitimate Customer that is receiving an error upon logging in ( ex: 503 / too many IP addresses ), you can remove this temporary ban by checking the box below. If the abusive behavior continues, s2Member will automatically re-instate IP Restrictions in the future. If you would like to gain further control over IP Restrictions, please check your General Options panel for s2Member.\'); return false;" tabindex="-1">[?]</a></th>'."\n";
221
+ echo '<td><label><input type="checkbox" name="ws_plugin__s2member_profile_ip_restrictions" id="ws-plugin--s2member-profile-ip-restrictions" value="1" /> Yes, delete/reset IP Restrictions associated with this Username.</label>'.((c_ws_plugin__s2member_ip_restrictions::specific_ip_restriction_breached_security(strtolower($user->user_login))) ? '<br /><em>*Note* this User HAS breached security through existing IP Restrictions.</em>' : '<br /><em>*Note* this User is NOT currently banned by any of your IP Restrictions.</em>').'</td>'."\n";
222
+ echo '</tr>'."\n";
223
  /**/
224
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
225
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_ip_restrictions", get_defined_vars());
226
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
227
  /**/
228
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) /* Only if configured. */
229
+ if($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level($level, "administrative"))
230
  {
231
+ echo '<tr>'."\n";
232
+ echo '<td colspan="2">'."\n";
233
+ echo '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>'."\n";
234
+ echo '</td>'."\n";
235
+ echo '</tr>'."\n";
236
  /**/
237
+ $fields = get_user_option("s2member_custom_fields", $user_id); /* Existing fields. */
238
  /**/
239
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
240
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_custom_fields", get_defined_vars());
241
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
242
  /**/
243
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
244
  {
245
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
246
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_before", get_defined_vars());
247
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
248
  /**/
249
+ if(in_array($field["id"], $fields_applicable)) /* Field applicable? */
250
  {
251
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
252
+ $field_id_class = preg_replace("/_/", "-", $field_var);
253
  /**/
254
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
255
+ if(apply_filters("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_display", true, get_defined_vars()))
256
  {
257
+ if(!empty($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
258
+ echo '<tr><td colspan="2"><div class="ws-plugin--s2member-profile-divider-section'.((!empty($field["sectitle"])) ? '-title' : '').'">'.((!empty($field["sectitle"])) ? $field["sectitle"] : '').'</div></td></tr>';
259
  /**/
260
+ echo '<tr>'."\n";
261
+ echo '<th><label for="ws-plugin--s2member-profile-'.esc_attr($field_id_class).'">'.((preg_match("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ucwords(preg_replace("/_/", " ", $field_var)) : $field["label"]).':</label></th>'."\n";
262
+ echo '<td>'.c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_profile_", "ws-plugin--s2member-profile-", "", ((preg_match("/^(text|textarea|select|selects)$/", $field["type"])) ? "width:99%;" : ""), "", "", $fields, $fields[$field_var], "administrative").'</td>'."\n";
263
+ echo '</tr>'."\n";
264
  }
265
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
266
  }
267
  /**/
268
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
269
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_after", get_defined_vars());
270
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
271
  }
272
  /**/
273
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
274
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_custom_fields", get_defined_vars());
275
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
276
  /**/
277
+ echo '<tr>'."\n";
278
+ echo '<td colspan="2">'."\n";
279
+ echo '<div style="height:1px; line-height:1px; background:#CCCCCC;"></div>'."\n";
280
+ echo '</td>'."\n";
281
+ echo '</tr>'."\n";
282
  }
283
  /**/
284
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
285
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_notes", get_defined_vars());
286
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
287
  /**/
288
+ echo '<tr>'."\n";
289
+ echo '<th><label for="ws-plugin--s2member-profile-s2member-notes">Administrative Notes:</label> <a href="#" onclick="alert(\'This is for Administrative purposes. You can keep a list of Notations about this account. These Notations are private; Users/Members will never see these.\\n\\n*Note* The s2Member software may `append` Notes to this field occasionally, under special circumstances. For example, when/if s2Member demotes a paid Member to a Free Subscriber, s2Member will leave a Note in this field.\'); return false;" tabindex="-1">[?]</a><br /><br /><small>These Notations are private; Users/Members will never see any of these notes.</small></th>'."\n";
290
+ echo '<td><textarea name="ws_plugin__s2member_profile_s2member_notes" id="ws-plugin--s2member-profile-s2member-notes" rows="5" wrap="off" spellcheck="false" style="width:99%;">'.format_to_edit(get_user_option("s2member_notes", $user_id)).'</textarea></td>'."\n";
291
+ echo '</tr>'."\n";
292
  /**/
293
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
294
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_notes", get_defined_vars());
295
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
296
  /**/
297
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
298
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after", get_defined_vars());
299
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
300
  /**/
301
+ echo '</table>'."\n";
302
  /**/
303
+ echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>'."\n";
304
  }
305
  /**/
306
+ else if($current_user->ID === $user->ID) /* Otherwise, a User can always edit their own Profile. */
307
  {
308
+ if /* Only if configured. */($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
309
+ if($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level($level, "profile"))
310
  {
311
+ echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>'."\n";
312
  /**/
313
+ echo '<h3>'._x("Additional Profile Fields", "s2member-front", "s2member").((is_multisite()) ? ' '._x("( for this site )", "s2member-front", "s2member") : "").'</h3>'."\n";
314
  /**/
315
+ echo '<table class="form-table">'."\n";
316
  /**/
317
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
318
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before", get_defined_vars());
319
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
320
  /**/
321
+ $fields = get_user_option("s2member_custom_fields", $user_id); /* Existing fields. */
322
  /**/
323
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
324
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_before_custom_fields", get_defined_vars());
325
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
326
  /**/
327
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
328
  {
329
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
330
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_before", get_defined_vars());
331
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
332
  /**/
333
+ if(in_array($field["id"], $fields_applicable)) /* Field applicable? */
334
  {
335
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
336
+ $field_id_class = preg_replace("/_/", "-", $field_var);
337
  /**/
338
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
339
+ if(apply_filters("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_display", true, get_defined_vars()))
340
  {
341
+ if(!empty($field["section"]) && $field["section"] === "yes") /* Starts a new section? */
342
+ echo '<tr><td colspan="2"><div class="ws-plugin--s2member-profile-divider-section'.((!empty($field["sectitle"])) ? '-title' : '').'">'.((!empty($field["sectitle"])) ? $field["sectitle"] : '').'</div></td></tr>';
343
  /**/
344
+ echo '<tr>'."\n";
345
+ echo '<th><label for="ws-plugin--s2member-profile-'.esc_attr($field_id_class).'">'.((preg_match("/^(checkbox|pre_checkbox)$/", $field["type"])) ? ucwords(preg_replace("/_/", " ", $field_var)) : $field["label"]).':</label></th>'."\n";
346
+ echo '<td>'.c_ws_plugin__s2member_custom_reg_fields::custom_field_gen(__FUNCTION__, $field, "ws_plugin__s2member_profile_", "ws-plugin--s2member-profile-", "", ((preg_match("/^(text|textarea|select|selects)$/", $field["type"])) ? "width:99%;" : ""), "", "", $fields, $fields[$field_var], "profile").'</td>'."\n";
347
+ echo '</tr>'."\n";
348
  }
349
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
350
  }
351
  /**/
352
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
353
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_during_custom_fields_after", get_defined_vars());
354
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
355
  }
356
  /**/
357
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
358
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after_custom_fields", get_defined_vars());
359
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
360
  /**/
361
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
362
+ do_action("ws_plugin__s2member_during_users_list_edit_cols_after", get_defined_vars());
363
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
364
  /**/
365
+ echo '</table>'."\n";
366
  /**/
367
+ echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>'."\n";
368
  }
369
  }
370
  }
371
  /**/
372
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
373
+ do_action("ws_plugin__s2member_after_users_list_edit_cols", get_defined_vars());
374
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
375
  /**/
376
  return; /* Return for uniformity. */
377
  }
387
  * @param int|str $user_id Expects a numeric WordPress® User ID passed in by the Action Hook.
388
  * @return null
389
  */
390
+ public static function users_list_update_cols($user_id = FALSE)
391
  {
392
  global $current_site, $current_blog; /* Multisite Networking. */
393
  /**/
394
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
395
+ do_action("ws_plugin__s2member_before_users_list_update_cols", get_defined_vars());
396
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
397
  /**/
398
+ $user = new WP_User($user_id); /* We need both of these objects. $user and $current_user. */
399
+ $current_user = (is_user_logged_in()) ? wp_get_current_user() : false; /* Current User. */
400
  /**/
401
+ if(is_object($user) && !empty($user->ID) && ($user_id = $user->ID) && is_object($current_user) && !empty($current_user->ID))
402
  {
403
+ if(current_user_can("edit_users") && (!is_multisite() || is_super_admin() || is_user_member_of_blog($user_id)))
404
  {
405
+ if(!empty($_POST) && is_array($_p = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST))))
406
  {
407
+ $old_user = unserialize(serialize($user)); /* Copy existing User obj. */
408
+ $old_role = c_ws_plugin__s2member_user_access::user_access_role($old_user);
409
  /**/
410
+ $role = /* Might be empty! */ (isset($_p["role"]) && $_p["role"] !== $old_role) ? $_p["role"] : $old_role;
411
+ $level = /* Might be `-1`. */ c_ws_plugin__s2member_user_access::user_access_role_to_level($role);
412
  /**/
413
+ $user->roles = (isset($_p["role"]) && $_p["role"] !== $old_role) ? /* Might be empty! */ array($_p["role"]): $old_user->roles;
414
+ $user->user_email = (isset($_p["email"]) && is_email($_p["email"]) && $_p["email"] !== $old_user->user_email && !email_exists($_p["email"])) ? $_p["email"] : $old_user->user_email;
415
+ $user->first_name = (isset($_p["first_name"]) && $_p["first_name"] !== $old_user->first_name) ? $_p["first_name"] : $old_user->first_name;
416
+ $user->last_name = (isset($_p["last_name"]) && $_p["last_name"] !== $old_user->last_name) ? $_p["last_name"] : $old_user->last_name;
417
  /**/
418
+ $auto_eot_time = (!empty($_p["ws_plugin__s2member_profile_s2member_auto_eot_time"])) ? strtotime($_p["ws_plugin__s2member_profile_s2member_auto_eot_time"]) : "";
419
  /**/
420
+ if($role !== $old_role) /* In this case, we need to fire Hook: `ws_plugin__s2member_during_collective_mods`. */
421
+ do_action("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars(), "user-role-change", "modification", $role, $user, $old_user);
422
  /**/
423
+ if(isset($_p["ws_plugin__s2member_profile_s2member_originating_blog"]) && is_multisite() && is_super_admin())
424
+ update_user_meta($user_id, "s2member_originating_blog", $_p["ws_plugin__s2member_profile_s2member_originating_blog"]);
425
  /**/
426
+ if(isset($_p["ws_plugin__s2member_profile_s2member_subscr_gateway"]))
427
+ update_user_option($user_id, "s2member_subscr_gateway", $_p["ws_plugin__s2member_profile_s2member_subscr_gateway"]);
428
  /**/
429
+ if(isset($_p["ws_plugin__s2member_profile_s2member_subscr_id"]))
430
+ update_user_option($user_id, "s2member_subscr_id", $_p["ws_plugin__s2member_profile_s2member_subscr_id"]);
431
  /**/
432
+ if(isset($_p["ws_plugin__s2member_profile_s2member_custom"]))
433
+ update_user_option($user_id, "s2member_custom", $_p["ws_plugin__s2member_profile_s2member_custom"]);
434
  /**/
435
+ if(isset($_p["ws_plugin__s2member_profile_s2member_registration_ip"]))
436
+ update_user_option($user_id, "s2member_registration_ip", $_p["ws_plugin__s2member_profile_s2member_registration_ip"]);
437
  /**/
438
+ if(isset($_p["ws_plugin__s2member_profile_s2member_notes"]))
439
+ update_user_option($user_id, "s2member_notes", $_p["ws_plugin__s2member_profile_s2member_notes"]);
440
  /**/
441
+ if(isset($_p["ws_plugin__s2member_profile_s2member_auto_eot_time"]) && isset($auto_eot_time))
442
+ update_user_option($user_id, "s2member_auto_eot_time", $auto_eot_time);
443
  /**/
444
+ if(isset($_p["ws_plugin__s2member_profile_s2member_ccaps"]))
445
  {
446
+ foreach($user->allcaps as $cap => $cap_enabled)
447
+ if(preg_match("/^access_s2member_ccap_/", $cap))
448
+ $user->remove_cap($ccap = $cap);
449
  /**/
450
+ if(!empty($_p["ws_plugin__s2member_profile_s2member_ccaps"]))
451
+ foreach(preg_split("/[\r\n\t\s;,]+/", $_p["ws_plugin__s2member_profile_s2member_ccaps"]) as $ccap)
452
+ if(strlen($ccap = trim(strtolower(preg_replace("/[^a-z_0-9]/i", "", $ccap)))))
453
+ $user->add_cap("access_s2member_ccap_".$ccap);
454
  }
455
  /**/
456
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
457
  {
458
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
459
  {
460
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
461
+ $field_id_class = preg_replace("/_/", "-", $field_var);
462
  /**/
463
+ if(isset($_p["ws_plugin__s2member_profile_".$field_var])) /* Field being set? */
464
  {
465
+ if((is_array($_p["ws_plugin__s2member_profile_".$field_var]) && !empty($_p["ws_plugin__s2member_profile_".$field_var])) || (is_string($_p["ws_plugin__s2member_profile_".$field_var]) && strlen($_p["ws_plugin__s2member_profile_".$field_var])))
466
+ $fields[$field_var] = $_p["ws_plugin__s2member_profile_".$field_var];
467
  else /* Else unset. */
468
+ unset($fields[$field_var]);
469
  }
470
  else /* Else ``unset()``. */
471
+ unset($fields[$field_var]);
472
  }
473
  }
474
  /**/
475
+ if(!empty($fields))
476
+ update_user_option($user_id, "s2member_custom_fields", $fields);
477
  else /* Else delete their Custom Fields? */
478
+ delete_user_option($user_id, "s2member_custom_fields");
479
  /**/
480
+ if($level > 0) /* We ONLY process this if they are higher than Level #0. */
481
  {
482
+ $pr_times = get_user_option("s2member_paid_registration_times", $user_id);
483
+ $pr_times["level"] = (empty($pr_times["level"])) ? time() : $pr_times["level"];
484
+ $pr_times["level".$level] = (empty($pr_times["level".$level])) ? time() : $pr_times["level".$level];
485
+ update_user_option($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
486
  }
487
  /**/
488
+ if(!empty($_p["ws_plugin__s2member_profile_opt_in"]) && !empty($role) && $level >= 0) /* Should we process List Servers? */
489
+ c_ws_plugin__s2member_list_servers::process_list_servers($role, $level, $user->user_login, ((!empty($_p["pass1"])) ? $_p["pass1"] : ""), $user->user_email, $user->first_name, $user->last_name, false, true, true, $user_id);
490
  /**/
491
+ if(!empty($_p["ws_plugin__s2member_profile_ip_restrictions"])) /* Delete/reset IP Restrictions? */
492
+ c_ws_plugin__s2member_ip_restrictions::delete_reset_specific_ip_restrictions(strtolower($user->user_login));
493
  /**/
494
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
495
+ do_action("ws_plugin__s2member_during_users_list_update_cols", get_defined_vars());
496
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
497
  }
498
  }
499
  /**/
500
+ else if($current_user->ID === $user->ID) /* Otherwise, a User can always edit their own Profile. */
501
  {
502
+ if(!empty($_POST) && is_array($_p = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST))))
503
  {
504
+ $role = /* Role is NOT changing here. */ c_ws_plugin__s2member_user_access::user_access_role($user);
505
+ $level = c_ws_plugin__s2member_user_access::user_access_role_to_level($role);
506
  /**/
507
+ if($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
508
+ if($fields_applicable = c_ws_plugin__s2member_custom_reg_fields::custom_fields_configured_at_level($level, "profile"))
509
  {
510
+ $_existing_fields = get_user_option("s2member_custom_fields", $user_id);
511
  /**/
512
+ foreach(json_decode($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"], true) as $field)
513
  {
514
+ $field_var = preg_replace("/[^a-z0-9]/i", "_", strtolower($field["id"]));
515
+ $field_id_class = preg_replace("/_/", "-", $field_var);
516
  /**/
517
+ if(!in_array($field["id"], $fields_applicable) || strpos($field["editable"], "no") === 0)
518
  {
519
+ if(isset($_existing_fields[$field_var]) && ((is_array($_existing_fields[$field_var]) && !empty($_existing_fields[$field_var])) || (is_string($_existing_fields[$field_var]) && strlen($_existing_fields[$field_var]))))
520
  $fields[$field_var] = $_existing_fields[$field_var];
521
  else /* Else ``unset()``. */
522
+ unset($fields[$field_var]);
523
  }
524
+ else if($field["required"] === "yes" && (!isset($_p["ws_plugin__s2member_profile_".$field_var]) || (!is_array($_p["ws_plugin__s2member_profile_".$field_var]) && !is_string($_p["ws_plugin__s2member_profile_".$field_var])) || (is_array($_p["ws_plugin__s2member_profile_".$field_var]) && empty($_p["ws_plugin__s2member_profile_".$field_var])) || (is_string($_p["ws_plugin__s2member_profile_".$field_var]) && !strlen($_p["ws_plugin__s2member_profile_".$field_var]))))
525
  {
526
+ if(isset($_existing_fields[$field_var]) && ((is_array($_existing_fields[$field_var]) && !empty($_existing_fields[$field_var])) || (is_string($_existing_fields[$field_var]) && strlen($_existing_fields[$field_var]))))
527
  $fields[$field_var] = $_existing_fields[$field_var];
528
  else /* Else ``unset()``. */
529
+ unset($fields[$field_var]);
530
  }
531
+ else if(isset($_p["ws_plugin__s2member_profile_".$field_var]))
532
  {
533
+ if((is_array($_p["ws_plugin__s2member_profile_".$field_var]) && !empty($_p["ws_plugin__s2member_profile_".$field_var])) || (is_string($_p["ws_plugin__s2member_profile_".$field_var]) && strlen($_p["ws_plugin__s2member_profile_".$field_var])))
534
+ $fields[$field_var] = $_p["ws_plugin__s2member_profile_".$field_var];
535
  else /* Else ``unset()``. */
536
+ unset($fields[$field_var]);
537
  }
538
  else /* Else ``unset()``. */
539
+ unset($fields[$field_var]);
540
  }
541
  /**/
542
+ if(!empty($fields))
543
+ update_user_option($user_id, "s2member_custom_fields", $fields);
544
  else /* Else delete their Custom Fields? */
545
+ delete_user_option($user_id, "s2member_custom_fields");
546
  }
547
  /**/
548
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
549
+ do_action("ws_plugin__s2member_during_users_list_update_cols", get_defined_vars());
550
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
551
  }
552
  }
553
  }
554
  /**/
555
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
556
+ do_action("ws_plugin__s2member_after_users_list_update_cols", get_defined_vars());
557
+ unset($__refs, $__v); /* Unset defined __refs, __v. */
558
  /**/
559
  return; /* Return for uniformity. */
560
  }
includes/codes.inc.php CHANGED
@@ -22,6 +22,7 @@ Add WordPress® Editor Shortcodes.
22
  add_shortcode ("s2Key", "c_ws_plugin__s2member_sc_keys::sc_get_key");
23
  add_shortcode ("s2Get", "c_ws_plugin__s2member_sc_gets::sc_get_details");
24
  add_shortcode ("s2File", "c_ws_plugin__s2member_sc_files::sc_get_file");
 
25
  /**/
26
  add_shortcode ("s2If", "c_ws_plugin__s2member_sc_if_conds::sc_if_conditionals");
27
  add_shortcode ("_s2If", "c_ws_plugin__s2member_sc_if_conds::sc_if_conditionals");
22
  add_shortcode ("s2Key", "c_ws_plugin__s2member_sc_keys::sc_get_key");
23
  add_shortcode ("s2Get", "c_ws_plugin__s2member_sc_gets::sc_get_details");
24
  add_shortcode ("s2File", "c_ws_plugin__s2member_sc_files::sc_get_file");
25
+ add_shortcode ("s2Stream", "c_ws_plugin__s2member_sc_files::sc_get_stream");
26
  /**/
27
  add_shortcode ("s2If", "c_ws_plugin__s2member_sc_if_conds::sc_if_conditionals");
28
  add_shortcode ("_s2If", "c_ws_plugin__s2member_sc_if_conds::sc_if_conditionals");
includes/menu-pages/code-samples/jwplayer-s2stream-mp3-rtmp-only.x-php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Copy/paste this Shortcode into any WordPress® Post or Page.
2
+ [s2Stream player="jwplayer-v6-rtmp-only" player_path="/jwplayer/jwplayer.js" file_download="audio.mp3" /]
includes/menu-pages/code-samples/jwplayer-s2stream-mp3-rtmp.x-php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Copy/paste this Shortcode into any WordPress® Post or Page.
2
+ [s2Stream player="jwplayer-v6-rtmp" player_path="/jwplayer/jwplayer.js" file_download="audio.mp3" /]
includes/menu-pages/code-samples/jwplayer-s2stream-mp3.x-php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Copy/paste this Shortcode into any WordPress® Post or Page.
2
+ [s2Stream player="jwplayer-v6" player_path="/jwplayer/jwplayer.js" file_download="audio.mp3" rewrite="yes" /]
includes/menu-pages/code-samples/jwplayer-s2stream-mp4-rtmp-only.x-php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Copy/paste this Shortcode into any WordPress® Post or Page.
2
+ [s2Stream player="jwplayer-v6-rtmp-only" player_path="/jwplayer/jwplayer.js" file_download="video.mp4" /]
includes/menu-pages/code-samples/jwplayer-s2stream-mp4-rtmp.x-php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Copy/paste this Shortcode into any WordPress® Post or Page.
2
+ [s2Stream player="jwplayer-v6-rtmp" player_path="/jwplayer/jwplayer.js" file_download="video.mp4" /]
includes/menu-pages/code-samples/jwplayer-s2stream-mp4.x-php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Copy/paste this Shortcode into any WordPress® Post or Page.
2
+ [s2Stream player="jwplayer-v6" player_path="/jwplayer/jwplayer.js" file_download="video.mp4" rewrite="yes" /]
includes/menu-pages/down-ops.inc.php CHANGED
@@ -261,7 +261,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
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
  /**/
@@ -349,7 +349,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
349
  echo '<div class="ws-menu-page-hr"></div>'."\n";
350
  /**/
351
  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";
352
- 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";
 
353
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon® CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon® CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>'."\n";
354
  echo (stripos(PHP_OS, "win") === 0 && c_ws_plugin__s2member_utils_conds::is_localhost()) ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon® CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront® URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows®</a> while you\'re developing. s2Member will automatically find it here: <code>C:\OpenSSL-Win[32/64]\bin\openssl.exe</code>.'.((file_exists("c:\openssl-win32\bin\openssl.exe") || file_exists("c:\openssl-win64\bin\openssl.exe")) ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] is NOT currently available )</strong>').'</em></p>'."\n" : '';
355
  /**/
@@ -491,6 +492,34 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
491
  /**/
492
  echo '<div class="ws-menu-page-hr"></div>'."\n";
493
  /**/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  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";
495
  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";
496
  /**/
@@ -514,10 +543,10 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
514
  {
515
  do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rtmp_streaming", get_defined_vars());
516
  /**/
517
- echo '<div class="ws-menu-page-group" title="JW Player® v5 &amp; RTMP Protocol Examples">'."\n";
518
  /**/
519
  echo '<div class="ws-menu-page-section ws-plugin--s2member-rtmp-streaming-section">'."\n";
520
- echo '<h3>JW Player® v5 &amp; RTMP Protocol Examples</h3>'."\n";
521
  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";
522
  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";
523
  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";
@@ -525,17 +554,20 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
525
  /**/
526
  echo '<div class="ws-menu-page-hr"></div>'."\n";
527
  /**/
528
- 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";
529
- 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-v5-standard-mp4.x-php")).'</p>'."\n";
530
  /**/
531
- 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";
532
- 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.s2member.com/codex/stable/s2member/api_functions/package-summary/" 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-v5-streaming-mp4.x-php")).'</p>'."\n";
533
  /**/
534
- 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";
535
- 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.s2member.com/codex/stable/s2member/api_functions/package-summary/" 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-v5-streaming-mp4-sca.x-php")).'</p>'."\n";
536
  /**/
537
- 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 fallbacks )</a></p>'."\n";
538
- 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.s2member.com/codex/stable/s2member/api_functions/package-summary/" 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-v5-streaming-mp4-webm.x-php")).'</p>'."\n";
 
 
 
539
  /**/
540
  echo '</div>'."\n";
541
  /**/
@@ -582,7 +614,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
582
  /**/
583
  echo '<div class="ws-menu-page-hr"></div>'."\n";
584
  /**/
585
- echo '<h4 style="margin:0;"><code>[s2File /]</code> Shortcode Attributes:</h4>'."\n";
586
  echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>'."\n";
587
  echo '<table class="form-table" style="margin-top:0;">'."\n";
588
  echo '<tbody>'."\n";
@@ -592,18 +624,18 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
592
  echo '<ul>'."\n";
593
  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";
594
  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";
595
- 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";
596
- 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";
597
  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";
598
  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";
599
  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";
600
- 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";
601
  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";
602
  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";
603
- 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";
604
- 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";
605
- 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";
606
- 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";
607
  do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2file_lis", get_defined_vars());
608
  echo '</ul>'."\n";
609
  echo '</td>'."\n";
@@ -614,6 +646,29 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
614
  /**/
615
  echo '<div class="ws-menu-page-hr"></div>'."\n";
616
  /**/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  echo '<h4 style="margin:0;"><code>[s2Key /]</code> Shortcode Attributes:</h4>'."\n";
618
  echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_key()" target="_blank" rel="external">s2member_file_download_key()</a> for PHP integration.</p>'."\n";
619
  echo '<table class="form-table" style="margin-top:0;">'."\n";
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 "Digitally Signed URLs", authenticated by the Amazon® S3 API. Documented for developers <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon® S3 URLs ( internally ); which allow Customers temporary access to specific files inside your S3 Bucket. s2Member\'s Digitally Signed URLs leading to Amazon® S3, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason ( not likely ), you can use this WordPress® Filter: <code>ws_plugin__s2member_amazon_s3_file_expires_time</code>.</em></p>'."\n";
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
  /**/
349
  echo '<div class="ws-menu-page-hr"></div>'."\n";
350
  /**/
351
  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";
352
+ echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon® CloudFront API. Documented for developers <a href="http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon® CloudFront URLs ( internally ); which allow Customers temporary access to specific files inside your S3 Bucket via CloudFront Distributions. s2Member\'s Digitally Signed URLs leading to Amazon® S3/CloudFront, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason ( not likely ), you can use this WordPress® Filter: <code>ws_plugin__s2member_amazon_cf_file_expires_time</code>.</em></p>'."\n";
353
+ echo '<p><em><strong>Linking To Protected Files:</strong> RTMP streams are special, but nothing else changes. s2Member\'s integration with Amazon® S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® CloudFront URL, which allows them access to a particular file via Amazon® CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>. If you\'re streaming audio/video files over the RTMP protocol, please review the section below: <code>JW Player® &amp; RTMP Protocol Examples</code>.</em></p>'."\n";
354
  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";
355
  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" : '';
356
  /**/
492
  /**/
493
  echo '<div class="ws-menu-page-hr"></div>'."\n";
494
  /**/
495
+ echo '<h3><code>[s2Stream /]</code> Video Shortcode Examples (recommended — it\'s the easiest way)</h3>'."\n";
496
+ /**/
497
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( MP4 file, via Rewrite URLs. Amazon® S3/CloudFront NOT required )</a></p>'."\n";
498
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-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 />Works with any audio/video file. This does NOT require s2Member to be integrated with Amazon® S3/CloudFront.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-s2stream-mp4.x-php")).'</p>'."\n";
499
+ /**/
500
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>'."\n";
501
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp" 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 />Streams with the RTMP protocol, plus there is a full download fallback of the MP4 source file if streaming is not possible on a particular device.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-s2stream-mp4-rtmp.x-php")).'</p>'."\n";
502
+ /**/
503
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp-only\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4 only, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>'."\n";
504
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp4-rtmp-only" 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 />Streams with the RTMP protocol only, with no access to the source file, only to the RTMP stream.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-s2stream-mp4-rtmp-only.x-php")).'</p>'."\n";
505
+ /**/
506
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
507
+ /**/
508
+ echo '<h3><code>[s2Stream /]</code> Audio Shortcode Examples (recommended — it\'s the easiest way)</h3>'."\n";
509
+ /**/
510
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3\').toggle(); return false;" class="ws-dotted-link">JW Player® ( MP3 file, via Rewrite URLs. Amazon® S3/CloudFront NOT required )</a></p>'."\n";
511
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3" 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 />Works with any audio/video file. This does NOT require s2Member to be integrated with Amazon® S3/CloudFront.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-s2stream-mp3.x-php")).'</p>'."\n";
512
+ /**/
513
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP3, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>'."\n";
514
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp" 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 />Streams with the RTMP protocol, plus there is a full download fallback of the MP3 source file if streaming is not possible on a particular device.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-s2stream-mp3-rtmp.x-php")).'</p>'."\n";
515
+ /**/
516
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp-only\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP3 only, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>'."\n";
517
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-s2stream-mp3-rtmp-only" 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 />Streams with the RTMP protocol only, with no access to the source file, only to the RTMP stream.<br />This requires s2Member to be integrated with Amazon® S3/CloudFront.<br /><br />'.c_ws_plugin__s2member_utils_strings::highlight_php(file_get_contents(dirname(__FILE__)."/code-samples/jwplayer-s2stream-mp3-rtmp-only.x-php")).'</p>'."\n";
518
+ /**/
519
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
520
+ /**/
521
+ echo '<h3>PHP Code Examples (for more advanced integrations via PHP — in WordPress® themes)</h3>'."\n";
522
+ /**/
523
  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";
524
  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";
525
  /**/
543
  {
544
  do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_before_rtmp_streaming", get_defined_vars());
545
  /**/
546
+ echo '<div class="ws-menu-page-group" title="JW Player® v5 &amp; RTMP Protocol Examples ( Deprecated )">'."\n";
547
  /**/
548
  echo '<div class="ws-menu-page-section ws-plugin--s2member-rtmp-streaming-section">'."\n";
549
+ echo '<h3>JW Player® v5 &amp; RTMP Protocol Examples ( Deprecated )</h3>'."\n";
550
  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";
551
  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";
552
  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";
554
  /**/
555
  echo '<div class="ws-menu-page-hr"></div>'."\n";
556
  /**/
557
+ echo '<h3>PHP Code Examples (for more advanced integrations)</h3>'."\n";
558
+ echo '<p>These examples exist from past versions of s2Member. JW Player® v5 is now outdated by JW Player® v6 (recommended).</p>'."\n";
559
  /**/
560
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-standard-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( MP4 file, via Rewrite URLs. Amazon® S3/CloudFront NOT required )</a></p>'."\n";
561
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-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-v5-standard-mp4.x-php")).'</p>'."\n";
562
  /**/
563
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-streaming-mp4\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s Amazon® S3/CloudFront integration )</a></p>'."\n";
564
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-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.s2member.com/codex/stable/s2member/api_functions/package-summary/" 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-v5-streaming-mp4.x-php")).'</p>'."\n";
565
  /**/
566
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-streaming-mp4-sca\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, via s2Member\'s JSON/Shortcode alternative )</a></p>'."\n";
567
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-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.s2member.com/codex/stable/s2member/api_functions/package-summary/" 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-v5-streaming-mp4-sca.x-php")).'</p>'."\n";
568
+ /**/
569
+ echo '<p style="font-size:110%;"><a href="#" onclick="jQuery(\'p#ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-streaming-mp4-webm\').toggle(); return false;" class="ws-dotted-link">JW Player® ( RTMP streaming MP4, advanced w/ multiple fallbacks )</a></p>'."\n";
570
+ echo '<p id="ws-plugin--s2member-rtmp-streaming-details-jwplayer-v5-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.s2member.com/codex/stable/s2member/api_functions/package-summary/" 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-v5-streaming-mp4-webm.x-php")).'</p>'."\n";
571
  /**/
572
  echo '</div>'."\n";
573
  /**/
614
  /**/
615
  echo '<div class="ws-menu-page-hr"></div>'."\n";
616
  /**/
617
+ echo '<h4 style="margin:0;"><code>[s2File /]</code> &amp; <code>[s2Stream /]</code> Shortcode Attributes:</h4>'."\n";
618
  echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>'."\n";
619
  echo '<table class="form-table" style="margin-top:0;">'."\n";
620
  echo '<tbody>'."\n";
624
  echo '<ul>'."\n";
625
  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";
626
  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";
627
+ echo '<li><code>stream="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. 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 if at all possible. 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="yes"</code> for you.</li>'."\n";
628
+ echo '<li><code>inline=""</code> Defaults to <code>[empty]</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. 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>, except in the case of the <code>[s2Stream /]</code> Shortcode where this defaults to <code>yes</code>. 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";
629
  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";
630
  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";
631
  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";
632
+ echo '<li><code>rewrite="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. 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®. If you\'re integrating with JW Player®, you MUST use <code>rewrite="yes"</code>.</li>'."\n";
633
  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";
634
  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";
635
+ echo '<li><code>url_to_storage_source="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. 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";
636
+ echo '<li><code>count_against_user="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. 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 with the <code>[s2File /]</code> Shortcode. 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";
637
+ echo '<li><code>check_user="no"</code> Defaults to <code>no</code> with <code>[s2File /]</code> Shortcode. Defaults to <code>yes</code> with <code>[s2Stream /]</code> Shortcode. 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 with the <code>[s2File /]</code> Shortcode. 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";
638
+ echo '<li><code>get_streamer_json="no"</code> Defaults to <code>no</code>. N/A with <code>[s2Stream /]</code> Shortcode. If <code>get_streamer_json="1|on|yes|true"</code>, the <code>[s2File /]</code> 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";
639
  do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2file_lis", get_defined_vars());
640
  echo '</ul>'."\n";
641
  echo '</td>'."\n";
646
  /**/
647
  echo '<div class="ws-menu-page-hr"></div>'."\n";
648
  /**/
649
+ echo '<h4 style="margin:0;">Additional <code>[s2Stream /]</code> Shortcode Attributes:</h4>'."\n";
650
+ echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_url()" target="_blank" rel="external">s2member_file_download_url()</a> for PHP integration.</p>'."\n";
651
+ echo '<table class="form-table" style="margin-top:0;">'."\n";
652
+ echo '<tbody>'."\n";
653
+ echo '<tr style="padding-top:0;">'."\n";
654
+ /**/
655
+ echo '<td style="padding-top:0;">'."\n";
656
+ echo '<ul>'."\n";
657
+ echo '<li><code>file_download="video.mp4"</code> Location of the audio/video 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";
658
+ echo '<li><code>player="jwplayer-v6-rtmp"</code> Required. Current supported players in this Shortcode include: <code>jwplayer-v6</code> (works with any audio/video file, and you do NOT need to have Amazon® S3 or CloudFront™ integrated for this to work), <code>jwplayer-v6-rtmp</code> (streams with the RTMP protocol, plus there is a full download fallback of the source file if streaming is not possible on a particular device; this requires both Amazon® S3 and CloudFront™ integration), <code>jwplayer-v6-rtmp-only</code> (streams with the RTMP protocol only, with no access to the source file, only to the RTMP stream; this requires both Amazon® S3 and CloudFront™ integration).</li>'."\n";
659
+ echo '<li><code>player_id=""</code> Optional. HTML div ID for the audio/video player. Defaults to a unique ID generated by s2Member® for each instance of your Shortcode.</li>'."\n";
660
+ echo '<li><code>player_path="/jwplayer/jwplayer.js"</code> Required. Path to the player\'s JavaScript file (ex: <code>/jwplayer/jwplayer.js</code> — you should upload the <a href="http://www.longtailvideo.com/players/" target="_blank" rel="external">/jwplayer</a> folder to the root of your web directory).</li>'."\n";
661
+ echo '<li><code>player_[setting]=""</code> Optional. Any additional attributes supported by your audio/video player, prefixed with <code>player_</code>. For JW Player™ v6, see <a href="http://www.longtailvideo.com/support/jw-player/28839/embedding-the-player" target="_blank" rel="external">this article please</a>. Examples: <code>player_width="480"</code>, <code>player_height="270"</code>, <code>player_image="http://www.example.com/wp-content/uploads/video-preview.jpg"</code>, <code>player_autostart="true"</code>, <code>player_skin="/jwplayer/my-skin.xml"</code>. Please note that "Advanced Options Blocks" listed on <a href="http://www.longtailvideo.com/support/jw-player/28839/embedding-the-player" target="_blank" rel="external">this page</a> are currently NOT supported here. All others are.</li>'."\n";
662
+ do_action("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_shortcode_attrs_s2stream_lis", get_defined_vars());
663
+ echo '</ul>'."\n";
664
+ echo '</td>'."\n";
665
+ /**/
666
+ echo '</tr>'."\n";
667
+ echo '</tbody>'."\n";
668
+ echo '</table>'."\n";
669
+ /**/
670
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
671
+ /**/
672
  echo '<h4 style="margin:0;"><code>[s2Key /]</code> Shortcode Attributes:</h4>'."\n";
673
  echo '<p style="margin:0;"><strong>See also:</strong> API Function <a href="http://www.s2member.com/codex/stable/s2member/api_functions/package-functions/#src_doc_s2member_file_download_key()" target="_blank" rel="external">s2member_file_download_key()</a> for PHP integration.</p>'."\n";
674
  echo '<table class="form-table" style="margin-top:0;">'."\n";
includes/templates/players/index.php ADDED
File without changes
includes/templates/players/jwplayer-v6-rtmp-only.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
3
+ exit("Do not access this file directly.");
4
+ ?>
5
+
6
+ <div id="%%player_id%%"></div>
7
+ <script type="text/javascript" src="%%player_path%%"></script>
8
+ <script type="text/javascript">
9
+ jwplayer('%%player_id%%').setup({
10
+
11
+ playlist:
12
+ [{
13
+ /* List all available sources. */ sources:
14
+ [
15
+ {file: '%%streamer%%/%%prefix%%%%file%%'}
16
+ ]
17
+ }],
18
+
19
+ image: '%%player_image%%',
20
+ title: '%%player_title%%',
21
+
22
+ controls: %%player_controls%%,
23
+ height: %%player_height%%,
24
+ skin: '%%player_skin%%',
25
+ stretching: '%%player_stretching%%',
26
+ width: %%player_width%%,
27
+
28
+ autostart: %%player_autostart%%,
29
+ fallback: %%player_fallback%%,
30
+ mute: %%player_mute%%,
31
+ primary: '%%player_primary%%',
32
+ repeat: %%player_repeat%%,
33
+ startparam: '%%player_startparam%%'
34
+ });
35
+ </script>
includes/templates/players/jwplayer-v6-rtmp.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
3
+ exit("Do not access this file directly.");
4
+ ?>
5
+
6
+ <div id="%%player_id%%"></div>
7
+ <script type="text/javascript" src="%%player_path%%"></script>
8
+ <script type="text/javascript">
9
+ jwplayer('%%player_id%%').setup({
10
+
11
+ playlist:
12
+ [{
13
+ /* List all available sources. */ sources:
14
+ [
15
+ {file: '%%streamer%%/%%prefix%%%%file%%'},
16
+ {file: '%%url%%'}
17
+ ]
18
+ }],
19
+
20
+ image: '%%player_image%%',
21
+ title: '%%player_title%%',
22
+
23
+ controls: %%player_controls%%,
24
+ height: %%player_height%%,
25
+ skin: '%%player_skin%%',
26
+ stretching: '%%player_stretching%%',
27
+ width: %%player_width%%,
28
+
29
+ autostart: %%player_autostart%%,
30
+ fallback: %%player_fallback%%,
31
+ mute: %%player_mute%%,
32
+ primary: '%%player_primary%%',
33
+ repeat: %%player_repeat%%,
34
+ startparam: '%%player_startparam%%'
35
+ });
36
+ </script>
includes/templates/players/jwplayer-v6.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
3
+ exit("Do not access this file directly.");
4
+ ?>
5
+
6
+ <div id="%%player_id%%"></div>
7
+ <script type="text/javascript" src="%%player_path%%"></script>
8
+ <script type="text/javascript">
9
+ jwplayer('%%player_id%%').setup({
10
+
11
+ playlist:
12
+ [{
13
+ /* List all available sources. */ sources:
14
+ [
15
+ {file: '%%url%%'}
16
+ ]
17
+ }],
18
+
19
+ image: '%%player_image%%',
20
+ title: '%%player_title%%',
21
+
22
+ controls: %%player_controls%%,
23
+ height: %%player_height%%,
24
+ skin: '%%player_skin%%',
25
+ stretching: '%%player_stretching%%',
26
+ width: %%player_width%%,
27
+
28
+ autostart: %%player_autostart%%,
29
+ fallback: %%player_fallback%%,
30
+ mute: %%player_mute%%,
31
+ primary: '%%player_primary%%',
32
+ repeat: %%player_repeat%%,
33
+ startparam: '%%player_startparam%%'
34
+ });
35
+ </script>
includes/translations/s2member.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the s2Member® Framework package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: s2Member® Framework 121213\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/___s2member\n"
7
- "POT-Creation-Date: 2013-01-17 00:57:01+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -76,33 +76,33 @@ msgctxt "s2member-front"
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:475
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:561
101
  msgctxt "s2member-front"
102
  msgid "Members Only"
103
  msgstr ""
104
 
105
- #: s2member/includes/classes/files-in.inc.php:567
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:705
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:708
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:712
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:715
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:719
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:722
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:725
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:729
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:732
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:735
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:837
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
  msgstr ""
@@ -182,12 +182,12 @@ msgstr ""
182
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
183
  #. exclude `%s` if you like.
184
 
185
- #: s2member/includes/classes/files-in.inc.php:844
186
  msgctxt "s2member-admin"
187
  msgid "Unable to delete existing Amazon® CloudFront Downloads Distro. %s"
188
  msgstr ""
189
 
190
- #: s2member/includes/classes/files-in.inc.php:856
191
  msgctxt "s2member-admin"
192
  msgid "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."
193
  msgstr ""
@@ -196,7 +196,7 @@ msgstr ""
196
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
197
  #. exclude `%s` if you like.
198
 
199
- #: s2member/includes/classes/files-in.inc.php:863
200
  msgctxt "s2member-admin"
201
  msgid "Unable to delete existing Amazon® CloudFront Streaming Distro. %s"
202
  msgstr ""
@@ -205,8 +205,8 @@ msgstr ""
205
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
206
  #. exclude `%s` if you like.
207
 
208
- #: s2member/includes/classes/files-in.inc.php:879
209
- #: s2member/includes/classes/files-in.inc.php:1063
210
  msgctxt "s2member-admin"
211
  msgid "Unable to delete existing Amazon® CloudFront Origin Access Identity. %s"
212
  msgstr ""
@@ -215,12 +215,12 @@ msgstr ""
215
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
216
  #. `%s` if you like.
217
 
218
- #: s2member/includes/classes/files-in.inc.php:920
219
  msgctxt "s2member-admin"
220
  msgid "Unable to update existing Amazon® S3 ACLs. %s"
221
  msgstr ""
222
 
223
- #: s2member/includes/classes/files-in.inc.php:923
224
  msgctxt "s2member-admin"
225
  msgid "Unable to update existing Amazon® S3 ACLs. Connection failed."
226
  msgstr ""
@@ -229,14 +229,14 @@ msgstr ""
229
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
230
  #. exclude `%s` if you like.
231
 
232
- #: s2member/includes/classes/files-in.inc.php:927
233
- #: s2member/includes/classes/files-in.inc.php:1350
234
  msgctxt "s2member-admin"
235
  msgid "Unable to create Amazon® CloudFront Streaming Distro. %s"
236
  msgstr ""
237
 
238
- #: s2member/includes/classes/files-in.inc.php:930
239
- #: s2member/includes/classes/files-in.inc.php:1353
240
  msgctxt "s2member-admin"
241
  msgid "Unable to create Amazon® CloudFront Streaming Distro. Connection failed."
242
  msgstr ""
@@ -245,14 +245,14 @@ msgstr ""
245
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
246
  #. exclude `%s` if you like.
247
 
248
- #: s2member/includes/classes/files-in.inc.php:934
249
- #: s2member/includes/classes/files-in.inc.php:1327
250
  msgctxt "s2member-admin"
251
  msgid "Unable to create Amazon® CloudFront Downloads Distro. %s"
252
  msgstr ""
253
 
254
- #: s2member/includes/classes/files-in.inc.php:937
255
- #: s2member/includes/classes/files-in.inc.php:1330
256
  msgctxt "s2member-admin"
257
  msgid "Unable to create Amazon® CloudFront Downloads Distro. Connection failed."
258
  msgstr ""
@@ -261,19 +261,19 @@ msgstr ""
261
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
262
  #. exclude `%s` if you like.
263
 
264
- #: s2member/includes/classes/files-in.inc.php:941
265
- #: s2member/includes/classes/files-in.inc.php:1108
266
  msgctxt "s2member-admin"
267
  msgid "Unable to create Amazon® CloudFront Origin Access Identity. %s"
268
  msgstr ""
269
 
270
- #: s2member/includes/classes/files-in.inc.php:944
271
- #: s2member/includes/classes/files-in.inc.php:1111
272
  msgctxt "s2member-admin"
273
  msgid "Unable to create Amazon® CloudFront Origin Access Identity. Connection failed."
274
  msgstr ""
275
 
276
- #: s2member/includes/classes/files-in.inc.php:947
277
  msgctxt "s2member-admin"
278
  msgid "Unable to clear existing Amazon® CloudFront Origin Access Identity."
279
  msgstr ""
@@ -282,19 +282,19 @@ msgstr ""
282
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
283
  #. exclude `%s` if you like.
284
 
285
- #: s2member/includes/classes/files-in.inc.php:951
286
- #: s2member/includes/classes/files-in.inc.php:1020
287
  msgctxt "s2member-admin"
288
  msgid "Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s"
289
  msgstr ""
290
 
291
- #: s2member/includes/classes/files-in.inc.php:954
292
- #: s2member/includes/classes/files-in.inc.php:1023
293
  msgctxt "s2member-admin"
294
  msgid "Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed."
295
  msgstr ""
296
 
297
- #: s2member/includes/classes/files-in.inc.php:957
298
  msgctxt "s2member-admin"
299
  msgid "Unable to clear existing Amazon® CloudFront Streaming Distro."
300
  msgstr ""
@@ -303,17 +303,17 @@ msgstr ""
303
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
304
  #. exclude `%s` if you like.
305
 
306
- #: s2member/includes/classes/files-in.inc.php:961
307
  msgctxt "s2member-admin"
308
  msgid "Unable to acquire existing Amazon® CloudFront Streaming Distro. %s"
309
  msgstr ""
310
 
311
- #: s2member/includes/classes/files-in.inc.php:964
312
  msgctxt "s2member-admin"
313
  msgid "Unable to acquire existing Amazon® CloudFront Streaming Distro. Connection failed."
314
  msgstr ""
315
 
316
- #: s2member/includes/classes/files-in.inc.php:967
317
  msgctxt "s2member-admin"
318
  msgid "Unable to clear existing Amazon® CloudFront Downloads Distro."
319
  msgstr ""
@@ -322,22 +322,22 @@ msgstr ""
322
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
323
  #. exclude `%s` if you like.
324
 
325
- #: s2member/includes/classes/files-in.inc.php:971
326
  msgctxt "s2member-admin"
327
  msgid "Unable to acquire existing Amazon® CloudFront Downloads Distro. %s"
328
  msgstr ""
329
 
330
- #: s2member/includes/classes/files-in.inc.php:974
331
  msgctxt "s2member-admin"
332
  msgid "Unable to acquire existing Amazon® CloudFront Downloads Distro. Connection failed."
333
  msgstr ""
334
 
335
- #: s2member/includes/classes/files-in.inc.php:977
336
  msgctxt "s2member-admin"
337
  msgid "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."
338
  msgstr ""
339
 
340
- #: s2member/includes/classes/files-in.inc.php:980
341
  msgctxt "s2member-admin"
342
  msgid "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."
343
  msgstr ""
@@ -346,34 +346,34 @@ msgstr ""
346
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
347
  #. exclude `%s` if you like.
348
 
349
- #: s2member/includes/classes/files-in.inc.php:1016
350
  msgctxt "s2member-admin"
351
  msgid "Existing Amazon® CloudFront Origin Access Identity NOT found. %s"
352
  msgstr ""
353
 
354
- #: s2member/includes/classes/files-in.inc.php:1026
355
  msgctxt "s2member-admin"
356
  msgid "Unable to acquire existing Amazon® CloudFront Origin Access Identity. Invalid Access ID."
357
  msgstr ""
358
 
359
- #: s2member/includes/classes/files-in.inc.php:1066
360
  msgctxt "s2member-admin"
361
  msgid "Unable to delete existing Amazon® CloudFront Origin Access Identity. Connection failed."
362
  msgstr ""
363
 
364
- #: s2member/includes/classes/files-in.inc.php:1069
365
  msgctxt "s2member-admin"
366
  msgid "Unable to delete existing Amazon® CloudFront Origin Access Identity. Invalid Access ID, ETag, or XML config."
367
  msgstr ""
368
 
369
- #: s2member/includes/classes/files-in.inc.php:1095
370
- #: s2member/includes/classes/files-in.inc.php:1314
371
- #: s2member/includes/classes/files-in.inc.php:1337
372
  msgctxt "s2member-admin"
373
  msgid "Created by s2Member, for S3 Bucket: %s."
374
  msgstr ""
375
 
376
- #: s2member/includes/classes/files-in.inc.php:1104
377
  msgctxt "s2member-admin"
378
  msgid "Unable to create/read Amazon® CloudFront Origin Access Identity. Unexpected response."
379
  msgstr ""
@@ -382,7 +382,7 @@ msgstr ""
382
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
383
  #. exclude `%s` if you like.
384
 
385
- #: s2member/includes/classes/files-in.inc.php:1148
386
  msgctxt "s2member-admin"
387
  msgid "Existing Amazon® CloudFront Distro NOT found. %s"
388
  msgstr ""
@@ -391,17 +391,17 @@ msgstr ""
391
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
392
  #. exclude `%s` if you like.
393
 
394
- #: s2member/includes/classes/files-in.inc.php:1152
395
  msgctxt "s2member-admin"
396
  msgid "Unable to acquire existing Amazon® CloudFront Distro. %s"
397
  msgstr ""
398
 
399
- #: s2member/includes/classes/files-in.inc.php:1155
400
  msgctxt "s2member-admin"
401
  msgid "Unable to acquire existing Amazon® CloudFront Distro. Connection failed."
402
  msgstr ""
403
 
404
- #: s2member/includes/classes/files-in.inc.php:1158
405
  msgctxt "s2member-admin"
406
  msgid "Unable to acquire existing Amazon® CloudFront Distro. Invalid Distro ID and/or Distro type."
407
  msgstr ""
@@ -410,24 +410,24 @@ msgstr ""
410
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
411
  #. exclude `%s` if you like.
412
 
413
- #: s2member/includes/classes/files-in.inc.php:1200
414
- #: s2member/includes/classes/files-in.inc.php:1273
415
  msgctxt "s2member-admin"
416
  msgid "Unable to disable existing Amazon® CloudFront Distro. %s"
417
  msgstr ""
418
 
419
- #: s2member/includes/classes/files-in.inc.php:1203
420
- #: s2member/includes/classes/files-in.inc.php:1276
421
  msgctxt "s2member-admin"
422
  msgid "Unable to disable existing Amazon® CloudFront Distro. Connection failed."
423
  msgstr ""
424
 
425
- #: s2member/includes/classes/files-in.inc.php:1206
426
  msgctxt "s2member-admin"
427
  msgid "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."
428
  msgstr ""
429
 
430
- #: s2member/includes/classes/files-in.inc.php:1212
431
  msgctxt "s2member-admin"
432
  msgid "Unable to disable existing Amazon® CloudFront Distro. Invalid Distro ID, ETag, or XML config."
433
  msgstr ""
@@ -436,12 +436,12 @@ msgstr ""
436
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
437
  #. exclude `%s` if you like.
438
 
439
- #: s2member/includes/classes/files-in.inc.php:1255
440
  msgctxt "s2member-admin"
441
  msgid "Unable to delete existing Amazon® CloudFront Distro. %s"
442
  msgstr ""
443
 
444
- #: s2member/includes/classes/files-in.inc.php:1258
445
  msgctxt "s2member-admin"
446
  msgid "Unable to delete existing Amazon® CloudFront Distro. Connection failed."
447
  msgstr ""
@@ -450,7 +450,7 @@ msgstr ""
450
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
451
  #. exclude `%s` if you like.
452
 
453
- #: s2member/includes/classes/files-in.inc.php:1262
454
  msgctxt "s2member-admin"
455
  msgid "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."
456
  msgstr ""
@@ -459,37 +459,37 @@ msgstr ""
459
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
460
  #. exclude `%s` if you like.
461
 
462
- #: s2member/includes/classes/files-in.inc.php:1266
463
  msgctxt "s2member-admin"
464
  msgid "Unable to check status of existing Amazon® CloudFront Distro. %s"
465
  msgstr ""
466
 
467
- #: s2member/includes/classes/files-in.inc.php:1269
468
  msgctxt "s2member-admin"
469
  msgid "Unable to check status of existing Amazon® CloudFront Distro. Connection failed."
470
  msgstr ""
471
 
472
- #: s2member/includes/classes/files-in.inc.php:1279
473
  msgctxt "s2member-admin"
474
  msgid "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."
475
  msgstr ""
476
 
477
- #: s2member/includes/classes/files-in.inc.php:1282
478
  msgctxt "s2member-admin"
479
  msgid "Unable to delete existing Amazon® CloudFront Distro. Invalid Distro ID or ETag."
480
  msgstr ""
481
 
482
- #: s2member/includes/classes/files-in.inc.php:1323
483
  msgctxt "s2member-admin"
484
  msgid "Unable to create/read Amazon® CloudFront Downloads Distro. Unexpected response."
485
  msgstr ""
486
 
487
- #: s2member/includes/classes/files-in.inc.php:1346
488
  msgctxt "s2member-admin"
489
  msgid "Unable to create/read Amazon® CloudFront Streaming Distro. Unexpected response."
490
  msgstr ""
491
 
492
- #: s2member/includes/classes/files-in.inc.php:1357
493
  msgctxt "s2member-admin"
494
  msgid "Unable to create Amazon® CloudFront Distro. Invalid Distro type."
495
  msgstr ""
2
  # This file is distributed under the same license as the s2Member® Framework package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: s2Member® Framework 130116\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/___s2member\n"
7
+ "POT-Creation-Date: 2013-01-21 09:34:11+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
76
  msgid "as a Member"
77
  msgstr ""
78
 
79
+ #: s2member/includes/classes/files-in.inc.php:105
80
+ #: s2member/includes/classes/files-in.inc.php:255
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:115
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:135
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:479
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:565
101
  msgctxt "s2member-front"
102
  msgid "Members Only"
103
  msgstr ""
104
 
105
+ #: s2member/includes/classes/files-in.inc.php:571
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:709
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:712
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:716
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:719
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:723
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:726
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:729
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:733
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:736
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:739
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:841
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
  msgstr ""
182
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
183
  #. exclude `%s` if you like.
184
 
185
+ #: s2member/includes/classes/files-in.inc.php:848
186
  msgctxt "s2member-admin"
187
  msgid "Unable to delete existing Amazon® CloudFront Downloads Distro. %s"
188
  msgstr ""
189
 
190
+ #: s2member/includes/classes/files-in.inc.php:860
191
  msgctxt "s2member-admin"
192
  msgid "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."
193
  msgstr ""
196
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
197
  #. exclude `%s` if you like.
198
 
199
+ #: s2member/includes/classes/files-in.inc.php:867
200
  msgctxt "s2member-admin"
201
  msgid "Unable to delete existing Amazon® CloudFront Streaming Distro. %s"
202
  msgstr ""
205
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
206
  #. exclude `%s` if you like.
207
 
208
+ #: s2member/includes/classes/files-in.inc.php:883
209
+ #: s2member/includes/classes/files-in.inc.php:1067
210
  msgctxt "s2member-admin"
211
  msgid "Unable to delete existing Amazon® CloudFront Origin Access Identity. %s"
212
  msgstr ""
215
  #. message, which comes from the Amazon® S3 API call. Feel free to exclude
216
  #. `%s` if you like.
217
 
218
+ #: s2member/includes/classes/files-in.inc.php:924
219
  msgctxt "s2member-admin"
220
  msgid "Unable to update existing Amazon® S3 ACLs. %s"
221
  msgstr ""
222
 
223
+ #: s2member/includes/classes/files-in.inc.php:927
224
  msgctxt "s2member-admin"
225
  msgid "Unable to update existing Amazon® S3 ACLs. Connection failed."
226
  msgstr ""
229
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
230
  #. exclude `%s` if you like.
231
 
232
+ #: s2member/includes/classes/files-in.inc.php:931
233
+ #: s2member/includes/classes/files-in.inc.php:1354
234
  msgctxt "s2member-admin"
235
  msgid "Unable to create Amazon® CloudFront Streaming Distro. %s"
236
  msgstr ""
237
 
238
+ #: s2member/includes/classes/files-in.inc.php:934
239
+ #: s2member/includes/classes/files-in.inc.php:1357
240
  msgctxt "s2member-admin"
241
  msgid "Unable to create Amazon® CloudFront Streaming Distro. Connection failed."
242
  msgstr ""
245
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
246
  #. exclude `%s` if you like.
247
 
248
+ #: s2member/includes/classes/files-in.inc.php:938
249
+ #: s2member/includes/classes/files-in.inc.php:1331
250
  msgctxt "s2member-admin"
251
  msgid "Unable to create Amazon® CloudFront Downloads Distro. %s"
252
  msgstr ""
253
 
254
+ #: s2member/includes/classes/files-in.inc.php:941
255
+ #: s2member/includes/classes/files-in.inc.php:1334
256
  msgctxt "s2member-admin"
257
  msgid "Unable to create Amazon® CloudFront Downloads Distro. Connection failed."
258
  msgstr ""
261
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
262
  #. exclude `%s` if you like.
263
 
264
+ #: s2member/includes/classes/files-in.inc.php:945
265
+ #: s2member/includes/classes/files-in.inc.php:1112
266
  msgctxt "s2member-admin"
267
  msgid "Unable to create Amazon® CloudFront Origin Access Identity. %s"
268
  msgstr ""
269
 
270
+ #: s2member/includes/classes/files-in.inc.php:948
271
+ #: s2member/includes/classes/files-in.inc.php:1115
272
  msgctxt "s2member-admin"
273
  msgid "Unable to create Amazon® CloudFront Origin Access Identity. Connection failed."
274
  msgstr ""
275
 
276
+ #: s2member/includes/classes/files-in.inc.php:951
277
  msgctxt "s2member-admin"
278
  msgid "Unable to clear existing Amazon® CloudFront Origin Access Identity."
279
  msgstr ""
282
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
283
  #. exclude `%s` if you like.
284
 
285
+ #: s2member/includes/classes/files-in.inc.php:955
286
+ #: s2member/includes/classes/files-in.inc.php:1024
287
  msgctxt "s2member-admin"
288
  msgid "Unable to acquire existing Amazon® CloudFront Origin Access Identity. %s"
289
  msgstr ""
290
 
291
+ #: s2member/includes/classes/files-in.inc.php:958
292
+ #: s2member/includes/classes/files-in.inc.php:1027
293
  msgctxt "s2member-admin"
294
  msgid "Unable to acquire existing Amazon® CloudFront Origin Access Identity. Connection failed."
295
  msgstr ""
296
 
297
+ #: s2member/includes/classes/files-in.inc.php:961
298
  msgctxt "s2member-admin"
299
  msgid "Unable to clear existing Amazon® CloudFront Streaming Distro."
300
  msgstr ""
303
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
304
  #. exclude `%s` if you like.
305
 
306
+ #: s2member/includes/classes/files-in.inc.php:965
307
  msgctxt "s2member-admin"
308
  msgid "Unable to acquire existing Amazon® CloudFront Streaming Distro. %s"
309
  msgstr ""
310
 
311
+ #: s2member/includes/classes/files-in.inc.php:968
312
  msgctxt "s2member-admin"
313
  msgid "Unable to acquire existing Amazon® CloudFront Streaming Distro. Connection failed."
314
  msgstr ""
315
 
316
+ #: s2member/includes/classes/files-in.inc.php:971
317
  msgctxt "s2member-admin"
318
  msgid "Unable to clear existing Amazon® CloudFront Downloads Distro."
319
  msgstr ""
322
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
323
  #. exclude `%s` if you like.
324
 
325
+ #: s2member/includes/classes/files-in.inc.php:975
326
  msgctxt "s2member-admin"
327
  msgid "Unable to acquire existing Amazon® CloudFront Downloads Distro. %s"
328
  msgstr ""
329
 
330
+ #: s2member/includes/classes/files-in.inc.php:978
331
  msgctxt "s2member-admin"
332
  msgid "Unable to acquire existing Amazon® CloudFront Downloads Distro. Connection failed."
333
  msgstr ""
334
 
335
+ #: s2member/includes/classes/files-in.inc.php:981
336
  msgctxt "s2member-admin"
337
  msgid "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."
338
  msgstr ""
339
 
340
+ #: s2member/includes/classes/files-in.inc.php:984
341
  msgctxt "s2member-admin"
342
  msgid "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."
343
  msgstr ""
346
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
347
  #. exclude `%s` if you like.
348
 
349
+ #: s2member/includes/classes/files-in.inc.php:1020
350
  msgctxt "s2member-admin"
351
  msgid "Existing Amazon® CloudFront Origin Access Identity NOT found. %s"
352
  msgstr ""
353
 
354
+ #: s2member/includes/classes/files-in.inc.php:1030
355
  msgctxt "s2member-admin"
356
  msgid "Unable to acquire existing Amazon® CloudFront Origin Access Identity. Invalid Access ID."
357
  msgstr ""
358
 
359
+ #: s2member/includes/classes/files-in.inc.php:1070
360
  msgctxt "s2member-admin"
361
  msgid "Unable to delete existing Amazon® CloudFront Origin Access Identity. Connection failed."
362
  msgstr ""
363
 
364
+ #: s2member/includes/classes/files-in.inc.php:1073
365
  msgctxt "s2member-admin"
366
  msgid "Unable to delete existing Amazon® CloudFront Origin Access Identity. Invalid Access ID, ETag, or XML config."
367
  msgstr ""
368
 
369
+ #: s2member/includes/classes/files-in.inc.php:1099
370
+ #: s2member/includes/classes/files-in.inc.php:1318
371
+ #: s2member/includes/classes/files-in.inc.php:1341
372
  msgctxt "s2member-admin"
373
  msgid "Created by s2Member, for S3 Bucket: %s."
374
  msgstr ""
375
 
376
+ #: s2member/includes/classes/files-in.inc.php:1108
377
  msgctxt "s2member-admin"
378
  msgid "Unable to create/read Amazon® CloudFront Origin Access Identity. Unexpected response."
379
  msgstr ""
382
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
383
  #. exclude `%s` if you like.
384
 
385
+ #: s2member/includes/classes/files-in.inc.php:1152
386
  msgctxt "s2member-admin"
387
  msgid "Existing Amazon® CloudFront Distro NOT found. %s"
388
  msgstr ""
391
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
392
  #. exclude `%s` if you like.
393
 
394
+ #: s2member/includes/classes/files-in.inc.php:1156
395
  msgctxt "s2member-admin"
396
  msgid "Unable to acquire existing Amazon® CloudFront Distro. %s"
397
  msgstr ""
398
 
399
+ #: s2member/includes/classes/files-in.inc.php:1159
400
  msgctxt "s2member-admin"
401
  msgid "Unable to acquire existing Amazon® CloudFront Distro. Connection failed."
402
  msgstr ""
403
 
404
+ #: s2member/includes/classes/files-in.inc.php:1162
405
  msgctxt "s2member-admin"
406
  msgid "Unable to acquire existing Amazon® CloudFront Distro. Invalid Distro ID and/or Distro type."
407
  msgstr ""
410
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
411
  #. exclude `%s` if you like.
412
 
413
+ #: s2member/includes/classes/files-in.inc.php:1204
414
+ #: s2member/includes/classes/files-in.inc.php:1277
415
  msgctxt "s2member-admin"
416
  msgid "Unable to disable existing Amazon® CloudFront Distro. %s"
417
  msgstr ""
418
 
419
+ #: s2member/includes/classes/files-in.inc.php:1207
420
+ #: s2member/includes/classes/files-in.inc.php:1280
421
  msgctxt "s2member-admin"
422
  msgid "Unable to disable existing Amazon® CloudFront Distro. Connection failed."
423
  msgstr ""
424
 
425
+ #: s2member/includes/classes/files-in.inc.php:1210
426
  msgctxt "s2member-admin"
427
  msgid "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."
428
  msgstr ""
429
 
430
+ #: s2member/includes/classes/files-in.inc.php:1216
431
  msgctxt "s2member-admin"
432
  msgid "Unable to disable existing Amazon® CloudFront Distro. Invalid Distro ID, ETag, or XML config."
433
  msgstr ""
436
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
437
  #. exclude `%s` if you like.
438
 
439
+ #: s2member/includes/classes/files-in.inc.php:1259
440
  msgctxt "s2member-admin"
441
  msgid "Unable to delete existing Amazon® CloudFront Distro. %s"
442
  msgstr ""
443
 
444
+ #: s2member/includes/classes/files-in.inc.php:1262
445
  msgctxt "s2member-admin"
446
  msgid "Unable to delete existing Amazon® CloudFront Distro. Connection failed."
447
  msgstr ""
450
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
451
  #. exclude `%s` if you like.
452
 
453
+ #: s2member/includes/classes/files-in.inc.php:1266
454
  msgctxt "s2member-admin"
455
  msgid "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."
456
  msgstr ""
459
  #. message, which comes from the Amazon® CloudFront API call. Feel free to
460
  #. exclude `%s` if you like.
461
 
462
+ #: s2member/includes/classes/files-in.inc.php:1270
463
  msgctxt "s2member-admin"
464
  msgid "Unable to check status of existing Amazon® CloudFront Distro. %s"
465
  msgstr ""
466
 
467
+ #: s2member/includes/classes/files-in.inc.php:1273
468
  msgctxt "s2member-admin"
469
  msgid "Unable to check status of existing Amazon® CloudFront Distro. Connection failed."
470
  msgstr ""
471
 
472
+ #: s2member/includes/classes/files-in.inc.php:1283
473
  msgctxt "s2member-admin"
474
  msgid "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."
475
  msgstr ""
476
 
477
+ #: s2member/includes/classes/files-in.inc.php:1286
478
  msgctxt "s2member-admin"
479
  msgid "Unable to delete existing Amazon® CloudFront Distro. Invalid Distro ID or ETag."
480
  msgstr ""
481
 
482
+ #: s2member/includes/classes/files-in.inc.php:1327
483
  msgctxt "s2member-admin"
484
  msgid "Unable to create/read Amazon® CloudFront Downloads Distro. Unexpected response."
485
  msgstr ""
486
 
487
+ #: s2member/includes/classes/files-in.inc.php:1350
488
  msgctxt "s2member-admin"
489
  msgid "Unable to create/read Amazon® CloudFront Streaming Distro. Unexpected response."
490
  msgstr ""
491
 
492
+ #: s2member/includes/classes/files-in.inc.php:1361
493
  msgctxt "s2member-admin"
494
  msgid "Unable to create Amazon® CloudFront Distro. Invalid Distro type."
495
  msgstr ""
readme.txt CHANGED
@@ -1,7 +1,7 @@
1
  === s2Member® Framework (Member Roles, Capabilities, Membership, PayPal Members) ===
2
 
3
- Version: 130116
4
- Stable tag: 130116
5
 
6
  SSL Compatible: yes
7
  bbPress® Compatible: yes
@@ -91,11 +91,17 @@ Please see [this FAQ entry](http://www.s2member.com/faqs/#s2-faqs-translations)
91
 
92
  == Upgrade Notice ==
93
 
94
- = v130116 =
95
  Maintenance release. Upgrade immediately.
96
 
97
  == Changelog ==
98
 
 
 
 
 
 
 
99
  = v130116 =
100
  * **(Maintenance Release) Upgrade immediately.**
101
  * **Compatibility (Issue #39)** Updated codes samples for JW Player®, to include the `mp4:` prefix when implementing RTMP streams against MP4 video files. Discussed in [this thread](http://www.s2member.com/forums/topic/cloudfront-subfolder-streaming-error/#post-35750).
1
  === s2Member® Framework (Member Roles, Capabilities, Membership, PayPal Members) ===
2
 
3
+ Version: 130121
4
+ Stable tag: 130121
5
 
6
  SSL Compatible: yes
7
  bbPress® Compatible: yes
91
 
92
  == Upgrade Notice ==
93
 
94
+ = v130121 =
95
  Maintenance release. Upgrade immediately.
96
 
97
  == Changelog ==
98
 
99
+ = v130121 =
100
+ * **(Maintenance Release) Upgrade immediately.**
101
+ * **New Feature** s2Member® now comes with a new Shortcode `[s2Stream file_download="video.mp4" player="jwplayer-v6" ... /]`, making it MUCH easier for site owners to implemement RTMP streams of audio/video content. For further details, please check your Dashboard under: `s2Member® -> Download Options -> JW Player® v6 and RTMP Protocol Examples`. See also: `s2Member® -> Download Options -> Shortcode Attributes (Explained)`.
102
+ * **Compatibility (Issue #75)** Updated s2Member's local file storage engine (for File Downloads via s2Member®), to support special characters in file names. Discussed in [this thread](http://www.s2member.com/forums/topic/problem-with-quotes-in-filename-downloads/#post-38395).
103
+ * **Bug Fix (Issue #71)** A bug first introduced in the previous release of v130116, where we added support for byte-range requests to s2Member's File Download functionality, was causing multiple byte-range requests (processed by s2Member) to count against each User/Member as multiple File Downloads. Fixed in this release.
104
+
105
  = v130116 =
106
  * **(Maintenance Release) Upgrade immediately.**
107
  * **Compatibility (Issue #39)** Updated codes samples for JW Player®, to include the `mp4:` prefix when implementing RTMP streams against MP4 video files. Discussed in [this thread](http://www.s2member.com/forums/topic/cloudfront-subfolder-streaming-error/#post-35750).
s2member.php CHANGED
@@ -19,8 +19,8 @@
19
  */
20
  /* -- This section for WordPress® parsing. ------------------------------------------------------------------------------
21
 
22
- Version: 130116
23
- Stable tag: 130116
24
 
25
  SSL Compatible: yes
26
  bbPress® Compatible: yes
@@ -75,7 +75,7 @@ if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
75
  * @var str
76
  */
77
  if(!defined("WS_PLUGIN__S2MEMBER_VERSION"))
78
- define("WS_PLUGIN__S2MEMBER_VERSION", "130116" /* !#distro-version#! */);
79
  /**
80
  * Minimum PHP version required to run s2Member.
81
  *
@@ -105,7 +105,7 @@ if(!defined("WS_PLUGIN__S2MEMBER_MIN_WP_VERSION"))
105
  * @var str
106
  */
107
  if(!defined("WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION"))
108
- define("WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION", "130116" /* !#distro-version#! */);
109
  /*
110
  Several compatibility checks.
111
  If all pass, load the s2Member plugin.
19
  */
20
  /* -- This section for WordPress® parsing. ------------------------------------------------------------------------------
21
 
22
+ Version: 130121
23
+ Stable tag: 130121
24
 
25
  SSL Compatible: yes
26
  bbPress® Compatible: yes
75
  * @var str
76
  */
77
  if(!defined("WS_PLUGIN__S2MEMBER_VERSION"))
78
+ define("WS_PLUGIN__S2MEMBER_VERSION", "130121" /* !#distro-version#! */);
79
  /**
80
  * Minimum PHP version required to run s2Member.
81
  *
105
  * @var str
106
  */
107
  if(!defined("WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION"))
108
+ define("WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION", "130121" /* !#distro-version#! */);
109
  /*
110
  Several compatibility checks.
111
  If all pass, load the s2Member plugin.