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

Version Description

Download this release

Release Info

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

Code changes from version 111011 to 111017

Files changed (30) hide show
  1. includes/classes/auto-eots.inc.php +4 -3
  2. includes/classes/email-configs.inc.php +6 -5
  3. includes/classes/files-in.inc.php +22 -54
  4. includes/classes/login-redirects.inc.php +13 -13
  5. includes/classes/paypal-notify-in-sp-refund-reversal.inc.php +4 -3
  6. includes/classes/paypal-notify-in-subscr-modify-w-level.inc.php +4 -3
  7. includes/classes/paypal-notify-in-subscr-or-rp-cancellation-w-level.inc.php +4 -3
  8. includes/classes/paypal-notify-in-subscr-or-rp-eots-w-level.inc.php +8 -6
  9. includes/classes/paypal-notify-in-subscr-or-rp-payment-w-level.inc.php +4 -3
  10. includes/classes/paypal-notify-in-subscr-or-wa-w-level.inc.php +29 -26
  11. includes/classes/paypal-notify-in-wa-ccaps-wo-level.inc.php +11 -10
  12. includes/classes/paypal-notify-in-web-accept-sp.inc.php +13 -12
  13. includes/classes/registrations.inc.php +4 -3
  14. includes/classes/ruris-sp.inc.php +4 -5
  15. includes/classes/systematics-sp.inc.php +2 -2
  16. includes/classes/systematics.inc.php +7 -3
  17. includes/classes/translations.inc.php +3 -2
  18. includes/classes/user-deletions.inc.php +4 -3
  19. includes/classes/utils-conds.inc.php +9 -8
  20. includes/classes/utils-dirs.inc.php +128 -39
  21. includes/classes/utils-s2o.inc.php +2 -2
  22. includes/classes/utils-strings.inc.php +132 -3
  23. includes/classes/utils-urls.inc.php +40 -6
  24. includes/menu-pages/down-ops.inc.php +4 -4
  25. includes/menu-pages/menu-pages-s.js +2 -2
  26. includes/templates/cfg-files/s2member-files.php +3 -3
  27. includes/translations/s2member.pot +88 -88
  28. includes/translations/translators.txt +1 -1
  29. readme.txt +13 -4
  30. s2member.php +8 -8
includes/classes/auto-eots.inc.php CHANGED
@@ -235,9 +235,10 @@ if (!class_exists ("c_ws_plugin__s2member_auto_eots"))
235
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
236
  break;
237
  /**/
238
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
239
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
240
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
241
  }
242
  /**/
243
  if ($email_configs_were_on) /* Back on? */
235
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
236
  break;
237
  /**/
238
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
239
+ /**/
240
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"]) as $recipient)
241
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
242
  }
243
  /**/
244
  if ($email_configs_were_on) /* Back on? */
includes/classes/email-configs.inc.php CHANGED
@@ -236,8 +236,9 @@ if (!class_exists ("c_ws_plugin__s2member_email_configs"))
236
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
237
  break;
238
  /**/
239
- if (($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
240
- c_ws_plugin__s2member_email_configs::email_config () . wp_mail ('"' . c_ws_plugin__s2member_utils_strings::esc_dq ($user_full_name) . '" <' . $user->user_email . '>', $sbj, $msg, "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") . c_ws_plugin__s2member_email_configs::email_config_release ();
 
241
  }
242
  }
243
  }
@@ -301,10 +302,10 @@ if (!class_exists ("c_ws_plugin__s2member_email_configs"))
301
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
302
  break;
303
  /**/
304
- if (($recipients = preg_split ("/;+/", preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
305
  {
306
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep ($recipients) as $recipient)
307
- ($recipient) ? wp_mail ($recipient, $sbj, $msg, "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
308
  }
309
  }
310
  }
236
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
237
  break;
238
  /**/
239
+ if (($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
240
+ /**/
241
+ c_ws_plugin__s2member_email_configs::email_config () . wp_mail ($user->user_email, $sbj, $msg, "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") . c_ws_plugin__s2member_email_configs::email_config_release ();
242
  }
243
  }
244
  }
302
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
303
  break;
304
  /**/
305
+ if (($rec = trim (preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
306
  {
307
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($rec) as $recipient) /* A possible list of recipients. */
308
+ wp_mail ($recipient, $sbj, $msg, "Content-Type: text/plain; charset=utf-8");
309
  }
310
  }
311
  }
includes/classes/files-in.inc.php CHANGED
@@ -297,16 +297,21 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
297
  return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ());
298
  }
299
  /**/
300
- else if ($creating) /* Else we're creating a URL w/ a query-string, pointing to local storage. */
301
  {
302
- $url = (isset ($req["file_download_key"])) ? (($key) ? "&s2member_file_download_key=" . urlencode ($key) : "") : "";
 
 
 
 
 
303
  $url .= (isset ($req["file_stream"])) ? (($stream) ? "&s2member_file_stream=yes" : "&s2member_file_stream=no") : "";
304
  $url .= (isset ($req["file_inline"])) ? (($inline) ? "&s2member_file_inline=yes" : "&s2member_file_inline=no") : "";
305
- $url .= (isset ($req["file_storage"])) ? (($storage) ? "&s2member_file_storage=" . urlencode ($storage) : "") : "";
306
  $url .= (isset ($req["file_remote"])) ? (($remote) ? "&s2member_file_remote=yes" : "&s2member_file_remote=no") : "";
307
  $url .= (isset ($req["skip_confirmation"])) ? (($skip_confirmation) ? "&s2member_skip_confirmation=yes" : "&s2member_skip_confirmation=no") : "";
308
  /**/
309
- $url = site_url ("/?" . ltrim ($url . "&s2member_file_download=/" . urlencode ($req["file_download"]), "&"));
310
  $url = ($ssl) ? preg_replace ("/^https?/", "https", $url) : preg_replace ("/^https?/", "http", $url);
311
  /**/
312
  return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ());
@@ -410,7 +415,7 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
410
  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)))))
411
  $return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
412
  /**/
413
- else if ($get_streamer_array && $streaming && is_array ($ups = @parse_url ($_url)) && ($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)))))
414
  $return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
415
  /**/
416
  else if ($get_streamer_array) /* Else, we MUST return false here, unable to acquire streamer/file. */
@@ -504,8 +509,7 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
504
  {
505
  $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
506
  /**/
507
- $s3_signature = str_pad (((strlen ($s3c["secret_key"]) > 64) ? pack ('H*', sha1 ($s3c["secret_key"])) : $s3c["secret_key"]), 64, chr (0x00));
508
- return pack ('H*', sha1 (($s3_signature ^ str_repeat (chr (0x5c), 64)) . pack ('H*', sha1 (($s3_signature ^ str_repeat (chr (0x36), 64)) . (string)$string))));
509
  }
510
  /**
511
  * Creates an Amazon® S3 HMAC-SHA1 signature URL.
@@ -531,12 +535,13 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
531
  /**/
532
  $s3c["expires"] = strtotime ("+" . apply_filters ("ws_plugin__s2member_amazon_s3_file_expires_time", "30 seconds", get_defined_vars ()));
533
  /**/
534
- $s3_file = add_query_arg (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);
535
  $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);
536
  $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("GET\n\n\n" . $s3c["expires"] . "\n" . "/" . $s3c["bucket"] . $s3_raw_file));
537
  /**/
538
  $s3_url = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "http" . (($ssl) ? "s" : "") . "://s3.amazonaws.com/" . $s3c["bucket"] . $s3_file : "http" . (($ssl) ? "s" : "") . "://" . $s3c["bucket"] . ".s3.amazonaws.com" . $s3_file;
539
- return add_query_arg (urlencode_deep (array ("AWSAccessKeyId" => $s3c["access_key"], "Expires" => $s3c["expires"], "Signature" => $s3_signature)), $s3_url);
 
540
  }
541
  /**
542
  * Auto-configures an Amazon® S3 Bucket's ACLs.
@@ -636,8 +641,7 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
636
  {
637
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
638
  /**/
639
- $cf_signature = str_pad (((strlen ($cfc["secret_key"]) > 64) ? pack ('H*', sha1 ($cfc["secret_key"])) : $cfc["secret_key"]), 64, chr (0x00));
640
- return pack ('H*', sha1 (($cf_signature ^ str_repeat (chr (0x5c), 64)) . pack ('H*', sha1 (($cf_signature ^ str_repeat (chr (0x36), 64)) . (string)$string))));
641
  }
642
  /**
643
  * Creates an Amazon® CloudFront RSA-SHA1 signature.
@@ -647,52 +651,15 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
647
  *
648
  * @param str $string Input string/data, to be signed by this routine.
649
  * @return str|bool An RSA-SHA1 signature for Amazon® CloudFront, else false on failure.
650
- */
651
- public static function amazon_cf_rsa_sign ($string = FALSE)
652
- {
653
- $cfc["private_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"];
654
- /**/
655
- if (stripos (PHP_SAPI, "apache") !== false) /* PHP is running as an Apache module? */
656
- if ( /* Some `mod_php` installs have issues with OpenSSL version conflicts. See: <http://www.apachelounge.com/viewtopic.php?t=4180>. */
657
- ($signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_shell_sign ($string)) /* Also try some other OpenSSL locations on Windows®. */
658
- || (stripos (PHP_OS, "win") === 0 && ($signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_shell_sign ($string, "C:\openssl-win32\bin\openssl.exe"))) #
659
- || (stripos (PHP_OS, "win") === 0 && ($signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_shell_sign ($string, "C:\openssl-win64\bin\openssl.exe"))))
660
- return $signature;
661
- /**/
662
- if (function_exists ("openssl_get_privatekey") && function_exists ("openssl_sign") && is_resource ($private_key = openssl_get_privatekey ($cfc["private_key"])))
663
- openssl_sign ((string)$string, $signature, $private_key, OPENSSL_ALGO_SHA1) . openssl_free_key ($private_key);
664
- /**/
665
- else if (function_exists ("shell_exec")) /* Last ditch effort here. */
666
- $signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_shell_sign ($string);
667
- /**/
668
- return (!empty ($signature)) ? $signature : false;
669
- }
670
- /**
671
- * Creates an Amazon® CloudFront RSA-SHA1 signature via ``shell_exec()`` to `openssl`.
672
  *
673
- * @package s2Member\Files
674
- * @since 110926
675
- *
676
- * @param str $string Input string/data, to be signed by this routine.
677
- * @param str $openssl Optional. A specific absolute path to OpenSSL application.
678
- * @return str|bool An RSA-SHA1 signature for Amazon® CloudFront, else false on failure.
679
  */
680
- public static function amazon_cf_rsa_shell_sign ($string = FALSE, $openssl = FALSE)
681
  {
682
  $cfc["private_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"];
683
  /**/
684
- if (function_exists ("shell_exec") && ($openssl = (($openssl && is_string ($openssl)) ? $openssl : "openssl")) && ($esa = "escapeshellarg"))
685
- {
686
- file_put_contents (($cf_string_file = get_temp_dir () . wp_unique_filename (get_temp_dir (), md5 (time () . "cf-string") . ".tmp")), (string)$string);
687
- file_put_contents (($cf_private_key_file = get_temp_dir () . wp_unique_filename (get_temp_dir (), md5 (time () . "cf-private-key") . ".tmp")), $cfc["private_key"]);
688
- file_put_contents (($cf_rsa_sha1_sig_file = get_temp_dir () . wp_unique_filename (get_temp_dir (), md5 (time () . "cf-rsa-sha1-signature-file") . ".tmp")), "");
689
- /**/
690
- @shell_exec($esa ($openssl) . " sha1 -sign " . $esa ($cf_private_key_file) . " -out " . $esa ($cf_rsa_sha1_sig_file) . " " . $esa ($cf_string_file));
691
- $signature = trim (file_get_contents ($cf_rsa_sha1_sig_file)); /* Now try to obtain signature file contents. */
692
- unlink($cf_rsa_sha1_sig_file) . unlink ($cf_private_key_file) . unlink ($cf_string_file); /* Cleanup. */
693
- }
694
- /**/
695
- return (!empty ($signature)) ? $signature : false;
696
  }
697
  /**
698
  * Creates an Amazon® CloudFront RSA-SHA1 signature URL.
@@ -722,14 +689,15 @@ if (!class_exists ("c_ws_plugin__s2member_files_in"))
722
  $cf_stream_extn_resource_exclusions = array_unique ((array)apply_filters ("ws_plugin__s2member_amazon_cf_file_streaming_extension_resource_exclusions", array ("mp3" /* MP3 files should NOT include an extension in their resource reference. */), get_defined_vars ()));
723
  $cf_resource = ($stream) ? ((in_array ($cf_extn, $cf_stream_extn_resource_exclusions)) ? substr ($file, 0, strrpos ($file, ".")) : $file) : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file;
724
  $cf_url = ($stream) ? "rtmp" . (($ssl) ? "e" : "") . "://" . (($cfc["distro_streaming_cname"]) ? $cfc["distro_streaming_cname"] : $cfc["distro_streaming_dname"]) . "/cfx/st/" . $file : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file;
725
- $cf_ip_res = (stripos ($_SERVER["HTTP_HOST"], "localhost") === false && strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") === false && (!defined ("LOCALHOST") || !LOCALHOST)) ? true : false; /* Don NOT restrict access to a particular IP during `localhost` development. The IP will NOT be the same one Amazon® CloudFront sees ( so will NOT jive ). */
726
  $cf_policy = '{"Statement":[{"Resource":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($cf_resource) . '","Condition":{' . (($cf_ip_res) ? '"IpAddress":{"AWS:SourceIp":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($_SERVER["REMOTE_ADDR"]) . '/32"},' : '') . '"DateLessThan":{"AWS:EpochTime":' . (int)$cfc["expires"] . '}}}]}';
727
  /**/
728
  $cf_signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_sign ($cf_policy);
729
  $cf_base64_url_safe_policy = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_policy, array ("+", "=", "/"), array ("-", "_", "~"), false);
730
  $cf_base64_url_safe_signature = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_signature, array ("+", "=", "/"), array ("-", "_", "~"), false);
731
  /**/
732
- return add_query_arg (urlencode_deep (array ("Policy" => $cf_base64_url_safe_policy, "Signature" => $cf_base64_url_safe_signature, "Key-Pair-Id" => $cfc["private_key_id"])), $cf_url);
 
733
  }
734
  /**
735
  * Auto-configures Amazon® S3/CloudFront distros.
297
  return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ());
298
  }
299
  /**/
300
+ else if ($creating) /* Else we're creating a URL w/ a query-string; w/ local storage. */
301
  {
302
+ /* * Note: we don't URL encode unreserved chars. Improves media player compatibility. */
303
+ $_url_e_key = ($key) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($key)) : "";
304
+ $_url_e_storage = ($storage) ? c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($storage)) : "";
305
+ $_url_e_file = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep (urlencode ($req["file_download"]));
306
+ /**/
307
+ $url = (isset ($req["file_download_key"])) ? (($key && $_url_e_key) ? "&s2member_file_download_key=" . $_url_e_key : "") : "";
308
  $url .= (isset ($req["file_stream"])) ? (($stream) ? "&s2member_file_stream=yes" : "&s2member_file_stream=no") : "";
309
  $url .= (isset ($req["file_inline"])) ? (($inline) ? "&s2member_file_inline=yes" : "&s2member_file_inline=no") : "";
310
+ $url .= (isset ($req["file_storage"])) ? (($storage && $_url_e_storage) ? "&s2member_file_storage=" . $_url_e_storage : "") : "";
311
  $url .= (isset ($req["file_remote"])) ? (($remote) ? "&s2member_file_remote=yes" : "&s2member_file_remote=no") : "";
312
  $url .= (isset ($req["skip_confirmation"])) ? (($skip_confirmation) ? "&s2member_skip_confirmation=yes" : "&s2member_skip_confirmation=no") : "";
313
  /**/
314
+ $url = site_url ("/?" . ltrim ($url . "&s2member_file_download=/" . $_url_e_file, "&"));
315
  $url = ($ssl) ? preg_replace ("/^https?/", "https", $url) : preg_replace ("/^https?/", "http", $url);
316
  /**/
317
  return apply_filters ("ws_plugin__s2member_file_download_access_url", $url, get_defined_vars ());
415
  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)))))
416
  $return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
417
  /**/
418
+ 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)))))
419
  $return = array ("streamer" => $streamer, "file" => preg_replace ("/^" . preg_quote ($streamer, "/") . "\//", "", $_url), "url" => preg_replace ("/^.+?\:/", (($ssl) ? "https:" : "http:"), $url));
420
  /**/
421
  else if ($get_streamer_array) /* Else, we MUST return false here, unable to acquire streamer/file. */
509
  {
510
  $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
511
  /**/
512
+ return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign ((string)$string, $s3c["secret_key"]);
 
513
  }
514
  /**
515
  * Creates an Amazon® S3 HMAC-SHA1 signature URL.
535
  /**/
536
  $s3c["expires"] = strtotime ("+" . apply_filters ("ws_plugin__s2member_amazon_s3_file_expires_time", "30 seconds", get_defined_vars ()));
537
  /**/
538
+ $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);
539
  $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);
540
  $s3_signature = base64_encode (c_ws_plugin__s2member_files_in::amazon_s3_sign ("GET\n\n\n" . $s3c["expires"] . "\n" . "/" . $s3c["bucket"] . $s3_raw_file));
541
  /**/
542
  $s3_url = ((strtolower ($s3c["bucket"]) !== $s3c["bucket"])) ? "http" . (($ssl) ? "s" : "") . "://s3.amazonaws.com/" . $s3c["bucket"] . $s3_file : "http" . (($ssl) ? "s" : "") . "://" . $s3c["bucket"] . ".s3.amazonaws.com" . $s3_file;
543
+ return add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */
544
+ (urlencode_deep (array ("AWSAccessKeyId" => $s3c["access_key"], "Expires" => $s3c["expires"], "Signature" => $s3_signature))), $s3_url);
545
  }
546
  /**
547
  * Auto-configures an Amazon® S3 Bucket's ACLs.
641
  {
642
  $cfc["secret_key"] = $s3c["secret_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_s3_files_secret_key"];
643
  /**/
644
+ return c_ws_plugin__s2member_utils_strings::hmac_sha1_sign ((string)$string, ($cfc["secret_key"] = $s3c["secret_key"]));
 
645
  }
646
  /**
647
  * Creates an Amazon® CloudFront RSA-SHA1 signature.
651
  *
652
  * @param str $string Input string/data, to be signed by this routine.
653
  * @return str|bool An RSA-SHA1 signature for Amazon® CloudFront, else false on failure.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  *
655
+ * @todo Double underscores *( i.e. base64 padding chars )* in the signature seem to cause issues for Amazon® CloudFront?
656
+ * See ticket: {@link https://forums.aws.amazon.com/thread.jspa?messageID=286182&#286182}
 
 
 
 
657
  */
658
+ public static function amazon_cf_rsa_sign ($string = FALSE)
659
  {
660
  $cfc["private_key"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"];
661
  /**/
662
+ return c_ws_plugin__s2member_utils_strings::rsa_sha1_sign ((string)$string, $cfc["private_key"]);
 
 
 
 
 
 
 
 
 
 
 
663
  }
664
  /**
665
  * Creates an Amazon® CloudFront RSA-SHA1 signature URL.
689
  $cf_stream_extn_resource_exclusions = array_unique ((array)apply_filters ("ws_plugin__s2member_amazon_cf_file_streaming_extension_resource_exclusions", array ("mp3" /* MP3 files should NOT include an extension in their resource reference. */), get_defined_vars ()));
690
  $cf_resource = ($stream) ? ((in_array ($cf_extn, $cf_stream_extn_resource_exclusions)) ? substr ($file, 0, strrpos ($file, ".")) : $file) : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file;
691
  $cf_url = ($stream) ? "rtmp" . (($ssl) ? "e" : "") . "://" . (($cfc["distro_streaming_cname"]) ? $cfc["distro_streaming_cname"] : $cfc["distro_streaming_dname"]) . "/cfx/st/" . $file : "http" . (($ssl) ? "s" : "") . "://" . (($cfc["distro_downloads_cname"]) ? $cfc["distro_downloads_cname"] : $cfc["distro_downloads_dname"]) . "/" . $file;
692
+ $cf_ip_res = (stripos ($_SERVER["HTTP_HOST"], "localhost") === false && strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") === false && (!defined ("LOCALHOST") || !LOCALHOST)) ? true : false; /* Don NOT restrict access to a particular IP during `localhost` development. The IP will NOT be the same one Amazon® CloudFront sees ( will NOT jive ). */
693
  $cf_policy = '{"Statement":[{"Resource":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($cf_resource) . '","Condition":{' . (($cf_ip_res) ? '"IpAddress":{"AWS:SourceIp":"' . c_ws_plugin__s2member_utils_strings::esc_dq ($_SERVER["REMOTE_ADDR"]) . '/32"},' : '') . '"DateLessThan":{"AWS:EpochTime":' . (int)$cfc["expires"] . '}}}]}';
694
  /**/
695
  $cf_signature = c_ws_plugin__s2member_files_in::amazon_cf_rsa_sign ($cf_policy);
696
  $cf_base64_url_safe_policy = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_policy, array ("+", "=", "/"), array ("-", "_", "~"), false);
697
  $cf_base64_url_safe_signature = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode ($cf_signature, array ("+", "=", "/"), array ("-", "_", "~"), false);
698
  /**/
699
+ return add_query_arg (c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep /* Don't encode unreserved chars. Maximizes media player compatibility. */
700
+ (urlencode_deep (array ("Policy" => $cf_base64_url_safe_policy, "Signature" => $cf_base64_url_safe_signature, "Key-Pair-Id" => $cfc["private_key_id"]))), $cf_url);
701
  }
702
  /**
703
  * Auto-configures Amazon® S3/CloudFront distros.
includes/classes/login-redirects.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 3.5
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
21
  {
@@ -40,7 +40,7 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
40
  */
41
  public static function login_redirect ($username = FALSE)
42
  {
43
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
44
  do_action ("ws_plugin__s2member_before_login_redirect", get_defined_vars ());
45
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
46
  /**/
@@ -55,7 +55,7 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
55
  update_user_option ($user_id, "s2member_login_counter", $logins);
56
  /**/
57
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"]) /* Nag em? */
58
- delete_user_setting ("default_password_nag") . update_user_option ($user_id, "default_password_nag", false, true);
59
  /**/
60
  $disable_login_ip_restrictions = apply_filters ("ws_plugin__s2member_disable_login_ip_restrictions", false, get_defined_vars ());
61
  /**/
@@ -68,25 +68,25 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
68
  /**/
69
  if (!$obey_redirect_to || empty ($_REQUEST["redirect_to"]) || !is_string ($_REQUEST["redirect_to"]) || $_REQUEST["redirect_to"] === admin_url () || preg_match ("/^\/?wp-admin\/?$/", $_REQUEST["redirect_to"]))
70
  {
71
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
72
  do_action ("ws_plugin__s2member_during_login_redirect", get_defined_vars ());
73
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
74
  /**/
75
  if ($redirect && is_string ($redirect)) /* Is this a string? */
76
- wp_redirect ($redirect); /* Dynamic URL introduced by a Filter? */
77
  /**/
78
  else if ($redirection_url = c_ws_plugin__s2member_login_redirects::login_redirection_url ($user))
79
- wp_redirect ($redirection_url); /* Special Redirection URL configured with s2Member. */
80
  /**/
81
  else /* Else we use the Login Welcome Page configured for s2Member. */
82
- wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));
83
  /**/
84
  exit (); /* Clean exit. */
85
  }
86
  }
87
  }
88
  /**/
89
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
90
  do_action ("ws_plugin__s2member_after_login_redirect", get_defined_vars ());
91
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
92
  /**/
@@ -104,7 +104,7 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
104
  */
105
  public static function login_redirection_url ($user = FALSE, $root_returns_false = FALSE)
106
  {
107
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
108
  do_action ("ws_plugin__s2member_before_login_redirection_url", get_defined_vars ());
109
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
110
  /**/
@@ -125,7 +125,7 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
125
  */
126
  public static function login_redirection_uri ($user = FALSE, $root_returns_false = FALSE)
127
  {
128
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
129
  do_action ("ws_plugin__s2member_before_login_redirection_uri", get_defined_vars ());
130
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
131
  /**/
@@ -147,7 +147,7 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
147
  */
148
  public static function fill_login_redirect_rc_vars ($url = FALSE, $user = FALSE, $root_returns_false = FALSE)
149
  {
150
- eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
151
  do_action ("ws_plugin__s2member_before_fill_login_redirect_rc_vars", get_defined_vars ());
152
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
153
  /**/
@@ -170,8 +170,8 @@ if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
170
  $url = preg_replace ("/%%current_user_ccaps%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_ccaps), $url);
171
  $url = preg_replace ("/%%current_user_logins%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_logins), $url);
172
  /**/
173
- if ( /* Only if s2Member's fault » */$url !== $orig_url && (!($parse = @parse_url ($url)) || strpos ($parse["path"], "//") !== false))
174
- $url = site_url ("/"); /* Defaults to home page. We don't return invalid URLs produced by empty Replacement Codes ( i.e. // ). */
175
  /**/
176
  if ($root_returns_false /* Used by s2Member's security gate. */ && c_ws_plugin__s2member_utils_conds::is_site_root ($url))
177
  $url = false; /* In case we need to return false on root URLs ( i.e. don't protect the Home Page inadvertently ). */
15
  * @since 3.5
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_login_redirects"))
21
  {
40
  */
41
  public static function login_redirect ($username = FALSE)
42
  {
43
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
44
  do_action ("ws_plugin__s2member_before_login_redirect", get_defined_vars ());
45
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
46
  /**/
55
  update_user_option ($user_id, "s2member_login_counter", $logins);
56
  /**/
57
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"]) /* Nag em? */
58
+ delete_user_setting("default_password_nag") . update_user_option ($user_id, "default_password_nag", false, true);
59
  /**/
60
  $disable_login_ip_restrictions = apply_filters ("ws_plugin__s2member_disable_login_ip_restrictions", false, get_defined_vars ());
61
  /**/
68
  /**/
69
  if (!$obey_redirect_to || empty ($_REQUEST["redirect_to"]) || !is_string ($_REQUEST["redirect_to"]) || $_REQUEST["redirect_to"] === admin_url () || preg_match ("/^\/?wp-admin\/?$/", $_REQUEST["redirect_to"]))
70
  {
71
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
72
  do_action ("ws_plugin__s2member_during_login_redirect", get_defined_vars ());
73
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
74
  /**/
75
  if ($redirect && is_string ($redirect)) /* Is this a string? */
76
+ wp_redirect($redirect); /* Dynamic URL introduced by a Filter? */
77
  /**/
78
  else if ($redirection_url = c_ws_plugin__s2member_login_redirects::login_redirection_url ($user))
79
+ wp_redirect($redirection_url); /* Special Redirection URL configured with s2Member. */
80
  /**/
81
  else /* Else we use the Login Welcome Page configured for s2Member. */
82
+ wp_redirect(get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));
83
  /**/
84
  exit (); /* Clean exit. */
85
  }
86
  }
87
  }
88
  /**/
89
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
90
  do_action ("ws_plugin__s2member_after_login_redirect", get_defined_vars ());
91
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
92
  /**/
104
  */
105
  public static function login_redirection_url ($user = FALSE, $root_returns_false = FALSE)
106
  {
107
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
108
  do_action ("ws_plugin__s2member_before_login_redirection_url", get_defined_vars ());
109
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
110
  /**/
125
  */
126
  public static function login_redirection_uri ($user = FALSE, $root_returns_false = FALSE)
127
  {
128
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
129
  do_action ("ws_plugin__s2member_before_login_redirection_uri", get_defined_vars ());
130
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
131
  /**/
147
  */
148
  public static function fill_login_redirect_rc_vars ($url = FALSE, $user = FALSE, $root_returns_false = FALSE)
149
  {
150
+ eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
151
  do_action ("ws_plugin__s2member_before_fill_login_redirect_rc_vars", get_defined_vars ());
152
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
153
  /**/
170
  $url = preg_replace ("/%%current_user_ccaps%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_ccaps), $url);
171
  $url = preg_replace ("/%%current_user_logins%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($user_logins), $url);
172
  /**/
173
+ if ( /* Only if s2Member's fault » */$url !== $orig_url && (!($parse = c_ws_plugin__s2member_utils_urls::parse_url ($url, -1, false)) || (!empty ($parse["path"]) && strpos ($parse["path"], "//") !== false)))
174
+ $url = site_url ("/"); /* Defaults to Home Page. We don't return invalid URLs produced by empty Replacement Codes ( i.e. with `//` ). */
175
  /**/
176
  if ($root_returns_false /* Used by s2Member's security gate. */ && c_ws_plugin__s2member_utils_conds::is_site_root ($url))
177
  $url = false; /* In case we need to return false on root URLs ( i.e. don't protect the Home Page inadvertently ). */
includes/classes/paypal-notify-in-sp-refund-reversal.inc.php CHANGED
@@ -119,9 +119,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_sp_refund_reversal"))
119
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
120
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
121
  /**/
122
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
123
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_ref_rev_notification_recipients"])) as $recipient)
124
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
125
  /**/
126
  $paypal["s2member_log"][] = "Specific Post/Page ~ Refund/Reversal Notification Emails have been processed.";
127
  }
119
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
120
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
121
  /**/
122
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
123
+ /**/
124
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_ref_rev_notification_recipients"]) as $recipient)
125
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
126
  /**/
127
  $paypal["s2member_log"][] = "Specific Post/Page ~ Refund/Reversal Notification Emails have been processed.";
128
  }
includes/classes/paypal-notify-in-subscr-modify-w-level.inc.php CHANGED
@@ -225,9 +225,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_modify_w_level
225
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
226
  break;
227
  /**/
228
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
229
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_notification_recipients"])) as $recipient)
230
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_modification_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_modification_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
231
  }
232
  /**/
233
  $paypal["s2member_log"][] = "Modification Notification Emails have been processed.";
225
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
226
  break;
227
  /**/
228
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
229
+ /**/
230
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_notification_recipients"]) as $recipient)
231
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_modification_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_modification_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
232
  }
233
  /**/
234
  $paypal["s2member_log"][] = "Modification Notification Emails have been processed.";
includes/classes/paypal-notify-in-subscr-or-rp-cancellation-w-level.inc.php CHANGED
@@ -159,9 +159,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_cancella
159
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
160
  break;
161
  /**/
162
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
163
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_recipients"])) as $recipient)
164
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_cancellation_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_cancellation_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
165
  }
166
  /**/
167
  $paypal["s2member_log"][] = "Cancellation Notification Emails have been processed.";
159
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
160
  break;
161
  /**/
162
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
163
+ /**/
164
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_recipients"]) as $recipient)
165
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_cancellation_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_cancellation_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
166
  }
167
  /**/
168
  $paypal["s2member_log"][] = "Cancellation Notification Emails have been processed.";
includes/classes/paypal-notify-in-subscr-or-rp-eots-w-level.inc.php CHANGED
@@ -204,9 +204,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
204
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
205
  break;
206
  /**/
207
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
208
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
209
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
210
  }
211
  /**/
212
  $paypal["s2member_log"][] = "EOT/Deletion Notification Emails have been processed.";
@@ -403,9 +404,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_eots_w_l
403
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
404
  break;
405
  /**/
406
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
407
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"])) as $recipient)
408
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
409
  }
410
  /**/
411
  $paypal["s2member_log"][] = "Refund/Reversal Notification Emails have been processed.";
204
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
205
  break;
206
  /**/
207
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
208
+ /**/
209
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"]) as $recipient)
210
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
211
  }
212
  /**/
213
  $paypal["s2member_log"][] = "EOT/Deletion Notification Emails have been processed.";
404
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
405
  break;
406
  /**/
407
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
408
+ /**/
409
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"]) as $recipient)
410
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
411
  }
412
  /**/
413
  $paypal["s2member_log"][] = "Refund/Reversal Notification Emails have been processed.";
includes/classes/paypal-notify-in-subscr-or-rp-payment-w-level.inc.php CHANGED
@@ -175,9 +175,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_rp_payment_
175
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
176
  break;
177
  /**/
178
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
179
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
180
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
181
  }
182
  }
183
  /**/
175
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
176
  break;
177
  /**/
178
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
179
+ /**/
180
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"]) as $recipient)
181
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
182
  }
183
  }
184
  /**/
includes/classes/paypal-notify-in-subscr-or-wa-w-level.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 110720
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"))
21
  {
@@ -40,7 +40,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
40
  */
41
  public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
- extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
  if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]))/**/
46
  && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
@@ -48,7 +48,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
48
  && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/
49
  && (!empty ($paypal["payer_email"]))/**/)
50
  {
51
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
52
  do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_signup", get_defined_vars ());
53
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
54
  /**/
@@ -76,7 +76,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
76
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
77
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
78
  /**/
79
- eval('$ipn_signup_vars = $paypal; unset($ipn_signup_vars["s2member_log"]);'); /* Create array of IPN signup vars w/o s2member_log. */
80
  /*
81
  New Subscription with advanced update vars ( option_name1, option_selection1 )? These variables are used in Subscr. Modifications.
82
  */
@@ -84,7 +84,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
84
  /* This advanced method is required whenever a Subscription that is already completed, or was never setup to recur in the first place needs to be modified.
85
  PayPal® will not allow the `modify=1|2` parameter to be used in those scenarios, because technically there is no billing to update; only the account. */
86
  {
87
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
88
  do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_signup_w_update_vars", get_defined_vars ());
89
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
90
  /**/
@@ -97,7 +97,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
97
  {
98
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
99
  /**/
100
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
101
  do_action ("ws_plugin__s2member_during_paypal_notify_during_before_subscr_signup_w_update_vars", get_defined_vars ());
102
  do_action ("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars (), "ipn-upgrade-downgrade", "modification", "s2member_level" . $paypal["level"]);
103
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
@@ -108,7 +108,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
108
  /**/
109
  if (is_multisite () && !is_user_member_of_blog ($user_id)) /* Must have a Role on this Blog. */
110
  {
111
- add_existing_user_to_blog(array ("user_id" => $user_id, "role" => "s2member_level" . $paypal["level"]));
112
  $user = new WP_User ($user_id);
113
  }
114
  /**/
@@ -253,9 +253,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
253
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
254
  break;
255
  /**/
256
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
257
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_notification_recipients"])) as $recipient)
258
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_modification_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_modification_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
259
  }
260
  /**/
261
  $paypal["s2member_log"][] = "Modification Notification Emails have been processed.";
@@ -292,7 +293,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
292
  }
293
  }
294
  /**/
295
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
296
  do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_signup_w_update_vars", get_defined_vars ());
297
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
298
  }
@@ -302,7 +303,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
302
  else
303
  $paypal["s2member_log"][] = "Unable to modify Subscription. Could not get the existing User ID from the DB. Please check the `on0` and `os0` variables in your Button Code.";
304
  /**/
305
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
306
  do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_signup_w_update_vars", get_defined_vars ());
307
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
308
  }
@@ -311,7 +312,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
311
  */
312
  else /* Else this is a normal Subscription signup, we are not updating anything. */
313
  {
314
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
315
  do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_signup_wo_update_vars", get_defined_vars ());
316
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
317
  /**/
@@ -358,12 +359,12 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
358
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
359
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
360
  /**/
361
- if (($recipients = preg_split ("/;+/", preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
362
  {
363
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep ($recipients) as $recipient) /* Go through the full list of recipients. */
364
- ($recipient) ? c_ws_plugin__s2member_email_configs::email_config () . wp_mail ($recipient, apply_filters ("ws_plugin__s2member_signup_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_signup_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") . c_ws_plugin__s2member_email_configs::email_config_release () : null;
365
  /**/
366
- $paypal["s2member_log"][] = "Signup Confirmation Email sent to: " . implode ("; ", $recipients) . ".";
367
  }
368
  /**/
369
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
@@ -424,9 +425,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
424
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
425
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
426
  /**/
427
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
428
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_recipients"])) as $recipient)
429
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_signup_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_signup_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
430
  /**/
431
  $paypal["s2member_log"][] = "Signup Notification Emails have been processed.";
432
  }
@@ -449,14 +451,14 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
449
  }
450
  }
451
  /**/
452
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
453
  do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_signup_wo_update_vars", get_defined_vars ());
454
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
455
  }
456
  else
457
  $paypal["s2member_log"][] = "Unable to generate Registration URL for Membership Access. Possible data corruption within the IPN response.";
458
  /**/
459
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
460
  do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_signup_wo_update_vars", get_defined_vars ());
461
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
462
  }
@@ -606,9 +608,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
606
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
607
  break;
608
  /**/
609
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
610
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
611
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
612
  }
613
  }
614
  /**/
@@ -652,7 +655,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"
652
  $paypal["s2member_log"][] = "Duplicate IPN. Already processed. This IPN will be ignored.";
653
  }
654
  /**/
655
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
656
  do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_signup", get_defined_vars ());
657
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
658
  /**/
15
  * @since 110720
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_subscr_or_wa_w_level"))
21
  {
40
  */
41
  public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
+ extract ($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
  if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]))/**/
46
  && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_w_level_regex"], $paypal["item_number"]))/**/
48
  && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/
49
  && (!empty ($paypal["payer_email"]))/**/)
50
  {
51
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
52
  do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_signup", get_defined_vars ());
53
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
54
  /**/
76
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
77
  $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
78
  /**/
79
+ eval ('$ipn_signup_vars = $paypal; unset($ipn_signup_vars["s2member_log"]);'); /* Create array of IPN signup vars w/o s2member_log. */
80
  /*
81
  New Subscription with advanced update vars ( option_name1, option_selection1 )? These variables are used in Subscr. Modifications.
82
  */
84
  /* This advanced method is required whenever a Subscription that is already completed, or was never setup to recur in the first place needs to be modified.
85
  PayPal® will not allow the `modify=1|2` parameter to be used in those scenarios, because technically there is no billing to update; only the account. */
86
  {
87
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
88
  do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_signup_w_update_vars", get_defined_vars ());
89
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
90
  /**/
97
  {
98
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
99
  /**/
100
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
101
  do_action ("ws_plugin__s2member_during_paypal_notify_during_before_subscr_signup_w_update_vars", get_defined_vars ());
102
  do_action ("ws_plugin__s2member_during_collective_mods", $user_id, get_defined_vars (), "ipn-upgrade-downgrade", "modification", "s2member_level" . $paypal["level"]);
103
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
108
  /**/
109
  if (is_multisite () && !is_user_member_of_blog ($user_id)) /* Must have a Role on this Blog. */
110
  {
111
+ add_existing_user_to_blog (array ("user_id" => $user_id, "role" => "s2member_level" . $paypal["level"]));
112
  $user = new WP_User ($user_id);
113
  }
114
  /**/
253
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
254
  break;
255
  /**/
256
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
257
+ /**/
258
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["modification_notification_recipients"]) as $recipient)
259
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_modification_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_modification_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
260
  }
261
  /**/
262
  $paypal["s2member_log"][] = "Modification Notification Emails have been processed.";
293
  }
294
  }
295
  /**/
296
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
297
  do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_signup_w_update_vars", get_defined_vars ());
298
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
299
  }
303
  else
304
  $paypal["s2member_log"][] = "Unable to modify Subscription. Could not get the existing User ID from the DB. Please check the `on0` and `os0` variables in your Button Code.";
305
  /**/
306
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
307
  do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_signup_w_update_vars", get_defined_vars ());
308
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
309
  }
312
  */
313
  else /* Else this is a normal Subscription signup, we are not updating anything. */
314
  {
315
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
316
  do_action ("ws_plugin__s2member_during_paypal_notify_before_subscr_signup_wo_update_vars", get_defined_vars ());
317
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
318
  /**/
359
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
360
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
361
  /**/
362
+ if (($rec = trim (preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
363
  {
364
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($rec) as $recipient) /* Go through a possible list of recipients. */
365
+ c_ws_plugin__s2member_email_configs::email_config () . wp_mail ($recipient, apply_filters ("ws_plugin__s2member_signup_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_signup_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") . c_ws_plugin__s2member_email_configs::email_config_release ();
366
  /**/
367
+ $paypal["s2member_log"][] = "Signup Confirmation Email sent to: " . $rec . ".";
368
  }
369
  /**/
370
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
425
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
426
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
427
  /**/
428
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
429
+ /**/
430
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_recipients"]) as $recipient)
431
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_signup_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_signup_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
432
  /**/
433
  $paypal["s2member_log"][] = "Signup Notification Emails have been processed.";
434
  }
451
  }
452
  }
453
  /**/
454
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
455
  do_action ("ws_plugin__s2member_during_paypal_notify_during_subscr_signup_wo_update_vars", get_defined_vars ());
456
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
457
  }
458
  else
459
  $paypal["s2member_log"][] = "Unable to generate Registration URL for Membership Access. Possible data corruption within the IPN response.";
460
  /**/
461
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
462
  do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_signup_wo_update_vars", get_defined_vars ());
463
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
464
  }
608
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
609
  break;
610
  /**/
611
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
612
+ /**/
613
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"]) as $recipient)
614
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
615
  }
616
  }
617
  /**/
655
  $paypal["s2member_log"][] = "Duplicate IPN. Already processed. This IPN will be ignored.";
656
  }
657
  /**/
658
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
659
  do_action ("ws_plugin__s2member_during_paypal_notify_after_subscr_signup", get_defined_vars ());
660
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
661
  /**/
includes/classes/paypal-notify-in-wa-ccaps-wo-level.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 110815
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
21
  {
@@ -40,14 +40,14 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
40
  */
41
  public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
- extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
  if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^web_accept$/i", $paypal["txn_type"]))/**/
46
  && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_wo_level_regex"], $paypal["item_number"]))/**/
47
  && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/
48
  && (!empty ($paypal["txn_id"]) && ($paypal["subscr_id"] = $paypal["txn_id"])) && (!empty ($paypal["payer_email"]))/**/)
49
  {
50
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
  do_action ("ws_plugin__s2member_during_paypal_notify_before_new_ccaps", get_defined_vars ());
52
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
@@ -68,7 +68,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
68
  {
69
  $processing = $during = true; /* Yes, we ARE processing this. */
70
  /**/
71
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
72
  do_action ("ws_plugin__s2member_during_paypal_notify_during_before_new_ccaps", get_defined_vars ());
73
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
74
  /**/
@@ -78,7 +78,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
78
  /**/
79
  if (is_multisite () && !is_user_member_of_blog ($user_id)) /* Must have a Role on this Blog. */
80
  {
81
- add_existing_user_to_blog(array ("user_id" => $user_id, "role" => get_option ("default_role")));
82
  $user = new WP_User ($user_id);
83
  }
84
  /**/
@@ -219,9 +219,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
219
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
220
  break;
221
  /**/
222
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
223
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
224
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
225
  }
226
  }
227
  /**/
@@ -258,7 +259,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
258
  }
259
  }
260
  /**/
261
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
262
  do_action ("ws_plugin__s2member_during_paypal_notify_during_new_ccaps", get_defined_vars ());
263
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
264
  }
@@ -278,7 +279,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
278
  $paypal["s2member_log"][] = "Duplicate IPN. Already processed. This IPN will be ignored.";
279
  }
280
  /**/
281
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
282
  do_action ("ws_plugin__s2member_during_paypal_notify_after_new_ccaps", get_defined_vars ());
283
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
284
  /**/
15
  * @since 110815
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_wa_ccaps_wo_level"))
21
  {
40
  */
41
  public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
+ extract ($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
  if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^web_accept$/i", $paypal["txn_type"]))/**/
46
  && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["membership_item_number_wo_level_regex"], $paypal["item_number"]))/**/
47
  && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/
48
  && (!empty ($paypal["txn_id"]) && ($paypal["subscr_id"] = $paypal["txn_id"])) && (!empty ($paypal["payer_email"]))/**/)
49
  {
50
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
  do_action ("ws_plugin__s2member_during_paypal_notify_before_new_ccaps", get_defined_vars ());
52
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
68
  {
69
  $processing = $during = true; /* Yes, we ARE processing this. */
70
  /**/
71
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
72
  do_action ("ws_plugin__s2member_during_paypal_notify_during_before_new_ccaps", get_defined_vars ());
73
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
74
  /**/
78
  /**/
79
  if (is_multisite () && !is_user_member_of_blog ($user_id)) /* Must have a Role on this Blog. */
80
  {
81
+ add_existing_user_to_blog (array ("user_id" => $user_id, "role" => get_option ("default_role")));
82
  $user = new WP_User ($user_id);
83
  }
84
  /**/
219
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
220
  break;
221
  /**/
222
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
223
+ /**/
224
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"]) as $recipient)
225
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
226
  }
227
  }
228
  /**/
259
  }
260
  }
261
  /**/
262
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
263
  do_action ("ws_plugin__s2member_during_paypal_notify_during_new_ccaps", get_defined_vars ());
264
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
265
  }
279
  $paypal["s2member_log"][] = "Duplicate IPN. Already processed. This IPN will be ignored.";
280
  }
281
  /**/
282
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
283
  do_action ("ws_plugin__s2member_during_paypal_notify_after_new_ccaps", get_defined_vars ());
284
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
285
  /**/
includes/classes/paypal-notify-in-web-accept-sp.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 110720
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
21
  {
@@ -40,14 +40,14 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
40
  */
41
  public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
- extract($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
  if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^web_accept$/i", $paypal["txn_type"]))/**/
46
  && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["sp_access_item_number_regex"], $paypal["item_number"]))/**/
47
  && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/
48
  && (!empty ($paypal["payer_email"])) && (!empty ($paypal["txn_id"]))/**/)
49
  {
50
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
  do_action ("ws_plugin__s2member_during_paypal_notify_before_sp_access", get_defined_vars ());
52
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
@@ -108,12 +108,12 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
108
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
109
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
110
  /**/
111
- if (($recipients = preg_split ("/;+/", preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
112
  {
113
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep ($recipients) as $recipient) /* Go through the full list of recipients. */
114
- ($recipient) ? c_ws_plugin__s2member_email_configs::email_config () . wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") . c_ws_plugin__s2member_email_configs::email_config_release () : null;
115
  /**/
116
- $paypal["s2member_log"][] = "Specific Post/Page Confirmation Email sent to: " . implode ("; ", $recipients) . ".";
117
  }
118
  /**/
119
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
@@ -172,9 +172,10 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
172
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
173
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
174
  /**/
175
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
176
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_recipients"])) as $recipient)
177
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_sale_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_sale_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
178
  /**/
179
  $paypal["s2member_log"][] = "Specific Post/Page ~ Sale Notification Emails have been processed.";
180
  }
@@ -213,7 +214,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
213
  }
214
  }
215
  /**/
216
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
217
  do_action ("ws_plugin__s2member_during_paypal_notify_during_sp_access", get_defined_vars ());
218
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
219
  }
@@ -227,7 +228,7 @@ if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
227
  $paypal["s2member_log"][] = "Duplicate IPN. Already processed. This IPN will be ignored.";
228
  }
229
  /**/
230
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
231
  do_action ("ws_plugin__s2member_during_paypal_notify_after_sp_access", get_defined_vars ());
232
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
233
  /**/
15
  * @since 110720
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_paypal_notify_in_web_accept_sp"))
21
  {
40
  */
41
  public static function cp ($vars = array ()) /* Conditional phase for ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
42
  {
43
+ extract ($vars); /* Extract all vars passed in from: ``c_ws_plugin__s2member_paypal_notify_in::paypal_notify()``. */
44
  /**/
45
  if (/**/(!empty ($paypal["txn_type"]) && preg_match ("/^web_accept$/i", $paypal["txn_type"]))/**/
46
  && (!empty ($paypal["item_number"]) && preg_match ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["sp_access_item_number_regex"], $paypal["item_number"]))/**/
47
  && (empty ($paypal["payment_status"]) || empty ($payment_status_issues) || !preg_match ($payment_status_issues, $paypal["payment_status"]))/**/
48
  && (!empty ($paypal["payer_email"])) && (!empty ($paypal["txn_id"]))/**/)
49
  {
50
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
  do_action ("ws_plugin__s2member_during_paypal_notify_before_sp_access", get_defined_vars ());
52
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
108
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
109
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
110
  /**/
111
+ if (($rec = trim (preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
112
  {
113
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($rec) as $recipient) /* Go through a possible list of recipients. */
114
+ c_ws_plugin__s2member_email_configs::email_config () . wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") . c_ws_plugin__s2member_email_configs::email_config_release ();
115
  /**/
116
+ $paypal["s2member_log"][] = "Specific Post/Page Confirmation Email sent to: " . $rec . ".";
117
  }
118
  /**/
119
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
172
  if (($msg = preg_replace ("/%%payer_email%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["payer_email"]), $msg)))
173
  if (($msg = preg_replace ("/%%user_ip%%/i", c_ws_plugin__s2member_utils_strings::esc_ds ($paypal["ip"]), $msg)))
174
  /**/
175
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
176
+ /**/
177
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_recipients"]) as $recipient)
178
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_sale_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_sale_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
179
  /**/
180
  $paypal["s2member_log"][] = "Specific Post/Page ~ Sale Notification Emails have been processed.";
181
  }
214
  }
215
  }
216
  /**/
217
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
218
  do_action ("ws_plugin__s2member_during_paypal_notify_during_sp_access", get_defined_vars ());
219
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
220
  }
228
  $paypal["s2member_log"][] = "Duplicate IPN. Already processed. This IPN will be ignored.";
229
  }
230
  /**/
231
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
232
  do_action ("ws_plugin__s2member_during_paypal_notify_after_sp_access", get_defined_vars ());
233
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
234
  /**/
includes/classes/registrations.inc.php CHANGED
@@ -975,9 +975,10 @@ if (!class_exists ("c_ws_plugin__s2member_registrations"))
975
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
976
  break;
977
  /**/
978
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
979
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_recipients"])) as $recipient)
980
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_registration_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_registration_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
981
  }
982
  /**/
983
  if ($email_configs_were_on) /* Back on? */
975
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
976
  break;
977
  /**/
978
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
979
+ /**/
980
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_recipients"]) as $recipient)
981
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_registration_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_registration_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
982
  }
983
  /**/
984
  if ($email_configs_were_on) /* Back on? */
includes/classes/ruris-sp.inc.php CHANGED
@@ -15,7 +15,7 @@
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_ruris_sp"))
21
  {
@@ -33,16 +33,15 @@ if (!class_exists ("c_ws_plugin__s2member_ruris_sp"))
33
  * @package s2Member\URIs
34
  * @since 3.5
35
  *
36
- * @param str $_uri A URI, or a full URL is also fine.
37
  * @param bool $check_user Test permissions against the current User? Defaults to true.
38
  * @return null|array Non-empty array ( with details ) if access is denied, else null if access is allowed.
39
  */
40
- public static function check_specific_ruri_level_access ($_uri = FALSE, $check_user = TRUE)
41
  {
42
  do_action ("ws_plugin__s2member_before_check_specific_ruri_level_access", get_defined_vars ());
43
  /**/
44
- if ($_uri && is_string ($_uri)) /* Could be a full URL too. */
45
- $uri = c_ws_plugin__s2member_utils_urls::parse_uri ($_uri);
46
  /**/
47
  $excluded = apply_filters ("ws_plugin__s2member_check_specific_ruri_level_access_excluded", false, get_defined_vars ());
48
  /**/
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_ruris_sp"))
21
  {
33
  * @package s2Member\URIs
34
  * @since 3.5
35
  *
36
+ * @param str $uri A URI, or a full URL is also fine.
37
  * @param bool $check_user Test permissions against the current User? Defaults to true.
38
  * @return null|array Non-empty array ( with details ) if access is denied, else null if access is allowed.
39
  */
40
+ public static function check_specific_ruri_level_access ($uri = FALSE, $check_user = TRUE)
41
  {
42
  do_action ("ws_plugin__s2member_before_check_specific_ruri_level_access", get_defined_vars ());
43
  /**/
44
+ $uri = ($uri && is_string ($uri) && ($uri = c_ws_plugin__s2member_utils_urls::parse_uri ($uri))) ? $uri : false;
 
45
  /**/
46
  $excluded = apply_filters ("ws_plugin__s2member_check_specific_ruri_level_access_excluded", false, get_defined_vars ());
47
  /**/
includes/classes/systematics-sp.inc.php CHANGED
@@ -65,7 +65,7 @@ if (!class_exists ("c_ws_plugin__s2member_systematics_sp"))
65
  {
66
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
67
  }
68
- else if ($uri && ($query = parse_url ($uri, PHP_URL_QUERY)) && strpos ($query, "s2member") === 0 && c_ws_plugin__s2member_utils_conds::is_site_root ($uri))
69
  {
70
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
71
  }
@@ -93,7 +93,7 @@ if (!class_exists ("c_ws_plugin__s2member_systematics_sp"))
93
  {
94
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_specific_page", true, get_defined_vars ()));
95
  }
96
- else if ($uri && preg_match ("/^\/(?:wp-.+?|xmlrpc)\.php$/", parse_url ($uri, PHP_URL_PATH))) /* A core WordPress® file? */
97
  {
98
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_specific_page", true, get_defined_vars ()));
99
  }
65
  {
66
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
67
  }
68
+ else if ($uri && ($query = c_ws_plugin__s2member_utils_urls::parse_url ($uri, PHP_URL_QUERY)) && strpos ($query, "s2member") === 0 && c_ws_plugin__s2member_utils_conds::is_site_root ($uri))
69
  {
70
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
71
  }
93
  {
94
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_specific_page", true, get_defined_vars ()));
95
  }
96
+ else if ($uri && preg_match ("/^\/(?:wp-.+?|xmlrpc)\.php$/", c_ws_plugin__s2member_utils_urls::parse_url ($uri, PHP_URL_PATH)))
97
  {
98
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_specific_page", true, get_defined_vars ()));
99
  }
includes/classes/systematics.inc.php CHANGED
@@ -15,7 +15,7 @@
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_systematics"))
21
  {
@@ -102,11 +102,15 @@ if (!class_exists ("c_ws_plugin__s2member_systematics"))
102
  {
103
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
104
  }
105
- else if ((defined ("DOING_CRON") && DOING_CRON) || strcasecmp (PHP_SAPI, "CLI") === 0) /* CLI, or WordPress® CRON job. */
106
  {
107
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
108
  }
109
- else if (preg_match ("/^\/(?:wp-.+?|xmlrpc)\.php$/", parse_url ($_SERVER["REQUEST_URI"], PHP_URL_PATH)) || (c_ws_plugin__s2member_utils_conds::bp_is_installed () && (bp_is_register_page () || bp_is_activation_page ())))
 
 
 
 
110
  {
111
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
112
  }
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_systematics"))
21
  {
102
  {
103
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
104
  }
105
+ else if ((defined ("DOING_CRON") && DOING_CRON) || strcasecmp (PHP_SAPI, "CLI") === 0) /* CLI ( command line ) or CRON job. */
106
  {
107
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
108
  }
109
+ else if (preg_match ("/^\/(?:wp-.+?|xmlrpc)\.php$/", c_ws_plugin__s2member_utils_urls::parse_url ($_SERVER["REQUEST_URI"], PHP_URL_PATH)))
110
+ {
111
+ return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
112
+ }
113
+ else if (c_ws_plugin__s2member_utils_conds::bp_is_installed () && (bp_is_register_page () || bp_is_activation_page ()))
114
  {
115
  return ($is_wp_systematic = apply_filters ("ws_plugin__s2member_is_wp_systematic_use_page", true, get_defined_vars ()));
116
  }
includes/classes/translations.inc.php CHANGED
@@ -15,7 +15,7 @@
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_translations"))
21
  {
@@ -39,7 +39,8 @@ if (!class_exists ("c_ws_plugin__s2member_translations"))
39
  */
40
  public static function load ()
41
  {
42
- load_plugin_textdomain ("s2member", false, c_ws_plugin__s2member_utils_dirs::rel_path (WP_PLUGIN_DIR, dirname (dirname (__FILE__)) . "/translations/"));
 
43
  /**/
44
  do_action ("ws_plugin__s2member_during_translations_load", get_defined_vars ());
45
  /**/
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_translations"))
21
  {
39
  */
40
  public static function load ()
41
  {
42
+ load_plugin_textdomain ("s2member", false, c_ws_plugin__s2member_utils_dirs::rel_path (WP_PLUGIN_DIR, dirname (dirname (__FILE__)) . "/translations"));
43
+ load_plugin_textdomain ("s2member"); /* Allows `.mo` file to be loaded from the `/wp-content/plugins/s2member-[locale].mo`. */
44
  /**/
45
  do_action ("ws_plugin__s2member_during_translations_load", get_defined_vars ());
46
  /**/
includes/classes/user-deletions.inc.php CHANGED
@@ -199,9 +199,10 @@ if (!class_exists ("c_ws_plugin__s2member_user_deletions"))
199
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
200
  break;
201
  /**/
202
- if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
203
- foreach (c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
204
- ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
205
  }
206
  /**/
207
  if ($email_configs_were_on) /* Back on? */
199
  if (!($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", c_ws_plugin__s2member_utils_strings::esc_ds (maybe_serialize ($val)), $msg)))
200
  break;
201
  /**/
202
+ if ($sbj && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg)))) /* Still have a ``$sbj`` and a ``$msg``? */
203
+ /**/
204
+ foreach (c_ws_plugin__s2member_utils_strings::parse_emails ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"]) as $recipient)
205
+ wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "Content-Type: text/plain; charset=utf-8");
206
  }
207
  /**/
208
  if ($email_configs_were_on) /* Back on? */
includes/classes/utils-conds.inc.php CHANGED
@@ -37,7 +37,8 @@ if (!class_exists ("c_ws_plugin__s2member_utils_conds"))
37
  */
38
  public static function pro_is_installed ()
39
  {
40
- return defined ("WS_PLUGIN__S2MEMBER_PRO_VERSION");
 
41
  }
42
  /**
43
  * Determines whether or not BuddyPress is installed.
@@ -50,13 +51,14 @@ if (!class_exists ("c_ws_plugin__s2member_utils_conds"))
50
  */
51
  public static function bp_is_installed ($query_active_plugins = NULL)
52
  {
53
- if (defined ("BP_VERSION")) /* Installed and active? */
54
- return true; /* This is the quickest/easiest way to determine. */
55
  /**/
56
  $s2o = (defined ("WS_PLUGIN__S2MEMBER_ONLY") && WS_PLUGIN__S2MEMBER_ONLY) ? true : false;
 
57
  if (($query_active_plugins = (!isset ($query_active_plugins) && $s2o) ? true : $query_active_plugins))
58
  {
59
- $buddypress = "buddypress/bp-loader.php"; /* BuddyPress loader. */
60
  /**/
61
  $active_plugins = (is_multisite ()) ? wp_get_active_network_plugins () : array ();
62
  $active_plugins = array_unique (array_merge ($active_plugins, wp_get_active_and_valid_plugins ()));
@@ -116,13 +118,12 @@ if (!class_exists ("c_ws_plugin__s2member_utils_conds"))
116
  */
117
  public static function is_site_root ($url_or_uri = FALSE)
118
  {
119
- if (($parse = @parse_url ($url_or_uri))) /* See: http://php.net/manual/en/function.parse-url.php. */
120
  {
121
  $parse["path"] = (!empty ($parse["path"])) ? ((strpos ($parse["path"], "/") === 0) ? $parse["path"] : "/" . $parse["path"]) : "/";
122
- $parse["path"] = preg_replace ("/\/+/", "/", $parse["path"]); /* Removes multi slashes. */
123
  /**/
124
- if (empty ($parse["host"]) || strcasecmp ($parse["host"], parse_url (site_url (), PHP_URL_HOST)) === 0)
125
- if ($parse["path"] === "/" || rtrim ($parse["path"], "/") === rtrim (parse_url (site_url (), PHP_URL_PATH), "/"))
126
  return true;
127
  }
128
  /**/
37
  */
38
  public static function pro_is_installed ()
39
  {
40
+ return (defined ("WS_PLUGIN__S2MEMBER_PRO_VERSION")
41
+ /* And loaded? */ && did_action ("ws_plugin__s2member_pro_after_loaded"));
42
  }
43
  /**
44
  * Determines whether or not BuddyPress is installed.
51
  */
52
  public static function bp_is_installed ($query_active_plugins = NULL)
53
  {
54
+ if (defined ("BP_VERSION") && did_action ("bp_core_loaded"))
55
+ return true; /* Quickest/easiest way to determine. */
56
  /**/
57
  $s2o = (defined ("WS_PLUGIN__S2MEMBER_ONLY") && WS_PLUGIN__S2MEMBER_ONLY) ? true : false;
58
+ /**/
59
  if (($query_active_plugins = (!isset ($query_active_plugins) && $s2o) ? true : $query_active_plugins))
60
  {
61
+ $buddypress = "buddypress/bp-loader.php"; /* BuddyPress. */
62
  /**/
63
  $active_plugins = (is_multisite ()) ? wp_get_active_network_plugins () : array ();
64
  $active_plugins = array_unique (array_merge ($active_plugins, wp_get_active_and_valid_plugins ()));
118
  */
119
  public static function is_site_root ($url_or_uri = FALSE)
120
  {
121
+ if (is_array ($parse = c_ws_plugin__s2member_utils_urls::parse_url ($url_or_uri)))
122
  {
123
  $parse["path"] = (!empty ($parse["path"])) ? ((strpos ($parse["path"], "/") === 0) ? $parse["path"] : "/" . $parse["path"]) : "/";
 
124
  /**/
125
+ if (empty ($parse["host"]) || strcasecmp ($parse["host"], c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_HOST)) === 0)
126
+ if ($parse["path"] === "/" || rtrim ($parse["path"], "/") === rtrim (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_PATH), "/"))
127
  return true;
128
  }
129
  /**/
includes/classes/utils-dirs.inc.php CHANGED
@@ -28,38 +28,60 @@ if (!class_exists ("c_ws_plugin__s2member_utils_dirs"))
28
  class c_ws_plugin__s2member_utils_dirs
29
  {
30
  /**
31
- * Formulates basename dirs from a full directory path.
32
  *
33
- * This takes Windows® `\app_data\` sub-folders into consideration.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  *
35
  * @package s2Member\Utilities
36
  * @since 110815
37
  *
38
- * @param str $dir_path Directory path.
39
- * @return str Basename directory path; including a possible `\app_data\` directory.
40
  */
41
- public static function basename_dir_app_data ($dir_path = FALSE)
42
  {
43
- $dir_path = rtrim ($dir_path, DIRECTORY_SEPARATOR . "/");
44
- /**/
45
- $dir_path = preg_replace ("/(" . preg_quote (DIRECTORY_SEPARATOR, "/") . "|\/)app_data$/i", "", $dir_path, 1, $app_data);
46
  /**/
47
- return basename ($dir_path) . (($app_data) ? "/app_data" : "");
48
  }
49
  /**
50
- * Strips a trailing `\app_data\` sub-directory from the full path.
51
  *
52
  * @package s2Member\Utilities
53
- * @since 3.5
54
  *
55
- * @param str $dir_path Directory path.
56
- * @return str Directory path without `\app_data\`.
57
  */
58
- public static function strip_dir_app_data ($dir_path = FALSE)
59
  {
60
- $dir_path = rtrim ($dir_path, DIRECTORY_SEPARATOR . "/");
61
  /**/
62
- return preg_replace ("/(" . preg_quote (DIRECTORY_SEPARATOR, "/") . "|\/)app_data$/i", "", $dir_path, 1);
63
  }
64
  /**
65
  * Finds the relative path, from one location to another.
@@ -67,51 +89,118 @@ if (!class_exists ("c_ws_plugin__s2member_utils_dirs"))
67
  * @package s2Member\Utilities
68
  * @since 110815
69
  *
70
- * @param str $from The directory to calculate a relative path from.
71
- * @param str $to The directory or file to build a relative path to.
72
- * @return str String with the relative path to ``$to``.
 
 
73
  */
74
- public static function rel_path ($from = FALSE, $to = FALSE)
75
  {
76
- if (!($rel_path = array ()) && is_string ($from) && strlen ($from) && is_string ($to) && strlen ($to))
77
  {
78
- $to = str_replace (DIRECTORY_SEPARATOR, "/", $to);
79
- $to = (strpos (basename ($to), ".") === false) ? rtrim ($to, "/") . "/" : $to;
80
- $to = $rel_path = preg_split ("/\//", $to);
 
 
 
 
81
  /**/
82
- $from = str_replace (DIRECTORY_SEPARATOR, "/", $from);
83
- $from = (strpos (basename ($from), ".") !== false) ? dirname ($from) : $from;
84
- $from = preg_split ("/\//", rtrim ($from, "/") . "/");
85
  /**/
86
- foreach ($from as $depth => $dir) /* Each ``$from`` directory. */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  {
88
- if (isset ($to[$depth]) && $dir === $to[$depth])
89
  array_shift($rel_path);
90
  /**/
91
- else if (($remaining = count ($from) - $depth) > 1)
92
  {
93
- $rel_path = array_pad ($rel_path, ((count ($rel_path) + $remaining - 1) * -1), "..");
 
94
  break; /* Stop now, no need to go any further. */
95
  }
96
- else
97
- $rel_path[0] = "./" . $rel_path[0];
 
 
 
98
  }
99
  }
100
  /**/
101
  return implode ("/", $rel_path);
102
  }
103
  /**
104
- * Shortens to a path from document root.
105
  *
106
  * @package s2Member\Utilities
107
- * @since 110815
108
  *
109
- * @param str $path Directory or file path.
110
- * @return str Shorther path, from document root.
 
111
  */
112
- public static function doc_root_path ($path = FALSE)
113
  {
114
- return preg_replace ("/^" . preg_quote (rtrim ($_SERVER["DOCUMENT_ROOT"], DIRECTORY_SEPARATOR . "/"), "/") . "/", "", (string)$path);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  }
116
  }
117
  }
28
  class c_ws_plugin__s2member_utils_dirs
29
  {
30
  /**
31
+ * Normalizes directory separators.
32
  *
33
+ * @package s2Member\Utilities
34
+ * @since 111017
35
+ *
36
+ * @param str $path Directory or file path.
37
+ * @return str Directory or file path, after having been normalized by this routine.
38
+ */
39
+ public static function n_dir_seps ($path = FALSE)
40
+ {
41
+ return rtrim (preg_replace ("/\/+/", "/", str_replace (array (DIRECTORY_SEPARATOR, "\\", "/"), "/", (string)$path)), "/");
42
+ }
43
+ /**
44
+ * Strips a trailing `/app_data/` sub-directory.
45
+ *
46
+ * @package s2Member\Utilities
47
+ * @since 3.5
48
+ *
49
+ * @param str $path Directory or file path.
50
+ * @return str Directory or file path without `/app_data/`.
51
+ */
52
+ public static function strip_dir_app_data ($path = FALSE)
53
+ {
54
+ return preg_replace ("/\/app_data$/", "", c_ws_plugin__s2member_utils_dirs::n_dir_seps ((string)$path));
55
+ }
56
+ /**
57
+ * Basename from a full directory or file path.
58
  *
59
  * @package s2Member\Utilities
60
  * @since 110815
61
  *
62
+ * @param str $path Directory or file path.
63
+ * @return str Basename; including a possible `/app_data/` directory.
64
  */
65
+ public static function basename_dir_app_data ($path = FALSE)
66
  {
67
+ $path = preg_replace ("/\/app_data$/", "", c_ws_plugin__s2member_utils_dirs::n_dir_seps ((string)$path), 1, $app_data);
 
 
68
  /**/
69
+ return basename ($path) . (($app_data) ? "/app_data" : "");
70
  }
71
  /**
72
+ * Shortens to a directory or file path, from document root.
73
  *
74
  * @package s2Member\Utilities
75
+ * @since 110815
76
  *
77
+ * @param str $path Directory or file path.
78
+ * @return str Shorther path, from document root.
79
  */
80
+ public static function doc_root_path ($path = FALSE)
81
  {
82
+ $doc_root = c_ws_plugin__s2member_utils_dirs::n_dir_seps ($_SERVER["DOCUMENT_ROOT"]);
83
  /**/
84
+ return preg_replace ("/^" . preg_quote ($doc_root, "/") . "/", "", c_ws_plugin__s2member_utils_dirs::n_dir_seps ((string)$path));
85
  }
86
  /**
87
  * Finds the relative path, from one location to another.
89
  * @package s2Member\Utilities
90
  * @since 110815
91
  *
92
+ * @param str $from The full directory path to calculate a relative path `from`.
93
+ * @param str $to The full directory or file path, which this routine will build a relative path `to`.
94
+ * @param bool $try_realpaths Defaults to true. When true, try to acquire ``realpath()``, thereby resolving all relative paths and/or symlinks in ``$from`` and ``$to`` args.
95
+ * @param bool $use_win_diff_drive_jctn Defaults to true. When true, we'll work around issues with different drives on Windows® by trying to create a directory junction.
96
+ * @return str String with the relative path to: ``$to``.
97
  */
98
+ public static function rel_path ($from = FALSE, $to = FALSE, $try_realpaths = TRUE, $use_win_diff_drive_jctn = TRUE)
99
  {
100
+ if ( /* Initialize/validate. */!($rel_path = array ()) && is_string ($from) && strlen ($from) && is_string ($to) && strlen ($to))
101
  {
102
+ $from = ($try_realpaths && ($_real_from = realpath ($from))) ? $_real_from : $from; /* Try this? */
103
+ $to = ($try_realpaths && ($_real_to = realpath ($to))) ? $_real_to : $to; /* Try to find realpath? */
104
+ /**/
105
+ $from = (is_file ($from)) ? dirname ($from) . "/" : $from . "/"; /* A (directory) with trailing `/`. */
106
+ /**/
107
+ $from = c_ws_plugin__s2member_utils_dirs::n_dir_seps ($from); /* Normalize directory separators now. */
108
+ $to = c_ws_plugin__s2member_utils_dirs::n_dir_seps ($to); /* Normalize directory separators here too. */
109
  /**/
110
+ $from = preg_split ("/\//", $from); /* Convert ``$from``, to an array. Split on each directory separator. */
111
+ $to = preg_split ("/\//", $to); /* Also convert ``$to``, to an array. Split this on each directory separator. */
 
112
  /**/
113
+ if ($use_win_diff_drive_jctn && stripos (PHP_OS, "win") === 0 /* Test for different drives on Windows® servers? */)
114
+ /**/
115
+ if (/*Drive? */preg_match ("/^([A-Z])\:$/i", $from[0], $_m) && ($_from_drive = $_m[1]) && preg_match ("/^([A-Z])\:$/i", $to[0], $_m) && ($_to_drive = $_m[1]))
116
+ if ( /* Are these locations on completely different drives? */$_from_drive !== $_to_drive)
117
+ {
118
+ $_from_drive_jctn = $_from_drive . ":/s2-" . $_to_drive . "-jctn";
119
+ $_sys_temp_dir_jctn = c_ws_plugin__s2member_utils_dirs::get_temp_dir (false) . "/s2-" . $_to_drive . "-jctn";
120
+ /**/
121
+ $_jctn = ($_sys_temp_dir_jctn && strpos ($_sys_temp_dir_jctn, $_from_drive) === 0) ? $_sys_temp_dir_jctn : $_from_drive_jctn;
122
+ /**/
123
+ if (($_from_drive_jctn_exists = (is_dir ($_from_drive_jctn)) ? true : false) || c_ws_plugin__s2member_utils_dirs::create_win_jctn ($_jctn, $_to_drive . ":/"))
124
+ {
125
+ array_shift /* Shift drive off and use junction now. */($to);
126
+ foreach (array_reverse (preg_split ("/\//", (($_from_drive_jctn_exists) ? $_from_drive_jctn : $_jctn))) as $_jctn_dir)
127
+ array_unshift ($to, $_jctn_dir);
128
+ }
129
+ else /* Else, we should trigger an error in this case. It's NOT possible to generate this. */
130
+ {
131
+ trigger_error ("Unable to generate a relative path across different Windows® drives." .
132
+ " Please create a Directory Junction here: " . $_from_drive_jctn . ", pointing to: " . $_to_drive . ":/", E_USER_ERROR);
133
+ }
134
+ }
135
+ /**/
136
+ unset ($_real_from, $_real_to, $_from_drive, $_to_drive, $_from_drive_jctn, $_sys_temp_dir_jctn, $_jctn, $_from_drive_jctn_exists, $_jctn_dir, $_m);
137
+ /**/
138
+ $rel_path = $to; /* Re-initialize. Start ``$rel_path`` as the value of the ``$to`` array. */
139
+ /**/
140
+ foreach (array_keys ($from) as $_depth) /* Each ``$from`` directory ``$_depth``. */
141
  {
142
+ if (isset ($from[$_depth], $to[$_depth]) && $from[$_depth] === $to[$_depth])
143
  array_shift($rel_path);
144
  /**/
145
+ else if (($_remaining = count ($from) - $_depth) > 1)
146
  {
147
+ $_left_p = -1 * (count ($rel_path) + ($_remaining - 1));
148
+ $rel_path = array_pad ($rel_path, $_left_p, "..");
149
  break; /* Stop now, no need to go any further. */
150
  }
151
+ else /* Else, set as the same directory `./[0]`. */
152
+ {
153
+ $rel_path[0] = "./" . $rel_path[0];
154
+ break; /* Stop now. */
155
+ }
156
  }
157
  }
158
  /**/
159
  return implode ("/", $rel_path);
160
  }
161
  /**
162
+ * Creates a directory Junction in Windows®.
163
  *
164
  * @package s2Member\Utilities
165
+ * @since 111013
166
  *
167
+ * @param str $jctn Directory location of the Junction ( i.e. the link ).
168
+ * @param str $target Target directory that this Junction will connect to.
169
+ * @return bool True if created successfully, or already exists, else false.
170
  */
171
+ public static function create_win_jctn ($jctn = FALSE, $target = FALSE)
172
  {
173
+ if ($jctn && is_string ($jctn) && $target && is_string ($target) && stripos (PHP_OS, "win") === 0)
174
+ {
175
+ if (is_dir ($jctn)) /* Does it already exist? If so return now. */
176
+ return true; /* Return now to save extra processing time below. */
177
+ /**/
178
+ else if ( /* Possible? */function_exists ("shell_exec") && ($esa = "escapeshellarg"))
179
+ {
180
+ @shell_exec("mklink /J " . $esa ($jctn) . " " . $esa ($target));
181
+ /**/
182
+ clearstatcache (); /* Clear ``stat()`` cache now. */
183
+ if (is_dir ($jctn)) /* Created successfully? */
184
+ return true;
185
+ }
186
+ }
187
+ return false; /* Else return false. */
188
+ }
189
+ /**
190
+ * Get the system's temporary directory.
191
+ *
192
+ * @package s2Member\Utilities
193
+ * @since 111017
194
+ *
195
+ * @param str $fallback Defaults to true. If true, fallback on WordPress® routine if not available, or if not writable.
196
+ * @return str|bool Full string path to a writable temp directory, else false on failure.
197
+ */
198
+ public static function get_temp_dir ($fallback = TRUE)
199
+ {
200
+ $temp_dir = (($temp_dir = realpath (sys_get_temp_dir ())) && is_writable ($temp_dir)) ? $temp_dir : false;
201
+ $temp_dir = (!$temp_dir && $fallback && ($wp_temp_dir = realpath (get_temp_dir ())) && is_writable ($wp_temp_dir)) ? $wp_temp_dir : $temp_dir;
202
+ /**/
203
+ return ($temp_dir) ? c_ws_plugin__s2member_utils_dirs::n_dir_seps ($temp_dir) : false;
204
  }
205
  }
206
  }
includes/classes/utils-s2o.inc.php CHANGED
@@ -64,8 +64,8 @@ if (!class_exists ("c_ws_plugin__s2member_utils_s2o"))
64
  {
65
  if ($wp_dir && is_dir ($wp_dir) && is_readable (($wp_settings = $wp_dir . "/wp-settings.php")) && $o_file && file_exists ($o_file) && ($_wp_settings = trim (file_get_contents ($wp_settings))))
66
  {
67
- $wp_shortinit_section = "/if *\( *SHORTINIT *\)[\r\n\t\s ]*\{?[\r\n\t\s ]*return false;[\r\n\t\s ]*\}?[\r\n\t\s ]*/";
68
- if (($_wp_settings_parts = preg_split ($wp_shortinit_section, $_wp_settings, 2)) && ($_wp_settings = trim ($_wp_settings_parts[1])) && ($_wp_settings = "<?php\n" . $_wp_settings))
69
  {
70
  if (($_wp_settings = str_replace ("__FILE__", "'" . str_replace ("'", "\'", $wp_settings) . "'", $_wp_settings))) /* Eval compatible. Hard-code the ``__FILE__`` location here. */
71
  {
64
  {
65
  if ($wp_dir && is_dir ($wp_dir) && is_readable (($wp_settings = $wp_dir . "/wp-settings.php")) && $o_file && file_exists ($o_file) && ($_wp_settings = trim (file_get_contents ($wp_settings))))
66
  {
67
+ $wp_shortinit_section /* Run ``preg_match()`` to confirm existence. */ = "/if *\( *SHORTINIT *\)[\r\n\t\s ]*\{?[\r\n\t\s ]*return false;[\r\n\t\s ]*\}?[\r\n\t\s ]*/";
68
+ if (preg_match ($wp_shortinit_section, $_wp_settings) && ($_wp_settings_parts = preg_split ($wp_shortinit_section, $_wp_settings, 2)) && ($_wp_settings = trim ($_wp_settings_parts[1])) && ($_wp_settings = "<?php\n" . $_wp_settings))
69
  {
70
  if (($_wp_settings = str_replace ("__FILE__", "'" . str_replace ("'", "\'", $wp_settings) . "'", $_wp_settings))) /* Eval compatible. Hard-code the ``__FILE__`` location here. */
71
  {
includes/classes/utils-strings.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 3.5
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
21
  {
@@ -290,7 +290,8 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
290
  */
291
  public static function base64_url_safe_encode ($string = FALSE, $url_unsafe_chars = array ("+", "/"), $url_safe_chars = array ("-", "_"), $trim_padding_chars = "=~.")
292
  {
293
- eval('$string = (string)$string; $trim_padding_chars = (string)$trim_padding_chars;');
 
294
  /**/
295
  $base64_url_safe = str_replace ((array)$url_unsafe_chars, (array)$url_safe_chars, base64_encode ($string));
296
  $base64_url_safe = (strlen ($trim_padding_chars)) ? rtrim ($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
@@ -314,7 +315,8 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
314
  */
315
  public static function base64_url_safe_decode ($base64_url_safe = FALSE, $url_unsafe_chars = array ("+", "/"), $url_safe_chars = array ("-", "_"), $trim_padding_chars = "=~.")
316
  {
317
- eval('$base64_url_safe = (string)$base64_url_safe; $trim_padding_chars = (string)$trim_padding_chars;');
 
318
  /**/
319
  $string = (strlen ($trim_padding_chars)) ? rtrim ($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
320
  $string = (strlen ($trim_padding_chars)) ? str_pad ($string, strlen ($string) % 4, "=", STR_PAD_RIGHT) : $string;
@@ -322,6 +324,133 @@ if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
322
  /**/
323
  return $string; /* Base64 decoded, with URL-safe replacements. */
324
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  }
326
  }
327
  ?>
15
  * @since 3.5
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_utils_strings"))
21
  {
290
  */
291
  public static function base64_url_safe_encode ($string = FALSE, $url_unsafe_chars = array ("+", "/"), $url_safe_chars = array ("-", "_"), $trim_padding_chars = "=~.")
292
  {
293
+ $string = (string)$string; /* Force string values here. String MUST be a string. */
294
+ $trim_padding_chars = (string)$trim_padding_chars; /* And force this one too. */
295
  /**/
296
  $base64_url_safe = str_replace ((array)$url_unsafe_chars, (array)$url_safe_chars, base64_encode ($string));
297
  $base64_url_safe = (strlen ($trim_padding_chars)) ? rtrim ($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
315
  */
316
  public static function base64_url_safe_decode ($base64_url_safe = FALSE, $url_unsafe_chars = array ("+", "/"), $url_safe_chars = array ("-", "_"), $trim_padding_chars = "=~.")
317
  {
318
+ $base64_url_safe = (string)$base64_url_safe; /* Force string values here. This MUST be a string. */
319
+ $trim_padding_chars = (string)$trim_padding_chars; /* And force this one too. */
320
  /**/
321
  $string = (strlen ($trim_padding_chars)) ? rtrim ($base64_url_safe, $trim_padding_chars) : $base64_url_safe;
322
  $string = (strlen ($trim_padding_chars)) ? str_pad ($string, strlen ($string) % 4, "=", STR_PAD_RIGHT) : $string;
324
  /**/
325
  return $string; /* Base64 decoded, with URL-safe replacements. */
326
  }
327
+ /**
328
+ * Generates an RSA-SHA1 signature.
329
+ *
330
+ * @package s2Member\Utilities
331
+ * @since 111017
332
+ *
333
+ * @param str $string Input string/data, to be signed by this routine.
334
+ * @param str $key The secret key that will be used in this signature.
335
+ * @return str|bool An RSA-SHA1 signature string, or false on failure.
336
+ */
337
+ public static function rsa_sha1_sign ($string = FALSE, $key = FALSE)
338
+ {
339
+ $key = /* Fixes key wrappers. */ c_ws_plugin__s2member_utils_strings::_rsa_sha1_key_fix_wrappers ((string)$key);
340
+ /**/
341
+ $signature = /* Command line. */ c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign ((string)$string, (string)$key);
342
+ /**/
343
+ if (empty ($signature) && stripos (PHP_OS, "win") === 0 && file_exists (($openssl = "c:\openssl-win32\bin\openssl.exe")))
344
+ $signature = c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign ((string)$string, (string)$key, /* Specific location. */ $openssl);
345
+ /**/
346
+ if (empty ($signature) && stripos (PHP_OS, "win") === 0 && file_exists (($openssl = "c:\openssl-win64\bin\openssl.exe")))
347
+ $signature = c_ws_plugin__s2member_utils_strings::_rsa_sha1_shell_sign ((string)$string, (string)$key, /* Specific location. */ $openssl);
348
+ /**/
349
+ if (empty ($signature) && function_exists ("openssl_get_privatekey") && function_exists ("openssl_sign") && is_resource ($private_key = openssl_get_privatekey ((string)$key)))
350
+ openssl_sign ((string)$string, $signature, $private_key, OPENSSL_ALGO_SHA1) . openssl_free_key ($private_key);
351
+ /**/
352
+ if (empty ($signature)) /* Now, if we're still empty, trigger an error here. */
353
+ trigger_error ("s2Member was unable to generate an RSA-SHA1 signature." .
354
+ " Please make sure your installation of PHP is compiled with OpenSSL: `openssl_sign()`." .
355
+ " See: http://php.net/manual/en/function.openssl-sign.php", E_USER_ERROR);
356
+ /**/
357
+ return (!empty ($signature)) ? $signature : false;
358
+ }
359
+ /**
360
+ * Generates an RSA-SHA1 signature from the command line.
361
+ *
362
+ * Used by {@link s2Member\Utilities\c_ws_plugin__s2member_utils_strings::rsa_sha1_sign()}.
363
+ *
364
+ * @package s2Member\Utilities
365
+ * @since 111017
366
+ *
367
+ * @param str $string Input string/data, to be signed by this routine.
368
+ * @param str $key The secret key that will be used in this signature.
369
+ * @param str $openssl Optional. Defaults to `openssl`. Path to OpenSSL executable.
370
+ * @return str|bool An RSA-SHA1 signature string, or false on failure.
371
+ */
372
+ public static function _rsa_sha1_shell_sign ($string = FALSE, $key = FALSE, $openssl = FALSE)
373
+ {
374
+ if (function_exists ("shell_exec") && ($esa = "escapeshellarg") && ($openssl = (($openssl && is_string ($openssl)) ? $openssl : "openssl")) && ($temp_dir = c_ws_plugin__s2member_utils_dirs::get_temp_dir ()))
375
+ {
376
+ file_put_contents (($string_file = $temp_dir . "/" . md5 (uniqid ("", true) . "rsa-sha1-string") . ".tmp"), (string)$string);
377
+ file_put_contents (($private_key_file = $temp_dir . "/" . md5 (uniqid ("", true) . "rsa-sha1-private-key") . ".tmp"), (string)$key);
378
+ file_put_contents (($rsa_sha1_sig_file = $temp_dir . "/" . md5 (uniqid ("", true) . "rsa-sha1-sig") . ".tmp"), "");
379
+ /**/
380
+ @shell_exec ($esa ($openssl) . " sha1 -sign " . $esa ($private_key_file) . " -out " . $esa ($rsa_sha1_sig_file) . " " . $esa ($string_file));
381
+ $signature = /* Do NOT trim here. */ file_get_contents ($rsa_sha1_sig_file); /* Was the signature was written? */
382
+ unlink ($rsa_sha1_sig_file) . unlink ($private_key_file) . unlink ($string_file); /* Cleanup. */
383
+ }
384
+ /**/
385
+ return (!empty ($signature)) ? $signature : false;
386
+ }
387
+ /**
388
+ * Fixes incomplete private key wrappers for RSA-SHA1 signing.
389
+ *
390
+ * Used by {@link s2Member\Utilities\c_ws_plugin__s2member_utils_strings::rsa_sha1_sign()}.
391
+ *
392
+ * @package s2Member\Utilities
393
+ * @since 111017
394
+ *
395
+ * @param str $key The secret key to be used in an RSA-SHA1 signature.
396
+ * @return str Key with incomplete wrappers corrected, when/if possible.
397
+ *
398
+ * @see http://www.faqs.org/qa/qa-14736.html
399
+ */
400
+ public static function _rsa_sha1_key_fix_wrappers ($key = FALSE)
401
+ {
402
+ if (($key = trim ((string)$key)) && (strpos ($key, "-----BEGIN RSA PRIVATE KEY-----") === false || strpos ($key, "-----END RSA PRIVATE KEY-----") === false))
403
+ {
404
+ foreach (($lines = c_ws_plugin__s2member_utils_strings::trim_deep (preg_split ("/[\r\n]+/", $key))) as $line => $value)
405
+ if (strpos ($value, "-") === 0) /* Begins with a boundary identifying character ( a hyphen `-` )? */
406
+ {
407
+ $boundaries = (empty ($boundaries)) ? 1 : $boundaries + 1; /* Counter. */
408
+ unset ($lines[$line]); /* Remove this boundary line. We'll fix these below. */
409
+ }
410
+ if (empty ($boundaries) || $boundaries <= 2) /* Do NOT modify keys with more than 2 boundaries. */
411
+ $key = "-----BEGIN RSA PRIVATE KEY-----\n" . implode ("\n", $lines) . "\n-----END RSA PRIVATE KEY-----";
412
+ }
413
+ return $key; /* Always a trimmed string here. */
414
+ }
415
+ /**
416
+ * Generates an HMAC-SHA1 signature.
417
+ *
418
+ * @package s2Member\Utilities
419
+ * @since 111017
420
+ *
421
+ * @param str $string Input string/data, to be signed by this routine.
422
+ * @param str $key The secret key that will be used in this signature.
423
+ * @return str An HMAC-SHA1 signature string.
424
+ */
425
+ public static function hmac_sha1_sign ($string = FALSE, $key = FALSE)
426
+ {
427
+ $key_64 = str_pad (((strlen ((string)$key) > 64) ? pack ('H*', sha1 ((string)$key)) : (string)$key), 64, chr (0x00));
428
+ /**/
429
+ return pack ('H*', sha1 (($key_64 ^ str_repeat (chr (0x5c), 64)) . pack ('H*', sha1 (($key_64 ^ str_repeat (chr (0x36), 64)) . (string)$string))));
430
+ }
431
+ /**
432
+ * Decodes unreserved chars encoded by PHP's ``urlencode()``, deeply.
433
+ *
434
+ * For further details regarding unreserved chars, see: {@link http://www.faqs.org/rfcs/rfc3986.html}.
435
+ *
436
+ * @package s2Member\Utilities
437
+ * @since 111017
438
+ *
439
+ * @param str|array $value Either a string, an array, or a multi-dimensional array, filled with integer and/or string values.
440
+ * @return str|array Either the input string, or the input array; after all unreserved chars are decoded properly.
441
+ */
442
+ public static function urldecode_ur_chars_deep ($value = array ())
443
+ {
444
+ if (is_array ($value)) /* Handles all types of arrays.
445
+ Note, we do NOT use ``array_map()`` here, because multiple args to ``array_map()`` causes a loss of string keys.
446
+ For further details, see: <http://php.net/manual/en/function.array-map.php>. */
447
+ {
448
+ foreach ($value as &$r) /* Reference. */
449
+ $r = c_ws_plugin__s2member_utils_strings::urldecode_ur_chars_deep ($r);
450
+ return $value; /* Return modified array. */
451
+ }
452
+ return str_replace (array ("%2D", "%2E", "%5F", "%7E"), array ("-", ".", "_", "~"), (string)$value);
453
+ }
454
  }
455
  }
456
  ?>
includes/classes/utils-urls.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 3.5
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_utils_urls"))
21
  {
@@ -88,25 +88,59 @@ if (!class_exists ("c_ws_plugin__s2member_utils_urls"))
88
  return $status; /* Else keep existing status code. */
89
  }
90
  /**
91
- * Parses out a full valid URI, from either a full URL, or a partial.
 
 
92
  *
93
  * @package s2Member\Utilities
94
  * @since 3.5
95
  *
96
  * @param str $url_or_uri Either a full URL, or a partial URI.
97
- * @return str|bool A valid URI, starting with `/` on success, else false.
98
  */
99
  public static function parse_uri ($url_or_uri = FALSE)
100
  {
101
- if (($parse = @parse_url ($url_or_uri))) /* See: http://php.net/manual/en/function.parse-url.php. */
102
  {
103
  $parse["path"] = (!empty ($parse["path"])) ? ((strpos ($parse["path"], "/") === 0) ? $parse["path"] : "/" . $parse["path"]) : "/";
104
- $parse["path"] = preg_replace ("/\/+/", "/", $parse["path"]); /* Removes multi slashes. */
105
  /**/
106
  return (!empty ($parse["query"])) ? $parse["path"] . "?" . $parse["query"] : $parse["path"];
107
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  /**/
109
- return false;
110
  }
111
  /**
112
  * Responsible for all remote communications processed by s2Member.
15
  * @since 3.5
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_utils_urls"))
21
  {
88
  return $status; /* Else keep existing status code. */
89
  }
90
  /**
91
+ * Parses out a full valid URI, from either a full URL, or a partial URI.
92
+ *
93
+ * Uses {@link s2Member\Utilities\c_ws_plugin__s2member_utils_urls::parse_url()}.
94
  *
95
  * @package s2Member\Utilities
96
  * @since 3.5
97
  *
98
  * @param str $url_or_uri Either a full URL, or a partial URI.
99
+ * @return str A valid URI, starting with `/` on success, else an empty string.
100
  */
101
  public static function parse_uri ($url_or_uri = FALSE)
102
  {
103
+ if (is_string ($url_or_uri) && is_array ($parse = c_ws_plugin__s2member_utils_urls::parse_url ($url_or_uri)))
104
  {
105
  $parse["path"] = (!empty ($parse["path"])) ? ((strpos ($parse["path"], "/") === 0) ? $parse["path"] : "/" . $parse["path"]) : "/";
 
106
  /**/
107
  return (!empty ($parse["query"])) ? $parse["path"] . "?" . $parse["query"] : $parse["path"];
108
  }
109
+ else /* Force a string return value here. */
110
+ return ""; /* Empty string. */
111
+ }
112
+ /**
113
+ * Parses a URL with same args as PHP's ``parse_url()`` function.
114
+ *
115
+ * This works around issues with this PHP function in versions prior to 5.3.8.
116
+ *
117
+ * @package s2Member\Utilities
118
+ * @since 111017
119
+ *
120
+ * @param str $url_or_uri Either a full URL, or a partial URI.
121
+ * @param bool|int $component Optional. See PHP documentation on ``parse_url()`` function.
122
+ * @param bool $clean_path Defaults to true. s2Member will cleanup any return array `path`.
123
+ * @return str|array|bool The return value from PHP's ``parse_url()`` function.
124
+ * However, if ``$component`` is passed, s2Member forces a string return.
125
+ */
126
+ public static function parse_url ($url_or_uri = FALSE, $component = FALSE, $clean_path = TRUE)
127
+ {
128
+ $component = ($component === false || $component === -1) ? -1 : $component;
129
+ /**/
130
+ if (is_string ($url_or_uri) && strpos ($url_or_uri, "?") !== "false") /* A query string? */
131
+ {
132
+ list ($_, $query) = preg_split ("/\?/", $url_or_uri, 2); /* Split at the query string. */
133
+ /* Works around bug in many versions of PHP. See: <https://bugs.php.net/bug.php?id=38143>. */
134
+ $query = str_replace ("://", urlencode ("://"), $query);
135
+ $url_or_uri = $_ . "?" . $query;
136
+ }
137
+ /**/
138
+ $parse = @parse_url ($url_or_uri, $component); /* Let PHP work its magic now. */
139
+ /**/
140
+ if ($clean_path && isset ($parse["path"]) && is_string ($parse["path"]) && !empty ($parse["path"]))
141
+ $parse["path"] = preg_replace ("/\/+/", "/", $parse["path"]);
142
  /**/
143
+ return ($component !== -1) ? /* Force a string return value here? */ (string)$parse : $parse;
144
  }
145
  /**
146
  * Responsible for all remote communications processed by s2Member.
includes/menu-pages/down-ops.inc.php CHANGED
@@ -15,7 +15,7 @@
15
  * @since 3.0
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
21
  {
@@ -350,7 +350,7 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
350
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon® CloudFront (below), are designed to create &amp; configure various components on your Amazon® Web Services account, which are all requirements for you to <a href="http://docs.amazonwebservices.com/AmazonCloudFront/2010-11-01/DeveloperGuide/index.html?HowToPrivateContent.html" target="_blank" rel="external">serve protected files through the Amazon® S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon® S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy ( i.e. permissions ) on your Amazon® S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>' . "\n";
351
  echo '<p><em><strong>Linking To Protected Files:</strong> Streamed files are special, but nothing else changes. s2Member\'s integration with Amazon® S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® CloudFront URL, which allows them access to a particular file via Amazon® CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>. For streaming audio/video files, please review the section below: <code>JW Player® &amp; RTMP Protocol Examples</code>.</em></p>' . "\n";
352
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon® CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon® CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>' . "\n";
353
- echo (stripos (PHP_OS, "win") === 0 && (stripos ($_SERVER["HTTP_HOST"], "localhost") !== false || strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") !== false || (defined ("LOCALHOST") && 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 currently unavailable )</strong>') . '</em></p>' . "\n" : '';
354
  /**/
355
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"] === "configured")
356
  echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon® CloudFront Distributions are: ( ALREADY configured! )</strong></em>' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) ? '<br /><em class="ws-menu-page-hilite">Downloads Distribution CNAME:</em> <em><code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]) . '</code></em>' : '') . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? '<br /><em class="ws-menu-page-hilite">Streaming Distribution CNAME:</em> <em><code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]) . '</code></em>' : '') . '</p>' . "\n";
@@ -442,7 +442,7 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
442
  /**/
443
  echo '<td>' . "\n";
444
  echo '<input type="text" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . '" /><br />' . "\n";
445
- echo 'Example: <code>s2-file-downloads.' . esc_html (parse_url (site_url (), PHP_URL_HOST)) . '</code>.<br />' . "\n";
446
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
447
  echo '</td>' . "\n";
448
  /**/
@@ -460,7 +460,7 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
460
  /**/
461
  echo '<td>' . "\n";
462
  echo '<input type="text" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . '" /><br />' . "\n";
463
- echo 'Example: <code>s2-streaming-files.' . esc_html (parse_url (site_url (), PHP_URL_HOST)) . '</code>.<br />' . "\n";
464
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
465
  echo '</td>' . "\n";
466
  /**/
15
  * @since 3.0
16
  */
17
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
+ exit ("Do not access this file directly.");
19
  /**/
20
  if (!class_exists ("c_ws_plugin__s2member_menu_page_down_ops"))
21
  {
350
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon® CloudFront (below), are designed to create &amp; configure various components on your Amazon® Web Services account, which are all requirements for you to <a href="http://docs.amazonwebservices.com/AmazonCloudFront/2010-11-01/DeveloperGuide/index.html?HowToPrivateContent.html" target="_blank" rel="external">serve protected files through the Amazon® S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon® S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy ( i.e. permissions ) on your Amazon® S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>' . "\n";
351
  echo '<p><em><strong>Linking To Protected Files:</strong> Streamed files are special, but nothing else changes. s2Member\'s integration with Amazon® S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>' . esc_html (site_url ("/?s2member_file_download=example-file.zip")) . '</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon® S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon® CloudFront URL, which allows them access to a particular file via Amazon® CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -> Download Options -> Basic Download Restrictions</code>. Also see: <code>s2Member -> Download Options -> Advanced Mod-Rewrite Linkage</code>. For streaming audio/video files, please review the section below: <code>JW Player® &amp; RTMP Protocol Examples</code>.</em></p>' . "\n";
352
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon® CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon® CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon® S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself ( such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code> ) that you want Amazon® CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -> Metadata ( i.e. headers )</code> on a per-file basis, from inside your Amazon® S3 Management Console. In short, when you upload a file to your Amazon® S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -> Metadata</code> accordingly.</em></p>' . "\n";
353
+ echo (stripos (PHP_OS, "win") === 0 && (stripos ($_SERVER["HTTP_HOST"], "localhost") !== false || strpos ($_SERVER["HTTP_HOST"], "127.0.0.1") !== false || (defined ("LOCALHOST") && LOCALHOST))) ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon® CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront® URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows®</a> while you\'re developing. s2Member will automatically find it here: <code>C:\OpenSSL-Win[32/64]\bin\openssl.exe</code>.' . ((file_exists ("c:\openssl-win32\bin\openssl.exe") || file_exists ("c:\openssl-win64\bin\openssl.exe")) ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] is NOT currently available )</strong>') . '</em></p>' . "\n" : '';
354
  /**/
355
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distros_auto_config_status"] === "configured")
356
  echo '<p><em class="ws-menu-page-hilite"><strong>Your Amazon® CloudFront Distributions are: ( ALREADY configured! )</strong></em>' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) ? '<br /><em class="ws-menu-page-hilite">Downloads Distribution CNAME:</em> <em><code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_dname"]) . '</code></em>' : '') . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) ? '<br /><em class="ws-menu-page-hilite">Streaming Distribution CNAME:</em> <em><code>' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . ' &mdash;&raquo; ' . esc_html ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_dname"]) . '</code></em>' : '') . '</p>' . "\n";
442
  /**/
443
  echo '<td>' . "\n";
444
  echo '<input type="text" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]) . '" /><br />' . "\n";
445
+ echo 'Example: <code>s2-file-downloads.' . esc_html (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_HOST)) . '</code>.<br />' . "\n";
446
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
447
  echo '</td>' . "\n";
448
  /**/
460
  /**/
461
  echo '<td>' . "\n";
462
  echo '<input type="text" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]) . '" /><br />' . "\n";
463
+ echo 'Example: <code>s2-streaming-files.' . esc_html (c_ws_plugin__s2member_utils_urls::parse_url (site_url (), PHP_URL_HOST)) . '</code>.<br />' . "\n";
464
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>' . "\n";
465
  echo '</td>' . "\n";
466
  /**/
includes/menu-pages/menu-pages-s.js CHANGED
@@ -352,7 +352,7 @@ jQuery(document).ready (function($)
352
  /**/
353
  var fieldId2Var = function(fieldId) /* Convert ids to variables. */
354
  {
355
- return( typeof fieldId === 'string') ? $.trim (fieldId).toLowerCase ().replace (/[^a-z0-9]/g, '_') : '';
356
  };
357
  /**/
358
  var fieldTypeDesc = function(type)
@@ -858,7 +858,7 @@ jQuery(document).ready (function($)
858
  var $visiblePrivateKeyEntry = $('textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry');
859
  var hiddenPrivateKeyValue = $.trim ($hiddenPrivateKey.val ()), visiblePrivateKeyEntryValue = $.trim ($visiblePrivateKeyEntry.val ());
860
  /**/
861
- if ((hiddenPrivateKeyValue && !visiblePrivateKeyEntryValue) || visiblePrivateKeyEntryValue.match (/[^\r\n\u25CF]/)) /* 9679.toString(16).toUpperCase() = 25CF ( i.e the hex value ). */
862
  $hiddenPrivateKey.val (visiblePrivateKeyEntryValue), $visiblePrivateKeyEntry.val (visiblePrivateKeyEntryValue.replace (/[^\r\n]/g, String.fromCharCode (9679)));
863
  };
864
  /**/
352
  /**/
353
  var fieldId2Var = function(fieldId) /* Convert ids to variables. */
354
  {
355
+ return ( typeof fieldId === 'string') ? $.trim (fieldId).toLowerCase ().replace (/[^a-z0-9]/g, '_') : '';
356
  };
357
  /**/
358
  var fieldTypeDesc = function(type)
858
  var $visiblePrivateKeyEntry = $('textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry');
859
  var hiddenPrivateKeyValue = $.trim ($hiddenPrivateKey.val ()), visiblePrivateKeyEntryValue = $.trim ($visiblePrivateKeyEntry.val ());
860
  /**/
861
+ if ((hiddenPrivateKeyValue && !visiblePrivateKeyEntryValue) || visiblePrivateKeyEntryValue.match (/[^\r\n\u25CF]/)) /* 9679.toString(16).toUpperCase() = 25CF. */
862
  $hiddenPrivateKey.val (visiblePrivateKeyEntryValue), $visiblePrivateKeyEntry.val (visiblePrivateKeyEntryValue.replace (/[^\r\n]/g, String.fromCharCode (9679)));
863
  };
864
  /**/
includes/templates/cfg-files/s2member-files.php CHANGED
@@ -3,9 +3,9 @@ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
3
  exit("Do not access this file directly.");
4
 
5
  global $base; /* A Multisite ``$base`` configuration? */
6
- $ws_plugin__s2member_temp_s_base = (!empty ($base)) ? $base : parse_url (network_home_url ("/"), PHP_URL_PATH);
7
- /* The function ``network_home_url ()`` defaults to ``home_url ()`` on standard WordPress® installs. */
8
- /* Must use the `home` URL here, because that's what WordPress® uses in it's `mod_rewrite` file. */
9
  ?>
10
 
11
  Options +FollowSymLinks -MultiViews
3
  exit("Do not access this file directly.");
4
 
5
  global $base; /* A Multisite ``$base`` configuration? */
6
+ $ws_plugin__s2member_temp_s_base = (!empty ($base)) ? $base : c_ws_plugin__s2member_utils_urls::parse_url (network_home_url ("/"), PHP_URL_PATH);
7
+ /* This works on Multisite installs too. The function ``network_home_url ()`` defaults to ``home_url ()`` on standard WordPress® installs. */
8
+ /* Do NOT use ``site`` URL. Must use the `home` URL here, because that's what WordPress® uses in its own `mod_rewrite` implementation. */
9
  ?>
10
 
11
  Options +FollowSymLinks -MultiViews
includes/translations/s2member.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the s2Member package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: s2Member 111011\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/.__s2member\n"
7
- "POT-Creation-Date: 2011-10-11 18:55:20+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -92,17 +92,17 @@ 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:364
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:450
101
  msgctxt "s2member-front"
102
  msgid "Members Only"
103
  msgstr ""
104
 
105
- #: s2member/includes/classes/files-in.inc.php:456
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:594
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:597
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:601
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:604
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:608
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:611
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:614
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:618
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:621
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:624
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:763
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:770
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:782
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:789
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:805
209
- #: s2member/includes/classes/files-in.inc.php:987
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:844
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:847
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:851
233
- #: s2member/includes/classes/files-in.inc.php:1275
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:854
239
- #: s2member/includes/classes/files-in.inc.php:1277
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:858
249
- #: s2member/includes/classes/files-in.inc.php:1254
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:861
255
- #: s2member/includes/classes/files-in.inc.php:1256
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:865
265
- #: s2member/includes/classes/files-in.inc.php:1032
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:868
271
- #: s2member/includes/classes/files-in.inc.php:1035
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:871
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:875
286
- #: s2member/includes/classes/files-in.inc.php:944
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:878
292
- #: s2member/includes/classes/files-in.inc.php:947
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:881
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:885
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:888
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:891
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:895
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:898
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:901
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:904
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:940
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:950
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:990
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:993
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:1019
370
- #: s2member/includes/classes/files-in.inc.php:1242
371
- #: s2member/includes/classes/files-in.inc.php:1263
372
  msgctxt "s2member-admin"
373
  msgid "Created by s2Member, for S3 Bucket: %s."
374
  msgstr ""
375
 
376
- #: s2member/includes/classes/files-in.inc.php:1028
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:1072
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:1076
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:1079
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:1082
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:1126
414
- #: s2member/includes/classes/files-in.inc.php:1201
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:1129
420
- #: s2member/includes/classes/files-in.inc.php:1204
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:1132
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:1138
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:1183
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:1186
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:1190
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:1194
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:1197
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:1207
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:1210
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:1250
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:1271
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:1281
493
  msgctxt "s2member-admin"
494
  msgid "Unable to create Amazon® CloudFront Distro. Invalid Distro type."
495
  msgstr ""
@@ -793,37 +793,37 @@ msgctxt "s2member-front paypal-button-lang-code"
793
  msgid "en_US"
794
  msgstr ""
795
 
796
- #: s2member/includes/classes/translations.inc.php:78
797
  msgctxt "s2member-front"
798
  msgid "Username:"
799
  msgstr ""
800
 
801
- #: s2member/includes/classes/translations.inc.php:82
802
  msgctxt "s2member-front"
803
  msgid "My Password:"
804
  msgstr ""
805
 
806
- #: s2member/includes/classes/translations.inc.php:90
807
  msgctxt "s2member-front"
808
  msgid "Username *"
809
  msgstr ""
810
 
811
- #: s2member/includes/classes/translations.inc.php:94
812
  msgctxt "s2member-front"
813
  msgid "Password *"
814
  msgstr ""
815
 
816
- #: s2member/includes/classes/translations.inc.php:98
817
  msgctxt "s2member-front"
818
  msgid "Email Address *"
819
  msgstr ""
820
 
821
- #: s2member/includes/classes/translations.inc.php:106
822
  msgctxt "s2member-front"
823
  msgid "Registration complete. Please log in."
824
  msgstr ""
825
 
826
- #: s2member/includes/classes/translations.inc.php:114
827
  msgctxt "s2member-front"
828
  msgid ""
829
  "You have been invited to join `%1$s` at\n"
@@ -832,19 +832,19 @@ msgid ""
832
  "%4$s\n"
833
  msgstr ""
834
 
835
- #: s2member/includes/classes/translations.inc.php:122
836
  msgctxt "s2member-front"
837
  msgid "Your account is now active. <a href=\"%1$s\">Visit site</a> or <a href=\"%2$s\">Log in</a>."
838
  msgstr ""
839
 
840
- #: s2member/includes/classes/translations.inc.php:143
841
- #: s2member/includes/classes/translations.inc.php:165
842
  msgctxt "s2member-front"
843
  msgid "By filling out the form below, you can <strong>add a site to your account</strong>."
844
  msgstr ""
845
 
846
- #: s2member/includes/classes/translations.inc.php:143
847
- #: s2member/includes/classes/translations.inc.php:165
848
  msgctxt "s2member-front"
849
  msgid "You may create up to <strong>%s</strong> site."
850
  msgid_plural "You may create up to <strong>%s</strong> sites."
2
  # This file is distributed under the same license as the s2Member package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: s2Member 111017\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/.__s2member\n"
7
+ "POT-Creation-Date: 2011-10-17 18:16:12+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
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:369
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:455
101
  msgctxt "s2member-front"
102
  msgid "Members Only"
103
  msgstr ""
104
 
105
+ #: s2member/includes/classes/files-in.inc.php:461
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:599
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:602
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:606
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:609
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:613
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:616
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:619
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:623
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:626
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:629
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:731
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:738
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:750
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:757
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:773
209
+ #: s2member/includes/classes/files-in.inc.php:955
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:812
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:815
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:819
233
+ #: s2member/includes/classes/files-in.inc.php:1243
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:822
239
+ #: s2member/includes/classes/files-in.inc.php:1245
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:826
249
+ #: s2member/includes/classes/files-in.inc.php:1222
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:829
255
+ #: s2member/includes/classes/files-in.inc.php:1224
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:833
265
+ #: s2member/includes/classes/files-in.inc.php:1000
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:836
271
+ #: s2member/includes/classes/files-in.inc.php:1003
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:839
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:843
286
+ #: s2member/includes/classes/files-in.inc.php:912
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:846
292
+ #: s2member/includes/classes/files-in.inc.php:915
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:849
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:853
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:856
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:859
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:863
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:866
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:869
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:872
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:908
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:918
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:958
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:961
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:987
370
+ #: s2member/includes/classes/files-in.inc.php:1210
371
+ #: s2member/includes/classes/files-in.inc.php:1231
372
  msgctxt "s2member-admin"
373
  msgid "Created by s2Member, for S3 Bucket: %s."
374
  msgstr ""
375
 
376
+ #: s2member/includes/classes/files-in.inc.php:996
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:1040
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:1044
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:1047
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:1050
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:1094
414
+ #: s2member/includes/classes/files-in.inc.php:1169
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:1097
420
+ #: s2member/includes/classes/files-in.inc.php:1172
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:1100
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:1106
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:1151
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:1154
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:1158
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:1162
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:1165
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:1175
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:1178
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:1218
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:1239
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:1249
493
  msgctxt "s2member-admin"
494
  msgid "Unable to create Amazon® CloudFront Distro. Invalid Distro type."
495
  msgstr ""
793
  msgid "en_US"
794
  msgstr ""
795
 
796
+ #: s2member/includes/classes/translations.inc.php:79
797
  msgctxt "s2member-front"
798
  msgid "Username:"
799
  msgstr ""
800
 
801
+ #: s2member/includes/classes/translations.inc.php:83
802
  msgctxt "s2member-front"
803
  msgid "My Password:"
804
  msgstr ""
805
 
806
+ #: s2member/includes/classes/translations.inc.php:91
807
  msgctxt "s2member-front"
808
  msgid "Username *"
809
  msgstr ""
810
 
811
+ #: s2member/includes/classes/translations.inc.php:95
812
  msgctxt "s2member-front"
813
  msgid "Password *"
814
  msgstr ""
815
 
816
+ #: s2member/includes/classes/translations.inc.php:99
817
  msgctxt "s2member-front"
818
  msgid "Email Address *"
819
  msgstr ""
820
 
821
+ #: s2member/includes/classes/translations.inc.php:107
822
  msgctxt "s2member-front"
823
  msgid "Registration complete. Please log in."
824
  msgstr ""
825
 
826
+ #: s2member/includes/classes/translations.inc.php:115
827
  msgctxt "s2member-front"
828
  msgid ""
829
  "You have been invited to join `%1$s` at\n"
832
  "%4$s\n"
833
  msgstr ""
834
 
835
+ #: s2member/includes/classes/translations.inc.php:123
836
  msgctxt "s2member-front"
837
  msgid "Your account is now active. <a href=\"%1$s\">Visit site</a> or <a href=\"%2$s\">Log in</a>."
838
  msgstr ""
839
 
840
+ #: s2member/includes/classes/translations.inc.php:144
841
+ #: s2member/includes/classes/translations.inc.php:166
842
  msgctxt "s2member-front"
843
  msgid "By filling out the form below, you can <strong>add a site to your account</strong>."
844
  msgstr ""
845
 
846
+ #: s2member/includes/classes/translations.inc.php:144
847
+ #: s2member/includes/classes/translations.inc.php:166
848
  msgctxt "s2member-front"
849
  msgid "You may create up to <strong>%s</strong> site."
850
  msgid_plural "You may create up to <strong>%s</strong> sites."
includes/translations/translators.txt CHANGED
@@ -8,6 +8,6 @@ Like WordPress® itself, we chose to use the GNU `gettext` localization framewor
8
 
9
  The file: `/s2member/includes/translations/s2member.pot` will be updated with each new release of s2Member.
10
 
11
- If this is your first translation of a WordPress® plugin, [this article](http://codex.wordpress.org/Translating_WordPress#Localization_Technology) and/or [this article](http://urbangiraffe.com/articles/translating-wordpress-themes-and-plugins/), might be of some assistance. When you are finished translating the `s2member.pot` file, place your completed `s2member-[locale].mo` file into this directory: `/s2member/includes/translations/`; and please feel free to [share your translation](http://www.primothemes.com/forums/viewforum.php?f=4) with the rest of the s2Member® community.
12
 
13
  Quick Tip: If you only need to translate the front-end of s2Member, please ignore entries in the `s2member.pot` file with a context matching `s2member-admin`. Those sections of s2Member are only seen by site Administrators; they are NOT used in s2Member's front-end integration with WordPress®. Skipping over translation entries with a context matching `s2member-admin` can save you time.
8
 
9
  The file: `/s2member/includes/translations/s2member.pot` will be updated with each new release of s2Member.
10
 
11
+ If this is your first translation of a WordPress® plugin, [this article](http://codex.wordpress.org/Translating_WordPress#Localization_Technology) and/or [this article](http://urbangiraffe.com/articles/translating-wordpress-themes-and-plugins/), might be of some assistance. When you are finished translating the `s2member.pot` file, place your completed `s2member-[locale].mo` file into this directory: `/wp-content/plugins/`; and please feel free to [share your translation](http://www.primothemes.com/forums/viewforum.php?f=4) with the rest of the s2Member® community.
12
 
13
  Quick Tip: If you only need to translate the front-end of s2Member, please ignore entries in the `s2member.pot` file with a context matching `s2member-admin`. Those sections of s2Member are only seen by site Administrators; they are NOT used in s2Member's front-end integration with WordPress®. Skipping over translation entries with a context matching `s2member-admin` can save you time.
readme.txt CHANGED
@@ -1,7 +1,7 @@
1
  === s2Member® ( Membership w/ PayPal® ) ===
2
 
3
- Version: 111011
4
- Stable tag: 111011
5
  Framework: WS-P-110523
6
 
7
  SSL Compatible: yes
@@ -98,7 +98,7 @@ Like WordPress® itself, we chose to use the GNU `gettext` localization framewor
98
 
99
  The file: `/s2member/includes/translations/s2member.pot` will be updated with each new release of s2Member.
100
 
101
- If this is your first translation of a WordPress® plugin, [this article](http://codex.wordpress.org/Translating_WordPress#Localization_Technology) and/or [this article](http://urbangiraffe.com/articles/translating-wordpress-themes-and-plugins/), might be of some assistance. When you are finished translating the `s2member.pot` file, place your completed `s2member-[locale].mo` file into this directory: `/s2member/includes/translations/`; and please feel free to [share your translation](http://www.primothemes.com/forums/viewforum.php?f=4) with the rest of the s2Member® community.
102
 
103
  Quick Tip: If you only need to translate the front-end of s2Member, please ignore entries in the `s2member.pot` file with a context matching `s2member-admin`. Those sections of s2Member are only seen by site Administrators; they are NOT used in s2Member's front-end integration with WordPress®. Skipping over translation entries with a context matching `s2member-admin` can save you time.
104
 
@@ -178,6 +178,15 @@ Please visit s2Member.com for [video tutorials](http://www.s2member.com/videos/)
178
 
179
  == Changelog ==
180
 
 
 
 
 
 
 
 
 
 
181
  = v111011 =
182
  * (s2Member/s2Member Pro) **Bug fix**. An array to string conversion error was found in Profile editing panels whenever a multi-option Select Menu was created as a Custom Registration/Profile Field with s2Member. Fixed in this release. For further details, please see [this thread](http://www.primothemes.com/forums/viewtopic.php?f=4&t=15416&p=44801#p45169).
183
  * (s2Member/s2Member Pro) **Email recipients / compatibility fix**. A bug found by an s2Member Pro customer, related to PHP's `mail()` function in PHP 5.2 < 5.2.11 was preventing some email messages from being processed properly. Fixed in this release. For further details, see [this thread](http://www.primothemes.com/forums/viewtopic.php?f=4&t=14957#p45222) and/or [this PHP bug report](https://bugs.php.net/bug.php?id=28038) please.
@@ -232,7 +241,7 @@ Please visit s2Member.com for [video tutorials](http://www.s2member.com/videos/)
232
  Like WordPress® itself, we chose to use the GNU `gettext` localization framework to provide localization infrastructure for s2Member®. GNU `gettext` is a mature, widely used framework for modular translation of software, and is the *de facto* standard for localization in the open source/free software realm. If you'd like to translate s2Member and/or s2Member Pro, please use the POT file found inside `/s2member/includes/translations/s2member.pot`, which contains all translation entries for both the s2Member Framework *( i.e. the free version )*, and also for s2Member Pro.
233
 
234
  The file: `/s2member/includes/translations/s2member.pot` will be updated with each new release of s2Member.
235
- If this is your first translation of a WordPress® plugin, [this article](http://codex.wordpress.org/Translating_WordPress#Localization_Technology) and/or [this article](http://urbangiraffe.com/articles/translating-wordpress-themes-and-plugins/), might be of some assistance. When you are finished translating the `s2member.pot` file, place your completed `s2member-[locale].mo` file into this directory: `/s2member/includes/translations/`; and please feel free to [share your translation](http://www.primothemes.com/forums/viewforum.php?f=4) with the rest of the s2Member® community.
236
 
237
  Quick Tip: If you only need to translate the front-end of s2Member, please ignore entries in the `s2member.pot` file with a context matching `s2member-admin`. Those sections of s2Member are only seen by site Administrators; they are NOT used in s2Member's front-end integration with WordPress®. Skipping over translation entries with a context matching `s2member-admin` can save you time.
238
  * (s2Member) **Bug fix / Multisite**. A bug fix related to site creation within the Dashboard on a Multisite Blog Farm, has been corrected in this release. For further details, please see [this thread](http://www.primothemes.com/forums/viewtopic.php?f=4&t=10307#p32628).
1
  === s2Member® ( Membership w/ PayPal® ) ===
2
 
3
+ Version: 111017
4
+ Stable tag: 111017
5
  Framework: WS-P-110523
6
 
7
  SSL Compatible: yes
98
 
99
  The file: `/s2member/includes/translations/s2member.pot` will be updated with each new release of s2Member.
100
 
101
+ If this is your first translation of a WordPress® plugin, [this article](http://codex.wordpress.org/Translating_WordPress#Localization_Technology) and/or [this article](http://urbangiraffe.com/articles/translating-wordpress-themes-and-plugins/), might be of some assistance. When you are finished translating the `s2member.pot` file, place your completed `s2member-[locale].mo` file into this directory: `/wp-content/plugins/`; and please feel free to [share your translation](http://www.primothemes.com/forums/viewforum.php?f=4) with the rest of the s2Member® community.
102
 
103
  Quick Tip: If you only need to translate the front-end of s2Member, please ignore entries in the `s2member.pot` file with a context matching `s2member-admin`. Those sections of s2Member are only seen by site Administrators; they are NOT used in s2Member's front-end integration with WordPress®. Skipping over translation entries with a context matching `s2member-admin` can save you time.
104
 
178
 
179
  == Changelog ==
180
 
181
+ = v111017 =
182
+ * (s2Member/s2Member Pro) **Bug fix**. s2Member now works around a known bug in PHP, related to the `parse_url()` function. For further details, please see [this PHP bug report](https://bugs.php.net/bug.php?id=38143).
183
+ * (s2Member/s2Member Pro) **Compatibility**. Improvements to s2Member's `wp_mail()` conformity, related to the reducton of `"Name" <email>` to just `email`. This release should work to further improve email deliverability in edge cases, particulary on sites running an SMTP mail plugin.
184
+ * (s2Member/s2Member Pro) **Compatibility**. Improvements to s2Member's JW Player® integration. s2Member now prevents `unreserved chars`, i.e. `array ("-", ".", "_", "~")` from being URL-encoded in file download URLs, maximizing compatibility with many media players, including JW Player®. In previous releases, JW Player® would randomly fail on some RTMP streams with error `Stream Not Found`. Fixed in this release, with [one exception](https://forums.aws.amazon.com/thread.jspa?messageID=286182&#286182). For further details, see [RFC 3896](http://www.faqs.org/rfcs/rfc3986.html).
185
+ * (s2Member/s2Member Pro) **Compatibility**. Initial testing against WordPress v3.3-beta1. Looks pretty good. A few minor cosmetic issues still need to be addressed in a future release of s2Member though.
186
+ * (s2Member/s2Member Pro) **Compatibility**. Tested against BuddyPress v1.5.1. Updated s2Member to support `$bp->maintenance_mode`, and other cases where `bp_core_loaded` is NOT fired at all.
187
+ * (s2Member/s2Member Pro) **Routine maintenance**. Some code optimization, some cleanup, and some organizational improvements in preparation for new features in a coming release.
188
+ * (s2Member/s2Member Pro) **Bug fix**. Edge case identified where the `/s2member-o.php` file was failing to fallback on full WordPress®. Fixed in this release.
189
+
190
  = v111011 =
191
  * (s2Member/s2Member Pro) **Bug fix**. An array to string conversion error was found in Profile editing panels whenever a multi-option Select Menu was created as a Custom Registration/Profile Field with s2Member. Fixed in this release. For further details, please see [this thread](http://www.primothemes.com/forums/viewtopic.php?f=4&t=15416&p=44801#p45169).
192
  * (s2Member/s2Member Pro) **Email recipients / compatibility fix**. A bug found by an s2Member Pro customer, related to PHP's `mail()` function in PHP 5.2 < 5.2.11 was preventing some email messages from being processed properly. Fixed in this release. For further details, see [this thread](http://www.primothemes.com/forums/viewtopic.php?f=4&t=14957#p45222) and/or [this PHP bug report](https://bugs.php.net/bug.php?id=28038) please.
241
  Like WordPress® itself, we chose to use the GNU `gettext` localization framework to provide localization infrastructure for s2Member®. GNU `gettext` is a mature, widely used framework for modular translation of software, and is the *de facto* standard for localization in the open source/free software realm. If you'd like to translate s2Member and/or s2Member Pro, please use the POT file found inside `/s2member/includes/translations/s2member.pot`, which contains all translation entries for both the s2Member Framework *( i.e. the free version )*, and also for s2Member Pro.
242
 
243
  The file: `/s2member/includes/translations/s2member.pot` will be updated with each new release of s2Member.
244
+ If this is your first translation of a WordPress® plugin, [this article](http://codex.wordpress.org/Translating_WordPress#Localization_Technology) and/or [this article](http://urbangiraffe.com/articles/translating-wordpress-themes-and-plugins/), might be of some assistance. When you are finished translating the `s2member.pot` file, place your completed `s2member-[locale].mo` file into this directory: `/wp-content/plugins/`; and please feel free to [share your translation](http://www.primothemes.com/forums/viewforum.php?f=4) with the rest of the s2Member® community.
245
 
246
  Quick Tip: If you only need to translate the front-end of s2Member, please ignore entries in the `s2member.pot` file with a context matching `s2member-admin`. Those sections of s2Member are only seen by site Administrators; they are NOT used in s2Member's front-end integration with WordPress®. Skipping over translation entries with a context matching `s2member-admin` can save you time.
247
  * (s2Member) **Bug fix / Multisite**. A bug fix related to site creation within the Dashboard on a Multisite Blog Farm, has been corrected in this release. For further details, please see [this thread](http://www.primothemes.com/forums/viewtopic.php?f=4&t=10307#p32628).
s2member.php CHANGED
@@ -19,8 +19,8 @@
19
  */
20
  /* -- This section for WordPress® parsing. ------------------------------------------------------------------------------
21
 
22
- Version: 111011
23
- Stable tag: 111011
24
  Framework: WS-P-110523
25
 
26
  SSL Compatible: yes
@@ -65,7 +65,7 @@ Tags: membership, members, member, register, signup, paypal, paypal pro, pay pal
65
 
66
  -- end section for WordPress® parsing. ------------------------------------------------------------------------------- */
67
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
68
- exit("Do not access this file directly.");
69
  /**
70
  * The installed version of s2Member.
71
  *
@@ -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", "111011");
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", "111011");
109
  /*
110
  Several compatibility checks.
111
  If all pass, load the s2Member plugin.
@@ -116,7 +116,7 @@ if (version_compare (PHP_VERSION, WS_PLUGIN__S2MEMBER_MIN_PHP_VERSION, ">=") &&
116
  /*
117
  Hook before loaded.
118
  */
119
- do_action("ws_plugin__s2member_before_loaded");
120
  /*
121
  System configuraton.
122
  */
@@ -128,7 +128,7 @@ if (version_compare (PHP_VERSION, WS_PLUGIN__S2MEMBER_MIN_PHP_VERSION, ">=") &&
128
  /*
129
  Hook after system config & Hooks are loaded.
130
  */
131
- do_action("ws_plugin__s2member_config_hooks_loaded");
132
  /*
133
  Load a possible Pro module, if/when available.
134
  */
@@ -149,7 +149,7 @@ if (version_compare (PHP_VERSION, WS_PLUGIN__S2MEMBER_MIN_PHP_VERSION, ">=") &&
149
  /*
150
  Hook after loaded.
151
  */
152
- do_action("ws_plugin__s2member_after_loaded");
153
  }
154
  /*
155
  Else NOT compatible. Do we need admin compatibility errors now?
19
  */
20
  /* -- This section for WordPress® parsing. ------------------------------------------------------------------------------
21
 
22
+ Version: 111017
23
+ Stable tag: 111017
24
  Framework: WS-P-110523
25
 
26
  SSL Compatible: yes
65
 
66
  -- end section for WordPress® parsing. ------------------------------------------------------------------------------- */
67
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
68
+ exit ("Do not access this file directly.");
69
  /**
70
  * The installed version of s2Member.
71
  *
75
  * @var str
76
  */
77
  if (!defined ("WS_PLUGIN__S2MEMBER_VERSION"))
78
+ define ("WS_PLUGIN__S2MEMBER_VERSION", "111017");
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", "111017");
109
  /*
110
  Several compatibility checks.
111
  If all pass, load the s2Member plugin.
116
  /*
117
  Hook before loaded.
118
  */
119
+ do_action ("ws_plugin__s2member_before_loaded");
120
  /*
121
  System configuraton.
122
  */
128
  /*
129
  Hook after system config & Hooks are loaded.
130
  */
131
+ do_action ("ws_plugin__s2member_config_hooks_loaded");
132
  /*
133
  Load a possible Pro module, if/when available.
134
  */
149
  /*
150
  Hook after loaded.
151
  */
152
+ do_action ("ws_plugin__s2member_after_loaded");
153
  }
154
  /*
155
  Else NOT compatible. Do we need admin compatibility errors now?