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

Version Description

= v160801 =

(Maintenance Release) Upgrade immediately.

Download this release

Release Info

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

Code changes from version 170221 to 170524

Files changed (71) hide show
  1. readme.txt +34 -4
  2. s2member.php +5 -5
  3. src/includes/classes/admin-notices.inc.php +2 -2
  4. src/includes/classes/files-in.inc.php +1 -1
  5. src/includes/classes/querys.inc.php +10 -10
  6. src/includes/classes/registrations.inc.php +1 -1
  7. src/includes/classes/sc-eots-in.inc.php +3 -1
  8. src/includes/classes/utils-defuse.inc.php +131 -0
  9. src/includes/classes/utils-encryption.inc.php +224 -228
  10. src/includes/classes/utils-time.inc.php +11 -10
  11. src/includes/functions/class-autoloader.inc.php +1 -0
  12. src/includes/menu-pages/api-ops.inc.php +2 -0
  13. src/includes/menu-pages/down-ops.inc.php +2 -0
  14. src/includes/menu-pages/els-ops.inc.php +2 -0
  15. src/includes/menu-pages/gen-ops.inc.php +2 -0
  16. src/includes/menu-pages/help.inc.php +2 -0
  17. src/includes/menu-pages/integrations.inc.php +2 -0
  18. src/includes/menu-pages/logs.inc.php +2 -0
  19. src/includes/menu-pages/menu-pages-s.min.js +2 -1
  20. src/includes/menu-pages/menu-pages.css +105 -106
  21. src/includes/menu-pages/menu-pages.js +3 -3
  22. src/includes/menu-pages/menu-pages.min.js +1 -1
  23. src/includes/menu-pages/mms-ops.inc.php +2 -0
  24. src/includes/menu-pages/paypal-buttons.inc.php +2 -0
  25. src/includes/menu-pages/paypal-ops.inc.php +3 -1
  26. src/includes/menu-pages/res-ops.inc.php +2 -0
  27. src/includes/menu-pages/scripting.inc.php +4 -2
  28. src/includes/menu-pages/start.inc.php +2 -0
  29. src/includes/menu-pages/trk-ops.inc.php +2 -0
  30. src/includes/syscon.inc.php +19 -2
  31. src/includes/translations/s2member.pot +48 -48
  32. src/vendor/autoload.php +1 -1
  33. src/vendor/composer/autoload_classmap.php +14 -0
  34. src/vendor/composer/autoload_files.php +10 -0
  35. src/vendor/composer/autoload_real.php +17 -3
  36. src/vendor/composer/installed.json +113 -1
  37. src/vendor/defuse/php-encryption/LICENSE +21 -0
  38. src/vendor/defuse/php-encryption/dist/Makefile +37 -0
  39. src/vendor/defuse/php-encryption/dist/box.json +25 -0
  40. src/vendor/defuse/php-encryption/dist/signingkey.asc +52 -0
  41. src/vendor/defuse/php-encryption/src/Core.php +434 -0
  42. src/vendor/defuse/php-encryption/src/Crypto.php +372 -0
  43. src/vendor/defuse/php-encryption/src/DerivedKeys.php +37 -0
  44. src/vendor/defuse/php-encryption/src/Encoding.php +212 -0
  45. src/vendor/defuse/php-encryption/src/Exception/BadFormatException.php +7 -0
  46. src/vendor/defuse/php-encryption/src/Exception/CryptoException.php +7 -0
  47. src/vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php +7 -0
  48. src/vendor/defuse/php-encryption/src/Exception/IOException.php +7 -0
  49. src/vendor/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php +7 -0
  50. src/vendor/defuse/php-encryption/src/File.php +755 -0
  51. src/vendor/defuse/php-encryption/src/Key.php +84 -0
  52. src/vendor/defuse/php-encryption/src/KeyOrPassword.php +119 -0
  53. src/vendor/defuse/php-encryption/src/KeyProtectedByPassword.php +112 -0
  54. src/vendor/defuse/php-encryption/src/RuntimeTests.php +242 -0
  55. src/vendor/paragonie/random_compat/LICENSE +22 -0
  56. src/vendor/paragonie/random_compat/build-phar.sh +5 -0
  57. src/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey +5 -0
  58. src/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc +11 -0
  59. src/vendor/paragonie/random_compat/lib/byte_safe_strings.php +181 -0
  60. src/vendor/paragonie/random_compat/lib/cast_to_int.php +74 -0
  61. src/vendor/paragonie/random_compat/lib/error_polyfill.php +49 -0
  62. src/vendor/paragonie/random_compat/lib/random.php +223 -0
  63. src/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php +88 -0
  64. src/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php +167 -0
  65. src/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php +88 -0
  66. src/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php +92 -0
  67. src/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php +77 -0
  68. src/vendor/paragonie/random_compat/lib/random_int.php +190 -0
  69. src/vendor/paragonie/random_compat/other/build_phar.php +57 -0
  70. src/vendor/paragonie/random_compat/psalm-autoload.php +9 -0
  71. src/vendor/paragonie/random_compat/psalm.xml +15 -0
readme.txt CHANGED
@@ -1,7 +1,7 @@
1
  === s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members) ===
2
 
3
- Version: 170221
4
- Stable tag: 170221
5
 
6
  SSL Compatible: yes
7
  bbPress® Compatible: yes
@@ -17,11 +17,11 @@ Authorize.Net® Compatible: yes w/s2Member® Pro
17
  Google® Checkout Compatible: yes w/s2Member® Pro
18
  ClickBank® Compatible: yes w/s2Member® Pro
19
 
20
- Tested up to: 4.8-alpha
21
  Requires at least: 4.2
22
 
23
  Requires PHP: 5.2
24
- Tested up to PHP: 7.0.15
25
 
26
  Copyright: © 2009 WebSharks, Inc.
27
  License: GNU General Public License v2 or later.
@@ -171,6 +171,36 @@ Released under the terms of the [GNU General Public License](http://www.gnu.org/
171
 
172
  == Changelog ==
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  = v170221 =
175
 
176
  - (s2Member/s2Member Pro) **JW Player v7:** This release adds support for JW Player v7 in the `[s2Stream /]` shortcode. See [Issue #774](https://github.com/websharks/s2member/issues/774).
1
  === s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members) ===
2
 
3
+ Version: 170524
4
+ Stable tag: 170524
5
 
6
  SSL Compatible: yes
7
  bbPress® Compatible: yes
17
  Google® Checkout Compatible: yes w/s2Member® Pro
18
  ClickBank® Compatible: yes w/s2Member® Pro
19
 
20
+ Tested up to: 4.9-alpha
21
  Requires at least: 4.2
22
 
23
  Requires PHP: 5.2
24
+ Tested up to PHP: 7.0.17
25
 
26
  Copyright: © 2009 WebSharks, Inc.
27
  License: GNU General Public License v2 or later.
171
 
172
  == Changelog ==
173
 
174
+ = v170524 =
175
+
176
+ - (s2Member/s2Member Pro) **PHP v7 Compat. Enhancements**: This release adds an integration with the [Defuse encryption library](https://github.com/defuse/php-encryption) for PHP, making it possible for s2Member to move away from the `mcrypt_*()` family of functions in versions of PHP >= 7.0.4, where the mcrypt library has been deprecated — `mcrypt_*()` will eventually be removed entirely.
177
+
178
+ Starting with this release of s2Member, if you're running s2Member on PHP v7.0.4+, the Defuse library will be used automatically instead of mcrypt. See [Issue #1079](https://github.com/websharks/s2member/pull/1079).
179
+
180
+ **Note:** Backward compatibility with mcrypt functions will remain for now, especially for the decryption of any data that was previously encrypted using RIJNDAEL-256; i.e., data encrypted by a previous release of the s2Member software. s2Member is capable of automatically determining the algorithm originally used to encrypt, which allows it to decrypt data using Defuse, else RIJNDAEL-256, else XOR as a last-ditch fallback.
181
+
182
+ **API Functions:** `s2member_encrypt()` & `s2member_decrypt()`. These two API Functions provided by s2Member are impacted by this change. Starting with this release, if you're running s2Member on PHP v7.0.4+, the Defuse library is used automatically instead of the older mcrypt extension. Not to worry though; the `s2member_decrypt()` function is still capable of decrypting data encrypted by previous versions of the s2Member software.
183
+
184
+ - (s2Member/s2Member Pro) **UI Fix:** All menu page notices should be given the `notice` class and the additional `notice-[type]` class instead of the older generic `updated` and `error` classes. Fixed in this release. Related to [Issue #1034](https://github.com/websharks/s2member/issues/1034)
185
+
186
+ - (s2Member/s2Member Pro) **UI Fix:** Plugins displaying Dashboard-wide notices using the older `updated` and `error` classes should be handled better to avoid displaying them below the s2Member header (on s2Member menu pages) and with non-default WordPress styles. See: [Issue #1034](https://github.com/websharks/s2member/issues/1034)
187
+
188
+ - (s2Member/s2Member Pro) **UI Fix:** Improving color highlighting in input fields following a media library insertion; e.g., when adding a custom logo to the login/registration page.
189
+
190
+ - (s2Member Pro) **Bug Fix:** Merchants using PayPal Pro (Payflow Edition) to charge a fixed non-recurring fee following an initial 100% free trial period, were seeing their member accounts EOTd after the trial ended, instead of the EOT Time being set to the end of the fixed term period. Props @patdumond, James Hall, and many others for reporting this in the forums and at GitHub. See [Issue #1077](https://github.com/websharks/s2member/issues/1077).
191
+
192
+ - (s2Member Pro) **Bug Fix:** Updating PHP syntax in Simple Export tool, for compatibility w/ modern versions of PHP. Props @patdumond for reporting and helping us locate the underlying cause of this problem. See [Issue #1055](https://github.com/websharks/s2member/issues/1055).
193
+
194
+ - (s2Member Pro) **Stripe Bug Fix:** This releases corrects a seemingly rare conflict between s2Member and Stripe on certain mobile devices and in certain scenarios. In a case we examined, there was a problematic CSS `z-index` setting in the s2Member source code that was, at times, causing problems in the stacking order, which resulted in a user's inability to enter details into the Stripe popup form. In this release, s2Member's customization of the `z-index` stacking order has been removed entirely, as it is no longer necessary in the latest revision of the Stripe popup, which already handles `z-index` adequately. Props @jaspuduf for reporting and for helping us diagnose the problem. See [Issue #1057](https://github.com/websharks/s2member/issues/1057).
195
+
196
+ - (s2Member/s2Member Pro) **Security Enhancement:** This release removes the `%%user_pass%%` Replacement Code from the API Registration Notification email that is sent to a site owner; i.e., when/if it is configured by a site owner. Props @patdumond see [Issue #954](https://github.com/websharks/s2member/issues/954). This Replacement Code was removed as a security precaution.
197
+
198
+ - (s2Member/s2Member Pro) **Bug Fix:** Resolving internal warning: 'PHP Warning: Parameter 2 to c_ws_plugin__s2member_querys::_query_level_access_coms() expected to be a reference, value given'. This was resolved by removing the strict 'by reference' requirement from the list of parameters requested by s2Member.
199
+
200
+ - (s2Member/s2Member Pro) **Bug Fix:** Resolving internal warning: 'PHP Warning: Illegal string offset 'user_id' in s2member/src/includes/classes/sc-eots-in.inc.php'. This was resolved by typecasting `$attr` to an array in cases where WordPress core passes this as a string; e.g., when there are no attributes.
201
+
202
+ - (s2Member Pro) **Bug Fix:** Incorrect default option value for `reject_prepaid=""` attribute in Stripe Pro-Forms. See: [Issue #1089](https://github.com/websharks/s2member/issues/1089)
203
+
204
  = v170221 =
205
 
206
  - (s2Member/s2Member Pro) **JW Player v7:** This release adds support for JW Player v7 in the `[s2Stream /]` shortcode. See [Issue #774](https://github.com/websharks/s2member/issues/774).
s2member.php CHANGED
@@ -20,8 +20,8 @@
20
  */
21
  /* -- This section for WordPress parsing. ------------------------------------------------------------------------------
22
 
23
- Version: 170221
24
- Stable tag: 170221
25
 
26
  SSL Compatible: yes
27
  bbPress Compatible: yes
@@ -40,7 +40,7 @@ Tested up to: 4.8-alpha
40
  Requires at least: 4.2
41
 
42
  Requires PHP: 5.2
43
- Tested up to PHP: 7.0.15
44
 
45
  Copyright: © 2009 WebSharks, Inc.
46
  License: GNU General Public License
@@ -77,7 +77,7 @@ if(!defined('WPINC')) // MUST have WordPress.
77
  *
78
  * @var string
79
  */
80
- ${__FILE__}['tmp'] = '170221'; //version//
81
  if(!defined('WS_PLUGIN__S2MEMBER_VERSION'))
82
  define('WS_PLUGIN__S2MEMBER_VERSION', ${__FILE__}['tmp']);
83
  /**
@@ -110,7 +110,7 @@ if(!defined('WS_PLUGIN__S2MEMBER_MIN_WP_VERSION'))
110
  *
111
  * @var string
112
  */
113
- ${__FILE__}['tmp'] = '170221'; //version//
114
  if(!defined('WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION'))
115
  define('WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION', ${__FILE__}['tmp']);
116
  /*
20
  */
21
  /* -- This section for WordPress parsing. ------------------------------------------------------------------------------
22
 
23
+ Version: 170524
24
+ Stable tag: 170524
25
 
26
  SSL Compatible: yes
27
  bbPress Compatible: yes
40
  Requires at least: 4.2
41
 
42
  Requires PHP: 5.2
43
+ Tested up to PHP: 7.0.17
44
 
45
  Copyright: © 2009 WebSharks, Inc.
46
  License: GNU General Public License
77
  *
78
  * @var string
79
  */
80
+ ${__FILE__}['tmp'] = '170524'; //version//
81
  if(!defined('WS_PLUGIN__S2MEMBER_VERSION'))
82
  define('WS_PLUGIN__S2MEMBER_VERSION', ${__FILE__}['tmp']);
83
  /**
110
  *
111
  * @var string
112
  */
113
+ ${__FILE__}['tmp'] = '170524'; //version//
114
  if(!defined('WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION'))
115
  define('WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION', ${__FILE__}['tmp']);
116
  /*
src/includes/classes/admin-notices.inc.php CHANGED
@@ -83,13 +83,13 @@ if(!class_exists('c_ws_plugin__s2member_admin_notices'))
83
  {
84
  if($dismiss && !empty($dismissal_link))
85
  $notice = $dismissal_link.$notice;
86
- echo '<div class="error fade"><p>'.$notice.'</p></div>';
87
  }
88
  else if($notice && is_string($notice))
89
  {
90
  if($dismiss && !empty($dismissal_link))
91
  $notice = $dismissal_link.$notice;
92
- echo '<div class="updated fade"><p>'.$notice.'</p></div>';
93
  }
94
  do_action('ws_plugin__s2member_after_display_admin_notice', get_defined_vars());
95
  }
83
  {
84
  if($dismiss && !empty($dismissal_link))
85
  $notice = $dismissal_link.$notice;
86
+ echo '<div class="notice notice-error"><p>'.$notice.'</p></div>';
87
  }
88
  else if($notice && is_string($notice))
89
  {
90
  if($dismiss && !empty($dismissal_link))
91
  $notice = $dismissal_link.$notice;
92
+ echo '<div class="notice notice-info"><p>'.$notice.'</p></div>';
93
  }
94
  do_action('ws_plugin__s2member_after_display_admin_notice', get_defined_vars());
95
  }
src/includes/classes/files-in.inc.php CHANGED
@@ -293,7 +293,7 @@ if(!class_exists('c_ws_plugin__s2member_files_in'))
293
 
294
  $file = $GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir'].'/'.$req['file_download'];
295
  $pathinfo = (!$using_amazon_storage && $file) ? pathinfo($file) : array();
296
- $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : 'application/octet-stream';
297
  $disposition = (($inline) ? 'inline' : 'attachment').'; filename="'.c_ws_plugin__s2member_utils_strings::esc_dq($basename).'"; filename*=UTF-8\'\''.rawurlencode($basename);
298
  $length = (!$using_amazon_storage && $file) ? filesize($file) : -1;
299
 
293
 
294
  $file = $GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir'].'/'.$req['file_download'];
295
  $pathinfo = (!$using_amazon_storage && $file) ? pathinfo($file) : array();
296
+ $mimetype = !empty($mimetypes[$extension]) ? $mimetypes[$extension] : 'application/octet-stream';
297
  $disposition = (($inline) ? 'inline' : 'attachment').'; filename="'.c_ws_plugin__s2member_utils_strings::esc_dq($basename).'"; filename*=UTF-8\'\''.rawurlencode($basename);
298
  $length = (!$using_amazon_storage && $file) ? filesize($file) : -1;
299
 
src/includes/classes/querys.inc.php CHANGED
@@ -49,9 +49,9 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
49
  *
50
  * @attaches-to ``add_action('pre_get_posts');``
51
  *
52
- * @param WP_Query $wp_query Expects ``$wp_query`` by reference.
53
  */
54
- public static function force_query_level_access(&$wp_query = NULL)
55
  {
56
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
57
  do_action('ws_plugin__s2member_before_force_query_level_access', get_defined_vars());
@@ -75,7 +75,7 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
75
  *
76
  * @attaches-to ``add_action('pre_get_posts');``
77
  *
78
- * @param WP_Query $wp_query Expects ``$wp_query`` by reference, from the Filter.
79
  * @param bool $force Optional. Defaults to false. If true, we bypass all standard conditions.
80
  * However, s2Member will NEVER bypass `supress_filters`.
81
  *
@@ -87,7 +87,7 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
87
  *
88
  * @see Workaround for bbPress and the `s` key. See: <http://bit.ly/1obLpv4>
89
  */
90
- public static function query_level_access(&$wp_query = NULL, $force = FALSE)
91
  {
92
  global $wpdb; // Global DB object reference.
93
 
@@ -263,9 +263,9 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
263
  * @package s2Member\Queries
264
  * @since 3.5
265
  *
266
- * @param WP_Query $wp_query Expects ``$wp_query`` by reference.
267
  */
268
- public static function _query_level_access_sys(&$wp_query = NULL)
269
  {
270
  global $wpdb; // Global DB object reference.
271
 
@@ -340,11 +340,11 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
340
  * @attaches-to ``add_filter('comment_feed_where');``
341
  *
342
  * @param string $cwhere Expects the SQL `WHERE` portion to be passed through by the Filter.
343
- * @param WP_Query $wp_query Expects ``$wp_query`` by reference, from the Filter.
344
  *
345
  * @return string The revised ``$cwhere`` string.
346
  */
347
- public static function _query_level_access_coms($cwhere = '', &$wp_query = NULL)
348
  {
349
  global $wpdb; // Global DB object reference.
350
 
@@ -368,11 +368,11 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
368
  * @package s2Member\Queries
369
  * @since 110912
370
  *
371
- * @param WP_Query $wp_query Expects ``$wp_query`` by reference.
372
  *
373
  * @return bool True if it's an AJAX search via `admin-ajax.php`, else false.
374
  */
375
- public static function _is_admin_ajax_search(&$wp_query = NULL)
376
  {
377
  global $wpdb; // Global DB object reference.
378
 
49
  *
50
  * @attaches-to ``add_action('pre_get_posts');``
51
  *
52
+ * @param WP_Query $wp_query Expects ``$wp_query``.
53
  */
54
+ public static function force_query_level_access($wp_query = NULL)
55
  {
56
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
57
  do_action('ws_plugin__s2member_before_force_query_level_access', get_defined_vars());
75
  *
76
  * @attaches-to ``add_action('pre_get_posts');``
77
  *
78
+ * @param WP_Query $wp_query Expects ``$wp_query`` from the Filter.
79
  * @param bool $force Optional. Defaults to false. If true, we bypass all standard conditions.
80
  * However, s2Member will NEVER bypass `supress_filters`.
81
  *
87
  *
88
  * @see Workaround for bbPress and the `s` key. See: <http://bit.ly/1obLpv4>
89
  */
90
+ public static function query_level_access($wp_query = NULL, $force = FALSE)
91
  {
92
  global $wpdb; // Global DB object reference.
93
 
263
  * @package s2Member\Queries
264
  * @since 3.5
265
  *
266
+ * @param WP_Query $wp_query Expects ``$wp_query``.
267
  */
268
+ public static function _query_level_access_sys($wp_query = NULL)
269
  {
270
  global $wpdb; // Global DB object reference.
271
 
340
  * @attaches-to ``add_filter('comment_feed_where');``
341
  *
342
  * @param string $cwhere Expects the SQL `WHERE` portion to be passed through by the Filter.
343
+ * @param WP_Query $wp_query Expects ``$wp_query`` from the Filter.
344
  *
345
  * @return string The revised ``$cwhere`` string.
346
  */
347
+ public static function _query_level_access_coms($cwhere = '', $wp_query = NULL)
348
  {
349
  global $wpdb; // Global DB object reference.
350
 
368
  * @package s2Member\Queries
369
  * @since 110912
370
  *
371
+ * @param WP_Query $wp_query Expects ``$wp_query``.
372
  *
373
  * @return bool True if it's an AJAX search via `admin-ajax.php`, else false.
374
  */
375
+ public static function _is_admin_ajax_search($wp_query = NULL)
376
  {
377
  global $wpdb; // Global DB object reference.
378
 
src/includes/classes/registrations.inc.php CHANGED
@@ -1138,7 +1138,7 @@ if(!class_exists('c_ws_plugin__s2member_registrations'))
1138
  $msg .= 'user_full_name: %%user_full_name%%'."\n";
1139
  $msg .= 'user_email: %%user_email%%'."\n";
1140
  $msg .= 'user_login: %%user_login%%'."\n";
1141
- $msg .= 'user_pass: %%user_pass%%'."\n";
1142
  $msg .= 'user_ip: %%user_ip%%'."\n";
1143
  $msg .= 'user_id: %%user_id%%'."\n";
1144
 
1138
  $msg .= 'user_full_name: %%user_full_name%%'."\n";
1139
  $msg .= 'user_email: %%user_email%%'."\n";
1140
  $msg .= 'user_login: %%user_login%%'."\n";
1141
+ //$msg .= 'user_pass: %%user_pass%%'."\n";
1142
  $msg .= 'user_ip: %%user_ip%%'."\n";
1143
  $msg .= 'user_id: %%user_id%%'."\n";
1144
 
src/includes/classes/sc-eots-in.inc.php CHANGED
@@ -50,6 +50,8 @@ if(!class_exists('c_ws_plugin__s2member_sc_eots_in'))
50
 
51
  c_ws_plugin__s2member_no_cache::no_cache_constants(true);
52
 
 
 
53
  $mode = ''; // Initialize shortcode mode and validate.
54
  if(!empty($attr['mode']) && in_array(strtolower($attr['mode']), array('fixed', 'next'), TRUE))
55
  $mode = strtolower($attr['mode']); // A specific mode; i.e., `fixed`, `next`.
@@ -76,7 +78,7 @@ if(!class_exists('c_ws_plugin__s2member_sc_eots_in'))
76
  'next_format' => $mode ? '%%date%%' : '<strong class="s2member-sc-eot-label -next">'._x('Next Payment:', 's2member-front', 's2member').'</strong> <span class="s2member-sc-eot-date -next">%%date%%</span>',
77
  'empty_format' => $mode ? (in_array($subscr_gateway, array('stripe', 'paypal', 'clickbank'), TRUE) ? _x('N/A', 's2member-front', 's2member') : _x('—', 's2member-front', 's2member')) : '',
78
  ),
79
- c_ws_plugin__s2member_utils_strings::trim_qts_deep((array)$attr)
80
  );
81
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
82
  do_action('ws_plugin__s2member_before_sc_eot_details_after_shortcode_atts', get_defined_vars());
50
 
51
  c_ws_plugin__s2member_no_cache::no_cache_constants(true);
52
 
53
+ $attr = (array) $attr; // Force an array.
54
+
55
  $mode = ''; // Initialize shortcode mode and validate.
56
  if(!empty($attr['mode']) && in_array(strtolower($attr['mode']), array('fixed', 'next'), TRUE))
57
  $mode = strtolower($attr['mode']); // A specific mode; i.e., `fixed`, `next`.
78
  'next_format' => $mode ? '%%date%%' : '<strong class="s2member-sc-eot-label -next">'._x('Next Payment:', 's2member-front', 's2member').'</strong> <span class="s2member-sc-eot-date -next">%%date%%</span>',
79
  'empty_format' => $mode ? (in_array($subscr_gateway, array('stripe', 'paypal', 'clickbank'), TRUE) ? _x('N/A', 's2member-front', 's2member') : _x('—', 's2member-front', 's2member')) : '',
80
  ),
81
+ c_ws_plugin__s2member_utils_strings::trim_qts_deep($attr)
82
  );
83
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
84
  do_action('ws_plugin__s2member_before_sc_eot_details_after_shortcode_atts', get_defined_vars());
src/includes/classes/utils-defuse.inc.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // @codingStandardsIgnoreFile
3
+ /**
4
+ * Encryption utilities.
5
+ *
6
+ * @since 170418 Defuse.
7
+ */
8
+ use Defuse\Crypto\Key;
9
+ use Defuse\Crypto\Crypto;
10
+ use c_ws_plugin__s2member_utils_strings as s;
11
+
12
+ if (!defined('WPINC')) { // MUST have.
13
+ exit('Do not access this file directly.');
14
+ }
15
+ if (!class_exists('c_ws_plugin__s2member_utils_defuse')) {
16
+ /**
17
+ * Encryption utilities.
18
+ *
19
+ * @since 170418 Defuse.
20
+ */
21
+ class c_ws_plugin__s2member_utils_defuse
22
+ {
23
+ /**
24
+ * Defuse key.
25
+ *
26
+ * @since 170418 Defuse.
27
+ *
28
+ * @param string $key A custom key.
29
+ *
30
+ * @return string Defuse encryption key.
31
+ */
32
+ public static function key($key = '')
33
+ {
34
+ $key = (string) $key;
35
+
36
+ if (isset($key[0])) { // Custom?
37
+ if (strpos($key, 'def00000') === 0) {
38
+ return $key; // Defuse key.
39
+ }
40
+ $sec_key = c_ws_plugin__s2member_utils_encryption::key($key);
41
+ $def_combo_keys = $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_custom_combo_encryption_keys'];
42
+
43
+ if ($sec_key && !empty($def_combo_keys[$sec_key])) {
44
+ return $def_combo_keys[$sec_key]; // Use existing key.
45
+ }
46
+ try { // Catch Defuse exceptions.
47
+ if (!($def_key = Key::createNewRandomKey()->saveToAsciiSafeString())) {
48
+ throw new Exception('Defuse keygen failure.');
49
+ }
50
+ } catch (Throwable $Exception) {
51
+ throw new Exception($Exception->getMessage());
52
+ }
53
+ $def_combo_keys[$sec_key] = $def_key;
54
+ array_unshift($def_combo_keys, 'update-signal');
55
+ $options['ws_plugin__s2member_def_custom_combo_encryption_keys'] = $def_combo_keys;
56
+ c_ws_plugin__s2member_menu_pages::update_all_options($options, true, false, false, false, false);
57
+ //
58
+ } else { // Default behavior is to use the configured key.
59
+ $sec_key = c_ws_plugin__s2member_utils_encryption::key();
60
+ $def_combo_key = $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key'];
61
+
62
+ if ($sec_key && $def_combo_key && strpos($def_combo_key, $sec_key."\n") === 0
63
+ && ($def_key = str_replace($sec_key."\n", '', $def_combo_key))) {
64
+ return $def_key; // Use existing key.
65
+ }
66
+ try { // Catch Defuse exceptions.
67
+ if (!($def_key = Key::createNewRandomKey()->saveToAsciiSafeString())) {
68
+ throw new Exception('Defuse keygen failure.');
69
+ }
70
+ } catch (Throwable $Exception) {
71
+ throw new Exception($Exception->getMessage());
72
+ }
73
+ $options['ws_plugin__s2member_def_combo_encryption_key'] = $sec_key."\n".$def_key;
74
+ c_ws_plugin__s2member_menu_pages::update_all_options($options, true, false, false, false, false);
75
+ }
76
+ return $def_key;
77
+ }
78
+
79
+ /**
80
+ * Defuse encryption.
81
+ *
82
+ * @since 170418 Defuse.
83
+ *
84
+ * @param string $string String to encrypt.
85
+ * @param string $key A custom key passed to `::key()`.
86
+ *
87
+ * @return string Encrypted string w/ a URL-safe base64 wrapper.
88
+ */
89
+ public static function encrypt($string, $key = '')
90
+ {
91
+ $string = (string) $string;
92
+
93
+ if (!isset($string[0])) {
94
+ return ''; // Not possible.
95
+ } // Empty string is an empty string.
96
+
97
+ try { // Catch Defuse exceptions.
98
+ $Key = Key::loadFromAsciiSafeString(self::key($key));
99
+ $encrypted = Crypto::encrypt($string, $Key, false);
100
+ return $base64 = s::base64_url_safe_encode($encrypted);
101
+ } catch (Throwable $Exception) {
102
+ throw new Exception($Exception->getMessage());
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Defuse decryption.
108
+ *
109
+ * @since 170418 Defuse.
110
+ *
111
+ * @param string $base64 String to decrypt.
112
+ * @param string $key A custom key passed to `::key()`.
113
+ *
114
+ * @return string Decrypted string.
115
+ */
116
+ public static function decrypt($base64, $key = '')
117
+ {
118
+ if (!is_string($base64) || !isset($base64[0])) {
119
+ return ''; // Not possible.
120
+ } // Fail when not a string or empty.
121
+
122
+ try { // Catch Defuse exceptions.
123
+ $Key = Key::loadFromAsciiSafeString(self::key($key));
124
+ $encrypted = s::base64_url_safe_decode($base64);
125
+ return $string = Crypto::decrypt($encrypted, $Key, false);
126
+ } catch (Throwable $Exception) {
127
+ return ''; // Soft failure.
128
+ }
129
+ }
130
+ }
131
+ }
src/includes/classes/utils-encryption.inc.php CHANGED
@@ -3,233 +3,229 @@
3
  /**
4
  * Encryption utilities.
5
  *
6
- * Copyright: © 2009-2011
7
- * {@link http://websharks-inc.com/ WebSharks, Inc.}
8
- * (coded in the USA)
9
- *
10
- * Released under the terms of the GNU General Public License.
11
- * You should have received a copy of the GNU General Public License,
12
- * along with this software. In the main directory, see: /licensing/
13
- * If not, see: {@link http://www.gnu.org/licenses/}.
14
- *
15
- * @package s2Member\Utilities
16
- * @since 3.5
17
  */
18
- if(!defined('WPINC')) // MUST have WordPress.
19
- exit ('Do not access this file directly.');
20
-
21
- if(!class_exists('c_ws_plugin__s2member_utils_encryption'))
22
- {
23
- /**
24
- * Encryption utilities.
25
- *
26
- * @package s2Member\Utilities
27
- * @since 3.5
28
- */
29
- class c_ws_plugin__s2member_utils_encryption
30
- {
31
- /**
32
- * Determines the proper encryption/decryption Key to use.
33
- *
34
- * @package s2Member\Utilities
35
- * @since 111106
36
- *
37
- * @param string $key Optional. Attempt to force a specific Key. Defaults to the one configured for s2Member. Short of that, defaults to: ``wp_salt()``.
38
- *
39
- * @return string Proper encryption/decryption Key. If ``$key`` is passed in, and it validates, we'll return that. Otherwise use a default Key.
40
- */
41
- public static function key($key = '')
42
- {
43
- if(($key = trim((string)$key)))
44
- return $key;
45
-
46
- if(($key = trim($GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key'])))
47
- return $key;
48
-
49
- if(($key = trim(wp_salt())))
50
- return $key;
51
-
52
- return ($key = md5($_SERVER['HTTP_HOST']));
53
- }
54
-
55
- /**
56
- * A unique, unguessable, non-numeric, caSe-insensitive key (20 chars max).
57
- *
58
- * @since 150124 Adding gift code generation.
59
- *
60
- * @note 32-bit systems usually have `PHP_INT_MAX` = `2147483647`.
61
- * We limit `mt_rand()` to a max of `999999999`.
62
- *
63
- * @note A max possible length of 20 chars assumes this function
64
- * will not be called after `Sat, 20 Nov 2286 17:46:39 GMT`.
65
- * At which point a UNIX timestamp will grow in size.
66
- *
67
- * @note Key always begins with a `k` to prevent PHP's `is_numeric()`
68
- * function from ever thinking it's a number in a different representation.
69
- * See: <http://php.net/manual/en/function.is-numeric.php> for further details.
70
- *
71
- * @return string A unique, unguessable, non-numeric, caSe-insensitive key (20 chars max).
72
- */
73
- public static function uunnci_key_20_max()
74
- {
75
- $microtime_19_max = number_format(microtime(TRUE), 9, '.', '');
76
- // e.g., `9999999999`.`999999999` (max decimals: `9`, max overall precision: `19`).
77
- // Assuming timestamp is never > 10 digits; i.e., before `Sat, 20 Nov 2286 17:46:39 GMT`.
78
-
79
- list($seconds_10_max, $microseconds_9_max) = explode('.', $microtime_19_max, 2);
80
- // e.g., `array(`9999999999`, `999999999`)`. Max total digits combined: `19`.
81
-
82
- $seconds_base36 = base_convert($seconds_10_max, '10', '36'); // e.g., max `9999999999`, to base 36.
83
- $microseconds_base36 = base_convert($microseconds_9_max, '10', '36'); // e.g., max `999999999`, to base 36.
84
- $mt_rand_base36 = base_convert(mt_rand(1, 999999999), '10', '36'); // e.g., max `999999999`, to base 36.
85
- $key = 'k'.$mt_rand_base36.$seconds_base36.$microseconds_base36; // e.g., `kgjdgxr4ldqpdrgjdgxr`.
86
-
87
- return $key; // Max possible value: `kgjdgxr4ldqpdrgjdgxr` (20 chars).
88
- }
89
-
90
- /**
91
- * RIJNDAEL 256: two-way encryption/decryption, with a URL-safe base64 wrapper.
92
- *
93
- * Falls back on XOR encryption/decryption when/if mcrypt is not possible.
94
- *
95
- * @package s2Member\Utilities
96
- * @since 3.5
97
- *
98
- * @param string $string A string of data to encrypt.
99
- * @param string $key Optional. Key used for encryption. Defaults to the one configured for s2Member. Short of that, defaults to: ``wp_salt()``.
100
- * @param bool $w_md5_cs Optional. Defaults to true. When true, an MD5 checksum is used in the encrypted string *(recommended)*.
101
- *
102
- * @return string Encrypted string.
103
- */
104
- public static function encrypt($string = '', $key = '', $w_md5_cs = TRUE)
105
- {
106
- if(function_exists('mcrypt_encrypt') && in_array('rijndael-256', mcrypt_list_algorithms()) && in_array('cbc', mcrypt_list_modes()))
107
- {
108
- $string = is_string($string) ? $string : '';
109
- $string = isset($string[0]) ? '~r2|'.$string : '';
110
-
111
- $key = c_ws_plugin__s2member_utils_encryption::key($key);
112
- $key = substr($key, 0, mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC));
113
-
114
- $iv = c_ws_plugin__s2member_utils_strings::random_str_gen(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), FALSE);
115
-
116
- if(isset($string[0]) && is_string($e = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_CBC, $iv)) && isset($e[0]))
117
- $e = '~r2:'.$iv.($w_md5_cs ? ':'.md5($e) : '').'|'.$e;
118
-
119
- return isset($e) && is_string($e) && isset($e[0])
120
- ? ($base64 = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($e))
121
- : ''; // Default to empty string.
122
- }
123
- return c_ws_plugin__s2member_utils_encryption::xencrypt($string, $key, $w_md5_cs);
124
- }
125
-
126
- /**
127
- * RIJNDAEL 256: two-way encryption/decryption, with a URL-safe base64 wrapper.
128
- *
129
- * Falls back on XOR encryption/decryption when mcrypt is not available.
130
- *
131
- * @package s2Member\Utilities
132
- * @since 3.5
133
- *
134
- * @param string $base64 A string of data to decrypt. Should still be base64 encoded.
135
- * @param string $key Optional. Key used originally for encryption. Defaults to the one configured for s2Member. Short of that, defaults to: ``wp_salt()``.
136
- *
137
- * @return string Decrypted string.
138
- */
139
- public static function decrypt($base64 = '', $key = '')
140
- {
141
- $base64 = is_string($base64) ? $base64 : '';
142
- $e = isset($base64[0]) ? c_ws_plugin__s2member_utils_strings::base64_url_safe_decode($base64) : '';
143
-
144
- if(function_exists('mcrypt_decrypt') && in_array('rijndael-256', mcrypt_list_algorithms()) && in_array('cbc', mcrypt_list_modes()))
145
- if(isset($e[0]) && preg_match('/^~r2\:([a-zA-Z0-9]+)(?:\:([a-zA-Z0-9]+))?\|(.*)$/s', $e, $iv_md5_e))
146
- {
147
- $key = c_ws_plugin__s2member_utils_encryption::key($key);
148
- $key = substr($key, 0, mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC));
149
-
150
- if(isset($iv_md5_e[3][0]) && (empty($iv_md5_e[2]) || $iv_md5_e[2] === md5($iv_md5_e[3])))
151
- $d = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $iv_md5_e[3], MCRYPT_MODE_CBC, $iv_md5_e[1]);
152
-
153
- if(isset($d) && is_string($d) && isset($d[0]))
154
- if(strlen($d = preg_replace('/^~r2\|/', '', $d, 1, $r2)) && $r2)
155
- $d = rtrim($d, "\0\4"); // See: <http://www.asciitable.com/>.
156
- else $d = ''; // Force empty string; bad decryption.
157
-
158
- return isset($d) && is_string($d) && isset($d[0])
159
- ? ($string = $d) // Decrypted string.
160
- : ''; // Default to empty string.
161
- }
162
- return c_ws_plugin__s2member_utils_encryption::xdecrypt($base64, $key);
163
- }
164
-
165
- /**
166
- * XOR two-way encryption/decryption, with a base64 wrapper.
167
- *
168
- * @package s2Member\Utilities
169
- * @since 3.5
170
- *
171
- * @param string $string A string of data to encrypt.
172
- * @param string $key Optional. Key used for encryption. Defaults to the one configured for s2Member. Short of that, defaults to: ``wp_salt()``.
173
- * @param bool $w_md5_cs Optional. Defaults to true. When true, an MD5 checksum is used in the encrypted string *(recommended)*.
174
- *
175
- * @return string Encrypted string.
176
- */
177
- public static function xencrypt($string = '', $key = '', $w_md5_cs = TRUE)
178
- {
179
- $string = is_string($string) ? $string : '';
180
- $string = isset($string[0]) ? '~xe|'.$string : '';
181
-
182
- $key = c_ws_plugin__s2member_utils_encryption::key($key);
183
-
184
- for($i = 1, $e = ''; $i <= strlen($string); $i++)
185
- {
186
- $char = substr($string, $i - 1, 1);
187
- $keychar = substr($key, ($i % strlen($key)) - 1, 1);
188
- $e .= chr(ord($char) + ord($keychar));
189
- }
190
- $e = isset($e[0]) ? '~xe'.($w_md5_cs ? ':'.md5($e) : '').'|'.$e : '';
191
-
192
- return isset($e) && is_string($e) && isset($e[0])
193
- ? ($base64 = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($e))
194
- : ''; // Default to empty string.
195
- }
196
-
197
- /**
198
- * XOR two-way encryption/decryption, with a base64 wrapper.
199
- *
200
- * @package s2Member\Utilities
201
- * @since 3.5
202
- *
203
- * @param string $base64 A string of data to decrypt. Should still be base64 encoded.
204
- * @param string $key Optional. Key used originally for encryption. Defaults to the one configured for s2Member. Short of that, defaults to: ``wp_salt()``.
205
- *
206
- * @return string Decrypted string.
207
- */
208
- public static function xdecrypt($base64 = '', $key = '')
209
- {
210
- $base64 = is_string($base64) ? $base64 : '';
211
- $e = isset($base64[0]) ? c_ws_plugin__s2member_utils_strings::base64_url_safe_decode($base64) : '';
212
-
213
- if(isset($e[0]) && preg_match('/^~xe(?:\:([a-zA-Z0-9]+))?\|(.*)$/s', $e, $md5_e))
214
- {
215
- $key = c_ws_plugin__s2member_utils_encryption::key($key);
216
-
217
- if(isset($md5_e[2][0]) && (empty($md5_e[1]) || $md5_e[1] === md5($md5_e[2])))
218
- for($i = 1, $d = ''; $i <= strlen($md5_e[2]); $i++)
219
- {
220
- $char = substr($md5_e[2], $i - 1, 1);
221
- $keychar = substr($key, ($i % strlen($key)) - 1, 1);
222
- $d .= chr(ord($char) - ord($keychar));
223
- }
224
- if(isset($d) && is_string($d) && isset($d[0]))
225
- if(!strlen($d = preg_replace('/^~xe\|/', '', $d, 1, $xe)) || !$xe)
226
- $d = ''; // Force empty string; bad decryption.
227
-
228
- return isset($d) && is_string($d) && isset($d[0])
229
- ? ($string = $d) // Decrypted string.
230
- : ''; // Default to empty string.
231
- }
232
- return ''; // Default to empty string.
233
- }
234
- }
 
 
 
 
 
 
235
  }
3
  /**
4
  * Encryption utilities.
5
  *
6
+ * @since 3.5 Nearly the first release.
 
 
 
 
 
 
 
 
 
 
7
  */
8
+ if (!defined('WPINC')) { // MUST have.
9
+ exit('Do not access this file directly.');
10
+ }
11
+ if (!class_exists('c_ws_plugin__s2member_utils_encryption')) {
12
+ /**
13
+ * Encryption utilities.
14
+ *
15
+ * @since 3.5 Nearly the first release.
16
+ */
17
+ class c_ws_plugin__s2member_utils_encryption
18
+ {
19
+ /**
20
+ * Encryption key.
21
+ *
22
+ * @since 111106 Get key.
23
+ *
24
+ * @param string $key Custom key.
25
+ *
26
+ * @return string Encryption key.
27
+ */
28
+ public static function key($key = '')
29
+ {
30
+ if (($key = trim((string) $key))) {
31
+ return $key;
32
+ } elseif (($key = $GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key'])) {
33
+ return $key;
34
+ } elseif (($key = wp_salt())) {
35
+ return $key;
36
+ }
37
+ return $key = md5($_SERVER['HTTP_HOST']);
38
+ }
39
+
40
+ /**
41
+ * A unique, unguessable, non-numeric, caSe-insensitive key (20 chars max).
42
+ *
43
+ * @since 150124 Adding gift code generation.
44
+ *
45
+ * @note 32-bit systems usually have `PHP_INT_MAX` = `2147483647`.
46
+ * We limit `mt_rand()` to a max of `999999999`.
47
+ *
48
+ * @note A max possible length of 20 chars assumes this function
49
+ * will not be called after `Sat, 20 Nov 2286 17:46:39 GMT`.
50
+ * At which point a UNIX timestamp will grow in size.
51
+ *
52
+ * @note Key always begins with a `k` to prevent PHP's `is_numeric()`
53
+ * function from ever thinking it's a number in a different representation.
54
+ * See: <http://php.net/manual/en/function.is-numeric.php> for further details.
55
+ *
56
+ * @return string A unique, unguessable, non-numeric, caSe-insensitive key (20 chars max).
57
+ */
58
+ public static function uunnci_key_20_max()
59
+ {
60
+ $microtime_19_max = number_format(microtime(true), 9, '.', '');
61
+ // e.g., `9999999999`.`999999999` (max decimals: `9`, max overall precision: `19`).
62
+ // Assuming timestamp is never > 10 digits; i.e., before `Sat, 20 Nov 2286 17:46:39 GMT`.
63
+
64
+ list($seconds_10_max, $microseconds_9_max) = explode('.', $microtime_19_max, 2);
65
+ // e.g., `array(`9999999999`, `999999999`)`. Max total digits combined: `19`.
66
+
67
+ $seconds_base36 = base_convert($seconds_10_max, '10', '36'); // e.g., max `9999999999`, to base 36.
68
+ $microseconds_base36 = base_convert($microseconds_9_max, '10', '36'); // e.g., max `999999999`, to base 36.
69
+ $mt_rand_base36 = base_convert(mt_rand(1, 999999999), '10', '36'); // e.g., max `999999999`, to base 36.
70
+ $key = 'k'.$mt_rand_base36.$seconds_base36.$microseconds_base36; // e.g., `kgjdgxr4ldqpdrgjdgxr`.
71
+
72
+ return $key; // Max possible value: `kgjdgxr4ldqpdrgjdgxr` (20 chars).
73
+ }
74
+
75
+ /**
76
+ * Encrypt w/ best possible technique.
77
+ *
78
+ * @since 3.5 Nearly the first release.
79
+ *
80
+ * @param string $string String to encrypt.
81
+ * @param string $key Optional custom encryption key.
82
+ * @param bool $w_md5_cs Defaults to true. When true, an MD5 checksum.
83
+ * @param bool|null $allow_defuse Allow Defuse encryption as a better alternative?
84
+ *
85
+ * @return string Encrypted string.
86
+ */
87
+ public static function encrypt($string = '', $key = '', $w_md5_cs = true, $allow_defuse = null)
88
+ {
89
+ $allow_defuse = isset($allow_defuse) ? $allow_defuse
90
+ : apply_filters('c_ws_plugin__s2member_allow_defuse', true);
91
+
92
+ if ($allow_defuse && version_compare(PHP_VERSION, '7.0.4', '>=')) {
93
+ return c_ws_plugin__s2member_utils_defuse::encrypt($string, $key);
94
+ } // This is a new/improved way of handling encryption.
95
+
96
+ if (function_exists('mcrypt_encrypt')
97
+ && in_array('rijndael-256', @mcrypt_list_algorithms())
98
+ && in_array('cbc', @mcrypt_list_modes())) {
99
+ //
100
+ $string = is_string($string) ? $string : '';
101
+ $string = isset($string[0]) ? '~r2|'.$string : '';
102
+
103
+ $key = self::key($key); // Get encryption key.
104
+ $key = substr($key, 0, @mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC));
105
+ $iv = c_ws_plugin__s2member_utils_strings::random_str_gen(@mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), false);
106
+
107
+ if (isset($string[0]) && is_string($e = @mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_CBC, $iv)) && isset($e[0])) {
108
+ $e = '~r2:'.$iv.($w_md5_cs ? ':'.md5($e) : '').'|'.$e;
109
+ }
110
+ return isset($e) && is_string($e) && isset($e[0])
111
+ ? ($base64 = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($e))
112
+ : ''; // Default to empty string.
113
+ }
114
+ return self::xencrypt($string, $key, $w_md5_cs);
115
+ }
116
+
117
+ /**
118
+ * Decrypt w/ best possible technique.
119
+ *
120
+ * @since 3.5 Nearly the first release.
121
+ *
122
+ * @param string $base64 String to decrypt (base64).
123
+ * @param string $key Optional custom decryption key.
124
+ * @param bool|null $allow_defuse Allow Defuse encryption as a better alternative?
125
+ *
126
+ * @return string Decrypted string, else empty string.
127
+ */
128
+ public static function decrypt($base64 = '', $key = '', $allow_defuse = null)
129
+ {
130
+ if (!is_string($base64) || !isset($base64[0])) {
131
+ return ''; // Not possible.
132
+ } // Fail when not a string or empty.
133
+
134
+ $allow_defuse = isset($allow_defuse) ? $allow_defuse
135
+ : apply_filters('c_ws_plugin__s2member_allow_defuse', true);
136
+
137
+ if ($allow_defuse && version_compare(PHP_VERSION, '7.0.4', '>=')
138
+ && ($_d = c_ws_plugin__s2member_utils_defuse::decrypt($base64, $key))) {
139
+ return $string = $_d; // Defuse success.
140
+ } // This is a new/improved way of handling decryption.
141
+
142
+ if (function_exists('mcrypt_decrypt')
143
+ && in_array('rijndael-256', @mcrypt_list_algorithms())
144
+ && in_array('cbc', @mcrypt_list_modes())) {
145
+ //
146
+ $e = c_ws_plugin__s2member_utils_strings::base64_url_safe_decode($base64);
147
+
148
+ if (preg_match('/^~r2\:([a-zA-Z0-9]+)(?:\:([a-zA-Z0-9]+))?\|(.*)$/s', $e, $iv_md5_e)) {
149
+ $key = self::key($key); // Get encryption key.
150
+ $key = substr($key, 0, @mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC));
151
+
152
+ if (isset($iv_md5_e[3][0]) && (empty($iv_md5_e[2]) || $iv_md5_e[2] === md5($iv_md5_e[3]))) {
153
+ $d = @mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $iv_md5_e[3], MCRYPT_MODE_CBC, $iv_md5_e[1]);
154
+ }
155
+ if (!isset($d)) { // Failed above?
156
+ return ''; // Empty string on failure.
157
+ } elseif (!strlen($d = preg_replace('/^~r2\|/', '', $d, 1, $r2)) || !$r2) {
158
+ return ''; // Empty string on failure.
159
+ }
160
+ return $string = rtrim($d, "\0\4");
161
+ }
162
+ }
163
+ return self::xdecrypt($base64, $key);
164
+ }
165
+
166
+ /**
167
+ * XOR two-way encryption/decryption, with a base64 wrapper.
168
+ *
169
+ * @since 3.5 Nearly the first release.
170
+ *
171
+ * @param string $string A string of data to encrypt.
172
+ * @param string $key Optional. Key used for encryption. Defaults to the one configured for s2Member. Short of that, defaults to: ``wp_salt()``.
173
+ * @param bool $w_md5_cs Optional. Defaults to true. When true, an MD5 checksum is used in the encrypted string *(recommended)*.
174
+ *
175
+ * @return string Encrypted string.
176
+ */
177
+ public static function xencrypt($string = '', $key = '', $w_md5_cs = true)
178
+ {
179
+ $string = is_string($string) ? $string : '';
180
+ $string = isset($string[0]) ? '~xe|'.$string : '';
181
+ $key = self::key($key); // Get encryption key.
182
+
183
+ for ($i = 1, $e = ''; $i <= strlen($string); ++$i) {
184
+ $char = substr($string, $i - 1, 1);
185
+ $keychar = substr($key, ($i % strlen($key)) - 1, 1);
186
+ $e .= chr(ord($char) + ord($keychar));
187
+ }
188
+ $e = isset($e[0]) ? '~xe'.($w_md5_cs ? ':'.md5($e) : '').'|'.$e : '';
189
+ return $base64 = isset($e[0]) ? ($base64 = c_ws_plugin__s2member_utils_strings::base64_url_safe_encode($e)) : '';
190
+ }
191
+
192
+ /**
193
+ * XOR decryption.
194
+ *
195
+ * @since 3.5 Nearly the first release.
196
+ *
197
+ * @param string $base64 String to decrypt (base64).
198
+ * @param string $key Optional custom decryption key.
199
+ *
200
+ * @return string Decrypted string.
201
+ */
202
+ public static function xdecrypt($base64 = '', $key = '')
203
+ {
204
+ if (!is_string($base64) || !isset($base64[0])) {
205
+ return ''; // Not possible.
206
+ } // Fail when not a string or empty.
207
+
208
+ $e = c_ws_plugin__s2member_utils_strings::base64_url_safe_decode($base64);
209
+
210
+ if (preg_match('/^~xe(?:\:([a-zA-Z0-9]+))?\|(.*)$/s', $e, $md5_e)) {
211
+ $key = self::key($key); // Get encryption key.
212
+
213
+ if (isset($md5_e[2][0]) && (empty($md5_e[1]) || $md5_e[1] === md5($md5_e[2]))) {
214
+ for ($i = 1, $d = ''; $i <= strlen($md5_e[2]); ++$i) {
215
+ $char = substr($md5_e[2], $i - 1, 1);
216
+ $keychar = substr($key, ($i % strlen($key)) - 1, 1);
217
+ $d .= chr(ord($char) - ord($keychar));
218
+ } // Reverse XOR encryption.
219
+ } // Else the checksum was not a match.
220
+
221
+ if (!isset($d)) { // Failed above?
222
+ return ''; // Empty string on failure.
223
+ } elseif (!strlen($d = preg_replace('/^~xe\|/', '', $d, 1, $xe)) || !$xe) {
224
+ return ''; // Empty string on failure.
225
+ }
226
+ return $string = $d; // Decryption success.
227
+ }
228
+ return ''; // Empty string on failure.
229
+ }
230
+ }
231
  }
src/includes/classes/utils-time.inc.php CHANGED
@@ -172,17 +172,18 @@ if(!class_exists('c_ws_plugin__s2member_utils_time'))
172
  {
173
  $registration_time = strtotime($user->user_registered);
174
  $last_payment_time = get_user_option('s2member_last_payment_time', $user_id);
 
175
  $last_payment_time = (int)$lpt ? (int)$lpt : (int)$last_payment_time;
176
  $last_paid_access_cap_time = 0; // Initialize the last access cap time.
177
- if(($access_cap_times = c_ws_plugin__s2member_access_cap_times::get_access_cap_times($user_id)))
178
- foreach(array_reverse($access_cap_times, TRUE) as $_time => $_cap)
179
- if(strpos($_cap, '-') !== 0 && $_cap !== 'level0')
180
- {
181
  $last_paid_access_cap_time = (integer)$_time;
182
  break; // Got what we need; stop here.
183
  }
184
- unset($_time, $_cap); // Housekeeping.
185
-
186
  if(($period1 = trim(strtoupper($period1))))
187
  {
188
  list($num, $span) = preg_split('/ /', $period1, 2);
@@ -215,13 +216,13 @@ if(!class_exists('c_ws_plugin__s2member_utils_time'))
215
  $p3_days = (int)$num * (int)$days;
216
  $p3_time = $p3_days * 86400;
217
  }
218
- if(!$last_payment_time) // No last payment time; i.e., has paid nothing yet?
219
  $auto_eot_time = ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time + $eot_grace_time;
220
 
221
- else if($p1_time && $last_payment_time <= ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time)
222
- $auto_eot_time = $last_payment_time + $p1_time + $eot_grace_time;
223
 
224
- else $auto_eot_time = $last_payment_time + $p3_time + $eot_grace_time;
225
  }
226
  else if($eotper) // Otherwise, if we have a specific EOT period; calculate from today.
227
  {
172
  {
173
  $registration_time = strtotime($user->user_registered);
174
  $last_payment_time = get_user_option('s2member_last_payment_time', $user_id);
175
+ $free_trial_expired_time = (int)get_user_option('s2member_free_trial_expired_time', $user_id);
176
  $last_payment_time = (int)$lpt ? (int)$lpt : (int)$last_payment_time;
177
  $last_paid_access_cap_time = 0; // Initialize the last access cap time.
178
+
179
+ if(($access_cap_times = c_ws_plugin__s2member_access_cap_times::get_access_cap_times($user_id))) {
180
+ foreach(array_reverse($access_cap_times, TRUE) as $_time => $_cap) {
181
+ if(strpos($_cap, '-') !== 0 && $_cap !== 'level0') {
182
  $last_paid_access_cap_time = (integer)$_time;
183
  break; // Got what we need; stop here.
184
  }
185
+ } // unset($_time, $_cap); // Housekeeping.
186
+ }
187
  if(($period1 = trim(strtoupper($period1))))
188
  {
189
  list($num, $span) = preg_split('/ /', $period1, 2);
216
  $p3_days = (int)$num * (int)$days;
217
  $p3_time = $p3_days * 86400;
218
  }
219
+ if(!$last_payment_time && !$free_trial_expired_time)
220
  $auto_eot_time = ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time + $eot_grace_time;
221
 
222
+ else if($p1_time && max($last_payment_time, $free_trial_expired_time) <= ($last_paid_access_cap_time ? $last_paid_access_cap_time : $registration_time) + $p1_time)
223
+ $auto_eot_time = max($last_payment_time, $free_trial_expired_time) + $p1_time + $eot_grace_time;
224
 
225
+ else $auto_eot_time = max($last_payment_time, $free_trial_expired_time) + $p3_time + $eot_grace_time;
226
  }
227
  else if($eotper) // Otherwise, if we have a specific EOT period; calculate from today.
228
  {
src/includes/functions/class-autoloader.inc.php CHANGED
@@ -84,4 +84,5 @@ if(!function_exists('ws_plugin__s2member_classes'))
84
  }
85
 
86
  spl_autoload_register('ws_plugin__s2member_classes');
 
87
  }
84
  }
85
 
86
  spl_autoload_register('ws_plugin__s2member_classes');
87
+ require_once dirname(dirname(dirname(__FILE__))).'/vendor/autoload.php';
88
  }
src/includes/menu-pages/api-ops.inc.php CHANGED
@@ -31,6 +31,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_api_ops"))
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/down-ops.inc.php CHANGED
@@ -31,6 +31,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/els-ops.inc.php CHANGED
@@ -31,6 +31,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_els_ops"))
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/gen-ops.inc.php CHANGED
@@ -31,6 +31,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/help.inc.php CHANGED
@@ -31,6 +31,8 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_help"))
31
  public function __construct ()
32
  {
33
  echo '<div class="wrap ws-menu-page">' . "\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display ();
31
  public function __construct ()
32
  {
33
  echo '<div class="wrap ws-menu-page">' . "\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display ();
src/includes/menu-pages/integrations.inc.php CHANGED
@@ -31,6 +31,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_integrations"))
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/logs.inc.php CHANGED
@@ -31,6 +31,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_logs"))
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
31
  public function __construct()
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/menu-pages-s.min.js CHANGED
@@ -1 +1,2 @@
1
- jQuery(document).ready(function($){var esc_attr=esc_html=function(string){if(/[&\<\>"']/.test(string=String(string))){string=string.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),string=string.replace(/"/g,"&quot;").replace(/'/g,"&#039;")}return string};ws_plugin__s2member_generateSecurityKey=function(obj){if(!obj){obj="#ws-plugin--s2member-sec-encryption-key"}var mt_rand=function(min,max){min=(arguments.length<1)?0:min;max=(arguments.length<2)?2147483647:max;return Math.floor(Math.random()*(max-min+1))+min};var chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#%^&*()";for(var i=0,key="";i<64;i++){key+=chars.substr(mt_rand(0,chars.length-1),1)}$(obj).val(key);return false};if(location.href.match(/page\=ws-plugin--s2member/)){$("input.ws-plugin--s2member-update-roles-button, input.ws-plugin--s2member-reset-roles-button").click(function(){var $this=$(this);$this.val("one moment please ...");var levels='<?php echo (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; ?>';var resetUpdate=($this.hasClass("ws-plugin--s2member-reset-roles-button"))?"Reset":"Update";$.post(ajaxurl,{action:"ws_plugin__s2member_update_roles_via_ajax",ws_plugin__s2member_update_roles_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-update-roles-via-ajax")); ?>'},function(response){if(response==="1"){alert("s2Member's Roles/Capabilities "+((resetUpdate.toLowerCase()==="reset")?"have been successfully reset":"updated successfully")+".\nYour installation of s2Member has Membership Levels 0-"+levels+"."),$this.val(resetUpdate+" Roles/Capabilities")}else{if(response==="l"){alert("Sorry, your request failed.\ns2Member's Roles/Capabilities are locked by Filter:\nws_plugin__s2member_lock_roles_caps"),$this.val(resetUpdate+" Roles/Capabilities")}else{alert("Sorry, your request failed.\nAccess denied. Do you have the ability to `create_users`?"),$this.val(resetUpdate+" Roles/Capabilities")}}});return false})}if(location.href.match(/page\=ws-plugin--s2member-logs/)){$("input#ws-plugin--s2member-gateway-debug-logs-extensive-1").click(function(){var $this=$(this),thisChecked=(this.checked)?true:false;if(thisChecked){$("input#ws-plugin--s2member-gateway-debug-logs-1").attr("checked","checked")}});var $toggles=$("a.ws-plugin--s2member-log-file-viewport-toggle");$toggles.click(function(){$("textarea#ws-plugin--s2member-log-file-viewer").each(function(){var $viewer=$(this);if($viewer.attr("data-state")!=="expanded"){$viewer.css({height:($viewer.prop("scrollHeight")+50)+"px","overflow-y":"auto"});$toggles.html("&#8657; normalize viewport &#10073;");$viewer.attr("data-state","expanded")}else{$viewer.css({height:"auto","overflow-y":"scroll"});$toggles.html("&#8659; expand viewport &#8659;");$viewer.attr("data-state","scrolling")}});return false})}if(location.href.match(/page\=ws-plugin--s2member-mms-ops/)){$("select#ws-plugin--s2member-mms-registration-file").change(function(){if($(this).val()==="wp-signup"){var gv=$("select#ws-plugin--s2member-mms-registration-grants").val(),l0v=$("input#ws-plugin--s2member-mms-registration-blogs-level0").val();$("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").show(),$("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").hide(),$("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").show();$("div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0")[((gv==="all")?"show":"hide")]();$("input#ws-plugin--s2member-mms-registration-blogs-level0").val(((gv==="all")?((l0v>0)?l0v:"1"):"0"))}else{if($(this).val()==="wp-login"){var gv=$("select#ws-plugin--s2member-mms-registration-grants").val(),l0v=$("input#ws-plugin--s2member-mms-registration-blogs-level0").val();$("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").hide(),$("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").show(),$("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").hide();$("div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0").hide();$("input#ws-plugin--s2member-mms-registration-blogs-level0").val("0")}}}).trigger("change");$("select#ws-plugin--s2member-mms-registration-grants").change(function(){$("select#ws-plugin--s2member-mms-registration-file").trigger("change")})}if(location.href.match(/page\=ws-plugin--s2member-gen-ops/)){ws_plugin__s2member_enableSecurityKey=function(){if(confirm("Edit Key? Are you sure?\nThis could break your installation!\n\n*Note* If you've been testing s2Member, feel free to change this Key before you go live. Just don't go live, and then change it. You'll have unhappy Customers. Data corruption WILL occur! For your safety, s2Member keeps a history of the last 10 Keys that you've used. If you get yourself into a real situation, s2Member will let you revert back to a previous Key.")){$("input#ws-plugin--s2member-sec-encryption-key").removeAttr("disabled")}return false};ws_plugin__s2member_securityKeyHistory=function(){$("div#ws-plugin--s2member-sec-encryption-key-history").toggle();return false};$("select#ws-plugin--s2member-new-user-emails-enabled").change(function(){var $pluggable=$("input#ws-plugin--s2member-pluggables-wp-new-user-notification"),$this=$(this),$newUserEmails=$("div#ws-plugin--s2member-new-user-emails");if($pluggable.val()==="0"||$this.val()==="0"){($pluggable.val()==="0")?$this.attr("disabled","disabled"):$this.removeAttr("disabled");$(":input",$newUserEmails).attr("disabled","disabled"),$newUserEmails.css("opacity","0.5")}else{$this.removeAttr("disabled"),$(":input",$newUserEmails).removeAttr("disabled"),$newUserEmails.css("opacity","")}}).trigger("change");$("select#ws-plugin--s2member-login-reg-design-enabled").change(function(){var $this=$(this),$loginRegDesign=$("div#ws-plugin--s2member-login-reg-design");if($this.val()==="0"){$(":input",$loginRegDesign).attr("disabled","disabled"),$loginRegDesign.css("opacity","0.5"),$loginRegDesign.hide()}else{$(":input",$loginRegDesign).removeAttr("disabled"),$loginRegDesign.css("opacity",""),$loginRegDesign.show()}}).trigger("change");$("select#ws-plugin--s2member-custom-reg-password").change(function(){var $this=$(this),$newUserNotification=$("div#ws-plugin--s2member-new-user-email-details");if($this.val()==="1"){$newUserNotification.css("opacity","0.5")}else{$newUserNotification.css("opacity","")}}).trigger("change");if($("input#ws-plugin--s2member-custom-reg-fields").length&&$("div#ws-plugin--s2member-custom-reg-field-configuration").length){(function(){var i,fieldDefaults,tools,table,$tools,$table;var $fields=$("input#ws-plugin--s2member-custom-reg-fields");var $configuration=$("div#ws-plugin--s2member-custom-reg-field-configuration");var fields=($fields.val())?$.JSON.parse($fields.val()):[];fields=(fields instanceof Array)?fields:[];fieldDefaults={section:"no",sectitle:"",id:"",label:"",type:"text",deflt:"",options:"",expected:"",required:"yes",levels:"all",editable:"yes",classes:"",styles:"",attrs:""};for(i=0;i<fields.length;i++){fields[i]=$.extend(true,{},fieldDefaults,fields[i])}tools='<div id="ws-plugin--s2member-custom-reg-field-configuration-tools"></div>',table='<table id="ws-plugin--s2member-custom-reg-field-configuration-table"></table>';$configuration.html(tools+table);$tools=$("div#ws-plugin--s2member-custom-reg-field-configuration-tools"),$table=$("table#ws-plugin--s2member-custom-reg-field-configuration-table");ws_plugin__s2member_customRegFieldSectionChange=function(select){var section=$(select).val();var sectitle_trs="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle";(section==="yes")?$(sectitle_trs).css("display",""):$(sectitle_trs).css("display","none")};ws_plugin__s2member_customRegFieldTypeChange=function(select){var type=$(select).val();var deflt_trs="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt",options_trs="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-options",expected_trs="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected";(type.match(/^(text|textarea)$/))?$(deflt_trs).css("display",""):$(deflt_trs).css("display","none");(type.match(/^(select|selects|checkboxes|radios)$/))?$(options_trs).css("display",""):$(options_trs).css("display","none");(type.match(/^(text|textarea)$/))?$(expected_trs).css("display",""):$(expected_trs).css("display","none")};ws_plugin__s2member_customRegFieldDelete=function(index){var newFields=new Array();for(var i=0;i<fields.length;i++){if(i!==index){newFields.push(fields[i])}}fields=newFields,updateFields(),buildTable()};ws_plugin__s2member_customRegFieldMoveUp=function(index){if(typeof fields[index]==="object"&&typeof fields[index-1]==="object"){var prevFieldObj=fields[index-1],thisFieldObj=fields[index];fields[index-1]=thisFieldObj,fields[index]=prevFieldObj;updateFields(),buildTable()}};ws_plugin__s2member_customRegFieldMoveDown=function(index){if(typeof fields[index]==="object"&&typeof fields[index+1]==="object"){var nextFieldObj=fields[index+1],thisFieldObj=fields[index];fields[index+1]=thisFieldObj,fields[index]=nextFieldObj;updateFields(),buildTable()}};ws_plugin__s2member_customRegFieldCreate=function(){var $table=$("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),field={};$(":input[property]",$table).each(function(){var $this=$(this),property=$this.attr("property"),val=$.trim($this.val());field[property]=val});if((field=validateField(field))){fields.push(field),updateFields(),buildTools(),buildTable(),scrollReset();setTimeout(function(){var row="tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+(fields.length-1);alert('Field created successfully.\n* Remember to "Save All Changes".')},500)}};ws_plugin__s2member_customRegFieldUpdate=function(index){var $table=$("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),field={};$(":input[property]",$table).each(function(){var $this=$(this),property=$this.attr("property"),val=$.trim($this.val());field[property]=val});if((field=validateField(field,index))){fields[index]=field,updateFields(),buildTools(),buildTable(),scrollReset();setTimeout(function(){var row="tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+index;alert('Field updated successfully.\n* Remember to "Save All Changes".')},500)}};ws_plugin__s2member_customRegFieldAdd=function(){buildTools(true)};ws_plugin__s2member_customRegFieldEdit=function(index){buildTools(false,index),scrollReset()};ws_plugin__s2member_customRegFieldCancel=function(){buildTools(),scrollReset()};var validateField=function(field,index){var editing=(typeof index==="number"&&typeof fields[index]==="object")?true:false,errors=[],options,i;if(typeof field!=="object"||typeof(field=$.extend(true,{},fieldDefaults,field))!=="object"){alert("Invalid field object. Please try again.");return false}field.sectitle=(field.section==="yes")?field.sectitle:"";field.deflt=(field.type.match(/^(text|textarea)$/))?field.deflt:"";field.deflt=(field.type.match(/^(text)$/))?field.deflt.replace(/[\r\n\t ]+/g," "):field.deflt;field.options=(field.type.match(/^(select|selects|checkboxes|radios)$/))?field.options:"";field.expected=(field.type.match(/^(text|textarea)$/))?field.expected:"";if(!field.id){errors.push("Unique Field ID:\nThis is required. Please try again.")}else{if(fieldIdExists(field.id)&&(!editing||field.id!==fields[index].id)){errors.push("Unique Field ID:\nThat Field ID already exists. Please try again.")}}if(!field.label){errors.push("Field Label/Description:\nThis is required. Please try again.")}if(field.type.match(/^(select|selects|checkboxes|radios)$/)&&!field.options){errors.push("Option Configuration File:\nThis is required. Please try again.")}else{if(field.type.match(/^(select|selects|checkboxes|radios)$/)){for(i=0;i<(options=field.options.split(/[\r\n]+/)).length;i++){if(!(options[i]=$.trim(options[i])).match(/^([^\|]*)(\|)([^\|]*)(\|default)?$/)){errors.push("Option Configuration File:\nInvalid configuration at line #"+(i+1)+".");break}}field.options=$.trim(options.join("\n"))}}if(!(field.levels=field.levels.replace(/ /g,""))){errors.push("Applicable Levels:\nThis is required. Please try again.")}else{if(!field.levels.match(/^(all|[0-9,]+)$/)){errors.push("Applicable Levels:\nShould be comma-delimited Levels, or just type: all.\n(examples: 0,1,2,3,4 or type the word: all)")}}if(field.classes&&field.classes.match(/[^a-z 0-9 _ \-]/i)){errors.push("CSS Classes:\nContains invalid characters. Please try again.\n(only: alphanumerics, underscores, hyphens, spaces)")}if(field.styles&&field.styles.match(/["\=\>\<]/)){errors.push('CSS Styles:\nContains invalid characters. Please try again.\n(do NOT use these characters: = " < >)')}if(field.attrs&&field.attrs.match(/[\>\<]/)){errors.push("Other Attributes:\nContains invalid characters. Please try again.\n(do NOT use these characters: < >)")}if(errors.length>0){alert(errors.join("\n\n"));return false}else{return field}};var updateFields=function(){$fields.val(((fields.length>0)?$.JSON.stringify(fields):""))};var fieldId2Var=function(fieldId){return(typeof fieldId==="string")?$.trim(fieldId).toLowerCase().replace(/[^a-z0-9]/g,"_"):""};var fieldTypeDesc=function(type){var types={text:"Text (single line)",textarea:"Textarea (multi-line)",select:"Select Menu (drop-down)",selects:"Select Menu (multi-option)",checkbox:"Checkbox (single)",pre_checkbox:"Checkbox (pre-checked)",checkboxes:"Checkboxes (multi-option)",radios:"Radio Buttons (multi-option)"};if(typeof types[type]==="string"){return types[type]}return""};var fieldIdExists=function(fieldId){for(var i=0;i<fields.length;i++){if(fields[i].id===fieldId){return true}}};var scrollReset=function(){scrollTo(0,$("div.ws-plugin--s2member-custom-reg-fields-section").offset()["top"]-100)};var buildTools=function(adding,index){var i=0,html="",form="",w=0,h=0,editing=(typeof index==="number"&&typeof fields[index]==="object")?true:false,displayForm=(adding||editing)?true:false,field=(editing)?$.extend(true,{},fieldDefaults,fields[index]):fieldDefaults;html+='<a href="#" onclick="ws_plugin__s2member_customRegFieldAdd(); return false;">Add New Field</a>';tb_remove(),$("div#ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form").remove();if(displayForm){form+='<div id="ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form">';form+='<table id="ws-plugin--s2member-custom-reg-field-configuration-tools-form">';form+="<tbody>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">Starts A New Section?</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">';form+='<td colspan="2">';form+='<select property="section" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section" onchange="ws_plugin__s2member_customRegFieldSectionChange(this);">';form+='<option value="no"'+((field.section==="no")?' selected="selected"':"")+'">No (this Field flows normally)</option>';form+='<option value="yes"'+((field.section==="yes")?' selected="selected"':"")+'">Yes (this Field begins a new section)</option>';form+="</select><br />";form+="<small>Optional. Allows Fields to be grouped into sections.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle ws-plugin--s2member-custom-reg-field-configuration-tools-form-section"'+((field.section==="yes")?"":' style="display:none;"')+'><td colspan="2"><hr /></td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle ws-plugin--s2member-custom-reg-field-configuration-tools-form-section"'+((field.section==="yes")?"":' style="display:none;"')+">";form+='<td colspan="2">';form+="Title for this new section? (optional)<br />";form+='<input type="text" property="sectitle" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle" value="'+esc_attr(field.sectitle)+'" /><br />';form+="<small>If empty, a simple divider will be used by default.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-type"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">Form Field Type: *</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';form+='<td colspan="2">';form+='<select property="type" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);">';form+='<option value="text"'+((field.type==="text")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("text"))+"</option>";form+='<option value="textarea"'+((field.type==="textarea")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("textarea"))+"</option>";form+='<option value="select"'+((field.type==="select")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("select"))+"</option>";form+='<option value="selects"'+((field.type==="selects")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("selects"))+"</option>";form+='<option value="checkbox"'+((field.type==="checkbox")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("checkbox"))+"</option>";form+='<option value="pre_checkbox"'+((field.type==="pre_checkbox")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("pre_checkbox"))+"</option>";form+='<option value="checkboxes"'+((field.type==="checkboxes")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("checkboxes"))+"</option>";form+='<option value="radios"'+((field.type==="radios")?' selected="selected"':"")+'">'+esc_html(fieldTypeDesc("radios"))+"</option>";form+="</select><br />";form+="<small>The options below may change, based on the Field Type you choose here.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-label"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">Field Label/Desc: *</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';form+='<td colspan="2">';form+='<input type="text" property="label" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label" value="'+esc_attr(field.label)+'" /><br />';form+="<small>Examples: <code>Choose Country</code>, <code>Street Address</code></small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-id"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">Unique Field ID: *</label></label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';form+='<td colspan="2">';form+='<input type="text" property="id" maxlength="25" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id" value="'+esc_attr(field.id)+'" /><br />';form+="<small>Examples: <code>country_code</code>, <code>street_address</code></small><br />";form+='<small>e.g., <code>[s2Get user_field="country_code" /]</code></small>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-required"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">Field Required: *</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';form+='<td colspan="2">';form+='<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';form+='<option value="yes"'+((field.required==="yes")?' selected="selected"':"")+'">Yes (required)</option>';form+='<option value="no"'+((field.required==="no")?' selected="selected"':"")+'">No (optional)</option>';form+="</select><br />";form+='<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />';form+="<small>* Administrators are exempt from this requirement.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+((field.type.match(/^(text|textarea)$/))?"":' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+((field.type.match(/^(text|textarea)$/))?"":' style="display:none;"')+">";form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt">Default Text Value: (optional)</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+((field.type.match(/^(text|textarea)$/))?"":' style="display:none;"')+">";form+='<td colspan="2">';form+='<textarea property="deflt" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt" rows="1">'+esc_html(field.deflt)+"</textarea><br />";form+="<small>Default value before user input is received.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((field.type.match(/^(select|selects|checkboxes|radios)$/))?"":' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((field.type.match(/^(select|selects|checkboxes|radios)$/))?"":' style="display:none;"')+">";form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * (one option per line)</label><br />';form+="<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((field.type.match(/^(select|selects|checkboxes|radios)$/))?"":' style="display:none;"')+">";form+='<td colspan="2">';form+='<textarea property="options" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options" rows="3">'+esc_html(field.options)+"</textarea><br />";form+="Here is a quick example:<br />";form+="<small>You can also specify a <em>default</em> option:</small><br />";form+="<code>US|United States|default</code><br />";form+="<code>CA|Canada</code><br />";form+="<code>VI|Virgin Islands (U.S.)</code>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((field.type.match(/^(text|textarea)$/))?"":' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((field.type.match(/^(text|textarea)$/))?"":' style="display:none;"')+">";form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((field.type.match(/^(text|textarea)$/))?"":' style="display:none;"')+">";form+='<td colspan="2">';form+='<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">';form+='<option value=""'+((field.expected==="")?' selected="selected"':"")+'">Anything Goes</option>';form+='<option disabled="disabled"></option>';form+='<optgroup label="Specific Input Types">';form+='<option value="numeric-wp-commas"'+((field.expected==="numeric-wp-commas")?' selected="selected"':"")+'">Numeric (with or without decimals, commas allowed)</option>';form+='<option value="numeric"'+((field.expected==="numeric")?' selected="selected"':"")+'">Numeric (with or without decimals, no commas)</option>';form+='<option value="integer"'+((field.expected==="integer")?' selected="selected"':"")+'">Integer (whole number, without any decimals)</option>';form+='<option value="integer-gt-0"'+((field.expected==="integer-gt-0")?' selected="selected"':"")+'">Integer > 0 (whole number, no decimals, greater than 0)</option>';form+='<option value="float"'+((field.expected==="float")?' selected="selected"':"")+'">Float (floating point number, decimals required)</option>';form+='<option value="float-gt-0"'+((field.expected==="float-gt-0")?' selected="selected"':"")+'">Float > 0 (floating point number, decimals required, greater than 0)</option>';form+='<option value="date"'+((field.expected==="date")?' selected="selected"':"")+'">Date (required date format: dd/mm/yyyy)</option>';form+='<option value="email"'+((field.expected==="email")?' selected="selected"':"")+'">Email (require valid email)</option>';form+='<option value="url"'+((field.expected==="url")?' selected="selected"':"")+'">Full URL (starting with http or https)</option>';form+='<option value="domain"'+((field.expected==="domain")?' selected="selected"':"")+'">Domain Name (domain name only, without http)</option>';form+='<option value="phone"'+((field.expected==="phone")?' selected="selected"':"")+'">Phone # (10 digits w/possible hyphens,spaces,brackets)</option>';form+='<option value="uszip"'+((field.expected==="uszip")?' selected="selected"':"")+'">US Zipcode (5-9 digits w/possible hyphen)</option>';form+='<option value="cazip"'+((field.expected==="cazip")?' selected="selected"':"")+'">Canadian Zipcode (6 alpha-numerics w/possible space)</option>';form+='<option value="uczip"'+((field.expected==="uczip")?' selected="selected"':"")+'">US/Canadian Zipcode (either a US or Canadian zipcode)</option>';form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Any Character Combination">';for(i=1;i<=25;i++){form+='<option value="any-'+i+'"'+((field.expected==="any-"+i)?' selected="selected"':"")+'">Any Character Combination ('+i+" character minimum)</option>";form+='<option value="any-'+i+'-e"'+((field.expected==="any-"+i+"-e")?' selected="selected"':"")+'">Any Character Combination (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">';for(i=1;i<=25;i++){form+='<option value="alphanumerics-spaces-punctuation-'+i+'"'+((field.expected==="alphanumerics-spaces-punctuation-"+i)?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation ('+i+" character minimum)</option>";form+='<option value="alphanumerics-spaces-punctuation-'+i+'-e"'+((field.expected==="alphanumerics-spaces-punctuation-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphanumerics &amp; Spaces Only">';for(i=1;i<=25;i++){form+='<option value="alphanumerics-spaces-'+i+'"'+((field.expected==="alphanumerics-spaces-"+i)?' selected="selected"':"")+'">Alphanumerics &amp; Spaces ('+i+" character minimum)</option>";form+='<option value="alphanumerics-spaces-'+i+'-e"'+((field.expected==="alphanumerics-spaces-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics &amp; Spaces (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphanumerics &amp; Punctuation Only">';for(i=1;i<=25;i++){form+='<option value="alphanumerics-punctuation-'+i+'"'+((field.expected==="alphanumerics-punctuation-"+i)?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation ('+i+" character minimum)</option>";form+='<option value="alphanumerics-punctuation-'+i+'-e"'+((field.expected==="alphanumerics-punctuation-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphanumerics Only">';for(i=1;i<=25;i++){form+='<option value="alphanumerics-'+i+'"'+((field.expected==="alphanumerics-"+i)?' selected="selected"':"")+'">Alphanumerics ('+i+" character minimum)</option>";form+='<option value="alphanumerics-'+i+'-e"'+((field.expected==="alphanumerics-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphabetics Only">';for(i=1;i<=25;i++){form+='<option value="alphabetics-'+i+'"'+((field.expected==="alphabetics-"+i)?' selected="selected"':"")+'">Alphabetics ('+i+" character minimum)</option>";form+='<option value="alphabetics-'+i+'-e"'+((field.expected==="alphabetics-"+i+"-e")?' selected="selected"':"")+'">Alphabetics (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Numeric Digits Only">';for(i=1;i<=25;i++){form+='<option value="numerics-'+i+'"'+((field.expected==="numerics-"+i)?' selected="selected"':"")+'">Numeric Digits ('+i+" digit minimum)</option>";form+='<option value="numerics-'+i+'-e"'+((field.expected==="numerics-"+i+"-e")?' selected="selected"':"")+'">Numeric Digits (exactly '+i+" digit"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+="</select><br />";form+="<small>Only Users/Members will be required to meet this criteria.</small><br />";form+="<small>* Administrators are exempt from this.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">Applicable Membership Levels: *</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';form+='<td colspan="2">';form+='<input type="text" property="levels" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels" value="'+esc_attr(field.levels)+'" /><br />';form+="<small>Please use comma-delimited Level #'s: <code>0,1,2,3,4</code> or type: <code>all</code>.</small><br />";form+="<small>This allows you to enable this field - only at specific Membership Levels.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">Allow Profile Edits: *</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';form+='<td colspan="2">';form+='<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';form+='<option value="yes"'+((field.editable==="yes")?' selected="selected"':"")+'">Yes (editable)</option>';form+='<option value="no"'+((field.editable==="no")?' selected="selected"':"")+'">No (uneditable after registration)</option>';form+='<option value="no-invisible"'+((field.editable==="no-invisible")?' selected="selected"':"")+'">No (uneditable &amp; totally invisible after registration)</option>';form+='<option value="no-always-invisible"'+((field.editable==="no-always-invisible")?' selected="selected"':"")+'">No (uneditable &amp; totally invisible, both during &amp; after registration)</option>';form+='<option value="yes-invisible"'+((field.editable==="yes-invisible")?' selected="selected"':"")+'">Yes (editable after registration / invisible during registration)</option>';form+="</select><br />";form+="<small>If <code>No</code>, this field will be un-editable after registration.</small><br />";form+="<small>* Administrators are exempt from this.</small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">CSS Classes: (optional)</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';form+='<td colspan="2">';form+='<input type="text" property="classes" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes" value="'+esc_attr(field.classes)+'" /><br />';form+="<small>Example: <code>my-style-1 my-style-2</code></small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">CSS Styles: (optional)</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';form+='<td colspan="2">';form+='<input type="text" property="styles" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles" value="'+esc_attr(field.styles)+'" /><br />';form+="<small>Example: <code>color:#000000; background:#FFFFFF;</code></small>";form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';form+='<td colspan="2">';form+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">Other Attributes: (optional)</label>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';form+='<td colspan="2">';form+='<input type="text" property="attrs" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs" value="'+esc_attr(field.attrs)+'" /><br />';form+='<small>Example: <code>onkeyup="" onblur=""</code></small>';form+="</td>";form+="</tr>";form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons"><td colspan="2">&nbsp;</td></tr>';form+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons">';form+='<td align="left">';form+='<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />';form+="</td>";form+='<td align="right">';form+='<input type="button" value="'+((editing)?"Update This Field":"Create Registration Field")+'" onclick="'+((editing)?"ws_plugin__s2member_customRegFieldUpdate("+index+");":"ws_plugin__s2member_customRegFieldCreate();")+'" />';form+="</td>";form+="</tr>";form+="</tbody>";form+="</table>";form+="<div>";$("body").append(form);tb_show(((editing)?"Editing Registration/Profile Field":"New Custom Registration/Profile Field"),"#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form");$("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form").show()}$tools.html(html)};var buildTable=function(){var l=fields.length,i=0,html="",eo="o";html+="<tbody>";html+="<tr>";html+="<th>Order</th>";html+="<th>Field Type</th>";html+="<th>Unique ID</th>";html+="<th>Required</th>";html+="<th>Levels</th>";html+="<th>- Tools -</th>";html+="</tr>";if(fields.length>0){for(i=0;i<fields.length;i++){html+='<tr class="'+esc_attr((eo=(eo==="o")?"e":"o"))+((fields[i].section==="yes")?" s":"")+" ws-plugin--s2member-custom-reg-field-configuration-table-row-"+i+'">';html+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-move-up" href="#" onclick="ws_plugin__s2member_customRegFieldMoveUp('+i+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-move-down" href="#" onclick="ws_plugin__s2member_customRegFieldMoveDown('+i+'); return false;"></a></td>';html+='<td nowrap="nowrap">'+esc_html(fieldTypeDesc(fields[i].type))+"</td>";html+='<td nowrap="nowrap">'+esc_html(fields[i].id)+"</td>";html+='<td nowrap="nowrap">'+esc_html(fields[i].required)+"</td>";html+='<td nowrap="nowrap">'+esc_html(fields[i].levels)+"</td>";html+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-edit" href="#" onclick="ws_plugin__s2member_customRegFieldEdit('+i+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-delete" href="#" onclick="ws_plugin__s2member_customRegFieldDelete('+i+'); return false;"></a></td>';html+="</tr>"}}else{html+="<tr>";html+='<td colspan="6">No Custom Fields are configured.</td>';html+="</tr>"}html+="</tbody>";$table.html(html)};buildTools(),buildTable()})()}}if(location.href.match(/page\=ws-plugin--s2member-res-ops/)){$("input#ws-plugin--s2member-brute-force-restrictions-reset-button").click(function(){var $this=$(this);$this.val("one moment please ...");$.post(ajaxurl,{action:"ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax",ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'},function(response){alert("s2Member's Brute Force Restriction Logs have all been reset."),$this.val("Reset Brute Force Logs")});return false});$("input#ws-plugin--s2member-ip-restrictions-reset-button").click(function(){var $this=$(this);$this.val("one moment please ...");$.post(ajaxurl,{action:"ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax",ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'},function(response){alert("s2Member's IP Restriction Logs have all been reset."),$this.val("Reset IP Restriction Logs")});return false});$('div.ws-plugin--s2member-query-level-access-section input[type="checkbox"][name="ws_plugin__s2member_filter_wp_query[]"]').change(function(){var thisChange=$(this).val();$('div.ws-plugin--s2member-query-level-access-section input[type="checkbox"][name="ws_plugin__s2member_filter_wp_query[]"]').each(function(){var $this=$(this),val=$this.val(),checkboxes='input[type="checkbox"]';if(val==="all"&&this.checked){$this.nextAll(checkboxes).attr({checked:"checked",disabled:"disabled"})}else{if(val==="all"&&!this.checked){$this.nextAll(checkboxes).removeAttr("disabled");(thisChange==="all")?$this.nextAll(checkboxes).removeAttr("checked"):null}}})}).last().trigger("change")}if(location.href.match(/page\=ws-plugin--s2member-down-ops/)){var updateCloudFrontPrivateKey=function(){var $hiddenPrivateKey=$("input#ws-plugin--s2member-amazon-cf-files-private-key");var $visiblePrivateKeyEntry=$("textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry");var hiddenPrivateKeyValue=$.trim($hiddenPrivateKey.val()),visiblePrivateKeyEntryValue=$.trim($visiblePrivateKeyEntry.val());if((hiddenPrivateKeyValue&&!visiblePrivateKeyEntryValue)||visiblePrivateKeyEntryValue.match(/[^\r\n\u25CF]/)){$hiddenPrivateKey.val(visiblePrivateKeyEntryValue),$visiblePrivateKeyEntry.val(visiblePrivateKeyEntryValue.replace(/[^\r\n]/g,String.fromCharCode(9679)))}};$("form#ws-plugin--s2member-options-form").submit(updateCloudFrontPrivateKey);$("textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry").change(updateCloudFrontPrivateKey).trigger("change");var updateCloudFrontDistroCfgs=function(){var $hiddenPrivateKey=$("input#ws-plugin--s2member-amazon-cf-files-private-key");var $visiblePrivateKeyId=$("input#ws-plugin--s2member-amazon-cf-files-private-key-id");var $autoConfigDistros=$("input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros");var $autoConfigDistrosStatus=$("input#ws-plugin--s2member-amazon-cf-files-distros-auto-config-status");var autoConfigDistrosStatusValue=$.trim($autoConfigDistrosStatus.val());var hiddenPrivateKeyValue=$.trim($hiddenPrivateKey.val()),visiblePrivateKeyIdValue=$.trim($visiblePrivateKeyId.val());var hiddenPrivateKeyPrevConfigValue=$.trim($hiddenPrivateKey.attr("data-s-prev-config-value")),visiblePrivateKeyIdPrevConfigValue=$.trim($visiblePrivateKeyId.attr("data-s-prev-config-value"));if(autoConfigDistrosStatusValue==="configured"&&((visiblePrivateKeyIdPrevConfigValue&&visiblePrivateKeyIdValue!==visiblePrivateKeyIdPrevConfigValue)||(hiddenPrivateKeyPrevConfigValue&&hiddenPrivateKeyValue!==hiddenPrivateKeyPrevConfigValue))){alert("s2Member will need to delete and re-configure your Amazon CloudFront distributions if you change this. When you're done editing, click (Save All Changes) below.");$autoConfigDistros.attr("checked","checked")}else{if(autoConfigDistrosStatusValue!=="configured"&&visiblePrivateKeyIdValue&&hiddenPrivateKeyValue){alert("s2Member will need to auto-configure your Amazon CloudFront distributions for you. When you're done editing, click (Save All Changes) below.");$autoConfigDistros.attr("checked","checked")}}};$("input#ws-plugin--s2member-amazon-cf-files-private-key-id").change(updateCloudFrontDistroCfgs);$("textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry").change(updateCloudFrontDistroCfgs);$("input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames").change(function(){var $this=$(this),thisChecked=(this.checked)?true:false;var $autoConfigDistros=$("input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros");var $autoConfigDistroCnames=$("div#ws-plugin--s2member-amazon-cf-files-auto-configure-distro-cnames");(thisChecked)?$autoConfigDistroCnames.show():$autoConfigDistroCnames.hide();(thisChecked)?$autoConfigDistros.attr("checked","checked"):null}).trigger("change")}if(location.href.match(/page\=ws-plugin--s2member-paypal-ops/)){$("select#ws-plugin--s2member-auto-eot-system-enabled").change(function(){var $this=$(this),val=$this.val();var $viaCron=$("p#ws-plugin--s2member-auto-eot-system-enabled-via-cron");if(val==2){$viaCron.show()}else{$viaCron.hide()}})}if(location.href.match(/page\=ws-plugin--s2member-paypal-buttons/)){$("div.ws-menu-page select[id]").filter(function(){return this.id.match(/^ws-plugin--s2member-(level[1-9][0-9]*|modification)-term$/)}).change(function(){var button=this.id.replace(/^ws-plugin--s2member-(.+?)-term$/g,"$1");var trialDisabled=($(this).val().split("-")[2].replace(/[^0-1BN]/g,"")==="BN")?1:0;$("p#ws-plugin--s2member-"+button+"-trial-line").css("display",(trialDisabled?"none":""));$("span#ws-plugin--s2member-"+button+"-trial-then").css("display",(trialDisabled?"none":""));$("span#ws-plugin--s2member-"+button+"-20p-rule").css("display",(trialDisabled?"none":""));(trialDisabled)?$("input#ws-plugin--s2member-"+button+"-trial-period").val(0):null;(trialDisabled)?$("input#ws-plugin--s2member-"+button+"-trial-amount").val("0.00"):null});$("div.ws-menu-page input[id]").filter(function(){return this.id.match(/^ws-plugin--s2member-(level[1-9][0-9]*|modification|ccap)-ccaps$/)}).keyup(function(){var value=this.value.replace(/^(-all|-al|-a|-)[;,]*/gi,""),_all=(this.value.match(/^(-all|-al|-a|-)[;,]*/i))?"-all,":"";if(value.match(/[^a-z_0-9,]/)){this.value=_all+$.trim($.trim(value).replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase())}});ws_plugin__s2member_paypalButtonGenerate=function(button){var shortCodeTemplate='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',shortCodeTemplateAttrs="",labels={};eval("<?php echo c_ws_plugin__s2member_utils_strings::esc_dq($labels); ?>");var shortCode=$("input#ws-plugin--s2member-"+button+"-shortcode");var code=$("textarea#ws-plugin--s2member-"+button+"-button");var modLevel=$("select#ws-plugin--s2member-modification-level");var level=(button==="modification")?modLevel.val().split(":",2)[1]:button.replace(/^level/,"");var label=labels["level"+level].replace(/"/g,"");var desc=$.trim($("input#ws-plugin--s2member-"+button+"-desc").val().replace(/"/g,""));var trialAmount=$("input#ws-plugin--s2member-"+button+"-trial-amount").val().replace(/[^0-9\.]/g,"");var trialPeriod=$("input#ws-plugin--s2member-"+button+"-trial-period").val().replace(/[^0-9]/g,"");var trialTerm=$("select#ws-plugin--s2member-"+button+"-trial-term").val().replace(/[^A-Z]/g,"");var regAmount=$("input#ws-plugin--s2member-"+button+"-amount").val().replace(/[^0-9\.]/g,"");var regPeriod=$("select#ws-plugin--s2member-"+button+"-term").val().split("-")[0].replace(/[^0-9]/g,"");var regTerm=$("select#ws-plugin--s2member-"+button+"-term").val().split("-")[1].replace(/[^A-Z]/g,"");var regRecur=$("select#ws-plugin--s2member-"+button+"-term").val().split("-")[2].replace(/[^0-1BN]/g,"");var regRecurTimes="",regRecurRetry="1";var localeCode="",digital="0",noShipping="1";var pageStyle=$.trim($("input#ws-plugin--s2member-"+button+"-page-style").val().replace(/"/g,""));var currencyCode=$("select#ws-plugin--s2member-"+button+"-currency").val().replace(/[^A-Z]/g,"");var cCaps=$.trim($.trim($("input#ws-plugin--s2member-"+button+"-ccaps").val()).replace(/^(-all|-al|-a|-)[;,]*/gi,"").replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase());cCaps=($.trim($("input#ws-plugin--s2member-"+button+"-ccaps").val()).match(/^(-all|-al|-a|-)[;,]*/i))?((cCaps)?"-all,":"-all")+cCaps.toLowerCase():cCaps.toLowerCase();trialPeriod=(regRecur==="BN")?"0":trialPeriod;trialAmount=(!trialAmount||isNaN(trialAmount)||trialAmount<0.01||trialPeriod<=0)?"0":trialAmount;var levelCcapsPer=(regRecur==="BN"&&regTerm!=="L")?level+":"+cCaps+":"+regPeriod+" "+regTerm:level+":"+cCaps;levelCcapsPer=levelCcapsPer.replace(/\:+$/g,"");if(trialAmount!=="0"&&(isNaN(trialAmount)||trialAmount<0)){alert("— Oops, a slight problem: —\n\nWhen provided, Trial Amount must be >= 0.00");return false}else{if(trialAmount!=="0"&&trialAmount>10000&&currencyCode.toUpperCase()==="USD"){alert("— Oops, a slight problem: —\n\nMaximum Trial Amount is: 10000.00");return false}else{if(trialTerm==="D"&&trialPeriod>90){alert("— Oops, a slight problem: —\n\nMaximum Trial Days is: 90.\nIf you want to offer more than 90 days, please choose Weeks or Months from the drop-down.");return false}else{if(trialTerm==="W"&&trialPeriod>52){alert("— Oops, a slight problem: —\n\nMaximum Trial Weeks is: 52.\nIf you want to offer more than 52 weeks, please choose Months from the drop-down.");return false}else{if(trialTerm==="M"&&trialPeriod>24){alert("— Oops, a slight problem: —\n\nMaximum Trial Months is: 24.\nIf you want to offer more than 24 months, please choose Years from the drop-down.");return false}else{if(trialTerm==="Y"&&trialPeriod>5){alert("— Oops, a slight problem: —\n\nMax Trial Period Years is: 5.");return false}else{if(!regAmount||isNaN(regAmount)||regAmount<0.01){alert("— Oops, a slight problem: —\n\nAmount must be >= 0.01");return false}else{if(regAmount>10000&&currencyCode.toUpperCase()==="USD"){alert("— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00");return false}else{if(!desc){alert("— Oops, a slight problem: —\n\nPlease type a Description for this Button.");return false}}}}}}}}}code.html(code.val().replace(/ \<\!--(\<input type\="hidden" name\="(amount|src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g," $1"));(parseInt(trialPeriod)<=0)?code.html(code.val().replace(/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g," <!--$1-->")):null;(regRecur==="BN")?code.html(code.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick$3")):null;(regRecur==="BN")?code.html(code.val().replace(/ (\<input type\="hidden" name\="(src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g," <!--$1-->")):null;(regRecur!=="BN")?code.html(code.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick-subscriptions$3")):null;(regRecur!=="BN")?code.html(code.val().replace(/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g," <!--$1-->")):null;shortCodeTemplateAttrs+=(button==="modification")?'modify="1" ':"";shortCodeTemplateAttrs+='level="'+esc_attr(level)+'" ccaps="'+esc_attr(cCaps)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'" custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"';shortCodeTemplateAttrs+=' ta="'+esc_attr(trialAmount)+'" tp="'+esc_attr(trialPeriod)+'" tt="'+esc_attr(trialTerm)+'" ra="'+esc_attr(regAmount)+'" rp="'+esc_attr(regPeriod)+'" rt="'+esc_attr(regTerm)+'" rr="'+esc_attr(regRecur)+'" rrt="'+esc_attr(regRecurTimes)+'" rra="'+esc_attr(regRecurRetry)+'"';shortCode.val(shortCodeTemplate.replace(/%%attrs%%/,shortCodeTemplateAttrs));code.html(code.val().replace(/ name\="lc" value\="(.*?)"/,' name="lc" value="'+esc_attr(localeCode)+'"'));code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/,' name="no_shipping" value="'+esc_attr(noShipping)+'"'));code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+esc_attr(desc)+'"'));code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+esc_attr(levelCcapsPer)+'"'));code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+esc_attr(pageStyle)+'"'));code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+esc_attr(currencyCode)+'"'));code.html(code.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));code.html(code.val().replace(/ name\="modify" value\="(.*?)"/,' name="modify" value="'+((button==="modification")?"1":"0")+'"'));code.html(code.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+esc_attr(regAmount)+'"'));code.html(code.val().replace(/ name\="src" value\="(.*?)"/,' name="src" value="'+esc_attr(regRecur)+'"'));code.html(code.val().replace(/ name\="srt" value\="(.*?)"/,' name="srt" value="'+esc_attr(regRecurTimes)+'"'));code.html(code.val().replace(/ name\="sra" value\="(.*?)"/,' name="sra" value="'+esc_attr(regRecurRetry)+'"'));code.html(code.val().replace(/ name\="a1" value\="(.*?)"/,' name="a1" value="'+esc_attr(trialAmount)+'"'));code.html(code.val().replace(/ name\="p1" value\="(.*?)"/,' name="p1" value="'+esc_attr(trialPeriod)+'"'));code.html(code.val().replace(/ name\="t1" value\="(.*?)"/,' name="t1" value="'+esc_attr(trialTerm)+'"'));code.html(code.val().replace(/ name\="a3" value\="(.*?)"/,' name="a3" value="'+esc_attr(regAmount)+'"'));code.html(code.val().replace(/ name\="p3" value\="(.*?)"/,' name="p3" value="'+esc_attr(regPeriod)+'"'));code.html(code.val().replace(/ name\="t3" value\="(.*?)"/,' name="t3" value="'+esc_attr(regTerm)+'"'));$("div#ws-plugin--s2member-"+button+"-button-prev").html(code.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g,Math.round(new Date().getTime())+"~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>").replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g,""));(button==="modification")?alert("Your Modification Button has been generated.\nPlease copy/paste the Shortcode into your Login Welcome Page, or wherever you feel it would be most appropriate.\n\n* Remember, Modification Buttons should be displayed to existing Users/Members, and they should be logged-in, BEFORE clicking this Button."):alert("Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.");shortCode.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalCcapButtonGenerate=function(){var shortCodeTemplate='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',shortCodeTemplateAttrs="";var shortCode=$("input#ws-plugin--s2member-ccap-shortcode");var code=$("textarea#ws-plugin--s2member-ccap-button");var desc=$.trim($("input#ws-plugin--s2member-ccap-desc").val().replace(/"/g,""));var regAmount=$("input#ws-plugin--s2member-ccap-amount").val().replace(/[^0-9\.]/g,"");var regPeriod=$("select#ws-plugin--s2member-ccap-term").val().split("-")[0].replace(/[^0-9]/g,"");var regTerm=$("select#ws-plugin--s2member-ccap-term").val().split("-")[1].replace(/[^A-Z]/g,"");var regRecur=$("select#ws-plugin--s2member-ccap-term").val().split("-")[2].replace(/[^0-1BN]/g,"");var localeCode="",digital="0",noShipping="1";var pageStyle=$.trim($("input#ws-plugin--s2member-ccap-page-style").val().replace(/"/g,""));var currencyCode=$("select#ws-plugin--s2member-ccap-currency").val().replace(/[^A-Z]/g,"");var cCaps=$.trim($.trim($("input#ws-plugin--s2member-ccap-ccaps").val()).replace(/^(-all|-al|-a|-)[;,]*/gi,"").replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase());cCaps=($.trim($("input#ws-plugin--s2member-ccap-ccaps").val()).match(/^(-all|-al|-a|-)[;,]*/i))?((cCaps)?"-all,":"-all")+cCaps.toLowerCase():cCaps.toLowerCase();var levelCcapsPer=(regRecur==="BN"&&regTerm!=="L")?"*:"+cCaps+":"+regPeriod+" "+regTerm:"*:"+cCaps;levelCcapsPer=levelCcapsPer.replace(/\:+$/g,"");if(!cCaps||cCaps==="-all"){alert("— Oops, a slight problem: —\n\nPlease provide at least one Custom Capability.");return false}else{if(!regAmount||isNaN(regAmount)||regAmount<0.01){alert("— Oops, a slight problem: —\n\nAmount must be >= 0.01");return false}else{if(regAmount>10000&&currencyCode.toUpperCase()==="USD"){alert("— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00");return false}else{if(!desc){alert("— Oops, a slight problem: —\n\nPlease type a Description for this Button.");return false}}}}shortCodeTemplateAttrs+='level="*" ccaps="'+esc_attr(cCaps)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'"';shortCodeTemplateAttrs+=' custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+esc_attr(regAmount)+'" rp="'+esc_attr(regPeriod)+'" rt="'+esc_attr(regTerm)+'" rr="'+esc_attr(regRecur)+'"';shortCode.val(shortCodeTemplate.replace(/%%attrs%%/,shortCodeTemplateAttrs));code.html(code.val().replace(/ name\="lc" value\="(.*?)"/,' name="lc" value="'+esc_attr(localeCode)+'"'));code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/,' name="no_shipping" value="'+esc_attr(noShipping)+'"'));code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+esc_attr(desc)+'"'));code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+esc_attr(levelCcapsPer)+'"'));code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+esc_attr(pageStyle)+'"'));code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+esc_attr(currencyCode)+'"'));code.html(code.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));code.html(code.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+esc_attr(regAmount)+'"'));$("div#ws-plugin--s2member-ccap-button-prev").html(code.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g,Math.round(new Date().getTime())+"~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>").replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g,""));alert("Your Button has been generated.\nPlease copy/paste the Shortcode into your Login Welcome Page, or wherever you feel it would be most appropriate.\n\n* Remember, Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button.");shortCode.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalSpButtonGenerate=function(){var shortCodeTemplate='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',shortCodeTemplateAttrs="";var shortCode=$("input#ws-plugin--s2member-sp-shortcode");var code=$("textarea#ws-plugin--s2member-sp-button");var leading=$("select#ws-plugin--s2member-sp-leading-id").val().replace(/[^0-9]/g,"");var additionals=$("select#ws-plugin--s2member-sp-additional-ids").val()||[];var hours=$("select#ws-plugin--s2member-sp-hours").val().replace(/[^0-9]/g,"");var regAmount=$("input#ws-plugin--s2member-sp-amount").val().replace(/[^0-9\.]/g,"");var desc=$.trim($("input#ws-plugin--s2member-sp-desc").val().replace(/"/g,""));var localeCode="",digital="0",noShipping="1";var pageStyle=$.trim($("input#ws-plugin--s2member-sp-page-style").val().replace(/"/g,""));var currencyCode=$("select#ws-plugin--s2member-sp-currency").val().replace(/[^A-Z]/g,"");if(!leading){alert("— Oops, a slight problem: —\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.");return false}else{if(!regAmount||isNaN(regAmount)||regAmount<0.01){alert("— Oops, a slight problem: —\n\nAmount must be >= 0.01");return false}else{if(regAmount>10000&&currencyCode.toUpperCase()==="USD"){alert("— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00");return false}else{if(!desc){alert("— Oops, a slight problem: —\n\nPlease type a Description for this Button.");return false}}}}for(var i=0,ids=leading;i<additionals.length;i++){if(additionals[i]&&additionals[i]!==leading){ids+=","+additionals[i]}}var spIdsHours="sp:"+ids+":"+hours;shortCodeTemplateAttrs+='sp="1" ids="'+esc_attr(ids)+'" exp="'+esc_attr(hours)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'"';shortCodeTemplateAttrs+=' custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+esc_attr(regAmount)+'"';shortCode.val(shortCodeTemplate.replace(/%%attrs%%/,shortCodeTemplateAttrs));code.html(code.val().replace(/ name\="lc" value\="(.*?)"/,' name="lc" value="'+esc_attr(localeCode)+'"'));code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/,' name="no_shipping" value="'+esc_attr(noShipping)+'"'));code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+esc_attr(desc)+'"'));code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+esc_attr(spIdsHours)+'"'));code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+esc_attr(pageStyle)+'"'));code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+esc_attr(currencyCode)+'"'));code.html(code.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));code.html(code.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+esc_attr(regAmount)+'"'));$("div#ws-plugin--s2member-sp-button-prev").html(code.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g,Math.round(new Date().getTime())+"~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>").replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g,""));alert("Your Button has been generated.\nPlease copy/paste the Shortcode into your WordPress Editor.");shortCode.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalRegLinkGenerate=function(){var level=$("select#ws-plugin--s2member-reg-link-level").val().replace(/[^0-9]/g,"");var subscrID=$.trim($("input#ws-plugin--s2member-reg-link-subscr-id").val());var custom=$.trim($("input#ws-plugin--s2member-reg-link-custom").val());var cCaps=$.trim($.trim($("input#ws-plugin--s2member-reg-link-ccaps").val()).replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase());var fixedTerm=$.trim($("input#ws-plugin--s2member-reg-link-fixed-term").val().replace(/[^A-Z 0-9]/gi,"").toUpperCase());var $link=$("p#ws-plugin--s2member-reg-link"),$loading=$("img#ws-plugin--s2member-reg-link-loading");var levelCcapsPer=(fixedTerm&&!fixedTerm.match(/L$/))?level+":"+cCaps+":"+fixedTerm:level+":"+cCaps;levelCcapsPer=levelCcapsPer.replace(/\:+$/g,"");if(!subscrID){alert("— Oops, a slight problem: —\n\nPaid Subscr. ID is a required value.");return false}else{if(!custom||custom.indexOf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq ($_SERVER["HTTP_HOST"]); ?>')!==0){alert("— Oops, a slight problem: —\n\nThe Custom Value MUST start with your domain name.");return false}else{if(fixedTerm&&!fixedTerm.match(/^[1-9]+ (D|W|M|Y|L)$/)){alert("— Oops, a slight problem: —\n\nThe Fixed Term Length is not formatted properly.");return false}}}$link.hide(),$loading.show(),$.post(ajaxurl,{action:"ws_plugin__s2member_reg_access_link_via_ajax",ws_plugin__s2member_reg_access_link_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-reg-access-link-via-ajax")); ?>',s2member_reg_access_link_subscr_gateway:"paypal",s2member_reg_access_link_subscr_id:subscrID,s2member_reg_access_link_custom:custom,s2member_reg_access_link_item_number:levelCcapsPer},function(response){$link.show().html('<a href="'+esc_attr(response)+'" target="_blank" rel="external">'+esc_html(response)+"</a>"),$loading.hide()});return false};ws_plugin__s2member_paypalSpLinkGenerate=function(){var leading=$("select#ws-plugin--s2member-sp-link-leading-id").val().replace(/[^0-9]/g,"");var additionals=$("select#ws-plugin--s2member-sp-link-additional-ids").val()||[];var hours=$("select#ws-plugin--s2member-sp-link-hours").val().replace(/[^0-9]/g,"");var $link=$("p#ws-plugin--s2member-sp-link"),$loading=$("img#ws-plugin--s2member-sp-link-loading");if(!leading){alert("— Oops, a slight problem: —\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.");return false}for(var i=0,ids=leading;i<additionals.length;i++){if(additionals[i]&&additionals[i]!==leading){ids+=","+additionals[i]}}$link.hide(),$loading.show(),$.post(ajaxurl,{action:"ws_plugin__s2member_sp_access_link_via_ajax",ws_plugin__s2member_sp_access_link_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link-via-ajax")); ?>',s2member_sp_access_link_ids:ids,s2member_sp_access_link_hours:hours},function(response){$link.show().html('<a href="'+esc_attr(response)+'" target="_blank" rel="external">'+esc_html(response)+"</a>"),$loading.hide()});return false}}if(location.href.match(/page\=ws-plugin--s2member-els-ops/)){$("select#ws-plugin--s2member-custom-reg-opt-in").change(function(){var $this=$(this),val=$this.val();var $rows=$("tr.ws-plugin--s2member-custom-reg-opt-in-label-row");var $prevImg=$("img.ws-plugin--s2member-custom-reg-opt-in-label-prev-img");if(val<=0){$rows.css("display","none"),$prevImg.attr("src",$prevImg.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))}else{if(val==1){$rows.css("display",""),$prevImg.attr("src",$prevImg.attr("src").replace(/\/unchecked\.png$/,"/checked.png"))}else{if(val==2){$rows.css("display",""),$prevImg.attr("src",$prevImg.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))}}}});$('div.ws-plugin--s2member-opt-out-section input[type="checkbox"][name="ws_plugin__s2member_custom_reg_auto_opt_outs[]"]').change(function(){var thisChange=$(this).val(),checkedIndexes=[];$('div.ws-plugin--s2member-opt-out-section input[type="checkbox"][name="ws_plugin__s2member_custom_reg_auto_opt_outs[]"]').each(function(){var $this=$(this),val=$this.val(),checkboxes='input[type="checkbox"]';if(val==="removal-deletion"&&this.checked){$this.nextAll(checkboxes).slice(0,2).attr({checked:"checked",disabled:"disabled"})}else{if(val==="removal-deletion"&&!this.checked){$this.nextAll(checkboxes).slice(0,2).removeAttr("disabled");(thisChange==="removal-deletion")?$this.nextAll(checkboxes).slice(0,2).removeAttr("checked"):null}else{if(val==="modification"&&this.checked){$this.nextAll(checkboxes).slice(0,3).attr({checked:"checked",disabled:"disabled"})}else{if(val==="modification"&&!this.checked){(thisChange==="modification")?$this.nextAll(checkboxes).slice(0,3).removeAttr("checked"):null;$this.nextAll(checkboxes).slice(0,3).removeAttr("disabled")}}}}}).each(function(index){(this.checked)?checkedIndexes.push(index):null});$("select#ws-plugin--s2member-custom-reg-auto-opt-out-transitions").removeAttr("disabled");if($.inArray(3,checkedIndexes)===-1&&$.inArray(4,checkedIndexes)===-1&&$.inArray(5,checkedIndexes)===-1&&$.inArray(6,checkedIndexes)===-1){$("select#ws-plugin--s2member-custom-reg-auto-opt-out-transitions").attr("disabled","disabled")}}).last().trigger("change")}});
 
1
+ jQuery(document).ready(function($){var esc_attr=esc_html=function(e){return/[&\<\>"']/.test(e=String(e))&&(e=e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),e=e.replace(/"/g,"&quot;").replace(/'/g,"&#039;")),e};if(ws_plugin__s2member_generateSecurityKey=function(e){e||(e="#ws-plugin--s2member-sec-encryption-key");for(var t=function(e,t){return e=arguments.length<1?0:e,t=arguments.length<2?2147483647:t,Math.floor(Math.random()*(t-e+1))+e},s="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#%^&*()",l=0,r="";l<64;l++)r+=s.substr(t(0,s.length-1),1);return $(e).val(r),!1},location.href.match(/page\=ws-plugin--s2member/)&&$("input.ws-plugin--s2member-update-roles-button, input.ws-plugin--s2member-reset-roles-button").click(function(){var e=$(this);e.val("one moment please ...");var t='<?php echo (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; ?>',s=e.hasClass("ws-plugin--s2member-reset-roles-button")?"Reset":"Update";return $.post(ajaxurl,{action:"ws_plugin__s2member_update_roles_via_ajax",ws_plugin__s2member_update_roles_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-update-roles-via-ajax")); ?>'},function(l){"1"===l?(alert("s2Member's Roles/Capabilities "+("reset"===s.toLowerCase()?"have been successfully reset":"updated successfully")+".\nYour installation of s2Member has Membership Levels 0-"+t+"."),e.val(s+" Roles/Capabilities")):"l"===l?(alert("Sorry, your request failed.\ns2Member's Roles/Capabilities are locked by Filter:\nws_plugin__s2member_lock_roles_caps"),e.val(s+" Roles/Capabilities")):(alert("Sorry, your request failed.\nAccess denied. Do you have the ability to `create_users`?"),e.val(s+" Roles/Capabilities"))}),!1}),location.href.match(/page\=ws-plugin--s2member-logs/)){$("input#ws-plugin--s2member-gateway-debug-logs-extensive-1").click(function(){var e=($(this),!!this.checked);e&&$("input#ws-plugin--s2member-gateway-debug-logs-1").attr("checked","checked")});var $toggles=$("a.ws-plugin--s2member-log-file-viewport-toggle");$toggles.click(function(){return $("textarea#ws-plugin--s2member-log-file-viewer").each(function(){var e=$(this);"expanded"!==e.attr("data-state")?(e.css({height:e.prop("scrollHeight")+50+"px","overflow-y":"auto"}),$toggles.html("&#8657; normalize viewport &#10073;"),e.attr("data-state","expanded")):(e.css({height:"auto","overflow-y":"scroll"}),$toggles.html("&#8659; expand viewport &#8659;"),e.attr("data-state","scrolling"))}),!1})}if(location.href.match(/page\=ws-plugin--s2member-mms-ops/)&&($("select#ws-plugin--s2member-mms-registration-file").change(function(){if("wp-signup"===$(this).val()){var e=$("select#ws-plugin--s2member-mms-registration-grants").val(),t=$("input#ws-plugin--s2member-mms-registration-blogs-level0").val();$("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").show(),$("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").hide(),$("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").show(),$("div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0")["all"===e?"show":"hide"](),$("input#ws-plugin--s2member-mms-registration-blogs-level0").val("all"===e?t>0?t:"1":"0")}else if("wp-login"===$(this).val()){var e=$("select#ws-plugin--s2member-mms-registration-grants").val(),t=$("input#ws-plugin--s2member-mms-registration-blogs-level0").val();$("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").hide(),$("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").show(),$("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").hide(),$("div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0").hide(),$("input#ws-plugin--s2member-mms-registration-blogs-level0").val("0")}}).trigger("change"),$("select#ws-plugin--s2member-mms-registration-grants").change(function(){$("select#ws-plugin--s2member-mms-registration-file").trigger("change")})),location.href.match(/page\=ws-plugin--s2member-gen-ops/)&&(ws_plugin__s2member_enableSecurityKey=function(){return confirm("Edit Key? Are you sure?\nThis could break your installation!\n\n*Note* If you've been testing s2Member, feel free to change this Key before you go live. Just don't go live, and then change it. You'll have unhappy Customers. Data corruption WILL occur! For your safety, s2Member keeps a history of the last 10 Keys that you've used. If you get yourself into a real situation, s2Member will let you revert back to a previous Key.")&&$("input#ws-plugin--s2member-sec-encryption-key").removeAttr("disabled"),!1},ws_plugin__s2member_securityKeyHistory=function(){return $("div#ws-plugin--s2member-sec-encryption-key-history").toggle(),!1},$("select#ws-plugin--s2member-new-user-emails-enabled").change(function(){var e=$("input#ws-plugin--s2member-pluggables-wp-new-user-notification"),t=$(this),s=$("div#ws-plugin--s2member-new-user-emails");"0"===e.val()||"0"===t.val()?("0"===e.val()?t.attr("disabled","disabled"):t.removeAttr("disabled"),$(":input",s).attr("disabled","disabled"),s.css("opacity","0.5")):(t.removeAttr("disabled"),$(":input",s).removeAttr("disabled"),s.css("opacity",""))}).trigger("change"),$("select#ws-plugin--s2member-login-reg-design-enabled").change(function(){var e=$(this),t=$("div#ws-plugin--s2member-login-reg-design");"0"===e.val()?($(":input",t).attr("disabled","disabled"),t.css("opacity","0.5"),t.hide()):($(":input",t).removeAttr("disabled"),t.css("opacity",""),t.show())}).trigger("change"),$("select#ws-plugin--s2member-custom-reg-password").change(function(){var e=$(this),t=$("div#ws-plugin--s2member-new-user-email-details");"1"===e.val()?t.css("opacity","0.5"):t.css("opacity","")}).trigger("change"),$("input#ws-plugin--s2member-custom-reg-fields").length&&$("div#ws-plugin--s2member-custom-reg-field-configuration").length&&!function(){var e,t,s,l,r,o,a=$("input#ws-plugin--s2member-custom-reg-fields"),i=$("div#ws-plugin--s2member-custom-reg-field-configuration"),n=a.val()?$.JSON.parse(a.val()):[];for(n=n instanceof Array?n:[],t={section:"no",sectitle:"",id:"",label:"",type:"text",deflt:"",options:"",expected:"",required:"yes",levels:"all",editable:"yes",classes:"",styles:"",attrs:""},e=0;e<n.length;e++)n[e]=$.extend(!0,{},t,n[e]);s='<div id="ws-plugin--s2member-custom-reg-field-configuration-tools"></div>',l='<table id="ws-plugin--s2member-custom-reg-field-configuration-table"></table>',i.html(s+l),r=$("div#ws-plugin--s2member-custom-reg-field-configuration-tools"),o=$("table#ws-plugin--s2member-custom-reg-field-configuration-table"),ws_plugin__s2member_customRegFieldSectionChange=function(e){var t=$(e).val(),s="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle";"yes"===t?$(s).css("display",""):$(s).css("display","none")},ws_plugin__s2member_customRegFieldTypeChange=function(e){var t=$(e).val(),s="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt",l="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-options",r="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected";t.match(/^(text|textarea)$/)?$(s).css("display",""):$(s).css("display","none"),t.match(/^(select|selects|checkboxes|radios)$/)?$(l).css("display",""):$(l).css("display","none"),t.match(/^(text|textarea)$/)?$(r).css("display",""):$(r).css("display","none")},ws_plugin__s2member_customRegFieldDelete=function(e){for(var t=new Array,s=0;s<n.length;s++)s!==e&&t.push(n[s]);n=t,m(),b()},ws_plugin__s2member_customRegFieldMoveUp=function(e){if("object"==typeof n[e]&&"object"==typeof n[e-1]){var t=n[e-1],s=n[e];n[e-1]=s,n[e]=t,m(),b()}},ws_plugin__s2member_customRegFieldMoveDown=function(e){if("object"==typeof n[e]&&"object"==typeof n[e+1]){var t=n[e+1],s=n[e];n[e+1]=s,n[e]=t,m(),b()}},ws_plugin__s2member_customRegFieldCreate=function(){var e=$("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),t={};$(":input[property]",e).each(function(){var e=$(this),s=e.attr("property"),l=$.trim(e.val());t[s]=l}),(t=c(t))&&(n.push(t),m(),g(),b(),d(),setTimeout(function(){"tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+(n.length-1);alert('Field created successfully.\n* Remember to "Save All Changes".')},500))},ws_plugin__s2member_customRegFieldUpdate=function(e){var t=$("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),s={};$(":input[property]",t).each(function(){var e=$(this),t=e.attr("property"),l=$.trim(e.val());s[t]=l}),(s=c(s,e))&&(n[e]=s,m(),g(),b(),d(),setTimeout(function(){alert('Field updated successfully.\n* Remember to "Save All Changes".')},500))},ws_plugin__s2member_customRegFieldAdd=function(){g(!0)},ws_plugin__s2member_customRegFieldEdit=function(e){g(!1,e),d()},ws_plugin__s2member_customRegFieldCancel=function(){g(),d()};var c=function(e,s){var l,r,o="number"==typeof s&&"object"==typeof n[s],a=[];if("object"!=typeof e||"object"!=typeof(e=$.extend(!0,{},t,e)))return alert("Invalid field object. Please try again."),!1;if(e.sectitle="yes"===e.section?e.sectitle:"",e.deflt=e.type.match(/^(text|textarea)$/)?e.deflt:"",e.deflt=e.type.match(/^(text)$/)?e.deflt.replace(/[\r\n\t ]+/g," "):e.deflt,e.options=e.type.match(/^(select|selects|checkboxes|radios)$/)?e.options:"",e.expected=e.type.match(/^(text|textarea)$/)?e.expected:"",e.id?!u(e.id)||o&&e.id===n[s].id||a.push("Unique Field ID:\nThat Field ID already exists. Please try again."):a.push("Unique Field ID:\nThis is required. Please try again."),e.label||a.push("Field Label/Description:\nThis is required. Please try again."),e.type.match(/^(select|selects|checkboxes|radios)$/)&&!e.options)a.push("Option Configuration File:\nThis is required. Please try again.");else if(e.type.match(/^(select|selects|checkboxes|radios)$/)){for(r=0;r<(l=e.options.split(/[\r\n]+/)).length;r++)if(!(l[r]=$.trim(l[r])).match(/^([^\|]*)(\|)([^\|]*)(\|default)?$/)){a.push("Option Configuration File:\nInvalid configuration at line #"+(r+1)+".");break}e.options=$.trim(l.join("\n"))}return(e.levels=e.levels.replace(/ /g,""))?e.levels.match(/^(all|[0-9,]+)$/)||a.push("Applicable Levels:\nShould be comma-delimited Levels, or just type: all.\n(examples: 0,1,2,3,4 or type the word: all)"):a.push("Applicable Levels:\nThis is required. Please try again."),e.classes&&e.classes.match(/[^a-z 0-9 _ \-]/i)&&a.push("CSS Classes:\nContains invalid characters. Please try again.\n(only: alphanumerics, underscores, hyphens, spaces)"),e.styles&&e.styles.match(/["\=\>\<]/)&&a.push('CSS Styles:\nContains invalid characters. Please try again.\n(do NOT use these characters: = " < >)'),e.attrs&&e.attrs.match(/[\>\<]/)&&a.push("Other Attributes:\nContains invalid characters. Please try again.\n(do NOT use these characters: < >)"),a.length>0?(alert(a.join("\n\n")),!1):e},m=function(){a.val(n.length>0?$.JSON.stringify(n):"")},p=function(e){var t={text:"Text (single line)",textarea:"Textarea (multi-line)",select:"Select Menu (drop-down)",selects:"Select Menu (multi-option)",checkbox:"Checkbox (single)",pre_checkbox:"Checkbox (pre-checked)",checkboxes:"Checkboxes (multi-option)",radios:"Radio Buttons (multi-option)"};return"string"==typeof t[e]?t[e]:""},u=function(e){for(var t=0;t<n.length;t++)if(n[t].id===e)return!0},d=function(){scrollTo(0,$("div.ws-plugin--s2member-custom-reg-fields-section").offset().top-100)},g=function(e,s){var l=0,o="",a="",i="number"==typeof s&&"object"==typeof n[s],c=!(!e&&!i),m=i?$.extend(!0,{},t,n[s]):t;if(o+='<a href="#" onclick="ws_plugin__s2member_customRegFieldAdd(); return false;">Add New Field</a>',tb_remove(),$("div#ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form").remove(),c){for(a+='<div id="ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form">',a+='<table id="ws-plugin--s2member-custom-reg-field-configuration-tools-form">',a+="<tbody>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">Starts A New Section?</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">',a+='<td colspan="2">',a+='<select property="section" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section" onchange="ws_plugin__s2member_customRegFieldSectionChange(this);">',a+='<option value="no"'+("no"===m.section?' selected="selected"':"")+'">No (this Field flows normally)</option>',a+='<option value="yes"'+("yes"===m.section?' selected="selected"':"")+'">Yes (this Field begins a new section)</option>',a+="</select><br />",a+="<small>Optional. Allows Fields to be grouped into sections.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle ws-plugin--s2member-custom-reg-field-configuration-tools-form-section"'+("yes"===m.section?"":' style="display:none;"')+'><td colspan="2"><hr /></td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle ws-plugin--s2member-custom-reg-field-configuration-tools-form-section"'+("yes"===m.section?"":' style="display:none;"')+">",a+='<td colspan="2">',a+="Title for this new section? (optional)<br />",a+='<input type="text" property="sectitle" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle" value="'+esc_attr(m.sectitle)+'" /><br />',a+="<small>If empty, a simple divider will be used by default.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-type"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">Form Field Type: *</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">',a+='<td colspan="2">',a+='<select property="type" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);">',a+='<option value="text"'+("text"===m.type?' selected="selected"':"")+'">'+esc_html(p("text"))+"</option>",a+='<option value="textarea"'+("textarea"===m.type?' selected="selected"':"")+'">'+esc_html(p("textarea"))+"</option>",a+='<option value="select"'+("select"===m.type?' selected="selected"':"")+'">'+esc_html(p("select"))+"</option>",a+='<option value="selects"'+("selects"===m.type?' selected="selected"':"")+'">'+esc_html(p("selects"))+"</option>",a+='<option value="checkbox"'+("checkbox"===m.type?' selected="selected"':"")+'">'+esc_html(p("checkbox"))+"</option>",a+='<option value="pre_checkbox"'+("pre_checkbox"===m.type?' selected="selected"':"")+'">'+esc_html(p("pre_checkbox"))+"</option>",a+='<option value="checkboxes"'+("checkboxes"===m.type?' selected="selected"':"")+'">'+esc_html(p("checkboxes"))+"</option>",a+='<option value="radios"'+("radios"===m.type?' selected="selected"':"")+'">'+esc_html(p("radios"))+"</option>",a+="</select><br />",a+="<small>The options below may change, based on the Field Type you choose here.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-label"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">Field Label/Desc: *</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">',a+='<td colspan="2">',a+='<input type="text" property="label" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label" value="'+esc_attr(m.label)+'" /><br />',a+="<small>Examples: <code>Choose Country</code>, <code>Street Address</code></small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-id"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">Unique Field ID: *</label></label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">',a+='<td colspan="2">',a+='<input type="text" property="id" maxlength="25" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id" value="'+esc_attr(m.id)+'" /><br />',a+="<small>Examples: <code>country_code</code>, <code>street_address</code></small><br />",a+='<small>e.g., <code>[s2Get user_field="country_code" /]</code></small>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-required"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">Field Required: *</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">',a+='<td colspan="2">',a+='<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">',a+='<option value="yes"'+("yes"===m.required?' selected="selected"':"")+'">Yes (required)</option>',a+='<option value="no"'+("no"===m.required?' selected="selected"':"")+'">No (optional)</option>',a+="</select><br />",a+='<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />',a+="<small>* Administrators are exempt from this requirement.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+(m.type.match(/^(text|textarea)$/)?"":' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+(m.type.match(/^(text|textarea)$/)?"":' style="display:none;"')+">",a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt">Default Text Value: (optional)</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+(m.type.match(/^(text|textarea)$/)?"":' style="display:none;"')+">",a+='<td colspan="2">',a+='<textarea property="deflt" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt" rows="1">'+esc_html(m.deflt)+"</textarea><br />",a+="<small>Default value before user input is received.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+(m.type.match(/^(select|selects|checkboxes|radios)$/)?"":' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+(m.type.match(/^(select|selects|checkboxes|radios)$/)?"":' style="display:none;"')+">",a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * (one option per line)</label><br />',a+="<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+(m.type.match(/^(select|selects|checkboxes|radios)$/)?"":' style="display:none;"')+">",a+='<td colspan="2">',a+='<textarea property="options" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options" rows="3">'+esc_html(m.options)+"</textarea><br />",a+="Here is a quick example:<br />",a+="<small>You can also specify a <em>default</em> option:</small><br />",a+="<code>US|United States|default</code><br />",a+="<code>CA|Canada</code><br />",a+="<code>VI|Virgin Islands (U.S.)</code>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+(m.type.match(/^(text|textarea)$/)?"":' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+(m.type.match(/^(text|textarea)$/)?"":' style="display:none;"')+">",a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+(m.type.match(/^(text|textarea)$/)?"":' style="display:none;"')+">",a+='<td colspan="2">',a+='<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">',a+='<option value=""'+(""===m.expected?' selected="selected"':"")+'">Anything Goes</option>',a+='<option disabled="disabled"></option>',a+='<optgroup label="Specific Input Types">',a+='<option value="numeric-wp-commas"'+("numeric-wp-commas"===m.expected?' selected="selected"':"")+'">Numeric (with or without decimals, commas allowed)</option>',a+='<option value="numeric"'+("numeric"===m.expected?' selected="selected"':"")+'">Numeric (with or without decimals, no commas)</option>',a+='<option value="integer"'+("integer"===m.expected?' selected="selected"':"")+'">Integer (whole number, without any decimals)</option>',a+='<option value="integer-gt-0"'+("integer-gt-0"===m.expected?' selected="selected"':"")+'">Integer > 0 (whole number, no decimals, greater than 0)</option>',a+='<option value="float"'+("float"===m.expected?' selected="selected"':"")+'">Float (floating point number, decimals required)</option>',a+='<option value="float-gt-0"'+("float-gt-0"===m.expected?' selected="selected"':"")+'">Float > 0 (floating point number, decimals required, greater than 0)</option>',a+='<option value="date"'+("date"===m.expected?' selected="selected"':"")+'">Date (required date format: dd/mm/yyyy)</option>',a+='<option value="email"'+("email"===m.expected?' selected="selected"':"")+'">Email (require valid email)</option>',a+='<option value="url"'+("url"===m.expected?' selected="selected"':"")+'">Full URL (starting with http or https)</option>',a+='<option value="domain"'+("domain"===m.expected?' selected="selected"':"")+'">Domain Name (domain name only, without http)</option>',a+='<option value="phone"'+("phone"===m.expected?' selected="selected"':"")+'">Phone # (10 digits w/possible hyphens,spaces,brackets)</option>',a+='<option value="uszip"'+("uszip"===m.expected?' selected="selected"':"")+'">US Zipcode (5-9 digits w/possible hyphen)</option>',a+='<option value="cazip"'+("cazip"===m.expected?' selected="selected"':"")+'">Canadian Zipcode (6 alpha-numerics w/possible space)</option>',a+='<option value="uczip"'+("uczip"===m.expected?' selected="selected"':"")+'">US/Canadian Zipcode (either a US or Canadian zipcode)</option>',a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Any Character Combination">',l=1;l<=25;l++)a+='<option value="any-'+l+'"'+(m.expected==="any-"+l?' selected="selected"':"")+'">Any Character Combination ('+l+" character minimum)</option>",a+='<option value="any-'+l+'-e"'+(m.expected==="any-"+l+"-e"?' selected="selected"':"")+'">Any Character Combination (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-spaces-punctuation-'+l+'"'+(m.expected==="alphanumerics-spaces-punctuation-"+l?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation ('+l+" character minimum)</option>",a+='<option value="alphanumerics-spaces-punctuation-'+l+'-e"'+(m.expected==="alphanumerics-spaces-punctuation-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphanumerics &amp; Spaces Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-spaces-'+l+'"'+(m.expected==="alphanumerics-spaces-"+l?' selected="selected"':"")+'">Alphanumerics &amp; Spaces ('+l+" character minimum)</option>",a+='<option value="alphanumerics-spaces-'+l+'-e"'+(m.expected==="alphanumerics-spaces-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics &amp; Spaces (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphanumerics &amp; Punctuation Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-punctuation-'+l+'"'+(m.expected==="alphanumerics-punctuation-"+l?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation ('+l+" character minimum)</option>",a+='<option value="alphanumerics-punctuation-'+l+'-e"'+(m.expected==="alphanumerics-punctuation-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphanumerics Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-'+l+'"'+(m.expected==="alphanumerics-"+l?' selected="selected"':"")+'">Alphanumerics ('+l+" character minimum)</option>",a+='<option value="alphanumerics-'+l+'-e"'+(m.expected==="alphanumerics-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphabetics Only">',l=1;l<=25;l++)a+='<option value="alphabetics-'+l+'"'+(m.expected==="alphabetics-"+l?' selected="selected"':"")+'">Alphabetics ('+l+" character minimum)</option>",a+='<option value="alphabetics-'+l+'-e"'+(m.expected==="alphabetics-"+l+"-e"?' selected="selected"':"")+'">Alphabetics (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Numeric Digits Only">',l=1;l<=25;l++)a+='<option value="numerics-'+l+'"'+(m.expected==="numerics-"+l?' selected="selected"':"")+'">Numeric Digits ('+l+" digit minimum)</option>",a+='<option value="numerics-'+l+'-e"'+(m.expected==="numerics-"+l+"-e"?' selected="selected"':"")+'">Numeric Digits (exactly '+l+" digit"+(l>1?"s":"")+")</option>";a+="</optgroup>",a+="</select><br />",a+="<small>Only Users/Members will be required to meet this criteria.</small><br />",a+="<small>* Administrators are exempt from this.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">Applicable Membership Levels: *</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">',a+='<td colspan="2">',a+='<input type="text" property="levels" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels" value="'+esc_attr(m.levels)+'" /><br />',a+="<small>Please use comma-delimited Level #'s: <code>0,1,2,3,4</code> or type: <code>all</code>.</small><br />",a+="<small>This allows you to enable this field - only at specific Membership Levels.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">Allow Profile Edits: *</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">',a+='<td colspan="2">',a+='<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">',a+='<option value="yes"'+("yes"===m.editable?' selected="selected"':"")+'">Yes (editable)</option>',a+='<option value="no"'+("no"===m.editable?' selected="selected"':"")+'">No (uneditable after registration)</option>',a+='<option value="no-invisible"'+("no-invisible"===m.editable?' selected="selected"':"")+'">No (uneditable &amp; totally invisible after registration)</option>',a+='<option value="no-always-invisible"'+("no-always-invisible"===m.editable?' selected="selected"':"")+'">No (uneditable &amp; totally invisible, both during &amp; after registration)</option>',a+='<option value="yes-invisible"'+("yes-invisible"===m.editable?' selected="selected"':"")+'">Yes (editable after registration / invisible during registration)</option>',a+="</select><br />",a+="<small>If <code>No</code>, this field will be un-editable after registration.</small><br />",a+="<small>* Administrators are exempt from this.</small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">CSS Classes: (optional)</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">',a+='<td colspan="2">',a+='<input type="text" property="classes" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes" value="'+esc_attr(m.classes)+'" /><br />',a+="<small>Example: <code>my-style-1 my-style-2</code></small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">CSS Styles: (optional)</label>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">',a+='<td colspan="2">',a+='<input type="text" property="styles" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles" value="'+esc_attr(m.styles)+'" /><br />',a+="<small>Example: <code>color:#000000; background:#FFFFFF;</code></small>",a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">',a+='<td colspan="2">',a+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">Other Attributes: (optional)</label>',
2
+ a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">',a+='<td colspan="2">',a+='<input type="text" property="attrs" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs" value="'+esc_attr(m.attrs)+'" /><br />',a+='<small>Example: <code>onkeyup="" onblur=""</code></small>',a+="</td>",a+="</tr>",a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons"><td colspan="2">&nbsp;</td></tr>',a+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons">',a+='<td align="left">',a+='<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />',a+="</td>",a+='<td align="right">',a+='<input type="button" value="'+(i?"Update This Field":"Create Registration Field")+'" onclick="'+(i?"ws_plugin__s2member_customRegFieldUpdate("+s+");":"ws_plugin__s2member_customRegFieldCreate();")+'" />',a+="</td>",a+="</tr>",a+="</tbody>",a+="</table>",a+="<div>",$("body").append(a),tb_show(i?"Editing Registration/Profile Field":"New Custom Registration/Profile Field","#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form"),$("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form").show()}r.html(o)},b=function(){var e=(n.length,0),t="",s="o";if(t+="<tbody>",t+="<tr>",t+="<th>Order</th>",t+="<th>Field Type</th>",t+="<th>Unique ID</th>",t+="<th>Required</th>",t+="<th>Levels</th>",t+="<th>- Tools -</th>",t+="</tr>",n.length>0)for(e=0;e<n.length;e++)t+='<tr class="'+esc_attr(s="o"===s?"e":"o")+("yes"===n[e].section?" s":"")+" ws-plugin--s2member-custom-reg-field-configuration-table-row-"+e+'">',t+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-move-up" href="#" onclick="ws_plugin__s2member_customRegFieldMoveUp('+e+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-move-down" href="#" onclick="ws_plugin__s2member_customRegFieldMoveDown('+e+'); return false;"></a></td>',t+='<td nowrap="nowrap">'+esc_html(p(n[e].type))+"</td>",t+='<td nowrap="nowrap">'+esc_html(n[e].id)+"</td>",t+='<td nowrap="nowrap">'+esc_html(n[e].required)+"</td>",t+='<td nowrap="nowrap">'+esc_html(n[e].levels)+"</td>",t+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-edit" href="#" onclick="ws_plugin__s2member_customRegFieldEdit('+e+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-delete" href="#" onclick="ws_plugin__s2member_customRegFieldDelete('+e+'); return false;"></a></td>',t+="</tr>";else t+="<tr>",t+='<td colspan="6">No Custom Fields are configured.</td>',t+="</tr>";t+="</tbody>",o.html(t)};g(),b()}()),location.href.match(/page\=ws-plugin--s2member-res-ops/)&&($("input#ws-plugin--s2member-brute-force-restrictions-reset-button").click(function(){var e=$(this);return e.val("one moment please ..."),$.post(ajaxurl,{action:"ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax",ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'},function(t){alert("s2Member's Brute Force Restriction Logs have all been reset."),e.val("Reset Brute Force Logs")}),!1}),$("input#ws-plugin--s2member-ip-restrictions-reset-button").click(function(){var e=$(this);return e.val("one moment please ..."),$.post(ajaxurl,{action:"ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax",ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'},function(t){alert("s2Member's IP Restriction Logs have all been reset."),e.val("Reset IP Restriction Logs")}),!1}),$('div.ws-plugin--s2member-query-level-access-section input[type="checkbox"][name="ws_plugin__s2member_filter_wp_query[]"]').change(function(){var e=$(this).val();$('div.ws-plugin--s2member-query-level-access-section input[type="checkbox"][name="ws_plugin__s2member_filter_wp_query[]"]').each(function(){var t=$(this),s=t.val(),l='input[type="checkbox"]';"all"===s&&this.checked?t.nextAll(l).attr({checked:"checked",disabled:"disabled"}):"all"!==s||this.checked||(t.nextAll(l).removeAttr("disabled"),"all"===e?t.nextAll(l).removeAttr("checked"):null)})}).last().trigger("change")),location.href.match(/page\=ws-plugin--s2member-down-ops/)){var updateCloudFrontPrivateKey=function(){var e=$("input#ws-plugin--s2member-amazon-cf-files-private-key"),t=$("textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry"),s=$.trim(e.val()),l=$.trim(t.val());(s&&!l||l.match(/[^\r\n\u25CF]/))&&(e.val(l),t.val(l.replace(/[^\r\n]/g,String.fromCharCode(9679))))};$("form#ws-plugin--s2member-options-form").submit(updateCloudFrontPrivateKey),$("textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry").change(updateCloudFrontPrivateKey).trigger("change");var updateCloudFrontDistroCfgs=function(){var e=$("input#ws-plugin--s2member-amazon-cf-files-private-key"),t=$("input#ws-plugin--s2member-amazon-cf-files-private-key-id"),s=$("input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros"),l=$("input#ws-plugin--s2member-amazon-cf-files-distros-auto-config-status"),r=$.trim(l.val()),o=$.trim(e.val()),a=$.trim(t.val()),i=$.trim(e.attr("data-s-prev-config-value")),n=$.trim(t.attr("data-s-prev-config-value"));"configured"===r&&(n&&a!==n||i&&o!==i)?(alert("s2Member will need to delete and re-configure your Amazon CloudFront distributions if you change this. When you're done editing, click (Save All Changes) below."),s.attr("checked","checked")):"configured"!==r&&a&&o&&(alert("s2Member will need to auto-configure your Amazon CloudFront distributions for you. When you're done editing, click (Save All Changes) below."),s.attr("checked","checked"))};$("input#ws-plugin--s2member-amazon-cf-files-private-key-id").change(updateCloudFrontDistroCfgs),$("textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry").change(updateCloudFrontDistroCfgs),$("input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames").change(function(){var e=($(this),!!this.checked),t=$("input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros"),s=$("div#ws-plugin--s2member-amazon-cf-files-auto-configure-distro-cnames");e?s.show():s.hide(),e?t.attr("checked","checked"):null}).trigger("change")}location.href.match(/page\=ws-plugin--s2member-paypal-ops/)&&$("select#ws-plugin--s2member-auto-eot-system-enabled").change(function(){var e=$(this),t=e.val(),s=$("p#ws-plugin--s2member-auto-eot-system-enabled-via-cron");2==t?s.show():s.hide()}),location.href.match(/page\=ws-plugin--s2member-paypal-buttons/)&&($("div.ws-menu-page select[id]").filter(function(){return this.id.match(/^ws-plugin--s2member-(level[1-9][0-9]*|modification)-term$/)}).change(function(){var e=this.id.replace(/^ws-plugin--s2member-(.+?)-term$/g,"$1"),t="BN"===$(this).val().split("-")[2].replace(/[^0-1BN]/g,"")?1:0;$("p#ws-plugin--s2member-"+e+"-trial-line").css("display",t?"none":""),$("span#ws-plugin--s2member-"+e+"-trial-then").css("display",t?"none":""),$("span#ws-plugin--s2member-"+e+"-20p-rule").css("display",t?"none":""),t?$("input#ws-plugin--s2member-"+e+"-trial-period").val(0):null,t?$("input#ws-plugin--s2member-"+e+"-trial-amount").val("0.00"):null}),$("div.ws-menu-page input[id]").filter(function(){return this.id.match(/^ws-plugin--s2member-(level[1-9][0-9]*|modification|ccap)-ccaps$/)}).keyup(function(){var e=this.value.replace(/^(-all|-al|-a|-)[;,]*/gi,""),t=this.value.match(/^(-all|-al|-a|-)[;,]*/i)?"-all,":"";e.match(/[^a-z_0-9,]/)&&(this.value=t+$.trim($.trim(e).replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase()))}),ws_plugin__s2member_paypalButtonGenerate=function(button){var shortCodeTemplate='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',shortCodeTemplateAttrs="",labels={};eval("<?php echo c_ws_plugin__s2member_utils_strings::esc_dq($labels); ?>");var shortCode=$("input#ws-plugin--s2member-"+button+"-shortcode"),code=$("textarea#ws-plugin--s2member-"+button+"-button"),modLevel=$("select#ws-plugin--s2member-modification-level"),level="modification"===button?modLevel.val().split(":",2)[1]:button.replace(/^level/,""),label=labels["level"+level].replace(/"/g,""),desc=$.trim($("input#ws-plugin--s2member-"+button+"-desc").val().replace(/"/g,"")),trialAmount=$("input#ws-plugin--s2member-"+button+"-trial-amount").val().replace(/[^0-9\.]/g,""),trialPeriod=$("input#ws-plugin--s2member-"+button+"-trial-period").val().replace(/[^0-9]/g,""),trialTerm=$("select#ws-plugin--s2member-"+button+"-trial-term").val().replace(/[^A-Z]/g,""),regAmount=$("input#ws-plugin--s2member-"+button+"-amount").val().replace(/[^0-9\.]/g,""),regPeriod=$("select#ws-plugin--s2member-"+button+"-term").val().split("-")[0].replace(/[^0-9]/g,""),regTerm=$("select#ws-plugin--s2member-"+button+"-term").val().split("-")[1].replace(/[^A-Z]/g,""),regRecur=$("select#ws-plugin--s2member-"+button+"-term").val().split("-")[2].replace(/[^0-1BN]/g,""),regRecurTimes="",regRecurRetry="1",localeCode="",digital="0",noShipping="1",pageStyle=$.trim($("input#ws-plugin--s2member-"+button+"-page-style").val().replace(/"/g,"")),currencyCode=$("select#ws-plugin--s2member-"+button+"-currency").val().replace(/[^A-Z]/g,""),cCaps=$.trim($.trim($("input#ws-plugin--s2member-"+button+"-ccaps").val()).replace(/^(-all|-al|-a|-)[;,]*/gi,"").replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase());cCaps=$.trim($("input#ws-plugin--s2member-"+button+"-ccaps").val()).match(/^(-all|-al|-a|-)[;,]*/i)?(cCaps?"-all,":"-all")+cCaps.toLowerCase():cCaps.toLowerCase(),trialPeriod="BN"===regRecur?"0":trialPeriod,trialAmount=!trialAmount||isNaN(trialAmount)||trialAmount<.01||trialPeriod<=0?"0":trialAmount;var levelCcapsPer="BN"===regRecur&&"L"!==regTerm?level+":"+cCaps+":"+regPeriod+" "+regTerm:level+":"+cCaps;return levelCcapsPer=levelCcapsPer.replace(/\:+$/g,""),"0"!==trialAmount&&(isNaN(trialAmount)||trialAmount<0)?(alert("— Oops, a slight problem: —\n\nWhen provided, Trial Amount must be >= 0.00"),!1):"0"!==trialAmount&&trialAmount>1e4&&"USD"===currencyCode.toUpperCase()?(alert("— Oops, a slight problem: —\n\nMaximum Trial Amount is: 10000.00"),!1):"D"===trialTerm&&trialPeriod>90?(alert("— Oops, a slight problem: —\n\nMaximum Trial Days is: 90.\nIf you want to offer more than 90 days, please choose Weeks or Months from the drop-down."),!1):"W"===trialTerm&&trialPeriod>52?(alert("— Oops, a slight problem: —\n\nMaximum Trial Weeks is: 52.\nIf you want to offer more than 52 weeks, please choose Months from the drop-down."),!1):"M"===trialTerm&&trialPeriod>24?(alert("— Oops, a slight problem: —\n\nMaximum Trial Months is: 24.\nIf you want to offer more than 24 months, please choose Years from the drop-down."),!1):"Y"===trialTerm&&trialPeriod>5?(alert("— Oops, a slight problem: —\n\nMax Trial Period Years is: 5."),!1):!regAmount||isNaN(regAmount)||regAmount<.01?(alert("— Oops, a slight problem: —\n\nAmount must be >= 0.01"),!1):regAmount>1e4&&"USD"===currencyCode.toUpperCase()?(alert("— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00"),!1):desc?(code.html(code.val().replace(/ \<\!--(\<input type\="hidden" name\="(amount|src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g," $1")),parseInt(trialPeriod)<=0?code.html(code.val().replace(/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g," <!--$1-->")):null,"BN"===regRecur?code.html(code.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick$3")):null,"BN"===regRecur?code.html(code.val().replace(/ (\<input type\="hidden" name\="(src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g," <!--$1-->")):null,"BN"!==regRecur?code.html(code.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick-subscriptions$3")):null,"BN"!==regRecur?code.html(code.val().replace(/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g," <!--$1-->")):null,shortCodeTemplateAttrs+="modification"===button?'modify="1" ':"",shortCodeTemplateAttrs+='level="'+esc_attr(level)+'" ccaps="'+esc_attr(cCaps)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'" custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"',shortCodeTemplateAttrs+=' ta="'+esc_attr(trialAmount)+'" tp="'+esc_attr(trialPeriod)+'" tt="'+esc_attr(trialTerm)+'" ra="'+esc_attr(regAmount)+'" rp="'+esc_attr(regPeriod)+'" rt="'+esc_attr(regTerm)+'" rr="'+esc_attr(regRecur)+'" rrt="'+esc_attr(regRecurTimes)+'" rra="'+esc_attr(regRecurRetry)+'"',shortCode.val(shortCodeTemplate.replace(/%%attrs%%/,shortCodeTemplateAttrs)),code.html(code.val().replace(/ name\="lc" value\="(.*?)"/,' name="lc" value="'+esc_attr(localeCode)+'"')),code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/,' name="no_shipping" value="'+esc_attr(noShipping)+'"')),code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+esc_attr(desc)+'"')),code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+esc_attr(levelCcapsPer)+'"')),code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+esc_attr(pageStyle)+'"')),code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+esc_attr(currencyCode)+'"')),code.html(code.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"')),code.html(code.val().replace(/ name\="modify" value\="(.*?)"/,' name="modify" value="'+("modification"===button?"1":"0")+'"')),code.html(code.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+esc_attr(regAmount)+'"')),code.html(code.val().replace(/ name\="src" value\="(.*?)"/,' name="src" value="'+esc_attr(regRecur)+'"')),code.html(code.val().replace(/ name\="srt" value\="(.*?)"/,' name="srt" value="'+esc_attr(regRecurTimes)+'"')),code.html(code.val().replace(/ name\="sra" value\="(.*?)"/,' name="sra" value="'+esc_attr(regRecurRetry)+'"')),code.html(code.val().replace(/ name\="a1" value\="(.*?)"/,' name="a1" value="'+esc_attr(trialAmount)+'"')),code.html(code.val().replace(/ name\="p1" value\="(.*?)"/,' name="p1" value="'+esc_attr(trialPeriod)+'"')),code.html(code.val().replace(/ name\="t1" value\="(.*?)"/,' name="t1" value="'+esc_attr(trialTerm)+'"')),code.html(code.val().replace(/ name\="a3" value\="(.*?)"/,' name="a3" value="'+esc_attr(regAmount)+'"')),code.html(code.val().replace(/ name\="p3" value\="(.*?)"/,' name="p3" value="'+esc_attr(regPeriod)+'"')),code.html(code.val().replace(/ name\="t3" value\="(.*?)"/,' name="t3" value="'+esc_attr(regTerm)+'"')),$("div#ws-plugin--s2member-"+button+"-button-prev").html(code.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g,Math.round((new Date).getTime())+"~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>").replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g,"")),"modification"===button?alert("Your Modification Button has been generated.\nPlease copy/paste the Shortcode into your Login Welcome Page, or wherever you feel it would be most appropriate.\n\n* Remember, Modification Buttons should be displayed to existing Users/Members, and they should be logged-in, BEFORE clicking this Button."):alert("Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page."),shortCode.each(function(){this.focus(),this.select()}),!1):(alert("— Oops, a slight problem: —\n\nPlease type a Description for this Button."),!1)},ws_plugin__s2member_paypalCcapButtonGenerate=function(){var e='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',t="",s=$("input#ws-plugin--s2member-ccap-shortcode"),l=$("textarea#ws-plugin--s2member-ccap-button"),r=$.trim($("input#ws-plugin--s2member-ccap-desc").val().replace(/"/g,"")),o=$("input#ws-plugin--s2member-ccap-amount").val().replace(/[^0-9\.]/g,""),a=$("select#ws-plugin--s2member-ccap-term").val().split("-")[0].replace(/[^0-9]/g,""),i=$("select#ws-plugin--s2member-ccap-term").val().split("-")[1].replace(/[^A-Z]/g,""),n=$("select#ws-plugin--s2member-ccap-term").val().split("-")[2].replace(/[^0-1BN]/g,""),c="",m="0",p="1",u=$.trim($("input#ws-plugin--s2member-ccap-page-style").val().replace(/"/g,"")),d=$("select#ws-plugin--s2member-ccap-currency").val().replace(/[^A-Z]/g,""),g=$.trim($.trim($("input#ws-plugin--s2member-ccap-ccaps").val()).replace(/^(-all|-al|-a|-)[;,]*/gi,"").replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase());g=$.trim($("input#ws-plugin--s2member-ccap-ccaps").val()).match(/^(-all|-al|-a|-)[;,]*/i)?(g?"-all,":"-all")+g.toLowerCase():g.toLowerCase();var b="BN"===n&&"L"!==i?"*:"+g+":"+a+" "+i:"*:"+g;return b=b.replace(/\:+$/g,""),g&&"-all"!==g?!o||isNaN(o)||o<.01?(alert("— Oops, a slight problem: —\n\nAmount must be >= 0.01"),!1):o>1e4&&"USD"===d.toUpperCase()?(alert("— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00"),!1):r?(t+='level="*" ccaps="'+esc_attr(g)+'" desc="'+esc_attr(r)+'" ps="'+esc_attr(u)+'" lc="'+esc_attr(c)+'" cc="'+esc_attr(d)+'" dg="'+esc_attr(m)+'" ns="'+esc_attr(p)+'"',t+=' custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+esc_attr(o)+'" rp="'+esc_attr(a)+'" rt="'+esc_attr(i)+'" rr="'+esc_attr(n)+'"',s.val(e.replace(/%%attrs%%/,t)),l.html(l.val().replace(/ name\="lc" value\="(.*?)"/,' name="lc" value="'+esc_attr(c)+'"')),l.html(l.val().replace(/ name\="no_shipping" value\="(.*?)"/,' name="no_shipping" value="'+esc_attr(p)+'"')),l.html(l.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+esc_attr(r)+'"')),l.html(l.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+esc_attr(b)+'"')),l.html(l.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+esc_attr(u)+'"')),l.html(l.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+esc_attr(d)+'"')),l.html(l.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"')),l.html(l.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+esc_attr(o)+'"')),$("div#ws-plugin--s2member-ccap-button-prev").html(l.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g,Math.round((new Date).getTime())+"~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>").replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g,"")),alert("Your Button has been generated.\nPlease copy/paste the Shortcode into your Login Welcome Page, or wherever you feel it would be most appropriate.\n\n* Remember, Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button."),s.each(function(){this.focus(),this.select()}),!1):(alert("— Oops, a slight problem: —\n\nPlease type a Description for this Button."),!1):(alert("— Oops, a slight problem: —\n\nPlease provide at least one Custom Capability."),!1)},ws_plugin__s2member_paypalSpButtonGenerate=function(){var e='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',t="",s=$("input#ws-plugin--s2member-sp-shortcode"),l=$("textarea#ws-plugin--s2member-sp-button"),r=$("select#ws-plugin--s2member-sp-leading-id").val().replace(/[^0-9]/g,""),o=$("select#ws-plugin--s2member-sp-additional-ids").val()||[],a=$("select#ws-plugin--s2member-sp-hours").val().replace(/[^0-9]/g,""),i=$("input#ws-plugin--s2member-sp-amount").val().replace(/[^0-9\.]/g,""),n=$.trim($("input#ws-plugin--s2member-sp-desc").val().replace(/"/g,"")),c="",m="0",p="1",u=$.trim($("input#ws-plugin--s2member-sp-page-style").val().replace(/"/g,"")),d=$("select#ws-plugin--s2member-sp-currency").val().replace(/[^A-Z]/g,"");if(!r)return alert("— Oops, a slight problem: —\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access."),!1;if(!i||isNaN(i)||i<.01)return alert("— Oops, a slight problem: —\n\nAmount must be >= 0.01"),!1;if(i>1e4&&"USD"===d.toUpperCase())return alert("— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00"),!1;if(!n)return alert("— Oops, a slight problem: —\n\nPlease type a Description for this Button."),!1;for(var g=0,b=r;g<o.length;g++)o[g]&&o[g]!==r&&(b+=","+o[g]);var f="sp:"+b+":"+a;return t+='sp="1" ids="'+esc_attr(b)+'" exp="'+esc_attr(a)+'" desc="'+esc_attr(n)+'" ps="'+esc_attr(u)+'" lc="'+esc_attr(c)+'" cc="'+esc_attr(d)+'" dg="'+esc_attr(m)+'" ns="'+esc_attr(p)+'"',t+=' custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+esc_attr(i)+'"',s.val(e.replace(/%%attrs%%/,t)),l.html(l.val().replace(/ name\="lc" value\="(.*?)"/,' name="lc" value="'+esc_attr(c)+'"')),l.html(l.val().replace(/ name\="no_shipping" value\="(.*?)"/,' name="no_shipping" value="'+esc_attr(p)+'"')),l.html(l.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+esc_attr(n)+'"')),l.html(l.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+esc_attr(f)+'"')),l.html(l.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+esc_attr(u)+'"')),l.html(l.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+esc_attr(d)+'"')),l.html(l.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"')),l.html(l.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+esc_attr(i)+'"')),$("div#ws-plugin--s2member-sp-button-prev").html(l.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g,Math.round((new Date).getTime())+"~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>").replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g,"")),alert("Your Button has been generated.\nPlease copy/paste the Shortcode into your WordPress Editor."),s.each(function(){this.focus(),this.select()}),!1},ws_plugin__s2member_paypalRegLinkGenerate=function(){var e=$("select#ws-plugin--s2member-reg-link-level").val().replace(/[^0-9]/g,""),t=$.trim($("input#ws-plugin--s2member-reg-link-subscr-id").val()),s=$.trim($("input#ws-plugin--s2member-reg-link-custom").val()),l=$.trim($.trim($("input#ws-plugin--s2member-reg-link-ccaps").val()).replace(/[ \-]/g,"_").replace(/[^a-z_0-9,]/gi,"").toLowerCase()),r=$.trim($("input#ws-plugin--s2member-reg-link-fixed-term").val().replace(/[^A-Z 0-9]/gi,"").toUpperCase()),o=$("p#ws-plugin--s2member-reg-link"),a=$("img#ws-plugin--s2member-reg-link-loading"),i=r&&!r.match(/L$/)?e+":"+l+":"+r:e+":"+l;return i=i.replace(/\:+$/g,""),t?s&&0===s.indexOf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq ($_SERVER["HTTP_HOST"]); ?>')?r&&!r.match(/^[1-9]+ (D|W|M|Y|L)$/)?(alert("— Oops, a slight problem: —\n\nThe Fixed Term Length is not formatted properly."),!1):(o.hide(),a.show(),$.post(ajaxurl,{action:"ws_plugin__s2member_reg_access_link_via_ajax",ws_plugin__s2member_reg_access_link_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-reg-access-link-via-ajax")); ?>',s2member_reg_access_link_subscr_gateway:"paypal",s2member_reg_access_link_subscr_id:t,s2member_reg_access_link_custom:s,s2member_reg_access_link_item_number:i},function(e){o.show().html('<a href="'+esc_attr(e)+'" target="_blank" rel="external">'+esc_html(e)+"</a>"),a.hide()}),!1):(alert("— Oops, a slight problem: —\n\nThe Custom Value MUST start with your domain name."),!1):(alert("— Oops, a slight problem: —\n\nPaid Subscr. ID is a required value."),!1)},ws_plugin__s2member_paypalSpLinkGenerate=function(){var e=$("select#ws-plugin--s2member-sp-link-leading-id").val().replace(/[^0-9]/g,""),t=$("select#ws-plugin--s2member-sp-link-additional-ids").val()||[],s=$("select#ws-plugin--s2member-sp-link-hours").val().replace(/[^0-9]/g,""),l=$("p#ws-plugin--s2member-sp-link"),r=$("img#ws-plugin--s2member-sp-link-loading");if(!e)return alert("— Oops, a slight problem: —\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access."),!1;for(var o=0,a=e;o<t.length;o++)t[o]&&t[o]!==e&&(a+=","+t[o]);return l.hide(),r.show(),$.post(ajaxurl,{action:"ws_plugin__s2member_sp_access_link_via_ajax",ws_plugin__s2member_sp_access_link_via_ajax:'<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link-via-ajax")); ?>',s2member_sp_access_link_ids:a,s2member_sp_access_link_hours:s},function(e){l.show().html('<a href="'+esc_attr(e)+'" target="_blank" rel="external">'+esc_html(e)+"</a>"),r.hide()}),!1}),location.href.match(/page\=ws-plugin--s2member-els-ops/)&&($("select#ws-plugin--s2member-custom-reg-opt-in").change(function(){var e=$(this),t=e.val(),s=$("tr.ws-plugin--s2member-custom-reg-opt-in-label-row"),l=$("img.ws-plugin--s2member-custom-reg-opt-in-label-prev-img");t<=0?(s.css("display","none"),l.attr("src",l.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))):1==t?(s.css("display",""),l.attr("src",l.attr("src").replace(/\/unchecked\.png$/,"/checked.png"))):2==t&&(s.css("display",""),l.attr("src",l.attr("src").replace(/\/checked\.png$/,"/unchecked.png")))}),$('div.ws-plugin--s2member-opt-out-section input[type="checkbox"][name="ws_plugin__s2member_custom_reg_auto_opt_outs[]"]').change(function(){var e=$(this).val(),t=[];$('div.ws-plugin--s2member-opt-out-section input[type="checkbox"][name="ws_plugin__s2member_custom_reg_auto_opt_outs[]"]').each(function(){var t=$(this),s=t.val(),l='input[type="checkbox"]';"removal-deletion"===s&&this.checked?t.nextAll(l).slice(0,2).attr({checked:"checked",disabled:"disabled"}):"removal-deletion"!==s||this.checked?"modification"===s&&this.checked?t.nextAll(l).slice(0,3).attr({checked:"checked",disabled:"disabled"}):"modification"!==s||this.checked||("modification"===e?t.nextAll(l).slice(0,3).removeAttr("checked"):null,t.nextAll(l).slice(0,3).removeAttr("disabled")):(t.nextAll(l).slice(0,2).removeAttr("disabled"),"removal-deletion"===e?t.nextAll(l).slice(0,2).removeAttr("checked"):null)}).each(function(e){this.checked?t.push(e):null}),$("select#ws-plugin--s2member-custom-reg-auto-opt-out-transitions").removeAttr("disabled"),$.inArray(3,t)===-1&&$.inArray(4,t)===-1&&$.inArray(5,t)===-1&&$.inArray(6,t)===-1&&$("select#ws-plugin--s2member-custom-reg-auto-opt-out-transitions").attr("disabled","disabled")}).last().trigger("change"))});
src/includes/menu-pages/menu-pages.css CHANGED
@@ -41,14 +41,7 @@ body[class*='s2member'] #wpwrap::before
41
  background : linear-gradient(to bottom, rgba(241, 241, 241, 1) 0%, rgba(241, 241, 241, 0.8) 20%, rgba(241, 241, 241, 0) 100%);
42
  }
43
  /*
44
- Align these with menu page.
45
- */
46
- div.updated.fade, div.error.fade
47
- {
48
- margin : 25px 25px 25px 5px;
49
- }
50
- /*
51
- These CSS selectors address common layout styles.
52
  */
53
  div.ws-menu-page
54
  {
@@ -56,35 +49,41 @@ div.ws-menu-page
56
  min-width : 800px;
57
  margin : 25px 25px 25px 5px;
58
  }
59
- div.ws-menu-page > :not(.fade) p,
60
- div.ws-menu-page > :not(.fade) code
 
 
 
 
 
 
61
  {
62
  font-size : inherit;
63
  }
64
- div.ws-menu-page > :not(.fade) a
65
  {
66
  color : #336695;
67
  }
68
- div.ws-menu-page > :not(.fade) a:hover,
69
- div.ws-menu-page > :not(.fade) a:active
70
  {
71
  color : #027E02;
72
  }
73
- div.ws-menu-page > :not(.fade) p:first-child,
74
- div.ws-menu-page > :not(.fade) pre:first-child
75
  {
76
  margin-top : 0;
77
  }
78
- div.ws-menu-page > :not(.fade) p:last-child,
79
- div.ws-menu-page > :not(.fade) pre:last-child
80
  {
81
  margin-bottom : 0;
82
  }
83
- div.ws-menu-page > :not(.fade) h3 + p
84
  {
85
  margin-top : 0;
86
  }
87
- div.ws-menu-page > :not(.fade) a.ws-dotted-link
88
  {
89
  text-decoration : none;
90
  border-bottom : 1px dotted;
@@ -135,19 +134,19 @@ div.ws-menu-page > h2:after
135
 
136
  background : url('<?php echo $i; ?>/s2___end.png') no-repeat right bottom;
137
  }
138
- div.ws-menu-page > :not(.fade) code
139
  {
140
  border-radius : 3px;
141
  padding : 1px 5px 1px 5px;
142
  background : rgba(255, 255, 255, 0.25);
143
  font-family : 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
144
  }
145
- div.ws-menu-page > :not(.fade) pre.code
146
  {
147
  padding : 0;
148
  background : none;
149
  }
150
- div.ws-menu-page > :not(.fade) pre.code > code
151
  {
152
  font-size : 90%;
153
  color : #EEEEEE;
@@ -160,8 +159,8 @@ div.ws-menu-page > :not(.fade) pre.code > code
160
  display : block;
161
  box-shadow : 0 0 5px 1px #000000 inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
162
  }
163
- div.ws-menu-page > :not(.fade) code.highlight-php,
164
- div.ws-menu-page > :not(.fade) code.highlight-shortcodes
165
  {
166
  font-size : 90%;
167
  color : #000000;
@@ -176,11 +175,11 @@ div.ws-menu-page > :not(.fade) code.highlight-shortcodes
176
  display : block;
177
  box-shadow : 0 0 5px 1px rgba(0, 0, 0, 0.38) inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
178
  }
179
- div.ws-menu-page > :not(.fade) img
180
  {
181
  border : 0;
182
  }
183
- div.ws-menu-page > :not(.fade) img.ws-menu-page-bordered
184
  {
185
  border-radius : 4px;
186
  padding : 10px;
@@ -188,50 +187,50 @@ div.ws-menu-page > :not(.fade) img.ws-menu-page-bordered
188
  border : 1px solid #AFAFAF;
189
  box-shadow : 0 0 2px 1px #D8D8D8 inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
190
  }
191
- div.ws-menu-page > :not(.fade) .ws-menu-page-right
192
  {
193
  margin-left : 25px;
194
  float : right;
195
  }
196
- div.ws-menu-page > :not(.fade) .ws-menu-page-left
197
  {
198
  margin-right : 25px;
199
  float : left;
200
  }
201
- div.ws-menu-page > :not(.fade) .ws-menu-page-center
202
  {
203
  margin-left : auto;
204
  margin-right : auto;
205
  display : block;
206
  }
207
- div.ws-menu-page > :not(.fade) ul.ws-menu-page-li-margins > li,
208
- div.ws-menu-page > :not(.fade) ol.ws-menu-page-li-margins > li
209
  {
210
  margin-top : 8px;
211
  margin-bottom : 8px;
212
  }
213
- div.ws-menu-page > :not(.fade) ul.ws-menu-page-li-margins > li:first-child,
214
- div.ws-menu-page > :not(.fade) ol.ws-menu-page-li-margins > li:first-child
215
  {
216
  margin-top : 0;
217
  }
218
- div.ws-menu-page > :not(.fade) ul.ws-menu-page-li-margins > li:last-child,
219
- div.ws-menu-page > :not(.fade) ol.ws-menu-page-li-margins > li:last-child
220
  {
221
  margin-bottom : 0;
222
  }
223
- div.ws-menu-page > :not(.fade) div.ws-menu-page-hr
224
  {
225
  height : 1px;
226
  line-height : 1px;
227
- background : #DDDDDD;
228
  margin : 10px 0 10px 0;
229
  }
230
- div.ws-menu-page > :not(.fade) .ws-menu-page-error
231
  {
232
  color : #962722;
233
  }
234
- div.ws-menu-page > :not(.fade) .ws-menu-page-hilite
235
  {
236
  font-size : 102%;
237
  background : #DFF0DF;
@@ -239,7 +238,7 @@ div.ws-menu-page > :not(.fade) .ws-menu-page-hilite
239
  border-radius : 3px;
240
  padding : 0 0.2em;
241
  }
242
- div.ws-menu-page > :not(.fade) .ws-menu-page-bright-hilite
243
  {
244
  font-size : 102%;
245
  background : #EBF084;
@@ -247,7 +246,7 @@ div.ws-menu-page > :not(.fade) .ws-menu-page-bright-hilite
247
  border-radius : 3px;
248
  padding : 0 0.2em;
249
  }
250
- div.ws-menu-page > :not(.fade) .ws-menu-page-warning-hilite
251
  {
252
  color : #FFFFFF;
253
  background : #AC3204;
@@ -255,7 +254,7 @@ div.ws-menu-page > :not(.fade) .ws-menu-page-warning-hilite
255
  border-radius : 3px;
256
  padding : 0 0.2em;
257
  }
258
- div.ws-menu-page > :not(.fade) .ws-menu-page-error-hilite
259
  {
260
  color : #FFFFFF;
261
  background : #962722;
@@ -263,18 +262,18 @@ div.ws-menu-page > :not(.fade) .ws-menu-page-error-hilite
263
  border-radius : 3px;
264
  padding : 0 0.2em;
265
  }
266
- div.ws-menu-page > :not(.fade) img.ws-menu-page-img-16
267
  {
268
  border : 0;
269
  width : 16px;
270
  height : 16px;
271
  }
272
- div.ws-menu-page > :not(.fade) .form-table td
273
  {
274
  font-size : inherit;
275
  line-height : inherit;
276
  }
277
- div.ws-menu-page > :not(.fade) label
278
  {
279
  text-shadow : none;
280
 
@@ -282,12 +281,12 @@ div.ws-menu-page > :not(.fade) label
282
  -moz-user-select : none;
283
  user-select : none;
284
  }
285
- div.ws-menu-page > :not(.fade) select,
286
- div.ws-menu-page > :not(.fade) select:focus,
287
- div.ws-menu-page > :not(.fade) textarea,
288
- div.ws-menu-page > :not(.fade) textarea:focus,
289
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
290
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
291
  {
292
  margin : 0;
293
  width : 100%;
@@ -299,78 +298,78 @@ div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):no
299
 
300
  box-sizing : border-box;
301
  }
302
- div.ws-menu-page > :not(.fade) textarea,
303
- div.ws-menu-page > :not(.fade) textarea:focus,
304
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
305
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
306
  {
307
  font-size : 1em; /* Font size again, for CodeMirror too. */
308
  font-family : 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
309
  }
310
- div.ws-menu-page > :not(.fade) textarea,
311
- div.ws-menu-page > :not(.fade) textarea:focus
312
  {
313
  height : auto; /* Textareas auto. */
314
  white-space : pre; /* Preserve whitespace. */
315
  }
316
- div.ws-menu-page > :not(.fade) select,
317
- div.ws-menu-page > :not(.fade) select:focus,
318
- div.ws-menu-page > :not(.fade) textarea,
319
- div.ws-menu-page > :not(.fade) textarea:focus,
320
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
321
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
322
  {
323
  border : 0;
324
  padding : 5px;
325
  border-radius : 4px;
326
  box-shadow : 0 0 1px 1px rgba(37, 47, 26, 0.75) inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
327
  }
328
- div.ws-menu-page > :not(.fade) select,
329
- div.ws-menu-page > :not(.fade) textarea,
330
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox'])
331
  {
332
  color : #F7F7F7;
333
  background : #73834B;
334
  }
335
- div.ws-menu-page > :not(.fade) select:focus,
336
- div.ws-menu-page > :not(.fade) textarea:focus,
337
- div.ws-menu-page > :not(.fade) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
338
  {
339
  background : #637041;
340
  }
341
- div.ws-menu-page > :not(.fade) input::-webkit-input-placeholder
342
  {
343
  padding-top : .1em;
344
  font-style : italic;
345
  color : rgba(255, 255, 255, 0.2);
346
  }
347
- div.ws-menu-page > :not(.fade) input::-moz-placeholder
348
  {
349
  padding-top : .1em;
350
  font-style : italic;
351
  color : rgba(255, 255, 255, 0.2);
352
  }
353
- div.ws-menu-page > :not(.fade) input:-moz-placeholder
354
  {
355
  padding-top : .1em;
356
  font-style : italic;
357
  color : rgba(255, 255, 255, 0.2);
358
  }
359
- div.ws-menu-page > :not(.fade) input:-ms-input-placeholder
360
  {
361
  padding-top : .1em;
362
  font-style : italic;
363
  color : rgba(255, 255, 255, 0.2);
364
  }
365
- div.ws-menu-page > :not(.fade) input[disabled],
366
- div.ws-menu-page > :not(.fade) select[disabled],
367
- div.ws-menu-page > :not(.fade) textarea[disabled]
368
  {
369
  opacity : 0.5;
370
  }
371
- div.ws-menu-page > :not(.fade) button,
372
- div.ws-menu-page > :not(.fade) input[type='button'],
373
- div.ws-menu-page > :not(.fade) input[type='submit']
374
  {
375
  line-height : 1em;
376
  font-size : 120%;
@@ -392,88 +391,88 @@ div.ws-menu-page > :not(.fade) input[type='submit']
392
  -moz-user-select : none;
393
  user-select : none;
394
  }
395
- div.ws-menu-page > :not(.fade) button:hover,
396
- div.ws-menu-page > :not(.fade) input[type='button']:hover,
397
- div.ws-menu-page > :not(.fade) input[type='submit']:hover
398
  {
399
  background : #0D1F2F;
400
  }
401
- div.ws-menu-page > :not(.fade) button:active,
402
- div.ws-menu-page > :not(.fade) input[type='button']:active,
403
- div.ws-menu-page > :not(.fade) input[type='submit']:active
404
  {
405
  -webkit-transform : scale(0.98, 0.98);
406
  transform : scale(0.98, 0.98);
407
  }
408
- div.ws-menu-page > :not(.fade) button[type='submit'],
409
- div.ws-menu-page > :not(.fade) input[type='submit']
410
  {
411
  font-size : 150%;
412
  font-weight : 600;
413
  background : #5F7523;
414
  }
415
- div.ws-menu-page > :not(.fade) button[type='submit']:hover,
416
- div.ws-menu-page > :not(.fade) input[type='submit']:hover
417
  {
418
  background : #4C6324;
419
  }
420
- div.ws-menu-page > :not(.fade) p.submit button[type='submit'],
421
- div.ws-menu-page > :not(.fade) p.submit input[type='submit']
422
  {
423
  width : 100%;
424
  }
425
- div.ws-menu-page > :not(.fade) input[type='file']
426
  {
427
  width : auto !important;
428
  }
429
- div.ws-menu-page > :not(.fade) .pro-preview
430
  {
431
  opacity : 0.5;
432
  }
433
- div.ws-menu-page > :not(.fade) .info,
434
- div.ws-menu-page > :not(.fade) .notice,
435
- div.ws-menu-page > :not(.fade) .warning,
436
- div.ws-menu-page > :not(.fade) .error:not(.fade)
437
  {
438
  border-radius : 5px;
439
  padding : 10px;
440
  margin : 0 0 25px 0;
441
  }
442
- div.ws-menu-page > :not(.fade) .info
443
  {
444
  background : #C9E0FA;
445
  border : 1px solid #35558A;
446
  }
447
- div.ws-menu-page > :not(.fade) .notice
448
  {
449
  background : #FFFBCC;
450
  border : 1px solid #E6DB55;
451
  }
452
- div.ws-menu-page > :not(.fade) .warning
453
  {
454
  background : #FADDAB;
455
  border : 1px solid #D29A04;
456
  }
457
- div.ws-menu-page > :not(.fade) .error:not(.fade)
458
  {
459
  background : #FABBC6;
460
  border : 1px solid #711E1E;
461
  }
462
- div.ws-menu-page > :not(.fade) .monospace
463
  {
464
  font-family : 'Monaco', 'Menlo', 'Consolas', 'Courier New', monospace;
465
  }
466
- div.ws-menu-page > :not(.fade) textarea.monospace
467
  {
468
  white-space : pre;
469
  }
470
- div.ws-menu-page > :not(.fade) .clearfix:before,
471
- div.ws-menu-page > :not(.fade) .clearfix:after
472
  {
473
  display : table;
474
  content : ' ';
475
  }
476
- div.ws-menu-page > :not(.fade) .clearfix:after
477
  {
478
  clear : both;
479
  }
41
  background : linear-gradient(to bottom, rgba(241, 241, 241, 1) 0%, rgba(241, 241, 241, 0.8) 20%, rgba(241, 241, 241, 0) 100%);
42
  }
43
  /*
44
+ Common layout styles.
 
 
 
 
 
 
 
45
  */
46
  div.ws-menu-page
47
  {
49
  min-width : 800px;
50
  margin : 25px 25px 25px 5px;
51
  }
52
+ div.ws-menu-page > .notice,
53
+ div.ws-menu-page > .updated,
54
+ div.ws-menu-page > .error
55
+ {
56
+ margin : 25px 25px 25px 5px;
57
+ }
58
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) p,
59
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) code
60
  {
61
  font-size : inherit;
62
  }
63
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) a
64
  {
65
  color : #336695;
66
  }
67
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) a:hover,
68
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) a:active
69
  {
70
  color : #027E02;
71
  }
72
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) p:first-child,
73
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) pre:first-child
74
  {
75
  margin-top : 0;
76
  }
77
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) p:last-child,
78
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) pre:last-child
79
  {
80
  margin-bottom : 0;
81
  }
82
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) h3 + p
83
  {
84
  margin-top : 0;
85
  }
86
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) a.ws-dotted-link
87
  {
88
  text-decoration : none;
89
  border-bottom : 1px dotted;
134
 
135
  background : url('<?php echo $i; ?>/s2___end.png') no-repeat right bottom;
136
  }
137
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) code
138
  {
139
  border-radius : 3px;
140
  padding : 1px 5px 1px 5px;
141
  background : rgba(255, 255, 255, 0.25);
142
  font-family : 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
143
  }
144
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) pre.code
145
  {
146
  padding : 0;
147
  background : none;
148
  }
149
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) pre.code > code
150
  {
151
  font-size : 90%;
152
  color : #EEEEEE;
159
  display : block;
160
  box-shadow : 0 0 5px 1px #000000 inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
161
  }
162
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) code.highlight-php,
163
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) code.highlight-shortcodes
164
  {
165
  font-size : 90%;
166
  color : #000000;
175
  display : block;
176
  box-shadow : 0 0 5px 1px rgba(0, 0, 0, 0.38) inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
177
  }
178
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) img
179
  {
180
  border : 0;
181
  }
182
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) img.ws-menu-page-bordered
183
  {
184
  border-radius : 4px;
185
  padding : 10px;
187
  border : 1px solid #AFAFAF;
188
  box-shadow : 0 0 2px 1px #D8D8D8 inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
189
  }
190
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-right
191
  {
192
  margin-left : 25px;
193
  float : right;
194
  }
195
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-left
196
  {
197
  margin-right : 25px;
198
  float : left;
199
  }
200
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-center
201
  {
202
  margin-left : auto;
203
  margin-right : auto;
204
  display : block;
205
  }
206
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) ul.ws-menu-page-li-margins > li,
207
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) ol.ws-menu-page-li-margins > li
208
  {
209
  margin-top : 8px;
210
  margin-bottom : 8px;
211
  }
212
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) ul.ws-menu-page-li-margins > li:first-child,
213
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) ol.ws-menu-page-li-margins > li:first-child
214
  {
215
  margin-top : 0;
216
  }
217
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) ul.ws-menu-page-li-margins > li:last-child,
218
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) ol.ws-menu-page-li-margins > li:last-child
219
  {
220
  margin-bottom : 0;
221
  }
222
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) div.ws-menu-page-hr
223
  {
224
  height : 1px;
225
  line-height : 1px;
226
+ background : #bdca9a;
227
  margin : 10px 0 10px 0;
228
  }
229
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-error
230
  {
231
  color : #962722;
232
  }
233
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-hilite
234
  {
235
  font-size : 102%;
236
  background : #DFF0DF;
238
  border-radius : 3px;
239
  padding : 0 0.2em;
240
  }
241
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-bright-hilite
242
  {
243
  font-size : 102%;
244
  background : #EBF084;
246
  border-radius : 3px;
247
  padding : 0 0.2em;
248
  }
249
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-warning-hilite
250
  {
251
  color : #FFFFFF;
252
  background : #AC3204;
254
  border-radius : 3px;
255
  padding : 0 0.2em;
256
  }
257
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .ws-menu-page-error-hilite
258
  {
259
  color : #FFFFFF;
260
  background : #962722;
262
  border-radius : 3px;
263
  padding : 0 0.2em;
264
  }
265
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) img.ws-menu-page-img-16
266
  {
267
  border : 0;
268
  width : 16px;
269
  height : 16px;
270
  }
271
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .form-table td
272
  {
273
  font-size : inherit;
274
  line-height : inherit;
275
  }
276
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) label
277
  {
278
  text-shadow : none;
279
 
281
  -moz-user-select : none;
282
  user-select : none;
283
  }
284
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select,
285
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select:focus,
286
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea,
287
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea:focus,
288
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
289
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
290
  {
291
  margin : 0;
292
  width : 100%;
298
 
299
  box-sizing : border-box;
300
  }
301
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea,
302
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea:focus,
303
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
304
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
305
  {
306
  font-size : 1em; /* Font size again, for CodeMirror too. */
307
  font-family : 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
308
  }
309
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea,
310
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea:focus
311
  {
312
  height : auto; /* Textareas auto. */
313
  white-space : pre; /* Preserve whitespace. */
314
  }
315
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select,
316
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select:focus,
317
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea,
318
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea:focus,
319
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
320
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
321
  {
322
  border : 0;
323
  padding : 5px;
324
  border-radius : 4px;
325
  box-shadow : 0 0 1px 1px rgba(37, 47, 26, 0.75) inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
326
  }
327
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select,
328
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea,
329
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox'])
330
  {
331
  color : #F7F7F7;
332
  background : #73834B;
333
  }
334
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select:focus,
335
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea:focus,
336
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus
337
  {
338
  background : #637041;
339
  }
340
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input::-webkit-input-placeholder
341
  {
342
  padding-top : .1em;
343
  font-style : italic;
344
  color : rgba(255, 255, 255, 0.2);
345
  }
346
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input::-moz-placeholder
347
  {
348
  padding-top : .1em;
349
  font-style : italic;
350
  color : rgba(255, 255, 255, 0.2);
351
  }
352
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:-moz-placeholder
353
  {
354
  padding-top : .1em;
355
  font-style : italic;
356
  color : rgba(255, 255, 255, 0.2);
357
  }
358
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input:-ms-input-placeholder
359
  {
360
  padding-top : .1em;
361
  font-style : italic;
362
  color : rgba(255, 255, 255, 0.2);
363
  }
364
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[disabled],
365
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) select[disabled],
366
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea[disabled]
367
  {
368
  opacity : 0.5;
369
  }
370
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) button,
371
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='button'],
372
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='submit']
373
  {
374
  line-height : 1em;
375
  font-size : 120%;
391
  -moz-user-select : none;
392
  user-select : none;
393
  }
394
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) button:hover,
395
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='button']:hover,
396
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='submit']:hover
397
  {
398
  background : #0D1F2F;
399
  }
400
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) button:active,
401
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='button']:active,
402
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='submit']:active
403
  {
404
  -webkit-transform : scale(0.98, 0.98);
405
  transform : scale(0.98, 0.98);
406
  }
407
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) button[type='submit'],
408
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='submit']
409
  {
410
  font-size : 150%;
411
  font-weight : 600;
412
  background : #5F7523;
413
  }
414
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) button[type='submit']:hover,
415
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='submit']:hover
416
  {
417
  background : #4C6324;
418
  }
419
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) p.submit button[type='submit'],
420
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) p.submit input[type='submit']
421
  {
422
  width : 100%;
423
  }
424
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) input[type='file']
425
  {
426
  width : auto !important;
427
  }
428
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .pro-preview
429
  {
430
  opacity : 0.5;
431
  }
432
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .info,
433
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .notice,
434
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .warning,
435
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .error:not(.notice):not(.updated):not(.error)
436
  {
437
  border-radius : 5px;
438
  padding : 10px;
439
  margin : 0 0 25px 0;
440
  }
441
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .info
442
  {
443
  background : #C9E0FA;
444
  border : 1px solid #35558A;
445
  }
446
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .notice
447
  {
448
  background : #FFFBCC;
449
  border : 1px solid #E6DB55;
450
  }
451
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .warning
452
  {
453
  background : #FADDAB;
454
  border : 1px solid #D29A04;
455
  }
456
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .error
457
  {
458
  background : #FABBC6;
459
  border : 1px solid #711E1E;
460
  }
461
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .monospace
462
  {
463
  font-family : 'Monaco', 'Menlo', 'Consolas', 'Courier New', monospace;
464
  }
465
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) textarea.monospace
466
  {
467
  white-space : pre;
468
  }
469
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .clearfix:before,
470
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .clearfix:after
471
  {
472
  display : table;
473
  content : ' ';
474
  }
475
+ div.ws-menu-page > :not(.notice):not(.updated):not(.error) .clearfix:after
476
  {
477
  clear : both;
478
  }
src/includes/menu-pages/menu-pages.js CHANGED
@@ -118,7 +118,7 @@ jQuery(document).ready( // DOM ready handler.
118
  src = (!src) ? $.trim($('img', html).attr('src')) : src;
119
 
120
  $inp.val(src),
121
- $inp.css({'background-color': '#FFFFCC'}),
122
  setTimeout(function()
123
  {
124
  $inp.css({'background-color': oBg});
@@ -132,7 +132,7 @@ jQuery(document).ready( // DOM ready handler.
132
  src = (!src) ? $.trim($('img', html).attr('src')) : src;
133
 
134
  $txt.val($.trim($txt.val()) + '\n' + src),
135
- $txt.css({'background-color': '#FFFFCC'}),
136
  setTimeout(function()
137
  {
138
  $txt.css({'background-color': oBg});
@@ -168,4 +168,4 @@ jQuery(document).ready( // DOM ready handler.
168
  }
169
  return true;
170
  });
171
- });
118
  src = (!src) ? $.trim($('img', html).attr('src')) : src;
119
 
120
  $inp.val(src),
121
+ $inp.css({'background-color': '#485230'}),
122
  setTimeout(function()
123
  {
124
  $inp.css({'background-color': oBg});
132
  src = (!src) ? $.trim($('img', html).attr('src')) : src;
133
 
134
  $txt.val($.trim($txt.val()) + '\n' + src),
135
+ $txt.css({'background-color': '#485230'}),
136
  setTimeout(function()
137
  {
138
  $txt.css({'background-color': oBg});
168
  }
169
  return true;
170
  });
171
+ });
src/includes/menu-pages/menu-pages.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(e){e(window).resize(window.tb_position=function(){var f=(e(window).width()>720)?720:e(window).width(),i=e(window).height(),g=(e("body.admin-bar").length)?28:0;e("#TB_window").css({width:f-50+"px",height:i-45-g+"px",top:25+g+"px","margin-top":0,"margin-left":"-"+parseInt(((f-50)/2),10)+"px"});e("#TB_ajaxContent").css({width:f-50+"px",height:i-75-g+"px",margin:0,padding:0})});var b=e("table.ws-menu-page-table td.ws-menu-page-table-r"),a=e("> .toggler",b),d=e("> .wrapper",b);var c=e("div.ws-menu-page-group");c.each(function(g){var i=e(this),h=i,j=e.trim(h.attr("title")),f=e('<div class="ws-menu-page-group-header">'+j+"</div>");f.css({"z-index":1}),f.insertBefore(h),f.click(function(){var l=e(this),k=l.next();if(l.hasClass("open")){l.add(k).removeClass("open")}else{l.add(k).addClass("open")}return false});if(c.length>1&&g===0){e('<div class="ws-menu-page-groups-hide"><i class="fa fa-chevron-up"></i></div>').insertBefore("div.ws-menu-page-toolbox").click(function(){e("div.ws-menu-page-group-header").each(function(){var l=e(this),k=l.next();l.add(k).removeClass("open")});return false});e('<div class="ws-menu-page-groups-show"><i class="fa fa-chevron-down"></i></div>').insertBefore("div.ws-menu-page-toolbox").click(function(){e("div.ws-menu-page-group-header").each(function(){var l=e(this),k=l.next();l.add(k).addClass("open")});return false})}if(h.attr("default-state")==="open"){f.trigger("click")}});a.click(function(){if(b.hasClass("open")){d.hide(),b.removeClass("open")}else{d.show(),b.addClass("open")}});if(a.attr("default-state")==="open"){a.click()}e("div.ws-menu-page-r-group-header").click(function(){var g=e(this),f=g.next();if(g.hasClass("open")){g.add(f).removeClass("open")}else{g.add(f).addClass("open")}return false});e("div.ws-menu-page-group-header:first, div.ws-menu-page-r-group-header:first").css({"margin-top":"0"});e("div.ws-menu-page-group-header:last, div.ws-menu-page-r-group-header:last, div.ws-menu-page-group:last").css({"margin-bottom":"0"});e("input.ws-menu-page-media-btn").filter(function(){return(e(this).attr("rel"))?true:false}).click(function(){var f=e(this);window.send_to_editor=function(j){var k,i,g=e.trim(f.attr("rel")),h,l;if(g&&(k=e("input#"+g)).length>0){h=k.css("background-color"),l=e.trim(e(j).attr("src"));l=(!l)?e.trim(e("img",j).attr("src")):l;k.val(l),k.css({"background-color":"#FFFFCC"}),setTimeout(function(){k.css({"background-color":h})},2000);tb_remove()}else{if(g&&(i=e("textarea#"+g)).length>0){h=i.css("background-color"),l=e.trim(e(j).attr("src"));l=(!l)?e.trim(e("img",j).attr("src")):l;i.val(e.trim(i.val())+"\n"+l),i.css({"background-color":"#FFFFCC"}),setTimeout(function(){i.css({"background-color":h})},2000);tb_remove()}}};tb_show("","./media-upload.php?type=image&TB_iframe=true");return false});e("form#ws-updates-form").submit(function(){var f="";if(!e.trim(e("input#ws-updates-fname").val())){f+="First Name missing, please try again.\n\n"}if(!e.trim(e("input#ws-updates-lname").val())){f+="Last Name missing, please try again.\n\n"}if(!e.trim(e("input#ws-updates-email").val())){f+="Email missing, please try again.\n\n"}else{if(!e("input#ws-updates-email").val().match(/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){f+="Invalid email address, please try again.\n\n"}}if(f=e.trim(f)){alert("— Oops, you missed something: —\n\n"+f);return false}return true})});
1
+ jQuery(document).ready(function(e){e(window).resize(window.tb_position=function(){var a=e(window).width()>720?720:e(window).width(),t=e(window).height(),n=e("body.admin-bar").length?28:0;e("#TB_window").css({width:a-50+"px",height:t-45-n+"px",top:25+n+"px","margin-top":0,"margin-left":"-"+parseInt((a-50)/2,10)+"px"}),e("#TB_ajaxContent").css({width:a-50+"px",height:t-75-n+"px",margin:0,padding:0})});var a=e("table.ws-menu-page-table td.ws-menu-page-table-r"),t=e("> .toggler",a),n=e("> .wrapper",a),s=e("div.ws-menu-page-group");s.each(function(a){var t=e(this),n=t,i=e.trim(n.attr("title")),r=e('<div class="ws-menu-page-group-header">'+i+"</div>");r.css({"z-index":1}),r.insertBefore(n),r.click(function(){var a=e(this),t=a.next();return a.hasClass("open")?a.add(t).removeClass("open"):a.add(t).addClass("open"),!1}),s.length>1&&0===a&&(e('<div class="ws-menu-page-groups-hide"><i class="fa fa-chevron-up"></i></div>').insertBefore("div.ws-menu-page-toolbox").click(function(){return e("div.ws-menu-page-group-header").each(function(){var a=e(this),t=a.next();a.add(t).removeClass("open")}),!1}),e('<div class="ws-menu-page-groups-show"><i class="fa fa-chevron-down"></i></div>').insertBefore("div.ws-menu-page-toolbox").click(function(){return e("div.ws-menu-page-group-header").each(function(){var a=e(this),t=a.next();a.add(t).addClass("open")}),!1})),"open"===n.attr("default-state")&&r.trigger("click")}),t.click(function(){a.hasClass("open")?(n.hide(),a.removeClass("open")):(n.show(),a.addClass("open"))}),"open"===t.attr("default-state")&&t.click(),e("div.ws-menu-page-r-group-header").click(function(){var a=e(this),t=a.next();return a.hasClass("open")?a.add(t).removeClass("open"):a.add(t).addClass("open"),!1}),e("div.ws-menu-page-group-header:first, div.ws-menu-page-r-group-header:first").css({"margin-top":"0"}),e("div.ws-menu-page-group-header:last, div.ws-menu-page-r-group-header:last, div.ws-menu-page-group:last").css({"margin-bottom":"0"}),e("input.ws-menu-page-media-btn").filter(function(){return!!e(this).attr("rel")}).click(function(){var a=e(this);return window.send_to_editor=function(t){var n,s,i,r,o=e.trim(a.attr("rel"));o&&(n=e("input#"+o)).length>0?(i=n.css("background-color"),r=e.trim(e(t).attr("src")),r=r?r:e.trim(e("img",t).attr("src")),n.val(r),n.css({"background-color":"#485230"}),setTimeout(function(){n.css({"background-color":i})},2e3),tb_remove()):o&&(s=e("textarea#"+o)).length>0&&(i=s.css("background-color"),r=e.trim(e(t).attr("src")),r=r?r:e.trim(e("img",t).attr("src")),s.val(e.trim(s.val())+"\n"+r),s.css({"background-color":"#485230"}),setTimeout(function(){s.css({"background-color":i})},2e3),tb_remove())},tb_show("","./media-upload.php?type=image&TB_iframe=true"),!1}),e("form#ws-updates-form").submit(function(){var a="";return e.trim(e("input#ws-updates-fname").val())||(a+="First Name missing, please try again.\n\n"),e.trim(e("input#ws-updates-lname").val())||(a+="Last Name missing, please try again.\n\n"),e.trim(e("input#ws-updates-email").val())?e("input#ws-updates-email").val().match(/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)||(a+="Invalid email address, please try again.\n\n"):a+="Email missing, please try again.\n\n",!(a=e.trim(a))||(alert("— Oops, you missed something: —\n\n"+a),!1)})});
src/includes/menu-pages/mms-ops.inc.php CHANGED
@@ -35,6 +35,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_mms_ops"))
35
  return; // Stop here.
36
  }
37
  echo '<div class="wrap ws-menu-page">'."\n";
 
 
38
 
39
  echo '<div class="ws-menu-page-toolbox">'."\n";
40
  c_ws_plugin__s2member_menu_pages_tb::display ();
35
  return; // Stop here.
36
  }
37
  echo '<div class="wrap ws-menu-page">'."\n";
38
+
39
+ echo '<div class="wp-header-end"></div>'."\n";
40
 
41
  echo '<div class="ws-menu-page-toolbox">'."\n";
42
  c_ws_plugin__s2member_menu_pages_tb::display ();
src/includes/menu-pages/paypal-buttons.inc.php CHANGED
@@ -32,6 +32,8 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_paypal_buttons"))
32
  {
33
  echo '<div class="wrap ws-menu-page">' . "\n";
34
 
 
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display ();
37
  echo '</div>'."\n";
32
  {
33
  echo '<div class="wrap ws-menu-page">' . "\n";
34
 
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
+
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display ();
39
  echo '</div>'."\n";
src/includes/menu-pages/paypal-ops.inc.php CHANGED
@@ -30,7 +30,9 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_paypal_ops"))
30
  {
31
  public function __construct()
32
  {
33
- echo '<div class="wrap ws-menu-page">'."\n";
 
 
34
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
30
  {
31
  public function __construct()
32
  {
33
+ echo '<div class="wrap ws-menu-page">'."\n";
34
+
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
 
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
src/includes/menu-pages/res-ops.inc.php CHANGED
@@ -32,6 +32,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_res_ops"))
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
 
 
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
37
  echo '</div>'."\n";
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
 
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
+
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
39
  echo '</div>'."\n";
src/includes/menu-pages/scripting.inc.php CHANGED
@@ -32,9 +32,11 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_scripting"))
32
  {
33
  public function __construct ()
34
  {
35
- echo '<div class="wrap ws-menu-page">' . "\n";
36
 
37
- echo '<div class="ws-menu-page-toolbox">'."\n";
 
 
38
  c_ws_plugin__s2member_menu_pages_tb::display ();
39
  echo '</div>'."\n";
40
 
32
  {
33
  public function __construct ()
34
  {
35
+ echo '<div class="wrap ws-menu-page">' . "\n";
36
 
37
+ echo '<div class="wp-header-end"></div>'."\n";
38
+
39
+ echo '<div class="ws-menu-page-toolbox">'."\n";
40
  c_ws_plugin__s2member_menu_pages_tb::display ();
41
  echo '</div>'."\n";
42
 
src/includes/menu-pages/start.inc.php CHANGED
@@ -32,6 +32,8 @@ if (!class_exists ("c_ws_plugin__s2member_menu_page_start"))
32
  {
33
  echo '<div class="wrap ws-menu-page">' . "\n";
34
 
 
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display ();
37
  echo '</div>'."\n";
32
  {
33
  echo '<div class="wrap ws-menu-page">' . "\n";
34
 
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
+
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display ();
39
  echo '</div>'."\n";
src/includes/menu-pages/trk-ops.inc.php CHANGED
@@ -32,6 +32,8 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_trk_ops"))
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
 
 
 
35
  echo '<div class="ws-menu-page-toolbox">'."\n";
36
  c_ws_plugin__s2member_menu_pages_tb::display();
37
  echo '</div>'."\n";
32
  {
33
  echo '<div class="wrap ws-menu-page">'."\n";
34
 
35
+ echo '<div class="wp-header-end"></div>'."\n";
36
+
37
  echo '<div class="ws-menu-page-toolbox">'."\n";
38
  c_ws_plugin__s2member_menu_pages_tb::display();
39
  echo '</div>'."\n";
src/includes/syscon.inc.php CHANGED
@@ -136,6 +136,11 @@ if(!function_exists('ws_plugin__s2member_configure_options_and_their_defaults'))
136
 
137
  $default_options['sec_encryption_key'] = '';
138
  $default_options['sec_encryption_key_history'] = array();
 
 
 
 
 
139
  $default_options['s_badge_status_enabled'] = '0';
140
 
141
  $default_options['max_ip_restriction'] = '5';
@@ -393,6 +398,15 @@ if(!function_exists('ws_plugin__s2member_configure_options_and_their_defaults'))
393
  else if($key === 'sec_encryption_key_history' && (!is_array($value) || empty($value)))
394
  $value = $default_options[$key];
395
 
 
 
 
 
 
 
 
 
 
396
  else if($key === 's_badge_status_enabled' && (!is_string($value) || !is_numeric($value)))
397
  $value = $default_options[$key];
398
 
@@ -604,11 +618,14 @@ if(!function_exists('ws_plugin__s2member_configure_options_and_their_defaults'))
604
  else if($key === 'wp_footer_code' && (!is_string($value) || !strlen($value)))
605
  $value = $default_options[$key];
606
  }
607
- if($options !== FALSE && is_string($options['sec_encryption_key']) && strlen($options['sec_encryption_key']) && !in_array($options['sec_encryption_key'], $GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history']))
608
- {
609
  array_unshift($GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'], $options['sec_encryption_key']);
610
  $GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'] = array_slice($GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'], 0, 10);
611
  }
 
 
 
 
612
  $GLOBALS['WS_PLUGIN__']['s2member']['o'] = apply_filters_ref_array('ws_plugin__s2member_options_before_checksum', array(&$GLOBALS['WS_PLUGIN__']['s2member']['o']));
613
 
614
  $GLOBALS['WS_PLUGIN__']['s2member']['o']['options_checksum'] = md5($checksum_prefix.serialize(array_merge($GLOBALS['WS_PLUGIN__']['s2member']['o'], array('options_checksum' => 0))));
136
 
137
  $default_options['sec_encryption_key'] = '';
138
  $default_options['sec_encryption_key_history'] = array();
139
+
140
+ $default_options['def_combo_encryption_key'] = '';
141
+ $default_options['def_combo_encryption_key_history'] = array();
142
+ $default_options['def_custom_combo_encryption_keys'] = array();
143
+
144
  $default_options['s_badge_status_enabled'] = '0';
145
 
146
  $default_options['max_ip_restriction'] = '5';
398
  else if($key === 'sec_encryption_key_history' && (!is_array($value) || empty($value)))
399
  $value = $default_options[$key];
400
 
401
+ else if($key === 'def_combo_encryption_key' && (!is_string($value) || !strlen($value)))
402
+ $value = $default_options[$key];
403
+
404
+ else if($key === 'def_combo_encryption_key_history' && (!is_array($value) || empty($value)))
405
+ $value = $default_options[$key];
406
+
407
+ else if($key === 'def_custom_combo_encryption_keys' && (!is_array($value) || empty($value)))
408
+ $value = $default_options[$key];
409
+
410
  else if($key === 's_badge_status_enabled' && (!is_string($value) || !is_numeric($value)))
411
  $value = $default_options[$key];
412
 
618
  else if($key === 'wp_footer_code' && (!is_string($value) || !strlen($value)))
619
  $value = $default_options[$key];
620
  }
621
+ if($options !== FALSE && is_string($options['sec_encryption_key']) && strlen($options['sec_encryption_key']) && !in_array($options['sec_encryption_key'], $GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'])) {
 
622
  array_unshift($GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'], $options['sec_encryption_key']);
623
  $GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'] = array_slice($GLOBALS['WS_PLUGIN__']['s2member']['o']['sec_encryption_key_history'], 0, 10);
624
  }
625
+ if($options !== FALSE && is_string($options['def_combo_encryption_key']) && strlen($options['def_combo_encryption_key']) && !in_array($options['def_combo_encryption_key'], $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'])) {
626
+ array_unshift($GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'], $options['def_combo_encryption_key']);
627
+ $GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'] = array_slice($GLOBALS['WS_PLUGIN__']['s2member']['o']['def_combo_encryption_key_history'], 0, 10);
628
+ }
629
  $GLOBALS['WS_PLUGIN__']['s2member']['o'] = apply_filters_ref_array('ws_plugin__s2member_options_before_checksum', array(&$GLOBALS['WS_PLUGIN__']['s2member']['o']));
630
 
631
  $GLOBALS['WS_PLUGIN__']['s2member']['o']['options_checksum'] = md5($checksum_prefix.serialize(array_merge($GLOBALS['WS_PLUGIN__']['s2member']['o'], array('options_checksum' => 0))));
src/includes/translations/s2member.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: 170221\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/s2member\n"
7
- "POT-Creation-Date: 2017-02-21 00:41:55+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -1975,7 +1975,7 @@ msgctxt "s2member-front"
1975
  msgid "No Billing Method; please try again."
1976
  msgstr ""
1977
 
1978
- #: pro/src/includes/syscon.inc.php:95 src/includes/syscon.inc.php:241
1979
  msgctxt "s2member-front"
1980
  msgid "Congratulations! (your membership has been approved)"
1981
  msgstr ""
@@ -1997,7 +1997,7 @@ msgid ""
1997
  "%s"
1998
  msgstr ""
1999
 
2000
- #: pro/src/includes/syscon.inc.php:99 src/includes/syscon.inc.php:253
2001
  msgctxt "s2member-front"
2002
  msgid "Thank You! (instructions for access)"
2003
  msgstr ""
@@ -3881,7 +3881,7 @@ msgid "as a Member"
3881
  msgstr ""
3882
 
3883
  #: src/includes/classes/email-configs.inc.php:254
3884
- #: src/includes/syscon.inc.php:215
3885
  msgctxt "s2member-front"
3886
  msgid ""
3887
  "Your Username/Password for:\n"
@@ -4549,27 +4549,27 @@ msgctxt "s2member-front"
4549
  msgid "If you need assistance, please <a href=\"%s\" target=\"_blank\">contact support</a>."
4550
  msgstr ""
4551
 
4552
- #: src/includes/classes/sc-eots-in.inc.php:74
4553
  msgctxt "s2member-front"
4554
  msgid "Access Expires:"
4555
  msgstr ""
4556
 
4557
- #: src/includes/classes/sc-eots-in.inc.php:75
4558
  msgctxt "s2member-front"
4559
  msgid "Access Expired:"
4560
  msgstr ""
4561
 
4562
- #: src/includes/classes/sc-eots-in.inc.php:76
4563
  msgctxt "s2member-front"
4564
  msgid "Next Payment:"
4565
  msgstr ""
4566
 
4567
- #: src/includes/classes/sc-eots-in.inc.php:77
4568
  msgctxt "s2member-front"
4569
  msgid "N/A"
4570
  msgstr ""
4571
 
4572
- #: src/includes/classes/sc-eots-in.inc.php:77
4573
  msgctxt "s2member-front"
4574
  msgid "—"
4575
  msgstr ""
@@ -4745,115 +4745,115 @@ msgid_plural "about %s years"
4745
  msgstr[0] ""
4746
  msgstr[1] ""
4747
 
4748
- #: src/includes/classes/utils-time.inc.php:277
4749
  msgctxt "s2member-front"
4750
  msgid "Daily"
4751
  msgstr ""
4752
 
4753
- #: src/includes/classes/utils-time.inc.php:277
4754
  msgctxt "s2member-front"
4755
  msgid "Weekly"
4756
  msgstr ""
4757
 
4758
- #: src/includes/classes/utils-time.inc.php:277
4759
  msgctxt "s2member-front"
4760
  msgid "Monthly"
4761
  msgstr ""
4762
 
4763
- #: src/includes/classes/utils-time.inc.php:277
4764
  msgctxt "s2member-front"
4765
  msgid "Yearly"
4766
  msgstr ""
4767
 
4768
- #: src/includes/classes/utils-time.inc.php:277
4769
- #: src/includes/classes/utils-time.inc.php:288
4770
  msgctxt "s2member-front"
4771
  msgid "Lifetime"
4772
  msgstr ""
4773
 
4774
- #: src/includes/classes/utils-time.inc.php:281
4775
  msgctxt "s2member-front"
4776
  msgid "Bi-Weekly"
4777
  msgstr ""
4778
 
4779
- #: src/includes/classes/utils-time.inc.php:282
4780
  msgctxt "s2member-front"
4781
  msgid "Bi-Monthly"
4782
  msgstr ""
4783
 
4784
- #: src/includes/classes/utils-time.inc.php:283
4785
  msgctxt "s2member-front"
4786
  msgid "Quarterly"
4787
  msgstr ""
4788
 
4789
- #: src/includes/classes/utils-time.inc.php:284
4790
  msgctxt "s2member-front"
4791
  msgid "Semi-Yearly"
4792
  msgstr ""
4793
 
4794
- #: src/includes/classes/utils-time.inc.php:288
4795
  msgctxt "s2member-front"
4796
  msgid "Day"
4797
  msgstr ""
4798
 
4799
- #: src/includes/classes/utils-time.inc.php:288
4800
  msgctxt "s2member-front"
4801
  msgid "Week"
4802
  msgstr ""
4803
 
4804
- #: src/includes/classes/utils-time.inc.php:288
4805
  msgctxt "s2member-front"
4806
  msgid "Month"
4807
  msgstr ""
4808
 
4809
- #: src/includes/classes/utils-time.inc.php:288
4810
  msgctxt "s2member-front"
4811
  msgid "Year"
4812
  msgstr ""
4813
 
4814
- #: src/includes/classes/utils-time.inc.php:294
4815
  msgctxt "s2member-front"
4816
  msgid "Days"
4817
  msgstr ""
4818
 
4819
- #: src/includes/classes/utils-time.inc.php:294
4820
  msgctxt "s2member-front"
4821
  msgid "Weeks"
4822
  msgstr ""
4823
 
4824
- #: src/includes/classes/utils-time.inc.php:294
4825
  msgctxt "s2member-front"
4826
  msgid "Months"
4827
  msgstr ""
4828
 
4829
- #: src/includes/classes/utils-time.inc.php:294
4830
  msgctxt "s2member-front"
4831
  msgid "Years"
4832
  msgstr ""
4833
 
4834
- #: src/includes/classes/utils-time.inc.php:294
4835
  msgctxt "s2member-front"
4836
  msgid "Lifetimes"
4837
  msgstr ""
4838
 
4839
  #. translators: Each cycle ( i.e., `each day/week/month` or `every 2
4840
  #. days/weeks/months`, etc. ). Cycles are translated elsewhere.
4841
- #: src/includes/classes/utils-time.inc.php:331
4842
- #: src/includes/classes/utils-time.inc.php:374
4843
  msgctxt "s2member-front"
4844
  msgid "each %2$s"
4845
  msgid_plural "every %1$s %3$s"
4846
  msgstr[0] ""
4847
  msgstr[1] ""
4848
 
4849
- #: src/includes/classes/utils-time.inc.php:334
4850
  msgctxt "s2member-front"
4851
  msgid "lifetime"
4852
  msgstr ""
4853
 
4854
  #. translators: Membership cycle ( i.e., `1 day/week/month` or `2
4855
  #. days/weeks/months`, etc. ). Most of this is translated elsewhere.
4856
- #: src/includes/classes/utils-time.inc.php:338
4857
  msgctxt "s2member-front"
4858
  msgid "%1$s %2$s"
4859
  msgid_plural "%1$s %3$s"
@@ -4862,7 +4862,7 @@ msgstr[1] ""
4862
 
4863
  #. translators: Cycle ( i.e., `for 1 day/week/month` or `for 2
4864
  #. days/weeks/months`, etc. ). Most of this is translated elsewhere.
4865
- #: src/includes/classes/utils-time.inc.php:381
4866
  msgctxt "s2member-front"
4867
  msgid "for %1$s %2$s"
4868
  msgid_plural "for %1$s %3$s"
@@ -5001,22 +5001,22 @@ msgctxt "s2member-front recaptcha-lang-code"
5001
  msgid "en"
5002
  msgstr ""
5003
 
5004
- #: src/includes/syscon.inc.php:157
5005
  msgctxt "s2member-front"
5006
  msgid "Yes, I want to receive updates via email."
5007
  msgstr ""
5008
 
5009
- #: src/includes/syscon.inc.php:214
5010
  msgctxt "s2member-front"
5011
  msgid "[%s] Username/Password"
5012
  msgstr ""
5013
 
5014
- #: src/includes/syscon.inc.php:218
5015
  msgctxt "s2member-front"
5016
  msgid "[%s] New User Registration"
5017
  msgstr ""
5018
 
5019
- #: src/includes/syscon.inc.php:219
5020
  msgctxt "s2member-front"
5021
  msgid ""
5022
  "New User Registration on your site:\n"
@@ -5028,7 +5028,7 @@ msgid ""
5028
  "IP Address: %%%%user_ip%%%%"
5029
  msgstr ""
5030
 
5031
- #: src/includes/syscon.inc.php:242
5032
  msgctxt "s2member-front"
5033
  msgid ""
5034
  "Thanks %%%%first_name%%%%! Your membership has been approved.\n"
@@ -5044,12 +5044,12 @@ msgid ""
5044
  "%s"
5045
  msgstr ""
5046
 
5047
- #: src/includes/syscon.inc.php:245 src/includes/syscon.inc.php:249
5048
  msgctxt "s2member-front"
5049
  msgid "Thank you! Your account has been updated."
5050
  msgstr ""
5051
 
5052
- #: src/includes/syscon.inc.php:246 src/includes/syscon.inc.php:250
5053
  msgctxt "s2member-front"
5054
  msgid ""
5055
  "Thanks %%%%first_name%%%%! Your account now has access to: %%%%item_name%%%%.\n"
@@ -5060,7 +5060,7 @@ msgid ""
5060
  "%s"
5061
  msgstr ""
5062
 
5063
- #: src/includes/syscon.inc.php:254
5064
  msgctxt "s2member-front"
5065
  msgid ""
5066
  "Thanks %%%%first_name%%%%!\n"
@@ -5077,32 +5077,32 @@ msgid ""
5077
  "%s"
5078
  msgstr ""
5079
 
5080
- #: src/includes/syscon.inc.php:293
5081
  msgctxt "s2member-front"
5082
  msgid "Free Subscriber"
5083
  msgstr ""
5084
 
5085
- #: src/includes/syscon.inc.php:293
5086
  msgctxt "s2member-front"
5087
  msgid "Bronze Member"
5088
  msgstr ""
5089
 
5090
- #: src/includes/syscon.inc.php:293
5091
  msgctxt "s2member-front"
5092
  msgid "Silver Member"
5093
  msgstr ""
5094
 
5095
- #: src/includes/syscon.inc.php:293
5096
  msgctxt "s2member-front"
5097
  msgid "Gold Member"
5098
  msgstr ""
5099
 
5100
- #: src/includes/syscon.inc.php:293
5101
  msgctxt "s2member-front"
5102
  msgid "Platinum Member"
5103
  msgstr ""
5104
 
5105
- #: src/includes/syscon.inc.php:293
5106
  msgctxt "s2member-front"
5107
  msgid "Level %s Member"
5108
  msgstr ""
2
  # This file is distributed under the same license as the package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: 170524\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/s2member\n"
7
+ "POT-Creation-Date: 2017-05-24 18:31:59+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
1975
  msgid "No Billing Method; please try again."
1976
  msgstr ""
1977
 
1978
+ #: pro/src/includes/syscon.inc.php:95 src/includes/syscon.inc.php:246
1979
  msgctxt "s2member-front"
1980
  msgid "Congratulations! (your membership has been approved)"
1981
  msgstr ""
1997
  "%s"
1998
  msgstr ""
1999
 
2000
+ #: pro/src/includes/syscon.inc.php:99 src/includes/syscon.inc.php:258
2001
  msgctxt "s2member-front"
2002
  msgid "Thank You! (instructions for access)"
2003
  msgstr ""
3881
  msgstr ""
3882
 
3883
  #: src/includes/classes/email-configs.inc.php:254
3884
+ #: src/includes/syscon.inc.php:220
3885
  msgctxt "s2member-front"
3886
  msgid ""
3887
  "Your Username/Password for:\n"
4549
  msgid "If you need assistance, please <a href=\"%s\" target=\"_blank\">contact support</a>."
4550
  msgstr ""
4551
 
4552
+ #: src/includes/classes/sc-eots-in.inc.php:76
4553
  msgctxt "s2member-front"
4554
  msgid "Access Expires:"
4555
  msgstr ""
4556
 
4557
+ #: src/includes/classes/sc-eots-in.inc.php:77
4558
  msgctxt "s2member-front"
4559
  msgid "Access Expired:"
4560
  msgstr ""
4561
 
4562
+ #: src/includes/classes/sc-eots-in.inc.php:78
4563
  msgctxt "s2member-front"
4564
  msgid "Next Payment:"
4565
  msgstr ""
4566
 
4567
+ #: src/includes/classes/sc-eots-in.inc.php:79
4568
  msgctxt "s2member-front"
4569
  msgid "N/A"
4570
  msgstr ""
4571
 
4572
+ #: src/includes/classes/sc-eots-in.inc.php:79
4573
  msgctxt "s2member-front"
4574
  msgid "—"
4575
  msgstr ""
4745
  msgstr[0] ""
4746
  msgstr[1] ""
4747
 
4748
+ #: src/includes/classes/utils-time.inc.php:278
4749
  msgctxt "s2member-front"
4750
  msgid "Daily"
4751
  msgstr ""
4752
 
4753
+ #: src/includes/classes/utils-time.inc.php:278
4754
  msgctxt "s2member-front"
4755
  msgid "Weekly"
4756
  msgstr ""
4757
 
4758
+ #: src/includes/classes/utils-time.inc.php:278
4759
  msgctxt "s2member-front"
4760
  msgid "Monthly"
4761
  msgstr ""
4762
 
4763
+ #: src/includes/classes/utils-time.inc.php:278
4764
  msgctxt "s2member-front"
4765
  msgid "Yearly"
4766
  msgstr ""
4767
 
4768
+ #: src/includes/classes/utils-time.inc.php:278
4769
+ #: src/includes/classes/utils-time.inc.php:289
4770
  msgctxt "s2member-front"
4771
  msgid "Lifetime"
4772
  msgstr ""
4773
 
4774
+ #: src/includes/classes/utils-time.inc.php:282
4775
  msgctxt "s2member-front"
4776
  msgid "Bi-Weekly"
4777
  msgstr ""
4778
 
4779
+ #: src/includes/classes/utils-time.inc.php:283
4780
  msgctxt "s2member-front"
4781
  msgid "Bi-Monthly"
4782
  msgstr ""
4783
 
4784
+ #: src/includes/classes/utils-time.inc.php:284
4785
  msgctxt "s2member-front"
4786
  msgid "Quarterly"
4787
  msgstr ""
4788
 
4789
+ #: src/includes/classes/utils-time.inc.php:285
4790
  msgctxt "s2member-front"
4791
  msgid "Semi-Yearly"
4792
  msgstr ""
4793
 
4794
+ #: src/includes/classes/utils-time.inc.php:289
4795
  msgctxt "s2member-front"
4796
  msgid "Day"
4797
  msgstr ""
4798
 
4799
+ #: src/includes/classes/utils-time.inc.php:289
4800
  msgctxt "s2member-front"
4801
  msgid "Week"
4802
  msgstr ""
4803
 
4804
+ #: src/includes/classes/utils-time.inc.php:289
4805
  msgctxt "s2member-front"
4806
  msgid "Month"
4807
  msgstr ""
4808
 
4809
+ #: src/includes/classes/utils-time.inc.php:289
4810
  msgctxt "s2member-front"
4811
  msgid "Year"
4812
  msgstr ""
4813
 
4814
+ #: src/includes/classes/utils-time.inc.php:295
4815
  msgctxt "s2member-front"
4816
  msgid "Days"
4817
  msgstr ""
4818
 
4819
+ #: src/includes/classes/utils-time.inc.php:295
4820
  msgctxt "s2member-front"
4821
  msgid "Weeks"
4822
  msgstr ""
4823
 
4824
+ #: src/includes/classes/utils-time.inc.php:295
4825
  msgctxt "s2member-front"
4826
  msgid "Months"
4827
  msgstr ""
4828
 
4829
+ #: src/includes/classes/utils-time.inc.php:295
4830
  msgctxt "s2member-front"
4831
  msgid "Years"
4832
  msgstr ""
4833
 
4834
+ #: src/includes/classes/utils-time.inc.php:295
4835
  msgctxt "s2member-front"
4836
  msgid "Lifetimes"
4837
  msgstr ""
4838
 
4839
  #. translators: Each cycle ( i.e., `each day/week/month` or `every 2
4840
  #. days/weeks/months`, etc. ). Cycles are translated elsewhere.
4841
+ #: src/includes/classes/utils-time.inc.php:332
4842
+ #: src/includes/classes/utils-time.inc.php:375
4843
  msgctxt "s2member-front"
4844
  msgid "each %2$s"
4845
  msgid_plural "every %1$s %3$s"
4846
  msgstr[0] ""
4847
  msgstr[1] ""
4848
 
4849
+ #: src/includes/classes/utils-time.inc.php:335
4850
  msgctxt "s2member-front"
4851
  msgid "lifetime"
4852
  msgstr ""
4853
 
4854
  #. translators: Membership cycle ( i.e., `1 day/week/month` or `2
4855
  #. days/weeks/months`, etc. ). Most of this is translated elsewhere.
4856
+ #: src/includes/classes/utils-time.inc.php:339
4857
  msgctxt "s2member-front"
4858
  msgid "%1$s %2$s"
4859
  msgid_plural "%1$s %3$s"
4862
 
4863
  #. translators: Cycle ( i.e., `for 1 day/week/month` or `for 2
4864
  #. days/weeks/months`, etc. ). Most of this is translated elsewhere.
4865
+ #: src/includes/classes/utils-time.inc.php:382
4866
  msgctxt "s2member-front"
4867
  msgid "for %1$s %2$s"
4868
  msgid_plural "for %1$s %3$s"
5001
  msgid "en"
5002
  msgstr ""
5003
 
5004
+ #: src/includes/syscon.inc.php:162
5005
  msgctxt "s2member-front"
5006
  msgid "Yes, I want to receive updates via email."
5007
  msgstr ""
5008
 
5009
+ #: src/includes/syscon.inc.php:219
5010
  msgctxt "s2member-front"
5011
  msgid "[%s] Username/Password"
5012
  msgstr ""
5013
 
5014
+ #: src/includes/syscon.inc.php:223
5015
  msgctxt "s2member-front"
5016
  msgid "[%s] New User Registration"
5017
  msgstr ""
5018
 
5019
+ #: src/includes/syscon.inc.php:224
5020
  msgctxt "s2member-front"
5021
  msgid ""
5022
  "New User Registration on your site:\n"
5028
  "IP Address: %%%%user_ip%%%%"
5029
  msgstr ""
5030
 
5031
+ #: src/includes/syscon.inc.php:247
5032
  msgctxt "s2member-front"
5033
  msgid ""
5034
  "Thanks %%%%first_name%%%%! Your membership has been approved.\n"
5044
  "%s"
5045
  msgstr ""
5046
 
5047
+ #: src/includes/syscon.inc.php:250 src/includes/syscon.inc.php:254
5048
  msgctxt "s2member-front"
5049
  msgid "Thank you! Your account has been updated."
5050
  msgstr ""
5051
 
5052
+ #: src/includes/syscon.inc.php:251 src/includes/syscon.inc.php:255
5053
  msgctxt "s2member-front"
5054
  msgid ""
5055
  "Thanks %%%%first_name%%%%! Your account now has access to: %%%%item_name%%%%.\n"
5060
  "%s"
5061
  msgstr ""
5062
 
5063
+ #: src/includes/syscon.inc.php:259
5064
  msgctxt "s2member-front"
5065
  msgid ""
5066
  "Thanks %%%%first_name%%%%!\n"
5077
  "%s"
5078
  msgstr ""
5079
 
5080
+ #: src/includes/syscon.inc.php:298
5081
  msgctxt "s2member-front"
5082
  msgid "Free Subscriber"
5083
  msgstr ""
5084
 
5085
+ #: src/includes/syscon.inc.php:298
5086
  msgctxt "s2member-front"
5087
  msgid "Bronze Member"
5088
  msgstr ""
5089
 
5090
+ #: src/includes/syscon.inc.php:298
5091
  msgctxt "s2member-front"
5092
  msgid "Silver Member"
5093
  msgstr ""
5094
 
5095
+ #: src/includes/syscon.inc.php:298
5096
  msgctxt "s2member-front"
5097
  msgid "Gold Member"
5098
  msgstr ""
5099
 
5100
+ #: src/includes/syscon.inc.php:298
5101
  msgctxt "s2member-front"
5102
  msgid "Platinum Member"
5103
  msgstr ""
5104
 
5105
+ #: src/includes/syscon.inc.php:298
5106
  msgctxt "s2member-front"
5107
  msgid "Level %s Member"
5108
  msgstr ""
src/vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit04945020f1860c6e52fcca37ab82eb4b::getLoader();
src/vendor/composer/autoload_classmap.php CHANGED
@@ -6,4 +6,18 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname(dirname($vendorDir));
7
 
8
  return array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  );
6
  $baseDir = dirname(dirname($vendorDir));
7
 
8
  return array(
9
+ 'Defuse\\Crypto\\Core' => $vendorDir . '/defuse/php-encryption/src/Core.php',
10
+ 'Defuse\\Crypto\\Crypto' => $vendorDir . '/defuse/php-encryption/src/Crypto.php',
11
+ 'Defuse\\Crypto\\DerivedKeys' => $vendorDir . '/defuse/php-encryption/src/DerivedKeys.php',
12
+ 'Defuse\\Crypto\\Encoding' => $vendorDir . '/defuse/php-encryption/src/Encoding.php',
13
+ 'Defuse\\Crypto\\Exception\\BadFormatException' => $vendorDir . '/defuse/php-encryption/src/Exception/BadFormatException.php',
14
+ 'Defuse\\Crypto\\Exception\\CryptoException' => $vendorDir . '/defuse/php-encryption/src/Exception/CryptoException.php',
15
+ 'Defuse\\Crypto\\Exception\\EnvironmentIsBrokenException' => $vendorDir . '/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php',
16
+ 'Defuse\\Crypto\\Exception\\IOException' => $vendorDir . '/defuse/php-encryption/src/Exception/IOException.php',
17
+ 'Defuse\\Crypto\\Exception\\WrongKeyOrModifiedCiphertextException' => $vendorDir . '/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php',
18
+ 'Defuse\\Crypto\\File' => $vendorDir . '/defuse/php-encryption/src/File.php',
19
+ 'Defuse\\Crypto\\Key' => $vendorDir . '/defuse/php-encryption/src/Key.php',
20
+ 'Defuse\\Crypto\\KeyOrPassword' => $vendorDir . '/defuse/php-encryption/src/KeyOrPassword.php',
21
+ 'Defuse\\Crypto\\KeyProtectedByPassword' => $vendorDir . '/defuse/php-encryption/src/KeyProtectedByPassword.php',
22
+ 'Defuse\\Crypto\\RuntimeTests' => $vendorDir . '/defuse/php-encryption/src/RuntimeTests.php',
23
  );
src/vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname(dirname($vendorDir));
7
+
8
+ return array(
9
+ '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
10
+ );
src/vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
@@ -40,6 +40,20 @@ class ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8
40
 
41
  $loader->register(true);
42
 
 
 
 
 
 
43
  return $loader;
44
  }
45
  }
 
 
 
 
 
 
 
 
 
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit04945020f1860c6e52fcca37ab82eb4b
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit04945020f1860c6e52fcca37ab82eb4b', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit04945020f1860c6e52fcca37ab82eb4b', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
40
 
41
  $loader->register(true);
42
 
43
+ $includeFiles = require __DIR__ . '/autoload_files.php';
44
+ foreach ($includeFiles as $fileIdentifier => $file) {
45
+ composerRequire04945020f1860c6e52fcca37ab82eb4b($fileIdentifier, $file);
46
+ }
47
+
48
  return $loader;
49
  }
50
  }
51
+
52
+ function composerRequire04945020f1860c6e52fcca37ab82eb4b($fileIdentifier, $file)
53
+ {
54
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
55
+ require $file;
56
+
57
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
58
+ }
59
+ }
src/vendor/composer/installed.json CHANGED
@@ -1 +1,113 @@
1
- []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "paragonie/random_compat",
4
+ "version": "v2.0.10",
5
+ "version_normalized": "2.0.10.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/paragonie/random_compat.git",
9
+ "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
14
+ "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "php": ">=5.2.0"
19
+ },
20
+ "require-dev": {
21
+ "phpunit/phpunit": "4.*|5.*"
22
+ },
23
+ "suggest": {
24
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
25
+ },
26
+ "time": "2017-03-13 16:27:32",
27
+ "type": "library",
28
+ "installation-source": "dist",
29
+ "autoload": {
30
+ "files": [
31
+ "lib/random.php"
32
+ ]
33
+ },
34
+ "notification-url": "https://packagist.org/downloads/",
35
+ "license": [
36
+ "MIT"
37
+ ],
38
+ "authors": [
39
+ {
40
+ "name": "Paragon Initiative Enterprises",
41
+ "email": "security@paragonie.com",
42
+ "homepage": "https://paragonie.com"
43
+ }
44
+ ],
45
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
46
+ "keywords": [
47
+ "csprng",
48
+ "pseudorandom",
49
+ "random"
50
+ ]
51
+ },
52
+ {
53
+ "name": "defuse/php-encryption",
54
+ "version": "2.0.3",
55
+ "version_normalized": "2.0.3.0",
56
+ "source": {
57
+ "type": "git",
58
+ "url": "https://github.com/defuse/php-encryption.git",
59
+ "reference": "2c6fea3d9a4eaaa8cef86b2a89f3660818117b33"
60
+ },
61
+ "dist": {
62
+ "type": "zip",
63
+ "url": "https://api.github.com/repos/defuse/php-encryption/zipball/2c6fea3d9a4eaaa8cef86b2a89f3660818117b33",
64
+ "reference": "2c6fea3d9a4eaaa8cef86b2a89f3660818117b33",
65
+ "shasum": ""
66
+ },
67
+ "require": {
68
+ "ext-openssl": "*",
69
+ "paragonie/random_compat": "~2.0",
70
+ "php": ">=5.4.0"
71
+ },
72
+ "require-dev": {
73
+ "nikic/php-parser": "^2.0"
74
+ },
75
+ "time": "2016-10-10 15:20:26",
76
+ "type": "library",
77
+ "installation-source": "dist",
78
+ "autoload": {
79
+ "classmap": [
80
+ "src"
81
+ ]
82
+ },
83
+ "notification-url": "https://packagist.org/downloads/",
84
+ "license": [
85
+ "MIT"
86
+ ],
87
+ "authors": [
88
+ {
89
+ "name": "Taylor Hornby",
90
+ "email": "taylor@defuse.ca",
91
+ "homepage": "https://defuse.ca/"
92
+ },
93
+ {
94
+ "name": "Scott Arciszewski",
95
+ "email": "info@paragonie.com",
96
+ "homepage": "https://paragonie.com"
97
+ }
98
+ ],
99
+ "description": "Secure PHP Encryption Library",
100
+ "keywords": [
101
+ "aes",
102
+ "authenticated encryption",
103
+ "cipher",
104
+ "crypto",
105
+ "cryptography",
106
+ "encrypt",
107
+ "encryption",
108
+ "openssl",
109
+ "security",
110
+ "symmetric key cryptography"
111
+ ]
112
+ }
113
+ ]
src/vendor/defuse/php-encryption/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Taylor Hornby <https://defuse.ca> and Paragon Initiative
4
+ Enterprises <https://paragonie.com>.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
7
+ this software and associated documentation files (the "Software"), to deal in
8
+ the Software without restriction, including without limitation the rights to
9
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10
+ the Software, and to permit persons to whom the Software is furnished to do so,
11
+ subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
src/vendor/defuse/php-encryption/dist/Makefile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This builds defuse-crypto.phar. To run this Makefile, `box` and `composer`
2
+ # must be installed and in your $PATH. Run it from inside the dist/ directory.
3
+
4
+ box := $(shell which box)
5
+ composer := "composer"
6
+
7
+ .PHONY: all
8
+ all: build-phar
9
+
10
+ .PHONY: sign-phar
11
+ sign-phar:
12
+ gpg -u 7B4B2D98 --armor --output defuse-crypto.phar.sig --detach-sig defuse-crypto.phar
13
+
14
+ # ensure we run in clean tree. export git tree and run there.
15
+ .PHONY: build-phar
16
+ build-phar:
17
+ @echo "Creating .phar from revision $(shell git rev-parse HEAD)."
18
+ rm -rf worktree
19
+ install -d worktree
20
+ (cd $(CURDIR)/..; git archive HEAD) | tar -x -C worktree
21
+ $(MAKE) -f $(CURDIR)/Makefile -C worktree defuse-crypto.phar
22
+ mv worktree/*.phar .
23
+ rm -rf worktree
24
+
25
+ .PHONY: clean
26
+ clean:
27
+ rm -vf defuse-crypto.phar defuse-crypto.phar.sig
28
+
29
+ # Inside workdir/:
30
+
31
+ defuse-crypto.phar: dist/box.json composer.lock
32
+ cp dist/box.json .
33
+ php -d phar.readonly=0 $(box) build -c box.json -v
34
+
35
+ composer.lock:
36
+ $(composer) install --no-dev
37
+
src/vendor/defuse/php-encryption/dist/box.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "chmod": "0755",
3
+ "finder": [
4
+ {
5
+ "in": "src",
6
+ "name": "*.php"
7
+ },
8
+ {
9
+ "in": "vendor/composer",
10
+ "name": "*.php"
11
+ },
12
+ {
13
+ "in": "vendor/paragonie",
14
+ "name": "*.php",
15
+ "exclude": "other"
16
+ }
17
+ ],
18
+ "compactors": [
19
+ "Herrera\\Box\\Compactor\\Php"
20
+ ],
21
+ "main": "vendor/autoload.php",
22
+ "output": "defuse-crypto.phar",
23
+ "shebang": false,
24
+ "stub": true
25
+ }
src/vendor/defuse/php-encryption/dist/signingkey.asc ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
2
+ Version: GnuPG v2
3
+
4
+ mQINBFarvO4BEACdQBaLt6SUBx1cB5liUu1qo+YwVLh9bxTregQtmEREMdTVqXYt
5
+ e5b79uL4pQp2GlKHcEyRURS+6rIIruM0oh9ZYGTJYPAkCDzJxaU2awZeFbfBvpCm
6
+ iF66/O4ZJI4mlT8dFKmxBJxDhfeOR2UmmhDiEsJK9FxBKUzvo/dWrX2pBzf8Y122
7
+ iIaVraSo+tymaf7vriaIf/NnSKhDw8dtQYGM4NMrxxsPTfbCF8XiboDgTkoD2A+6
8
+ NpOJYxA4Veedsf2TP9YLhljH4m5yYlfjjqBzbBCPWuE6Hhy5Xze9mncgDr7LKenm
9
+ Ctf2NxW6y4O3RCI+9eLlBfFWB+KuGV87/b5daetX7NNLbjID8z2rqEa+d6wu5xA5
10
+ Ta2uiVkAOEovr3XnkayZ9zth+Za7w7Ai0ln0N/LVMkM+Gu4z/pJv6HjmTGDM2wJb
11
+ fs+UOM0TFdg+N81Do67XT2M4o0MeHyUqsIiWpYa2Qf1PNmqTQNJnRk8uZZ9I96Nh
12
+ eCgNuCbhsQiYBMicox+xmuWAlGAfA06y0kCtmqGhiBGArdJlWvUqPqGiZ4Hln9z0
13
+ FJmXDOh0Q/FIPxcDg8mKRRbx+lOP389PLsPpj4b2B/4PEgfpCCOwuKpLotATZxC1
14
+ 9JwFk0Y/cvUUkq4a+nAJBNtBbtRJkEesuuUnRq6XexmnE3uUucDcV0XCSwARAQAB
15
+ tCBUYXlsb3IgSG9ybmJ5IDx0YXlsb3JAZGVmdXNlLmNhPokCPQQTAQgAJwUCVqu8
16
+ 7gIbAwUJB4TOAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRA4XuBVoSkVOJbx
17
+ EACG0F9blPMAsK05EWyNnnS4mw25zPfbaqqEvYbquAeM0nBpRDm7sRn2MNR0AL4g
18
+ 7XrtxE/4qYkdEl6f2wFCQeRhZgxE3w22llredzLme11Hic8hn4i7ysdIw0r9dMMR
19
+ kjgR5UcWpv8iU847czyK09PkKW2EaLRbX2qbA7rNU5qCFKeD4Sy4bBTteISeVsHo
20
+ Vr9o1/bRrMhgZ++ts8hYf0LmujIf5cxp+qcdKwCXSnS/gmmXaKRMCPv/Wdlq9bt6
21
+ LX9jZB9lXBdGxcBJeFOsTG+QRDiVjg3d6i3o3TAKV87ALBI4v2ADEYtN8lviHo3/
22
+ SovVKv6zrUsZHxhoGiLTiksNrYsKMmiMxdJCoOazmtUPnZ4UOtT8NdqMPoKvdoRz
23
+ f4rhZ+f5jSVD9OuX2PDmfyq21Rdiym7Vcgr+uTIFJ3ShRHjWb/ytCwoB2FeGY6+G
24
+ AKY58bTQvUIqEJvSov/+TAqZ4BfOuSdTLcHglV1OdUu2SFZvU2gmyVp0l5elGv5t
25
+ FyUlBJUkQT9MtvsdLOR7vQi8QapV+9LWpqwvaj9hyEJz848DQ2sdYTphUytFHv7H
26
+ k58DAtVhTrVjHyeefjiYtMl6vSAgTjy5LWAUpo5TfhdGrAi0Tdd/GD7amHoWoDy8
27
+ EKXKq2xPLo3JOdkWYQUi5NErzEskfsSzpCOgyDJmGetWK7kCDQRWq7zuARAAu7/i
28
+ cm8cjgLhHEX/bgfwOT2hLOLSjjve0O8YFSuJO9XqIHXqmfVOrqWtfG0Mh4bwlfqc
29
+ MAvBfF5NSSPfAE4ftBAQ1e5jEv8hJeqICpq3IHTFX4etBs49NfNkyveQl/amVTu1
30
+ +/O5J4CuIcsEf3y0Xuu38n7EB3SfMQCWLcOR1NyZoX3bI+CGRpOVVoFse3ljSWL4
31
+ LhLVl0WiEMXULsussEoN+c6x9KCyAi/jFOrxrTrFC//sZesKj6KucoqKGfwMWrrv
32
+ IeRT9Ga8Wn5MJnQu0aWg+zVVYqTedXZLNLODgQIInFnXO0seBXy15yDok1y5bkx2
33
+ sinKg4+mueYaGUpoUti0hM3J3yaC34i6Cwa8MQoLNw1JIS/oNtKjpMxyV10w8aoc
34
+ PHRK3n7UYp10mJHx7aM+lldSKvVS1NTQmI4vloNLwMp324H5ANDFAlRUz7mysVnu
35
+ DEEvigPSPxs5ZYENu/i7pCQC5qHfhrlBrQwTjhegr0pQPcumy2fO5SGC9l/5B7ev
36
+ bqQSZmDeWWoTvh2w2wl5/RWAsgZKx6rDtkCqYx7sSBY17uorrxP24LP4zhq7NxRV
37
+ nfdsLogbCFNVQ66u7qvq5zFccdFtg9h1HQWdS7wbnKSBGZoo5gl6js7GGtxfGbb0
38
+ oQ9kp6eciF4U92r6POhVgbRe4CfPo50nqgZBddkAEQEAAYkCJQQYAQgADwUCVqu8
39
+ 7gIbDAUJB4TOAAAKCRA4XuBVoSkVOFJ8D/9J8IJ4XWUU3FYIaHJ3XeSoxDmTi7d5
40
+ WmNdf1lmwz82MQjG4uw17oCbvQzmj4/a/CM1Ly4v0WwBhUf9aiNErD0ByHASFnuc
41
+ tlQBLVJdk0vRyD0fZakGg64qCA76hiySjMhlGHkQFyP2mDORc2GNu/OqFGm79pXT
42
+ ZUplXxd431E603/agM5xJrweutMMpP1nBFTSEMJvbMNzDVN8I1A1CH4zVmAVxOUk
43
+ sQ5L5rXW+KeXWyiMF24+l2CMnkQ2CxfHpkcpfPJs1Cbt+TIBSSofIqK8QJXrb/2f
44
+ Zpl/ftqW7Xe86rJFrB/Y/77LDWx10rqWEvfCqrBxrMj7ONAQfbKQF/IjAwDN17Wf
45
+ 1K74rqKnRu+KHCyNM89s1iDbQC9kzZfzYt4AEOvAH/ZQDMZffzPSbnfkBerExFpa
46
+ 93XMuiR66jiBsf9IXIQeydpJD4Ogl2sSUSxFEJxJ/bBSxPxC5w7/BVMA7Am1y8Zo
47
+ 3hrpqnX2PBzxG7L0FZ6fYkfR3p8JS7vI6nByBf2IDv8W32wn43olPf+u6uobHLvt
48
+ ttapOjwPAhPDalRuxs9U6WSg06QJkT/0F8TFUPWpsFmKTl+G4Ty7PHWsjeeNHJCL
49
+ 7/5RQboFY3k8Jy3/sIofABO6Un9LJivDuu9PxqA0IgvaS6Mja8JdCCk9Nyk4vHB7
50
+ IEgAL/CYqrk38w==
51
+ =lmD7
52
+ -----END PGP PUBLIC KEY BLOCK-----
src/vendor/defuse/php-encryption/src/Core.php ADDED
@@ -0,0 +1,434 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ final class Core
8
+ {
9
+ const HEADER_VERSION_SIZE = 4;
10
+ const MINIMUM_CIPHERTEXT_SIZE = 84;
11
+
12
+ const CURRENT_VERSION = "\xDE\xF5\x02\x00";
13
+
14
+ const CIPHER_METHOD = 'aes-256-ctr';
15
+ const BLOCK_BYTE_SIZE = 16;
16
+ const KEY_BYTE_SIZE = 32;
17
+ const SALT_BYTE_SIZE = 32;
18
+ const MAC_BYTE_SIZE = 32;
19
+ const HASH_FUNCTION_NAME = 'sha256';
20
+ const ENCRYPTION_INFO_STRING = 'DefusePHP|V2|KeyForEncryption';
21
+ const AUTHENTICATION_INFO_STRING = 'DefusePHP|V2|KeyForAuthentication';
22
+ const BUFFER_BYTE_SIZE = 1048576;
23
+
24
+ const LEGACY_CIPHER_METHOD = 'aes-128-cbc';
25
+ const LEGACY_BLOCK_BYTE_SIZE = 16;
26
+ const LEGACY_KEY_BYTE_SIZE = 16;
27
+ const LEGACY_HASH_FUNCTION_NAME = 'sha256';
28
+ const LEGACY_MAC_BYTE_SIZE = 32;
29
+ const LEGACY_ENCRYPTION_INFO_STRING = 'DefusePHP|KeyForEncryption';
30
+ const LEGACY_AUTHENTICATION_INFO_STRING = 'DefusePHP|KeyForAuthentication';
31
+
32
+ /*
33
+ * V2.0 Format: VERSION (4 bytes) || SALT (32 bytes) || IV (16 bytes) ||
34
+ * CIPHERTEXT (varies) || HMAC (32 bytes)
35
+ *
36
+ * V1.0 Format: HMAC (32 bytes) || IV (16 bytes) || CIPHERTEXT (varies).
37
+ */
38
+
39
+ /**
40
+ * Adds an integer to a block-sized counter.
41
+ *
42
+ * @param string $ctr
43
+ * @param int $inc
44
+ *
45
+ * @throws Ex\EnvironmentIsBrokenException
46
+ *
47
+ * @return string
48
+ */
49
+ public static function incrementCounter($ctr, $inc)
50
+ {
51
+ if (Core::ourStrlen($ctr) !== Core::BLOCK_BYTE_SIZE) {
52
+ throw new Ex\EnvironmentIsBrokenException(
53
+ 'Trying to increment a nonce of the wrong size.'
54
+ );
55
+ }
56
+
57
+ if (! \is_int($inc)) {
58
+ throw new Ex\EnvironmentIsBrokenException(
59
+ 'Trying to increment nonce by a non-integer.'
60
+ );
61
+ }
62
+
63
+ if ($inc < 0) {
64
+ throw new Ex\EnvironmentIsBrokenException(
65
+ 'Trying to increment nonce by a negative amount.'
66
+ );
67
+ }
68
+
69
+ if ($inc > PHP_INT_MAX - 255) {
70
+ throw new Ex\EnvironmentIsBrokenException(
71
+ 'Integer overflow may occur.'
72
+ );
73
+ }
74
+
75
+ /*
76
+ * We start at the rightmost byte (big-endian)
77
+ * So, too, does OpenSSL: http://stackoverflow.com/a/3146214/2224584
78
+ */
79
+ for ($i = Core::BLOCK_BYTE_SIZE - 1; $i >= 0; --$i) {
80
+ $sum = \ord($ctr[$i]) + $inc;
81
+
82
+ /* Detect integer overflow and fail. */
83
+ if (! \is_int($sum)) {
84
+ throw new Ex\EnvironmentIsBrokenException(
85
+ 'Integer overflow in CTR mode nonce increment.'
86
+ );
87
+ }
88
+
89
+ $ctr[$i] = \pack('C', $sum & 0xFF);
90
+ $inc = $sum >> 8;
91
+ }
92
+ return $ctr;
93
+ }
94
+
95
+ /**
96
+ * Returns a random byte string of the specified length.
97
+ *
98
+ * @param int $octets
99
+ *
100
+ * @throws Ex\EnvironmentIsBrokenException
101
+ *
102
+ * @return string
103
+ */
104
+ public static function secureRandom($octets)
105
+ {
106
+ self::ensureFunctionExists('random_bytes');
107
+ try {
108
+ return \random_bytes($octets);
109
+ } catch (\Exception $ex) {
110
+ throw new Ex\EnvironmentIsBrokenException(
111
+ 'Your system does not have a secure random number generator.'
112
+ );
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Computes the HKDF key derivation function specified in
118
+ * http://tools.ietf.org/html/rfc5869.
119
+ *
120
+ * @param string $hash Hash Function
121
+ * @param string $ikm Initial Keying Material
122
+ * @param int $length How many bytes?
123
+ * @param string $info What sort of key are we deriving?
124
+ * @param string $salt
125
+ *
126
+ * @throws Ex\EnvironmentIsBrokenException
127
+ *
128
+ * @return string
129
+ */
130
+ public static function HKDF($hash, $ikm, $length, $info = '', $salt = null)
131
+ {
132
+ $digest_length = Core::ourStrlen(\hash_hmac($hash, '', '', true));
133
+
134
+ // Sanity-check the desired output length.
135
+ if (empty($length) || ! \is_int($length) ||
136
+ $length < 0 || $length > 255 * $digest_length) {
137
+ throw new Ex\EnvironmentIsBrokenException(
138
+ 'Bad output length requested of HKDF.'
139
+ );
140
+ }
141
+
142
+ // "if [salt] not provided, is set to a string of HashLen zeroes."
143
+ if (\is_null($salt)) {
144
+ $salt = \str_repeat("\x00", $digest_length);
145
+ }
146
+
147
+ // HKDF-Extract:
148
+ // PRK = HMAC-Hash(salt, IKM)
149
+ // The salt is the HMAC key.
150
+ $prk = \hash_hmac($hash, $ikm, $salt, true);
151
+
152
+ // HKDF-Expand:
153
+
154
+ // This check is useless, but it serves as a reminder to the spec.
155
+ if (Core::ourStrlen($prk) < $digest_length) {
156
+ throw new Ex\EnvironmentIsBrokenException();
157
+ }
158
+
159
+ // T(0) = ''
160
+ $t = '';
161
+ $last_block = '';
162
+ for ($block_index = 1; Core::ourStrlen($t) < $length; ++$block_index) {
163
+ // T(i) = HMAC-Hash(PRK, T(i-1) | info | 0x??)
164
+ $last_block = \hash_hmac(
165
+ $hash,
166
+ $last_block . $info . \chr($block_index),
167
+ $prk,
168
+ true
169
+ );
170
+ // T = T(1) | T(2) | T(3) | ... | T(N)
171
+ $t .= $last_block;
172
+ }
173
+
174
+ // ORM = first L octets of T
175
+ $orm = Core::ourSubstr($t, 0, $length);
176
+ if ($orm === false) {
177
+ throw new Ex\EnvironmentIsBrokenException();
178
+ }
179
+ return $orm;
180
+ }
181
+
182
+ /**
183
+ * Checks if two equal-length strings are the same without leaking
184
+ * information through side channels.
185
+ *
186
+ * @param string $expected
187
+ * @param string $given
188
+ *
189
+ * @throws Ex\EnvironmentIsBrokenException
190
+ *
191
+ * @return bool
192
+ */
193
+ public static function hashEquals($expected, $given)
194
+ {
195
+ static $native = null;
196
+ if ($native === null) {
197
+ $native = \function_exists('hash_equals');
198
+ }
199
+ if ($native) {
200
+ return \hash_equals($expected, $given);
201
+ }
202
+
203
+ // We can't just compare the strings with '==', since it would make
204
+ // timing attacks possible. We could use the XOR-OR constant-time
205
+ // comparison algorithm, but that may not be a reliable defense in an
206
+ // interpreted language. So we use the approach of HMACing both strings
207
+ // with a random key and comparing the HMACs.
208
+
209
+ // We're not attempting to make variable-length string comparison
210
+ // secure, as that's very difficult. Make sure the strings are the same
211
+ // length.
212
+ if (Core::ourStrlen($expected) !== Core::ourStrlen($given)) {
213
+ throw new Ex\EnvironmentIsBrokenException();
214
+ }
215
+
216
+ $blind = Core::secureRandom(32);
217
+ $message_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $given, $blind);
218
+ $correct_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $expected, $blind);
219
+ return $correct_compare === $message_compare;
220
+ }
221
+ /**
222
+ * Throws an exception if the constant doesn't exist.
223
+ *
224
+ * @param string $name
225
+ *
226
+ * @throws Ex\EnvironmentIsBrokenException
227
+ */
228
+ public static function ensureConstantExists($name)
229
+ {
230
+ if (! \defined($name)) {
231
+ throw new Ex\EnvironmentIsBrokenException();
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Throws an exception if the function doesn't exist.
237
+ *
238
+ * @param string $name
239
+ *
240
+ * @throws Ex\EnvironmentIsBrokenException
241
+ */
242
+ public static function ensureFunctionExists($name)
243
+ {
244
+ if (! \function_exists($name)) {
245
+ throw new Ex\EnvironmentIsBrokenException();
246
+ }
247
+ }
248
+
249
+ /*
250
+ * We need these strlen() and substr() functions because when
251
+ * 'mbstring.func_overload' is set in php.ini, the standard strlen() and
252
+ * substr() are replaced by mb_strlen() and mb_substr().
253
+ */
254
+
255
+ /**
256
+ * Computes the length of a string in bytes.
257
+ *
258
+ * @param string $str
259
+ *
260
+ * @throws Ex\EnvironmentIsBrokenException
261
+ *
262
+ * @return int
263
+ */
264
+ public static function ourStrlen($str)
265
+ {
266
+ static $exists = null;
267
+ if ($exists === null) {
268
+ $exists = \function_exists('mb_strlen');
269
+ }
270
+ if ($exists) {
271
+ $length = \mb_strlen($str, '8bit');
272
+ if ($length === false) {
273
+ throw new Ex\EnvironmentIsBrokenException();
274
+ }
275
+ return $length;
276
+ } else {
277
+ return \strlen($str);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Behaves roughly like the function substr() in PHP 7 does.
283
+ *
284
+ * @param string $str
285
+ * @param int $start
286
+ * @param int $length
287
+ *
288
+ * @throws Ex\EnvironmentIsBrokenException
289
+ *
290
+ * @return string
291
+ */
292
+ public static function ourSubstr($str, $start, $length = null)
293
+ {
294
+ static $exists = null;
295
+ if ($exists === null) {
296
+ $exists = \function_exists('mb_substr');
297
+ }
298
+
299
+ if ($exists) {
300
+ // mb_substr($str, 0, NULL, '8bit') returns an empty string on PHP
301
+ // 5.3, so we have to find the length ourselves.
302
+ if (! isset($length)) {
303
+ if ($start >= 0) {
304
+ $length = Core::ourStrlen($str) - $start;
305
+ } else {
306
+ $length = -$start;
307
+ }
308
+ }
309
+
310
+ // This is required to make mb_substr behavior identical to substr.
311
+ // Without this, mb_substr() would return false, contra to what the
312
+ // PHP documentation says (it doesn't say it can return false.)
313
+ if ($start === Core::ourStrlen($str) && $length === 0) {
314
+ return '';
315
+ }
316
+
317
+ if ($start > Core::ourStrlen($str)) {
318
+ return false;
319
+ }
320
+
321
+ $substr = \mb_substr($str, $start, $length, '8bit');
322
+ if (Core::ourStrlen($substr) !== $length) {
323
+ throw new Ex\EnvironmentIsBrokenException(
324
+ 'Your version of PHP has bug #66797. Its implementation of
325
+ mb_substr() is incorrect. See the details here:
326
+ https://bugs.php.net/bug.php?id=66797'
327
+ );
328
+ }
329
+ return $substr;
330
+ }
331
+
332
+ // Unlike mb_substr(), substr() doesn't accept NULL for length
333
+ if (isset($length)) {
334
+ return \substr($str, $start, $length);
335
+ } else {
336
+ return \substr($str, $start);
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Computes the PBKDF2 password-based key derivation function.
342
+ *
343
+ * The PBKDF2 function is defined in RFC 2898. Test vectors can be found in
344
+ * RFC 6070. This implementation of PBKDF2 was originally created by Taylor
345
+ * Hornby, with improvements from http://www.variations-of-shadow.com/.
346
+ *
347
+ * @param string $algorithm The hash algorithm to use. Recommended: SHA256
348
+ * @param string $password The password.
349
+ * @param string $salt A salt that is unique to the password.
350
+ * @param int $count Iteration count. Higher is better, but slower. Recommended: At least 1000.
351
+ * @param int $key_length The length of the derived key in bytes.
352
+ * @param bool $raw_output If true, the key is returned in raw binary format. Hex encoded otherwise.
353
+ *
354
+ * @throws Ex\EnvironmentIsBrokenException
355
+ *
356
+ * @return string A $key_length-byte key derived from the password and salt.
357
+ */
358
+ public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
359
+ {
360
+ // Type checks:
361
+ if (! \is_string($algorithm)) {
362
+ throw new \InvalidArgumentException(
363
+ 'pbkdf2(): algorithm must be a string'
364
+ );
365
+ }
366
+ if (! \is_string($password)) {
367
+ throw new \InvalidArgumentException(
368
+ 'pbkdf2(): password must be a string'
369
+ );
370
+ }
371
+ if (! \is_string($salt)) {
372
+ throw new \InvalidArgumentException(
373
+ 'pbkdf2(): salt must be a string'
374
+ );
375
+ }
376
+ // Coerce strings to integers with no information loss or overflow
377
+ $count += 0;
378
+ $key_length += 0;
379
+
380
+ $algorithm = \strtolower($algorithm);
381
+ if (! \in_array($algorithm, \hash_algos(), true)) {
382
+ throw new Ex\EnvironmentIsBrokenException(
383
+ 'Invalid or unsupported hash algorithm.'
384
+ );
385
+ }
386
+
387
+ // Whitelist, or we could end up with people using CRC32.
388
+ $ok_algorithms = [
389
+ 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
390
+ 'ripemd160', 'ripemd256', 'ripemd320', 'whirlpool',
391
+ ];
392
+ if (! \in_array($algorithm, $ok_algorithms, true)) {
393
+ throw new Ex\EnvironmentIsBrokenException(
394
+ 'Algorithm is not a secure cryptographic hash function.'
395
+ );
396
+ }
397
+
398
+ if ($count <= 0 || $key_length <= 0) {
399
+ throw new Ex\EnvironmentIsBrokenException(
400
+ 'Invalid PBKDF2 parameters.'
401
+ );
402
+ }
403
+
404
+ if (\function_exists('hash_pbkdf2')) {
405
+ // The output length is in NIBBLES (4-bits) if $raw_output is false!
406
+ if (! $raw_output) {
407
+ $key_length = $key_length * 2;
408
+ }
409
+ return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
410
+ }
411
+
412
+ $hash_length = Core::ourStrlen(\hash($algorithm, '', true));
413
+ $block_count = \ceil($key_length / $hash_length);
414
+
415
+ $output = '';
416
+ for ($i = 1; $i <= $block_count; $i++) {
417
+ // $i encoded as 4 bytes, big endian.
418
+ $last = $salt . \pack('N', $i);
419
+ // first iteration
420
+ $last = $xorsum = \hash_hmac($algorithm, $last, $password, true);
421
+ // perform the other $count - 1 iterations
422
+ for ($j = 1; $j < $count; $j++) {
423
+ $xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
424
+ }
425
+ $output .= $xorsum;
426
+ }
427
+
428
+ if ($raw_output) {
429
+ return Core::ourSubstr($output, 0, $key_length);
430
+ } else {
431
+ return Encoding::binToHex(Core::ourSubstr($output, 0, $key_length));
432
+ }
433
+ }
434
+ }
src/vendor/defuse/php-encryption/src/Crypto.php ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ class Crypto
8
+ {
9
+ /**
10
+ * Encrypts a string with a Key.
11
+ *
12
+ * @param string $plaintext
13
+ * @param Key $key
14
+ * @param bool $raw_binary
15
+ *
16
+ * @throws Ex\EnvironmentIsBrokenException
17
+ *
18
+ * @return string
19
+ */
20
+ public static function encrypt($plaintext, Key $key, $raw_binary = false)
21
+ {
22
+ return self::encryptInternal(
23
+ $plaintext,
24
+ KeyOrPassword::createFromKey($key),
25
+ $raw_binary
26
+ );
27
+ }
28
+
29
+ /**
30
+ * Encrypts a string with a password, using a slow key derivation function
31
+ * to make password cracking more expensive.
32
+ *
33
+ * @param string $plaintext
34
+ * @param string $password
35
+ * @param bool $raw_binary
36
+ *
37
+ * @throws Ex\EnvironmentIsBrokenException
38
+ *
39
+ * @return string
40
+ */
41
+ public static function encryptWithPassword($plaintext, $password, $raw_binary = false)
42
+ {
43
+ return self::encryptInternal(
44
+ $plaintext,
45
+ KeyOrPassword::createFromPassword($password),
46
+ $raw_binary
47
+ );
48
+ }
49
+
50
+ /**
51
+ * Decrypts a ciphertext to a string with a Key.
52
+ *
53
+ * @param string $ciphertext
54
+ * @param Key $key
55
+ * @param bool $raw_binary
56
+ *
57
+ * @throws Ex\EnvironmentIsBrokenException
58
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
59
+ *
60
+ * @return string
61
+ */
62
+ public static function decrypt($ciphertext, Key $key, $raw_binary = false)
63
+ {
64
+ return self::decryptInternal(
65
+ $ciphertext,
66
+ KeyOrPassword::createFromKey($key),
67
+ $raw_binary
68
+ );
69
+ }
70
+
71
+ /**
72
+ * Decrypts a ciphertext to a string with a password, using a slow key
73
+ * derivation function to make password cracking more expensive.
74
+ *
75
+ * @param string $ciphertext
76
+ * @param string $password
77
+ * @param bool $raw_binary
78
+ *
79
+ * @throws Ex\EnvironmentIsBrokenException
80
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
81
+ *
82
+ * @return string
83
+ */
84
+ public static function decryptWithPassword($ciphertext, $password, $raw_binary = false)
85
+ {
86
+ return self::decryptInternal(
87
+ $ciphertext,
88
+ KeyOrPassword::createFromPassword($password),
89
+ $raw_binary
90
+ );
91
+ }
92
+
93
+ /**
94
+ * Decrypts a legacy ciphertext produced by version 1 of this library.
95
+ *
96
+ * @param string $ciphertext
97
+ * @param string $key
98
+ *
99
+ * @throws Ex\EnvironmentIsBrokenException
100
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
101
+ *
102
+ * @return string
103
+ */
104
+ public static function legacyDecrypt($ciphertext, $key)
105
+ {
106
+ RuntimeTests::runtimeTest();
107
+
108
+ // Extract the HMAC from the front of the ciphertext.
109
+ if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) {
110
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
111
+ 'Ciphertext is too short.'
112
+ );
113
+ }
114
+ $hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE);
115
+ if ($hmac === false) {
116
+ throw new Ex\EnvironmentIsBrokenException();
117
+ }
118
+ $ciphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE);
119
+ if ($ciphertext === false) {
120
+ throw new Ex\EnvironmentIsBrokenException();
121
+ }
122
+
123
+ // Regenerate the same authentication sub-key.
124
+ $akey = Core::HKDF(
125
+ Core::LEGACY_HASH_FUNCTION_NAME,
126
+ $key,
127
+ Core::LEGACY_KEY_BYTE_SIZE,
128
+ Core::LEGACY_AUTHENTICATION_INFO_STRING,
129
+ null
130
+ );
131
+
132
+ if (self::verifyHMAC($hmac, $ciphertext, $akey)) {
133
+ // Regenerate the same encryption sub-key.
134
+ $ekey = Core::HKDF(
135
+ Core::LEGACY_HASH_FUNCTION_NAME,
136
+ $key,
137
+ Core::LEGACY_KEY_BYTE_SIZE,
138
+ Core::LEGACY_ENCRYPTION_INFO_STRING,
139
+ null
140
+ );
141
+
142
+ // Extract the IV from the ciphertext.
143
+ if (Core::ourStrlen($ciphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) {
144
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
145
+ 'Ciphertext is too short.'
146
+ );
147
+ }
148
+ $iv = Core::ourSubstr($ciphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE);
149
+ if ($iv === false) {
150
+ throw new Ex\EnvironmentIsBrokenException();
151
+ }
152
+ $ciphertext = Core::ourSubstr($ciphertext, Core::LEGACY_BLOCK_BYTE_SIZE);
153
+ if ($ciphertext === false) {
154
+ throw new Ex\EnvironmentIsBrokenException();
155
+ }
156
+
157
+ // Do the decryption.
158
+ $plaintext = self::plainDecrypt($ciphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD);
159
+ return $plaintext;
160
+ } else {
161
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
162
+ 'Integrity check failed.'
163
+ );
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Encrypts a string with either a key or a password.
169
+ *
170
+ * @param string $plaintext
171
+ * @param KeyOrPassword $secret
172
+ * @param bool $raw_binary
173
+ *
174
+ * @return string
175
+ */
176
+ private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary)
177
+ {
178
+ RuntimeTests::runtimeTest();
179
+
180
+ $salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
181
+ $keys = $secret->deriveKeys($salt);
182
+ $ekey = $keys->getEncryptionKey();
183
+ $akey = $keys->getAuthenticationKey();
184
+ $iv = Core::secureRandom(Core::BLOCK_BYTE_SIZE);
185
+
186
+ $ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv);
187
+ $auth = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true);
188
+ $ciphertext = $ciphertext . $auth;
189
+
190
+ if ($raw_binary) {
191
+ return $ciphertext;
192
+ }
193
+ return Encoding::binToHex($ciphertext);
194
+ }
195
+
196
+ /**
197
+ * Decrypts a ciphertext to a string with either a key or a password.
198
+ *
199
+ * @param string $ciphertext
200
+ * @param KeyOrPassword $secret
201
+ * @param bool $raw_binary
202
+ *
203
+ * @throws Ex\EnvironmentIsBrokenException
204
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
205
+ *
206
+ * @return string
207
+ */
208
+ private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary)
209
+ {
210
+ RuntimeTests::runtimeTest();
211
+
212
+ if (! $raw_binary) {
213
+ try {
214
+ $ciphertext = Encoding::hexToBin($ciphertext);
215
+ } catch (Ex\BadFormatException $ex) {
216
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
217
+ 'Ciphertext has invalid hex encoding.'
218
+ );
219
+ }
220
+ }
221
+
222
+ if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) {
223
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
224
+ 'Ciphertext is too short.'
225
+ );
226
+ }
227
+
228
+ // Get and check the version header.
229
+ $header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE);
230
+ if ($header !== Core::CURRENT_VERSION) {
231
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
232
+ 'Bad version header.'
233
+ );
234
+ }
235
+
236
+ // Get the salt.
237
+ $salt = Core::ourSubstr(
238
+ $ciphertext,
239
+ Core::HEADER_VERSION_SIZE,
240
+ Core::SALT_BYTE_SIZE
241
+ );
242
+ if ($salt === false) {
243
+ throw new Ex\EnvironmentIsBrokenException();
244
+ }
245
+
246
+ // Get the IV.
247
+ $iv = Core::ourSubstr(
248
+ $ciphertext,
249
+ Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,
250
+ Core::BLOCK_BYTE_SIZE
251
+ );
252
+ if ($iv === false) {
253
+ throw new Ex\EnvironmentIsBrokenException();
254
+ }
255
+
256
+ // Get the HMAC.
257
+ $hmac = Core::ourSubstr(
258
+ $ciphertext,
259
+ Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,
260
+ Core::MAC_BYTE_SIZE
261
+ );
262
+ if ($hmac === false) {
263
+ throw new Ex\EnvironmentIsBrokenException();
264
+ }
265
+
266
+ // Get the actual encrypted ciphertext.
267
+ $encrypted = Core::ourSubstr(
268
+ $ciphertext,
269
+ Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE +
270
+ Core::BLOCK_BYTE_SIZE,
271
+ Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE -
272
+ Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE
273
+ );
274
+ if ($encrypted === false) {
275
+ throw new Ex\EnvironmentIsBrokenException();
276
+ }
277
+
278
+ // Derive the separate encryption and authentication keys from the key
279
+ // or password, whichever it is.
280
+ $keys = $secret->deriveKeys($salt);
281
+
282
+ if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) {
283
+ $plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD);
284
+ return $plaintext;
285
+ } else {
286
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
287
+ 'Integrity check failed.'
288
+ );
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Raw unauthenticated encryption (insecure on its own).
294
+ *
295
+ * @param string $plaintext
296
+ * @param string $key
297
+ * @param string $iv
298
+ *
299
+ * @throws Ex\EnvironmentIsBrokenException
300
+ *
301
+ * @return string
302
+ */
303
+ protected static function plainEncrypt($plaintext, $key, $iv)
304
+ {
305
+ Core::ensureConstantExists('OPENSSL_RAW_DATA');
306
+ Core::ensureFunctionExists('openssl_encrypt');
307
+ $ciphertext = \openssl_encrypt(
308
+ $plaintext,
309
+ Core::CIPHER_METHOD,
310
+ $key,
311
+ OPENSSL_RAW_DATA,
312
+ $iv
313
+ );
314
+
315
+ if ($ciphertext === false) {
316
+ throw new Ex\EnvironmentIsBrokenException(
317
+ 'openssl_encrypt() failed.'
318
+ );
319
+ }
320
+
321
+ return $ciphertext;
322
+ }
323
+
324
+ /**
325
+ * Raw unauthenticated decryption (insecure on its own).
326
+ *
327
+ * @param string $ciphertext
328
+ * @param string $key
329
+ * @param string $iv
330
+ * @param string $cipherMethod
331
+ *
332
+ * @throws Ex\EnvironmentIsBrokenException
333
+ *
334
+ * @return string
335
+ */
336
+ protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod)
337
+ {
338
+ Core::ensureConstantExists('OPENSSL_RAW_DATA');
339
+ Core::ensureFunctionExists('openssl_decrypt');
340
+ $plaintext = \openssl_decrypt(
341
+ $ciphertext,
342
+ $cipherMethod,
343
+ $key,
344
+ OPENSSL_RAW_DATA,
345
+ $iv
346
+ );
347
+ if ($plaintext === false) {
348
+ throw new Ex\EnvironmentIsBrokenException(
349
+ 'openssl_decrypt() failed.'
350
+ );
351
+ }
352
+
353
+ return $plaintext;
354
+ }
355
+
356
+ /**
357
+ * Verifies an HMAC without leaking information through side-channels.
358
+ *
359
+ * @param string $correct_hmac
360
+ * @param string $message
361
+ * @param string $key
362
+ *
363
+ * @throws Ex\EnvironmentIsBrokenException
364
+ *
365
+ * @return bool
366
+ */
367
+ protected static function verifyHMAC($correct_hmac, $message, $key)
368
+ {
369
+ $message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
370
+ return Core::hashEquals($correct_hmac, $message_hmac);
371
+ }
372
+ }
src/vendor/defuse/php-encryption/src/DerivedKeys.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ final class DerivedKeys
6
+ {
7
+ private $akey = null;
8
+ private $ekey = null;
9
+
10
+ /**
11
+ * Returns the authentication key.
12
+ */
13
+ public function getAuthenticationKey()
14
+ {
15
+ return $this->akey;
16
+ }
17
+
18
+ /**
19
+ * Returns the encryption key.
20
+ */
21
+ public function getEncryptionKey()
22
+ {
23
+ return $this->ekey;
24
+ }
25
+
26
+ /**
27
+ * Constructor for DerivedKeys.
28
+ *
29
+ * @param string $akey
30
+ * @param string $ekey
31
+ */
32
+ public function __construct($akey, $ekey)
33
+ {
34
+ $this->akey = $akey;
35
+ $this->ekey = $ekey;
36
+ }
37
+ }
src/vendor/defuse/php-encryption/src/Encoding.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ final class Encoding
8
+ {
9
+ const CHECKSUM_BYTE_SIZE = 32;
10
+ const CHECKSUM_HASH_ALGO = 'sha256';
11
+ const SERIALIZE_HEADER_BYTES = 4;
12
+
13
+ /**
14
+ * Converts a byte string to a hexadecimal string without leaking
15
+ * information through side channels.
16
+ *
17
+ * @param string $byte_string
18
+ *
19
+ * @throws Ex\EnvironmentIsBrokenException
20
+ *
21
+ * @return string
22
+ */
23
+ public static function binToHex($byte_string)
24
+ {
25
+ $hex = '';
26
+ $len = Core::ourStrlen($byte_string);
27
+ for ($i = 0; $i < $len; ++$i) {
28
+ $c = \ord($byte_string[$i]) & 0xf;
29
+ $b = \ord($byte_string[$i]) >> 4;
30
+ $hex .= \pack(
31
+ 'CC',
32
+ 87 + $b + ((($b - 10) >> 8) & ~38),
33
+ 87 + $c + ((($c - 10) >> 8) & ~38)
34
+ );
35
+ }
36
+ return $hex;
37
+ }
38
+
39
+ /**
40
+ * Converts a hexadecimal string into a byte string without leaking
41
+ * information through side channels.
42
+ *
43
+ * @param string $hex_string
44
+ *
45
+ * @throws Ex\BadFormatException
46
+ * @throws Ex\EnvironmentIsBrokenException
47
+ *
48
+ * @return string
49
+ */
50
+ public static function hexToBin($hex_string)
51
+ {
52
+ $hex_pos = 0;
53
+ $bin = '';
54
+ $hex_len = Core::ourStrlen($hex_string);
55
+ $state = 0;
56
+ $c_acc = 0;
57
+
58
+ while ($hex_pos < $hex_len) {
59
+ $c = \ord($hex_string[$hex_pos]);
60
+ $c_num = $c ^ 48;
61
+ $c_num0 = ($c_num - 10) >> 8;
62
+ $c_alpha = ($c & ~32) - 55;
63
+ $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
64
+ if (($c_num0 | $c_alpha0) === 0) {
65
+ throw new Ex\BadFormatException(
66
+ 'Encoding::hexToBin() input is not a hex string.'
67
+ );
68
+ }
69
+ $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
70
+ if ($state === 0) {
71
+ $c_acc = $c_val * 16;
72
+ } else {
73
+ $bin .= \pack('C', $c_acc | $c_val);
74
+ }
75
+ $state ^= 1;
76
+ ++$hex_pos;
77
+ }
78
+ return $bin;
79
+ }
80
+
81
+ /*
82
+ * SECURITY NOTE ON APPLYING CHECKSUMS TO SECRETS:
83
+ *
84
+ * The checksum introduces a potential security weakness. For example,
85
+ * suppose we apply a checksum to a key, and that an adversary has an
86
+ * exploit against the process containing the key, such that they can
87
+ * overwrite an arbitrary byte of memory and then cause the checksum to
88
+ * be verified and learn the result.
89
+ *
90
+ * In this scenario, the adversary can extract the key one byte at
91
+ * a time by overwriting it with their guess of its value and then
92
+ * asking if the checksum matches. If it does, their guess was right.
93
+ * This kind of attack may be more easy to implement and more reliable
94
+ * than a remote code execution attack.
95
+ *
96
+ * This attack also applies to authenticated encryption as a whole, in
97
+ * the situation where the adversary can overwrite a byte of the key
98
+ * and then cause a valid ciphertext to be decrypted, and then
99
+ * determine whether the MAC check passed or failed.
100
+ *
101
+ * By using the full SHA256 hash instead of truncating it, I'm ensuring
102
+ * that both ways of going about the attack are equivalently difficult.
103
+ * A shorter checksum of say 32 bits might be more useful to the
104
+ * adversary as an oracle in case their writes are coarser grained.
105
+ *
106
+ * Because the scenario assumes a serious vulnerability, we don't try
107
+ * to prevent attacks of this style.
108
+ */
109
+
110
+ /**
111
+ * INTERNAL USE ONLY: Applies a version header, applies a checksum, and
112
+ * then encodes a byte string into a range of printable ASCII characters.
113
+ *
114
+ * @param string $header
115
+ * @param string $bytes
116
+ *
117
+ * @throws Ex\EnvironmentIsBrokenException
118
+ *
119
+ * @return string
120
+ */
121
+ public static function saveBytesToChecksummedAsciiSafeString($header, $bytes)
122
+ {
123
+ // Headers must be a constant length to prevent one type's header from
124
+ // being a prefix of another type's header, leading to ambiguity.
125
+ if (Core::ourStrlen($header) !== self::SERIALIZE_HEADER_BYTES) {
126
+ throw new Ex\EnvironmentIsBrokenException(
127
+ 'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.'
128
+ );
129
+ }
130
+
131
+ return Encoding::binToHex(
132
+ $header .
133
+ $bytes .
134
+ \hash(
135
+ self::CHECKSUM_HASH_ALGO,
136
+ $header . $bytes,
137
+ true
138
+ )
139
+ );
140
+ }
141
+
142
+ /**
143
+ * INTERNAL USE ONLY: Decodes, verifies the header and checksum, and returns
144
+ * the encoded byte string.
145
+ *
146
+ * @param string $expected_header
147
+ * @param string $string
148
+ *
149
+ * @throws Ex\EnvironmentIsBrokenException
150
+ * @throws Ex\BadFormatException
151
+ *
152
+ * @return string
153
+ */
154
+ public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string)
155
+ {
156
+ // Headers must be a constant length to prevent one type's header from
157
+ // being a prefix of another type's header, leading to ambiguity.
158
+ if (Core::ourStrlen($expected_header) !== self::SERIALIZE_HEADER_BYTES) {
159
+ throw new Ex\EnvironmentIsBrokenException(
160
+ 'Header must be 4 bytes.'
161
+ );
162
+ }
163
+
164
+ $bytes = Encoding::hexToBin($string);
165
+
166
+ /* Make sure we have enough bytes to get the version header and checksum. */
167
+ if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) {
168
+ throw new Ex\BadFormatException(
169
+ 'Encoded data is shorter than expected.'
170
+ );
171
+ }
172
+
173
+ /* Grab the version header. */
174
+ $actual_header = Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES);
175
+
176
+ if ($actual_header !== $expected_header) {
177
+ throw new Ex\BadFormatException(
178
+ 'Invalid header.'
179
+ );
180
+ }
181
+
182
+ /* Grab the bytes that are part of the checksum. */
183
+ $checked_bytes = Core::ourSubstr(
184
+ $bytes,
185
+ 0,
186
+ Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE
187
+ );
188
+
189
+ /* Grab the included checksum. */
190
+ $checksum_a = Core::ourSubstr(
191
+ $bytes,
192
+ Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE,
193
+ self::CHECKSUM_BYTE_SIZE
194
+ );
195
+
196
+ /* Re-compute the checksum. */
197
+ $checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true);
198
+
199
+ /* Check if the checksum matches. */
200
+ if (! Core::hashEquals($checksum_a, $checksum_b)) {
201
+ throw new Ex\BadFormatException(
202
+ "Data is corrupted, the checksum doesn't match"
203
+ );
204
+ }
205
+
206
+ return Core::ourSubstr(
207
+ $bytes,
208
+ self::SERIALIZE_HEADER_BYTES,
209
+ Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE
210
+ );
211
+ }
212
+ }
src/vendor/defuse/php-encryption/src/Exception/BadFormatException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto\Exception;
4
+
5
+ class BadFormatException extends \Defuse\Crypto\Exception\CryptoException
6
+ {
7
+ }
src/vendor/defuse/php-encryption/src/Exception/CryptoException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto\Exception;
4
+
5
+ class CryptoException extends \Exception
6
+ {
7
+ }
src/vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto\Exception;
4
+
5
+ class EnvironmentIsBrokenException extends \Defuse\Crypto\Exception\CryptoException
6
+ {
7
+ }
src/vendor/defuse/php-encryption/src/Exception/IOException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto\Exception;
4
+
5
+ class IOException extends \Defuse\Crypto\Exception\CryptoException
6
+ {
7
+ }
src/vendor/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto\Exception;
4
+
5
+ class WrongKeyOrModifiedCiphertextException extends \Defuse\Crypto\Exception\CryptoException
6
+ {
7
+ }
src/vendor/defuse/php-encryption/src/File.php ADDED
@@ -0,0 +1,755 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ final class File
8
+ {
9
+ /**
10
+ * Encrypts the input file, saving the ciphertext to the output file.
11
+ *
12
+ * @param string $inputFilename
13
+ * @param string $outputFilename
14
+ * @param Key $key
15
+ *
16
+ * @throws Ex\EnvironmentIsBrokenException
17
+ * @throws Ex\IOException
18
+ */
19
+ public static function encryptFile($inputFilename, $outputFilename, Key $key)
20
+ {
21
+ self::encryptFileInternal(
22
+ $inputFilename,
23
+ $outputFilename,
24
+ KeyOrPassword::createFromKey($key)
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Encrypts a file with a password, using a slow key derivation function to
30
+ * make password cracking more expensive.
31
+ *
32
+ * @param string $inputFilename
33
+ * @param string $outputFilename
34
+ * @param string $password
35
+ *
36
+ * @throws Ex\EnvironmentIsBrokenException
37
+ * @throws Ex\IOException
38
+ */
39
+ public static function encryptFileWithPassword($inputFilename, $outputFilename, $password)
40
+ {
41
+ self::encryptFileInternal(
42
+ $inputFilename,
43
+ $outputFilename,
44
+ KeyOrPassword::createFromPassword($password)
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Decrypts the input file, saving the plaintext to the output file.
50
+ *
51
+ * @param string $inputFilename
52
+ * @param string $outputFilename
53
+ * @param Key $key
54
+ *
55
+ * @throws Ex\EnvironmentIsBrokenException
56
+ * @throws Ex\IOException
57
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
58
+ */
59
+ public static function decryptFile($inputFilename, $outputFilename, Key $key)
60
+ {
61
+ self::decryptFileInternal(
62
+ $inputFilename,
63
+ $outputFilename,
64
+ KeyOrPassword::createFromKey($key)
65
+ );
66
+ }
67
+
68
+ /**
69
+ * Decrypts a file with a password, using a slow key derivation function to
70
+ * make password cracking more expensive.
71
+ *
72
+ * @param string $inputFilename
73
+ * @param string $outputFilename
74
+ * @param string $password
75
+ *
76
+ * @throws Ex\EnvironmentIsBrokenException
77
+ * @throws Ex\IOException
78
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
79
+ */
80
+ public static function decryptFileWithPassword($inputFilename, $outputFilename, $password)
81
+ {
82
+ self::decryptFileInternal(
83
+ $inputFilename,
84
+ $outputFilename,
85
+ KeyOrPassword::createFromPassword($password)
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Takes two resource handles and encrypts the contents of the first,
91
+ * writing the ciphertext into the second.
92
+ *
93
+ * @param resource $inputHandle
94
+ * @param resource $outputHandle
95
+ * @param Key $key
96
+ *
97
+ * @throws Ex\EnvironmentIsBrokenException
98
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
99
+ */
100
+ public static function encryptResource($inputHandle, $outputHandle, Key $key)
101
+ {
102
+ self::encryptResourceInternal(
103
+ $inputHandle,
104
+ $outputHandle,
105
+ KeyOrPassword::createFromKey($key)
106
+ );
107
+ }
108
+
109
+ /**
110
+ * Encrypts the contents of one resource handle into another with a
111
+ * password, using a slow key derivation function to make password cracking
112
+ * more expensive.
113
+ *
114
+ * @param resource $inputHandle
115
+ * @param resource $outputHandle
116
+ * @param string $password
117
+ *
118
+ * @throws Ex\EnvironmentIsBrokenException
119
+ * @throws Ex\IOException
120
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
121
+ */
122
+ public static function encryptResourceWithPassword($inputHandle, $outputHandle, $password)
123
+ {
124
+ self::encryptResourceInternal(
125
+ $inputHandle,
126
+ $outputHandle,
127
+ KeyOrPassword::createFromPassword($password)
128
+ );
129
+ }
130
+
131
+ /**
132
+ * Takes two resource handles and decrypts the contents of the first,
133
+ * writing the plaintext into the second.
134
+ *
135
+ * @param resource $inputHandle
136
+ * @param resource $outputHandle
137
+ * @param Key $key
138
+ *
139
+ * @throws Ex\EnvironmentIsBrokenException
140
+ * @throws Ex\IOException
141
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
142
+ */
143
+ public static function decryptResource($inputHandle, $outputHandle, Key $key)
144
+ {
145
+ self::decryptResourceInternal(
146
+ $inputHandle,
147
+ $outputHandle,
148
+ KeyOrPassword::createFromKey($key)
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Decrypts the contents of one resource into another with a password, using
154
+ * a slow key derivation function to make password cracking more expensive.
155
+ *
156
+ * @param resource $inputHandle
157
+ * @param resource $outputHandle
158
+ * @param string $password
159
+ *
160
+ * @throws Ex\EnvironmentIsBrokenException
161
+ * @throws Ex\IOException
162
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
163
+ */
164
+ public static function decryptResourceWithPassword($inputHandle, $outputHandle, $password)
165
+ {
166
+ self::decryptResourceInternal(
167
+ $inputHandle,
168
+ $outputHandle,
169
+ KeyOrPassword::createFromPassword($password)
170
+ );
171
+ }
172
+
173
+ /**
174
+ * Encrypts a file with either a key or a password.
175
+ *
176
+ * @param string $inputFilename
177
+ * @param string $outputFilename
178
+ * @param KeyOrPassword $secret
179
+ *
180
+ * @throws Ex\CryptoException
181
+ * @throws Ex\IOException
182
+ */
183
+ private static function encryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
184
+ {
185
+ /* Open the input file. */
186
+ $if = @\fopen($inputFilename, 'rb');
187
+ if ($if === false) {
188
+ throw new Ex\IOException(
189
+ 'Cannot open input file for encrypting: ' .
190
+ self::getLastErrorMessage()
191
+ );
192
+ }
193
+ if (\is_callable('\\stream_set_read_buffer')) {
194
+ /* This call can fail, but the only consequence is performance. */
195
+ \stream_set_read_buffer($if, 0);
196
+ }
197
+
198
+ /* Open the output file. */
199
+ $of = @\fopen($outputFilename, 'wb');
200
+ if ($of === false) {
201
+ \fclose($if);
202
+ throw new Ex\IOException(
203
+ 'Cannot open output file for encrypting: ' .
204
+ self::getLastErrorMessage()
205
+ );
206
+ }
207
+ if (\is_callable('\\stream_set_write_buffer')) {
208
+ /* This call can fail, but the only consequence is performance. */
209
+ \stream_set_write_buffer($of, 0);
210
+ }
211
+
212
+ /* Perform the encryption. */
213
+ try {
214
+ self::encryptResourceInternal($if, $of, $secret);
215
+ } catch (Ex\CryptoException $ex) {
216
+ \fclose($if);
217
+ \fclose($of);
218
+ throw $ex;
219
+ }
220
+
221
+ /* Close the input file. */
222
+ if (\fclose($if) === false) {
223
+ \fclose($of);
224
+ throw new Ex\IOException(
225
+ 'Cannot close input file after encrypting'
226
+ );
227
+ }
228
+
229
+ /* Close the output file. */
230
+ if (\fclose($of) === false) {
231
+ throw new Ex\IOException(
232
+ 'Cannot close output file after encrypting'
233
+ );
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Decrypts a file with either a key or a password.
239
+ *
240
+ * @param string $inputFilename
241
+ * @param string $outputFilename
242
+ * @param KeyOrPassword $secret
243
+ *
244
+ * @throws Ex\CryptoException
245
+ * @throws Ex\IOException
246
+ */
247
+ private static function decryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
248
+ {
249
+ /* Open the input file. */
250
+ $if = @\fopen($inputFilename, 'rb');
251
+ if ($if === false) {
252
+ throw new Ex\IOException(
253
+ 'Cannot open input file for decrypting: ' .
254
+ self::getLastErrorMessage()
255
+ );
256
+ }
257
+
258
+ if (\is_callable('\\stream_set_read_buffer')) {
259
+ /* This call can fail, but the only consequence is performance. */
260
+ \stream_set_read_buffer($if, 0);
261
+ }
262
+
263
+ /* Open the output file. */
264
+ $of = @\fopen($outputFilename, 'wb');
265
+ if ($of === false) {
266
+ \fclose($if);
267
+ throw new Ex\IOException(
268
+ 'Cannot open output file for decrypting: ' .
269
+ self::getLastErrorMessage()
270
+ );
271
+ }
272
+
273
+ if (\is_callable('\\stream_set_write_buffer')) {
274
+ /* This call can fail, but the only consequence is performance. */
275
+ \stream_set_write_buffer($of, 0);
276
+ }
277
+
278
+ /* Perform the decryption. */
279
+ try {
280
+ self::decryptResourceInternal($if, $of, $secret);
281
+ } catch (Ex\CryptoException $ex) {
282
+ \fclose($if);
283
+ \fclose($of);
284
+ throw $ex;
285
+ }
286
+
287
+ /* Close the input file. */
288
+ if (\fclose($if) === false) {
289
+ \fclose($of);
290
+ throw new Ex\IOException(
291
+ 'Cannot close input file after decrypting'
292
+ );
293
+ }
294
+
295
+ /* Close the output file. */
296
+ if (\fclose($of) === false) {
297
+ throw new Ex\IOException(
298
+ 'Cannot close output file after decrypting'
299
+ );
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Encrypts a resource with either a key or a password.
305
+ *
306
+ * @param resource $inputHandle
307
+ * @param resource $outputHandle
308
+ * @param KeyOrPassword $secret
309
+ *
310
+ * @throws Ex\EnvironmentIsBrokenException
311
+ * @throws Ex\IOException
312
+ */
313
+ private static function encryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
314
+ {
315
+ if (! \is_resource($inputHandle)) {
316
+ throw new Ex\IOException(
317
+ 'Input handle must be a resource!'
318
+ );
319
+ }
320
+ if (! \is_resource($outputHandle)) {
321
+ throw new Ex\IOException(
322
+ 'Output handle must be a resource!'
323
+ );
324
+ }
325
+
326
+ $inputStat = \fstat($inputHandle);
327
+ $inputSize = $inputStat['size'];
328
+
329
+ $file_salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
330
+ $keys = $secret->deriveKeys($file_salt);
331
+ $ekey = $keys->getEncryptionKey();
332
+ $akey = $keys->getAuthenticationKey();
333
+
334
+ $ivsize = Core::BLOCK_BYTE_SIZE;
335
+ $iv = Core::secureRandom($ivsize);
336
+
337
+ /* Initialize a streaming HMAC state. */
338
+ $hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
339
+ if ($hmac === false) {
340
+ throw new Ex\EnvironmentIsBrokenException(
341
+ 'Cannot initialize a hash context'
342
+ );
343
+ }
344
+
345
+ /* Write the header, salt, and IV. */
346
+ self::writeBytes(
347
+ $outputHandle,
348
+ Core::CURRENT_VERSION . $file_salt . $iv,
349
+ Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize
350
+ );
351
+
352
+ /* Add the header, salt, and IV to the HMAC. */
353
+ \hash_update($hmac, Core::CURRENT_VERSION);
354
+ \hash_update($hmac, $file_salt);
355
+ \hash_update($hmac, $iv);
356
+
357
+ /* $thisIv will be incremented after each call to the encryption. */
358
+ $thisIv = $iv;
359
+
360
+ /* How many blocks do we encrypt at a time? We increment by this value. */
361
+ $inc = Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE;
362
+
363
+ /* Loop until we reach the end of the input file. */
364
+ $at_file_end = false;
365
+ while (! (\feof($inputHandle) || $at_file_end)) {
366
+ /* Find out if we can read a full buffer, or only a partial one. */
367
+ $pos = \ftell($inputHandle);
368
+ if ($pos === false) {
369
+ throw new Ex\IOException(
370
+ 'Could not get current position in input file during encryption'
371
+ );
372
+ }
373
+ if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {
374
+ /* We're at the end of the file, so we need to break out of the loop. */
375
+ $at_file_end = true;
376
+ $read = self::readBytes(
377
+ $inputHandle,
378
+ $inputSize - $pos
379
+ );
380
+ } else {
381
+ $read = self::readBytes(
382
+ $inputHandle,
383
+ Core::BUFFER_BYTE_SIZE
384
+ );
385
+ }
386
+
387
+ /* Encrypt this buffer. */
388
+ $encrypted = \openssl_encrypt(
389
+ $read,
390
+ Core::CIPHER_METHOD,
391
+ $ekey,
392
+ OPENSSL_RAW_DATA,
393
+ $thisIv
394
+ );
395
+
396
+ if ($encrypted === false) {
397
+ throw new Ex\EnvironmentIsBrokenException(
398
+ 'OpenSSL encryption error'
399
+ );
400
+ }
401
+
402
+ /* Write this buffer's ciphertext. */
403
+ self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));
404
+ /* Add this buffer's ciphertext to the HMAC. */
405
+ \hash_update($hmac, $encrypted);
406
+
407
+ /* Increment the counter by the number of blocks in a buffer. */
408
+ $thisIv = Core::incrementCounter($thisIv, $inc);
409
+ /* WARNING: Usually, unless the file is a multiple of the buffer
410
+ * size, $thisIv will contain an incorrect value here on the last
411
+ * iteration of this loop. */
412
+ }
413
+
414
+ /* Get the HMAC and append it to the ciphertext. */
415
+ $final_mac = \hash_final($hmac, true);
416
+ self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
417
+ }
418
+
419
+ /**
420
+ * Decrypts a file-backed resource with either a key or a password.
421
+ *
422
+ * @param resource $inputHandle
423
+ * @param resource $outputHandle
424
+ * @param KeyOrPassword $secret
425
+ *
426
+ * @throws Ex\EnvironmentIsBrokenException
427
+ * @throws Ex\IOException
428
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
429
+ */
430
+ public static function decryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
431
+ {
432
+ if (! \is_resource($inputHandle)) {
433
+ throw new Ex\IOException(
434
+ 'Input handle must be a resource!'
435
+ );
436
+ }
437
+ if (! \is_resource($outputHandle)) {
438
+ throw new Ex\IOException(
439
+ 'Output handle must be a resource!'
440
+ );
441
+ }
442
+
443
+ /* Make sure the file is big enough for all the reads we need to do. */
444
+ $stat = \fstat($inputHandle);
445
+ if ($stat['size'] < Core::MINIMUM_CIPHERTEXT_SIZE) {
446
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
447
+ 'Input file is too small to have been created by this library.'
448
+ );
449
+ }
450
+
451
+ /* Check the version header. */
452
+ $header = self::readBytes($inputHandle, Core::HEADER_VERSION_SIZE);
453
+ if ($header !== Core::CURRENT_VERSION) {
454
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
455
+ 'Bad version header.'
456
+ );
457
+ }
458
+
459
+ /* Get the salt. */
460
+ $file_salt = self::readBytes($inputHandle, Core::SALT_BYTE_SIZE);
461
+
462
+ /* Get the IV. */
463
+ $ivsize = Core::BLOCK_BYTE_SIZE;
464
+ $iv = self::readBytes($inputHandle, $ivsize);
465
+
466
+ /* Derive the authentication and encryption keys. */
467
+ $keys = $secret->deriveKeys($file_salt);
468
+ $ekey = $keys->getEncryptionKey();
469
+ $akey = $keys->getAuthenticationKey();
470
+
471
+ /* We'll store the MAC of each buffer-sized chunk as we verify the
472
+ * actual MAC, so that we can check them again when decrypting. */
473
+ $macs = [];
474
+
475
+ /* $thisIv will be incremented after each call to the decryption. */
476
+ $thisIv = $iv;
477
+
478
+ /* How many blocks do we encrypt at a time? We increment by this value. */
479
+ $inc = Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE;
480
+
481
+ /* Get the HMAC. */
482
+ if (\fseek($inputHandle, (-1 * Core::MAC_BYTE_SIZE), SEEK_END) === false) {
483
+ throw new Ex\IOException(
484
+ 'Cannot seek to beginning of MAC within input file'
485
+ );
486
+ }
487
+
488
+ /* Get the position of the last byte in the actual ciphertext. */
489
+ $cipher_end = \ftell($inputHandle);
490
+ if ($cipher_end === false) {
491
+ throw new Ex\IOException(
492
+ 'Cannot read input file'
493
+ );
494
+ }
495
+ /* We have the position of the first byte of the HMAC. Go back by one. */
496
+ --$cipher_end;
497
+
498
+ /* Read the HMAC. */
499
+ $stored_mac = self::readBytes($inputHandle, Core::MAC_BYTE_SIZE);
500
+
501
+ /* Initialize a streaming HMAC state. */
502
+ $hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
503
+ if ($hmac === false) {
504
+ throw new Ex\EnvironmentIsBrokenException(
505
+ 'Cannot initialize a hash context'
506
+ );
507
+ }
508
+
509
+ /* Reset file pointer to the beginning of the file after the header */
510
+ if (\fseek($inputHandle, Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
511
+ throw new Ex\IOException(
512
+ 'Cannot read seek within input file'
513
+ );
514
+ }
515
+
516
+ /* Seek to the start of the actual ciphertext. */
517
+ if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize, SEEK_CUR) === false) {
518
+ throw new Ex\IOException(
519
+ 'Cannot seek input file to beginning of ciphertext'
520
+ );
521
+ }
522
+
523
+ /* PASS #1: Calculating the HMAC. */
524
+
525
+ \hash_update($hmac, $header);
526
+ \hash_update($hmac, $file_salt);
527
+ \hash_update($hmac, $iv);
528
+ $hmac2 = \hash_copy($hmac);
529
+
530
+ $break = false;
531
+ while (! $break) {
532
+ $pos = \ftell($inputHandle);
533
+ if ($pos === false) {
534
+ throw new Ex\IOException(
535
+ 'Could not get current position in input file during decryption'
536
+ );
537
+ }
538
+
539
+ /* Read the next buffer-sized chunk (or less). */
540
+ if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
541
+ $break = true;
542
+ $read = self::readBytes(
543
+ $inputHandle,
544
+ $cipher_end - $pos + 1
545
+ );
546
+ } else {
547
+ $read = self::readBytes(
548
+ $inputHandle,
549
+ Core::BUFFER_BYTE_SIZE
550
+ );
551
+ }
552
+
553
+ /* Update the HMAC. */
554
+ \hash_update($hmac, $read);
555
+
556
+ /* Remember this buffer-sized chunk's HMAC. */
557
+ $chunk_mac = \hash_copy($hmac);
558
+ if ($chunk_mac === false) {
559
+ throw new Ex\EnvironmentIsBrokenException(
560
+ 'Cannot duplicate a hash context'
561
+ );
562
+ }
563
+ $macs []= \hash_final($chunk_mac);
564
+ }
565
+
566
+ /* Get the final HMAC, which should match the stored one. */
567
+ $final_mac = \hash_final($hmac, true);
568
+
569
+ /* Verify the HMAC. */
570
+ if (! Core::hashEquals($final_mac, $stored_mac)) {
571
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
572
+ 'Integrity check failed.'
573
+ );
574
+ }
575
+
576
+ /* PASS #2: Decrypt and write output. */
577
+
578
+ /* Rewind to the start of the actual ciphertext. */
579
+ if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize + Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
580
+ throw new Ex\IOException(
581
+ 'Could not move the input file pointer during decryption'
582
+ );
583
+ }
584
+
585
+ $at_file_end = false;
586
+ while (! $at_file_end) {
587
+ $pos = \ftell($inputHandle);
588
+ if ($pos === false) {
589
+ throw new Ex\IOException(
590
+ 'Could not get current position in input file during decryption'
591
+ );
592
+ }
593
+
594
+ /* Read the next buffer-sized chunk (or less). */
595
+ if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
596
+ $at_file_end = true;
597
+ $read = self::readBytes(
598
+ $inputHandle,
599
+ $cipher_end - $pos + 1
600
+ );
601
+ } else {
602
+ $read = self::readBytes(
603
+ $inputHandle,
604
+ Core::BUFFER_BYTE_SIZE
605
+ );
606
+ }
607
+
608
+ /* Recalculate the MAC (so far) and compare it with the one we
609
+ * remembered from pass #1 to ensure attackers didn't change the
610
+ * ciphertext after MAC verification. */
611
+ \hash_update($hmac2, $read);
612
+ $calc_mac = \hash_copy($hmac2);
613
+ if ($calc_mac === false) {
614
+ throw new Ex\EnvironmentIsBrokenException(
615
+ 'Cannot duplicate a hash context'
616
+ );
617
+ }
618
+ $calc = \hash_final($calc_mac);
619
+
620
+ if (empty($macs)) {
621
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
622
+ 'File was modified after MAC verification'
623
+ );
624
+ } elseif (! Core::hashEquals(\array_shift($macs), $calc)) {
625
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
626
+ 'File was modified after MAC verification'
627
+ );
628
+ }
629
+
630
+ /* Decrypt this buffer-sized chunk. */
631
+ $decrypted = \openssl_decrypt(
632
+ $read,
633
+ Core::CIPHER_METHOD,
634
+ $ekey,
635
+ OPENSSL_RAW_DATA,
636
+ $thisIv
637
+ );
638
+ if ($decrypted === false) {
639
+ throw new Ex\EnvironmentIsBrokenException(
640
+ 'OpenSSL decryption error'
641
+ );
642
+ }
643
+
644
+ /* Write the plaintext to the output file. */
645
+ self::writeBytes(
646
+ $outputHandle,
647
+ $decrypted,
648
+ Core::ourStrlen($decrypted)
649
+ );
650
+
651
+ /* Increment the IV by the amount of blocks in a buffer. */
652
+ $thisIv = Core::incrementCounter($thisIv, $inc);
653
+ /* WARNING: Usually, unless the file is a multiple of the buffer
654
+ * size, $thisIv will contain an incorrect value here on the last
655
+ * iteration of this loop. */
656
+ }
657
+ }
658
+
659
+ /**
660
+ * Read from a stream; prevent partial reads.
661
+ *
662
+ * @param resource $stream
663
+ * @param int $num_bytes
664
+ *
665
+ * @throws Ex\IOException
666
+ * @throws Ex\EnvironmentIsBrokenException
667
+ *
668
+ * @return string
669
+ */
670
+ public static function readBytes($stream, $num_bytes)
671
+ {
672
+ if ($num_bytes < 0) {
673
+ throw new Ex\EnvironmentIsBrokenException(
674
+ 'Tried to read less than 0 bytes'
675
+ );
676
+ } elseif ($num_bytes === 0) {
677
+ return '';
678
+ }
679
+ $buf = '';
680
+ $remaining = $num_bytes;
681
+ while ($remaining > 0 && ! \feof($stream)) {
682
+ $read = \fread($stream, $remaining);
683
+
684
+ if ($read === false) {
685
+ throw new Ex\IOException(
686
+ 'Could not read from the file'
687
+ );
688
+ }
689
+ $buf .= $read;
690
+ $remaining -= Core::ourStrlen($read);
691
+ }
692
+ if (Core::ourStrlen($buf) !== $num_bytes) {
693
+ throw new Ex\IOException(
694
+ 'Tried to read past the end of the file'
695
+ );
696
+ }
697
+ return $buf;
698
+ }
699
+
700
+ /**
701
+ * Write to a stream; prevents partial writes.
702
+ *
703
+ * @param resource $stream
704
+ * @param string $buf
705
+ * @param int $num_bytes
706
+ *
707
+ * @throws Ex\IOException
708
+ *
709
+ * @return string
710
+ */
711
+ public static function writeBytes($stream, $buf, $num_bytes = null)
712
+ {
713
+ $bufSize = Core::ourStrlen($buf);
714
+ if ($num_bytes === null) {
715
+ $num_bytes = $bufSize;
716
+ }
717
+ if ($num_bytes > $bufSize) {
718
+ throw new Ex\IOException(
719
+ 'Trying to write more bytes than the buffer contains.'
720
+ );
721
+ }
722
+ if ($num_bytes < 0) {
723
+ throw new Ex\IOException(
724
+ 'Tried to write less than 0 bytes'
725
+ );
726
+ }
727
+ $remaining = $num_bytes;
728
+ while ($remaining > 0) {
729
+ $written = \fwrite($stream, $buf, $remaining);
730
+ if ($written === false) {
731
+ throw new Ex\IOException(
732
+ 'Could not write to the file'
733
+ );
734
+ }
735
+ $buf = Core::ourSubstr($buf, $written, null);
736
+ $remaining -= $written;
737
+ }
738
+ return $num_bytes;
739
+ }
740
+
741
+ /**
742
+ * Returns the last PHP error's or warning's message string.
743
+ *
744
+ * @return string
745
+ */
746
+ private static function getLastErrorMessage()
747
+ {
748
+ $error = error_get_last();
749
+ if ($error === null) {
750
+ return '[no PHP error]';
751
+ } else {
752
+ return $error['message'];
753
+ }
754
+ }
755
+ }
src/vendor/defuse/php-encryption/src/Key.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ final class Key
8
+ {
9
+ const KEY_CURRENT_VERSION = "\xDE\xF0\x00\x00";
10
+ const KEY_BYTE_SIZE = 32;
11
+
12
+ private $key_bytes = null;
13
+
14
+ /**
15
+ * Creates new random key.
16
+ *
17
+ * @throws Ex\EnvironmentIsBrokenException
18
+ *
19
+ * @return Key
20
+ */
21
+ public static function createNewRandomKey()
22
+ {
23
+ return new Key(Core::secureRandom(self::KEY_BYTE_SIZE));
24
+ }
25
+
26
+ /**
27
+ * Loads a Key from its encoded form.
28
+ *
29
+ * @param string $saved_key_string
30
+ *
31
+ * @throws Ex\BadFormatException
32
+ * @throws Ex\EnvironmentIsBrokenException
33
+ *
34
+ * @return Key
35
+ */
36
+ public static function loadFromAsciiSafeString($saved_key_string)
37
+ {
38
+ $key_bytes = Encoding::loadBytesFromChecksummedAsciiSafeString(self::KEY_CURRENT_VERSION, $saved_key_string);
39
+ return new Key($key_bytes);
40
+ }
41
+
42
+ /**
43
+ * Encodes the Key into a string of printable ASCII characters.
44
+ *
45
+ * @throws Ex\EnvironmentIsBrokenException
46
+ *
47
+ * @return string
48
+ */
49
+ public function saveToAsciiSafeString()
50
+ {
51
+ return Encoding::saveBytesToChecksummedAsciiSafeString(
52
+ self::KEY_CURRENT_VERSION,
53
+ $this->key_bytes
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Gets the raw bytes of the key.
59
+ *
60
+ * @return string
61
+ */
62
+ public function getRawBytes()
63
+ {
64
+ return $this->key_bytes;
65
+ }
66
+
67
+ /**
68
+ * Constructs a new Key object from a string of raw bytes.
69
+ *
70
+ * @param string $bytes
71
+ *
72
+ * @throws Ex\EnvironmentIsBrokenException
73
+ */
74
+ private function __construct($bytes)
75
+ {
76
+ if (Core::ourStrlen($bytes) !== self::KEY_BYTE_SIZE) {
77
+ throw new Ex\EnvironmentIsBrokenException(
78
+ 'Bad key length.'
79
+ );
80
+ }
81
+ $this->key_bytes = $bytes;
82
+ }
83
+
84
+ }
src/vendor/defuse/php-encryption/src/KeyOrPassword.php ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ final class KeyOrPassword
8
+ {
9
+ const PBKDF2_ITERATIONS = 100000;
10
+ const SECRET_TYPE_KEY = 1;
11
+ const SECRET_TYPE_PASSWORD = 2;
12
+
13
+ private $secret_type = null;
14
+ private $secret = null;
15
+
16
+ /**
17
+ * Initializes an instance of KeyOrPassword from a key.
18
+ *
19
+ * @param Key $key
20
+ *
21
+ * @return KeyOrPassword
22
+ */
23
+ public static function createFromKey(Key $key)
24
+ {
25
+ return new KeyOrPassword(self::SECRET_TYPE_KEY, $key);
26
+ }
27
+
28
+ /**
29
+ * Initializes an instance of KeyOrPassword from a password.
30
+ *
31
+ * @param string $password
32
+ *
33
+ * @return KeyOrPassword
34
+ */
35
+ public static function createFromPassword($password)
36
+ {
37
+ return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
38
+ }
39
+
40
+ /**
41
+ * Derives authentication and encryption keys from the secret, using a slow
42
+ * key derivation function if the secret is a password.
43
+ *
44
+ * @param string $salt
45
+ *
46
+ * @throws Ex\EnvironmentIsBrokenException
47
+ *
48
+ * @return DerivedKeys
49
+ */
50
+ public function deriveKeys($salt)
51
+ {
52
+ if (Core::ourStrlen($salt) !== Core::SALT_BYTE_SIZE) {
53
+ throw new Ex\EnvironmentIsBrokenException('Bad salt.');
54
+ }
55
+
56
+ if ($this->secret_type === self::SECRET_TYPE_KEY) {
57
+ $akey = Core::HKDF(
58
+ Core::HASH_FUNCTION_NAME,
59
+ $this->secret->getRawBytes(),
60
+ Core::KEY_BYTE_SIZE,
61
+ Core::AUTHENTICATION_INFO_STRING,
62
+ $salt
63
+ );
64
+ $ekey = Core::HKDF(
65
+ Core::HASH_FUNCTION_NAME,
66
+ $this->secret->getRawBytes(),
67
+ Core::KEY_BYTE_SIZE,
68
+ Core::ENCRYPTION_INFO_STRING,
69
+ $salt
70
+ );
71
+ return new DerivedKeys($akey, $ekey);
72
+ } elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
73
+ /* Our PBKDF2 polyfill is vulnerable to a DoS attack documented in
74
+ * GitHub issue #230. The fix is to pre-hash the password to ensure
75
+ * it is short. We do the prehashing here instead of in pbkdf2() so
76
+ * that pbkdf2() still computes the function as defined by the
77
+ * standard. */
78
+ $prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);
79
+ $prekey = Core::pbkdf2(
80
+ Core::HASH_FUNCTION_NAME,
81
+ $prehash,
82
+ $salt,
83
+ self::PBKDF2_ITERATIONS,
84
+ Core::KEY_BYTE_SIZE,
85
+ true
86
+ );
87
+ $akey = Core::HKDF(
88
+ Core::HASH_FUNCTION_NAME,
89
+ $prekey,
90
+ Core::KEY_BYTE_SIZE,
91
+ Core::AUTHENTICATION_INFO_STRING,
92
+ $salt
93
+ );
94
+ /* Note the cryptographic re-use of $salt here. */
95
+ $ekey = Core::HKDF(
96
+ Core::HASH_FUNCTION_NAME,
97
+ $prekey,
98
+ Core::KEY_BYTE_SIZE,
99
+ Core::ENCRYPTION_INFO_STRING,
100
+ $salt
101
+ );
102
+ return new DerivedKeys($akey, $ekey);
103
+ } else {
104
+ throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Constructor for KeyOrPassword.
110
+ *
111
+ * @param int $secret_type
112
+ * @param mixed $secret (either a Key or a password string)
113
+ */
114
+ private function __construct($secret_type, $secret)
115
+ {
116
+ $this->secret_type = $secret_type;
117
+ $this->secret = $secret;
118
+ }
119
+ }
src/vendor/defuse/php-encryption/src/KeyProtectedByPassword.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ final class KeyProtectedByPassword
8
+ {
9
+ const PASSWORD_KEY_CURRENT_VERSION = "\xDE\xF1\x00\x00";
10
+
11
+ private $encrypted_key = null;
12
+
13
+ /**
14
+ * Creates a random key protected by the provided password.
15
+ *
16
+ * @param string $password
17
+ *
18
+ * @throws Ex\EnvironmentIsBrokenException
19
+ *
20
+ * @return KeyProtectedByPassword
21
+ */
22
+ public static function createRandomPasswordProtectedKey($password)
23
+ {
24
+ $inner_key = Key::createNewRandomKey();
25
+ /* The password is hashed as a form of poor-man's domain separation
26
+ * between this use of encryptWithPassword() and other uses of
27
+ * encryptWithPassword() that the user may also be using as part of the
28
+ * same protocol. */
29
+ $encrypted_key = Crypto::encryptWithPassword(
30
+ $inner_key->saveToAsciiSafeString(),
31
+ \hash(Core::HASH_FUNCTION_NAME, $password, true),
32
+ true
33
+ );
34
+
35
+ return new KeyProtectedByPassword($encrypted_key);
36
+ }
37
+
38
+ /**
39
+ * Loads a KeyProtectedByPassword from its encoded form.
40
+ *
41
+ * @param string $saved_key_string
42
+ *
43
+ * @throws Ex\BadFormatException
44
+ *
45
+ * @return KeyProtectedByPassword
46
+ */
47
+ public static function loadFromAsciiSafeString($saved_key_string)
48
+ {
49
+ $encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
50
+ self::PASSWORD_KEY_CURRENT_VERSION,
51
+ $saved_key_string
52
+ );
53
+ return new KeyProtectedByPassword($encrypted_key);
54
+ }
55
+
56
+ /**
57
+ * Encodes the KeyProtectedByPassword into a string of printable ASCII
58
+ * characters.
59
+ *
60
+ * @throws Ex\EnvironmentIsBrokenException
61
+ *
62
+ * @return string
63
+ */
64
+ public function saveToAsciiSafeString()
65
+ {
66
+ return Encoding::saveBytesToChecksummedAsciiSafeString(
67
+ self::PASSWORD_KEY_CURRENT_VERSION,
68
+ $this->encrypted_key
69
+ );
70
+ }
71
+
72
+ /**
73
+ * Decrypts the protected key, returning an unprotected Key object that can
74
+ * be used for encryption and decryption.
75
+ *
76
+ * @throws Ex\EnvironmentIsBrokenException
77
+ * @throws Ex\WrongKeyOrModifiedCiphertextException
78
+ *
79
+ * @return Key
80
+ */
81
+ public function unlockKey($password)
82
+ {
83
+ try {
84
+ $inner_key_encoded = Crypto::decryptWithPassword(
85
+ $this->encrypted_key,
86
+ \hash(Core::HASH_FUNCTION_NAME, $password, true),
87
+ true
88
+ );
89
+ return Key::loadFromAsciiSafeString($inner_key_encoded);
90
+ } catch (Ex\BadFormatException $ex) {
91
+ /* This should never happen unless an attacker replaced the
92
+ * encrypted key ciphertext with some other ciphertext that was
93
+ * encrypted with the same password. We transform the exception type
94
+ * here in order to make the API simpler, avoiding the need to
95
+ * document that this method might throw an Ex\BadFormatException. */
96
+ throw new Ex\WrongKeyOrModifiedCiphertextException(
97
+ "The decrypted key was found to be in an invalid format. " .
98
+ "This very likely indicates it was modified by an attacker."
99
+ );
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Constructor for KeyProtectedByPassword.
105
+ *
106
+ * @param string $encrypted_key
107
+ */
108
+ private function __construct($encrypted_key)
109
+ {
110
+ $this->encrypted_key = $encrypted_key;
111
+ }
112
+ }
src/vendor/defuse/php-encryption/src/RuntimeTests.php ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Defuse\Crypto;
4
+
5
+ use Defuse\Crypto\Exception as Ex;
6
+
7
+ /*
8
+ * We're using static class inheritance to get access to protected methods
9
+ * inside Crypto. To make it easy to know where the method we're calling can be
10
+ * found, within this file, prefix calls with `Crypto::` or `RuntimeTests::`,
11
+ * and don't use `self::`.
12
+ */
13
+
14
+ class RuntimeTests extends Crypto
15
+ {
16
+ /**
17
+ * Runs the runtime tests.
18
+ *
19
+ * @throws Ex\EnvironmentIsBrokenException
20
+ */
21
+ public static function runtimeTest()
22
+ {
23
+ // 0: Tests haven't been run yet.
24
+ // 1: Tests have passed.
25
+ // 2: Tests are running right now.
26
+ // 3: Tests have failed.
27
+ static $test_state = 0;
28
+
29
+ if ($test_state === 1 || $test_state === 2) {
30
+ return;
31
+ }
32
+
33
+ if ($test_state === 3) {
34
+ /* If an intermittent problem caused a test to fail previously, we
35
+ * want that to be indicated to the user with every call to this
36
+ * library. This way, if the user first does something they really
37
+ * don't care about, and just ignores all exceptions, they won't get
38
+ * screwed when they then start to use the library for something
39
+ * they do care about. */
40
+ throw new Ex\EnvironmentIsBrokenException('Tests failed previously.');
41
+ }
42
+
43
+ try {
44
+ $test_state = 2;
45
+
46
+ Core::ensureFunctionExists('openssl_get_cipher_methods');
47
+ if (\in_array(Core::CIPHER_METHOD, \openssl_get_cipher_methods()) === false) {
48
+ throw new Ex\EnvironmentIsBrokenException(
49
+ 'Cipher method not supported. This is normally caused by an outdated ' .
50
+ 'version of OpenSSL (and/or OpenSSL compiled for FIPS compliance). ' .
51
+ 'Please upgrade to a newer version of OpenSSL that supports ' .
52
+ Core::CIPHER_METHOD . ' to use this library.'
53
+ );
54
+ }
55
+
56
+ RuntimeTests::AESTestVector();
57
+ RuntimeTests::HMACTestVector();
58
+ RuntimeTests::HKDFTestVector();
59
+
60
+ RuntimeTests::testEncryptDecrypt();
61
+ if (Core::ourStrlen(Key::createNewRandomKey()->getRawBytes()) != Core::KEY_BYTE_SIZE) {
62
+ throw new Ex\EnvironmentIsBrokenException();
63
+ }
64
+
65
+ if (Core::ENCRYPTION_INFO_STRING == Core::AUTHENTICATION_INFO_STRING) {
66
+ throw new Ex\EnvironmentIsBrokenException();
67
+ }
68
+ } catch (Ex\EnvironmentIsBrokenException $ex) {
69
+ // Do this, otherwise it will stay in the "tests are running" state.
70
+ $test_state = 3;
71
+ throw $ex;
72
+ }
73
+
74
+ // Change this to '0' make the tests always re-run (for benchmarking).
75
+ $test_state = 1;
76
+ }
77
+
78
+ /**
79
+ * High-level tests of Crypto operations.
80
+ *
81
+ * @throws Ex\EnvironmentIsBrokenException
82
+ */
83
+ private static function testEncryptDecrypt()
84
+ {
85
+ $key = Key::createNewRandomKey();
86
+ $data = "EnCrYpT EvErYThInG\x00\x00";
87
+
88
+ // Make sure encrypting then decrypting doesn't change the message.
89
+ $ciphertext = Crypto::encrypt($data, $key, true);
90
+ try {
91
+ $decrypted = Crypto::decrypt($ciphertext, $key, true);
92
+ } catch (Ex\WrongKeyOrModifiedCiphertextException $ex) {
93
+ // It's important to catch this and change it into a
94
+ // Ex\EnvironmentIsBrokenException, otherwise a test failure could trick
95
+ // the user into thinking it's just an invalid ciphertext!
96
+ throw new Ex\EnvironmentIsBrokenException();
97
+ }
98
+ if ($decrypted !== $data) {
99
+ throw new Ex\EnvironmentIsBrokenException();
100
+ }
101
+
102
+ // Modifying the ciphertext: Appending a string.
103
+ try {
104
+ Crypto::decrypt($ciphertext . 'a', $key, true);
105
+ throw new Ex\EnvironmentIsBrokenException();
106
+ } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
107
+ }
108
+
109
+ // Modifying the ciphertext: Changing an HMAC byte.
110
+ $indices_to_change = [
111
+ 0, // The header.
112
+ Core::HEADER_VERSION_SIZE + 1, // the salt
113
+ Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 1, // the IV
114
+ Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + Core::BLOCK_BYTE_SIZE + 1, // the ciphertext
115
+ ];
116
+
117
+ foreach ($indices_to_change as $index) {
118
+ try {
119
+ $ciphertext[$index] = \chr((\ord($ciphertext[$index]) + 1) % 256);
120
+ Crypto::decrypt($ciphertext, $key, true);
121
+ throw new Ex\EnvironmentIsBrokenException();
122
+ } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
123
+ }
124
+ }
125
+
126
+ // Decrypting with the wrong key.
127
+ $key = Key::createNewRandomKey();
128
+ $data = 'abcdef';
129
+ $ciphertext = Crypto::encrypt($data, $key, true);
130
+ $wrong_key = Key::createNewRandomKey();
131
+ try {
132
+ Crypto::decrypt($ciphertext, $wrong_key, true);
133
+ throw new Ex\EnvironmentIsBrokenException();
134
+ } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
135
+ }
136
+
137
+ // Ciphertext too small.
138
+ $key = Key::createNewRandomKey();
139
+ $ciphertext = \str_repeat('A', Core::MINIMUM_CIPHERTEXT_SIZE - 1);
140
+ try {
141
+ Crypto::decrypt($ciphertext, $key, true);
142
+ throw new Ex\EnvironmentIsBrokenException();
143
+ } catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Test HKDF against test vectors.
149
+ *
150
+ * @throws Ex\EnvironmentIsBrokenException
151
+ */
152
+ private static function HKDFTestVector()
153
+ {
154
+ // HKDF test vectors from RFC 5869
155
+
156
+ // Test Case 1
157
+ $ikm = \str_repeat("\x0b", 22);
158
+ $salt = Encoding::hexToBin('000102030405060708090a0b0c');
159
+ $info = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9');
160
+ $length = 42;
161
+ $okm = Encoding::hexToBin(
162
+ '3cb25f25faacd57a90434f64d0362f2a' .
163
+ '2d2d0a90cf1a5a4c5db02d56ecc4c5bf' .
164
+ '34007208d5b887185865'
165
+ );
166
+ $computed_okm = Core::HKDF('sha256', $ikm, $length, $info, $salt);
167
+ if ($computed_okm !== $okm) {
168
+ throw new Ex\EnvironmentIsBrokenException();
169
+ }
170
+
171
+ // Test Case 7
172
+ $ikm = \str_repeat("\x0c", 22);
173
+ $length = 42;
174
+ $okm = Encoding::hexToBin(
175
+ '2c91117204d745f3500d636a62f64f0a' .
176
+ 'b3bae548aa53d423b0d1f27ebba6f5e5' .
177
+ '673a081d70cce7acfc48'
178
+ );
179
+ $computed_okm = Core::HKDF('sha1', $ikm, $length, '', null);
180
+ if ($computed_okm !== $okm) {
181
+ throw new Ex\EnvironmentIsBrokenException();
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Test HMAC against test vectors.
187
+ *
188
+ * @throws Ex\EnvironmentIsBrokenException
189
+ */
190
+ private static function HMACTestVector()
191
+ {
192
+ // HMAC test vector From RFC 4231 (Test Case 1)
193
+ $key = \str_repeat("\x0b", 20);
194
+ $data = 'Hi There';
195
+ $correct = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
196
+ if (\hash_hmac(Core::HASH_FUNCTION_NAME, $data, $key) !== $correct) {
197
+ throw new Ex\EnvironmentIsBrokenException();
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Test AES against test vectors.
203
+ *
204
+ * @throws Ex\EnvironmentIsBrokenException
205
+ */
206
+ private static function AESTestVector()
207
+ {
208
+ // AES CTR mode test vector from NIST SP 800-38A
209
+ $key = Encoding::hexToBin(
210
+ '603deb1015ca71be2b73aef0857d7781' .
211
+ '1f352c073b6108d72d9810a30914dff4'
212
+ );
213
+ $iv = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
214
+ $plaintext = Encoding::hexToBin(
215
+ '6bc1bee22e409f96e93d7e117393172a' .
216
+ 'ae2d8a571e03ac9c9eb76fac45af8e51' .
217
+ '30c81c46a35ce411e5fbc1191a0a52ef' .
218
+ 'f69f2445df4f9b17ad2b417be66c3710'
219
+ );
220
+ $ciphertext = Encoding::hexToBin(
221
+ '601ec313775789a5b7a7f504bbf3d228' .
222
+ 'f443e3ca4d62b59aca84e990cacaf5c5' .
223
+ '2b0930daa23de94ce87017ba2d84988d' .
224
+ 'dfc9c58db67aada613c2dd08457941a6'
225
+ );
226
+
227
+ $computed_ciphertext = Crypto::plainEncrypt($plaintext, $key, $iv);
228
+ if ($computed_ciphertext !== $ciphertext) {
229
+ echo \str_repeat("\n", 30);
230
+ echo \bin2hex($computed_ciphertext);
231
+ echo "\n---\n";
232
+ echo \bin2hex($ciphertext);
233
+ echo \str_repeat("\n", 30);
234
+ throw new Ex\EnvironmentIsBrokenException();
235
+ }
236
+
237
+ $computed_plaintext = Crypto::plainDecrypt($ciphertext, $key, $iv, Core::CIPHER_METHOD);
238
+ if ($computed_plaintext !== $plaintext) {
239
+ throw new Ex\EnvironmentIsBrokenException();
240
+ }
241
+ }
242
+ }
src/vendor/paragonie/random_compat/LICENSE ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Paragon Initiative Enterprises
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
src/vendor/paragonie/random_compat/build-phar.sh ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) )
4
+
5
+ php -dphar.readonly=0 "$basedir/other/build_phar.php" $*
src/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ -----BEGIN PUBLIC KEY-----
2
+ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
3
+ pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
4
+ +h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
5
+ -----END PUBLIC KEY-----
src/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN PGP SIGNATURE-----
2
+ Version: GnuPG v2.0.22 (MingW32)
3
+
4
+ iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip
5
+ QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg
6
+ 1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW
7
+ NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA
8
+ NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV
9
+ JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74=
10
+ =B6+8
11
+ -----END PGP SIGNATURE-----
src/vendor/paragonie/random_compat/lib/byte_safe_strings.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!is_callable('RandomCompat_strlen')) {
30
+ if (
31
+ defined('MB_OVERLOAD_STRING') &&
32
+ ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
33
+ ) {
34
+ /**
35
+ * strlen() implementation that isn't brittle to mbstring.func_overload
36
+ *
37
+ * This version uses mb_strlen() in '8bit' mode to treat strings as raw
38
+ * binary rather than UTF-8, ISO-8859-1, etc
39
+ *
40
+ * @param string $binary_string
41
+ *
42
+ * @throws TypeError
43
+ *
44
+ * @return int
45
+ */
46
+ function RandomCompat_strlen($binary_string)
47
+ {
48
+ if (!is_string($binary_string)) {
49
+ throw new TypeError(
50
+ 'RandomCompat_strlen() expects a string'
51
+ );
52
+ }
53
+
54
+ return (int) mb_strlen($binary_string, '8bit');
55
+ }
56
+
57
+ } else {
58
+ /**
59
+ * strlen() implementation that isn't brittle to mbstring.func_overload
60
+ *
61
+ * This version just used the default strlen()
62
+ *
63
+ * @param string $binary_string
64
+ *
65
+ * @throws TypeError
66
+ *
67
+ * @return int
68
+ */
69
+ function RandomCompat_strlen($binary_string)
70
+ {
71
+ if (!is_string($binary_string)) {
72
+ throw new TypeError(
73
+ 'RandomCompat_strlen() expects a string'
74
+ );
75
+ }
76
+ return (int) strlen($binary_string);
77
+ }
78
+ }
79
+ }
80
+
81
+ if (!is_callable('RandomCompat_substr')) {
82
+
83
+ if (
84
+ defined('MB_OVERLOAD_STRING')
85
+ &&
86
+ ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
87
+ ) {
88
+ /**
89
+ * substr() implementation that isn't brittle to mbstring.func_overload
90
+ *
91
+ * This version uses mb_substr() in '8bit' mode to treat strings as raw
92
+ * binary rather than UTF-8, ISO-8859-1, etc
93
+ *
94
+ * @param string $binary_string
95
+ * @param int $start
96
+ * @param int $length (optional)
97
+ *
98
+ * @throws TypeError
99
+ *
100
+ * @return string
101
+ */
102
+ function RandomCompat_substr($binary_string, $start, $length = null)
103
+ {
104
+ if (!is_string($binary_string)) {
105
+ throw new TypeError(
106
+ 'RandomCompat_substr(): First argument should be a string'
107
+ );
108
+ }
109
+
110
+ if (!is_int($start)) {
111
+ throw new TypeError(
112
+ 'RandomCompat_substr(): Second argument should be an integer'
113
+ );
114
+ }
115
+
116
+ if ($length === null) {
117
+ /**
118
+ * mb_substr($str, 0, NULL, '8bit') returns an empty string on
119
+ * PHP 5.3, so we have to find the length ourselves.
120
+ */
121
+ $length = RandomCompat_strlen($binary_string) - $start;
122
+ } elseif (!is_int($length)) {
123
+ throw new TypeError(
124
+ 'RandomCompat_substr(): Third argument should be an integer, or omitted'
125
+ );
126
+ }
127
+
128
+ // Consistency with PHP's behavior
129
+ if ($start === RandomCompat_strlen($binary_string) && $length === 0) {
130
+ return '';
131
+ }
132
+ if ($start > RandomCompat_strlen($binary_string)) {
133
+ return '';
134
+ }
135
+
136
+ return (string) mb_substr($binary_string, $start, $length, '8bit');
137
+ }
138
+
139
+ } else {
140
+
141
+ /**
142
+ * substr() implementation that isn't brittle to mbstring.func_overload
143
+ *
144
+ * This version just uses the default substr()
145
+ *
146
+ * @param string $binary_string
147
+ * @param int $start
148
+ * @param int $length (optional)
149
+ *
150
+ * @throws TypeError
151
+ *
152
+ * @return string
153
+ */
154
+ function RandomCompat_substr($binary_string, $start, $length = null)
155
+ {
156
+ if (!is_string($binary_string)) {
157
+ throw new TypeError(
158
+ 'RandomCompat_substr(): First argument should be a string'
159
+ );
160
+ }
161
+
162
+ if (!is_int($start)) {
163
+ throw new TypeError(
164
+ 'RandomCompat_substr(): Second argument should be an integer'
165
+ );
166
+ }
167
+
168
+ if ($length !== null) {
169
+ if (!is_int($length)) {
170
+ throw new TypeError(
171
+ 'RandomCompat_substr(): Third argument should be an integer, or omitted'
172
+ );
173
+ }
174
+
175
+ return (string) substr($binary_string, $start, $length);
176
+ }
177
+
178
+ return (string) substr($binary_string, $start);
179
+ }
180
+ }
181
+ }
src/vendor/paragonie/random_compat/lib/cast_to_int.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!is_callable('RandomCompat_intval')) {
30
+
31
+ /**
32
+ * Cast to an integer if we can, safely.
33
+ *
34
+ * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
35
+ * (non-inclusive), it will sanely cast it to an int. If you it's equal to
36
+ * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
37
+ * lose precision, so the <= and => operators might accidentally let a float
38
+ * through.
39
+ *
40
+ * @param int|float $number The number we want to convert to an int
41
+ * @param boolean $fail_open Set to true to not throw an exception
42
+ *
43
+ * @return float|int
44
+ *
45
+ * @throws TypeError
46
+ */
47
+ function RandomCompat_intval($number, $fail_open = false)
48
+ {
49
+ if (is_int($number) || is_float($number)) {
50
+ $number += 0;
51
+ } elseif (is_numeric($number)) {
52
+ $number += 0;
53
+ }
54
+
55
+ if (
56
+ is_float($number)
57
+ &&
58
+ $number > ~PHP_INT_MAX
59
+ &&
60
+ $number < PHP_INT_MAX
61
+ ) {
62
+ $number = (int) $number;
63
+ }
64
+
65
+ if (is_int($number)) {
66
+ return (int) $number;
67
+ } elseif (!$fail_open) {
68
+ throw new TypeError(
69
+ 'Expected an integer.'
70
+ );
71
+ }
72
+ return $number;
73
+ }
74
+ }
src/vendor/paragonie/random_compat/lib/error_polyfill.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!class_exists('Error', false)) {
30
+ // We can't really avoid making this extend Exception in PHP 5.
31
+ class Error extends Exception
32
+ {
33
+
34
+ }
35
+ }
36
+
37
+ if (!class_exists('TypeError', false)) {
38
+ if (is_subclass_of('Error', 'Exception')) {
39
+ class TypeError extends Error
40
+ {
41
+
42
+ }
43
+ } else {
44
+ class TypeError extends Exception
45
+ {
46
+
47
+ }
48
+ }
49
+ }
src/vendor/paragonie/random_compat/lib/random.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * @version 2.0.10
7
+ * @released 2017-03-13
8
+ *
9
+ * The MIT License (MIT)
10
+ *
11
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
12
+ *
13
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ * of this software and associated documentation files (the "Software"), to deal
15
+ * in the Software without restriction, including without limitation the rights
16
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ * copies of the Software, and to permit persons to whom the Software is
18
+ * furnished to do so, subject to the following conditions:
19
+ *
20
+ * The above copyright notice and this permission notice shall be included in
21
+ * all copies or substantial portions of the Software.
22
+ *
23
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ * SOFTWARE.
30
+ */
31
+
32
+ if (!defined('PHP_VERSION_ID')) {
33
+ // This constant was introduced in PHP 5.2.7
34
+ $RandomCompatversion = array_map('intval', explode('.', PHP_VERSION));
35
+ define(
36
+ 'PHP_VERSION_ID',
37
+ $RandomCompatversion[0] * 10000
38
+ + $RandomCompatversion[1] * 100
39
+ + $RandomCompatversion[2]
40
+ );
41
+ $RandomCompatversion = null;
42
+ }
43
+
44
+ /**
45
+ * PHP 7.0.0 and newer have these functions natively.
46
+ */
47
+ if (PHP_VERSION_ID >= 70000) {
48
+ return;
49
+ }
50
+
51
+ if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
52
+ define('RANDOM_COMPAT_READ_BUFFER', 8);
53
+ }
54
+
55
+ $RandomCompatDIR = dirname(__FILE__);
56
+
57
+ require_once $RandomCompatDIR . '/byte_safe_strings.php';
58
+ require_once $RandomCompatDIR . '/cast_to_int.php';
59
+ require_once $RandomCompatDIR . '/error_polyfill.php';
60
+
61
+ if (!is_callable('random_bytes')) {
62
+ /**
63
+ * PHP 5.2.0 - 5.6.x way to implement random_bytes()
64
+ *
65
+ * We use conditional statements here to define the function in accordance
66
+ * to the operating environment. It's a micro-optimization.
67
+ *
68
+ * In order of preference:
69
+ * 1. Use libsodium if available.
70
+ * 2. fread() /dev/urandom if available (never on Windows)
71
+ * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
72
+ * 4. COM('CAPICOM.Utilities.1')->GetRandom()
73
+ *
74
+ * See RATIONALE.md for our reasoning behind this particular order
75
+ */
76
+ if (extension_loaded('libsodium')) {
77
+ // See random_bytes_libsodium.php
78
+ if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
79
+ require_once $RandomCompatDIR . '/random_bytes_libsodium.php';
80
+ } elseif (method_exists('Sodium', 'randombytes_buf')) {
81
+ require_once $RandomCompatDIR . '/random_bytes_libsodium_legacy.php';
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Reading directly from /dev/urandom:
87
+ */
88
+ if (DIRECTORY_SEPARATOR === '/') {
89
+ // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
90
+ // way to exclude Windows.
91
+ $RandomCompatUrandom = true;
92
+ $RandomCompat_basedir = ini_get('open_basedir');
93
+
94
+ if (!empty($RandomCompat_basedir)) {
95
+ $RandomCompat_open_basedir = explode(
96
+ PATH_SEPARATOR,
97
+ strtolower($RandomCompat_basedir)
98
+ );
99
+ $RandomCompatUrandom = (array() !== array_intersect(
100
+ array('/dev', '/dev/', '/dev/urandom'),
101
+ $RandomCompat_open_basedir
102
+ ));
103
+ $RandomCompat_open_basedir = null;
104
+ }
105
+
106
+ if (
107
+ !is_callable('random_bytes')
108
+ &&
109
+ $RandomCompatUrandom
110
+ &&
111
+ @is_readable('/dev/urandom')
112
+ ) {
113
+ // Error suppression on is_readable() in case of an open_basedir
114
+ // or safe_mode failure. All we care about is whether or not we
115
+ // can read it at this point. If the PHP environment is going to
116
+ // panic over trying to see if the file can be read in the first
117
+ // place, that is not helpful to us here.
118
+
119
+ // See random_bytes_dev_urandom.php
120
+ require_once $RandomCompatDIR . '/random_bytes_dev_urandom.php';
121
+ }
122
+ // Unset variables after use
123
+ $RandomCompat_basedir = null;
124
+ } else {
125
+ $RandomCompatUrandom = false;
126
+ }
127
+
128
+ /**
129
+ * mcrypt_create_iv()
130
+ *
131
+ * We only want to use mcypt_create_iv() if:
132
+ *
133
+ * - random_bytes() hasn't already been defined
134
+ * - the mcrypt extensions is loaded
135
+ * - One of these two conditions is true:
136
+ * - We're on Windows (DIRECTORY_SEPARATOR !== '/')
137
+ * - We're not on Windows and /dev/urandom is readabale
138
+ * (i.e. we're not in a chroot jail)
139
+ * - Special case:
140
+ * - If we're not on Windows, but the PHP version is between
141
+ * 5.6.10 and 5.6.12, we don't want to use mcrypt. It will
142
+ * hang indefinitely. This is bad.
143
+ * - If we're on Windows, we want to use PHP >= 5.3.7 or else
144
+ * we get insufficient entropy errors.
145
+ */
146
+ if (
147
+ !is_callable('random_bytes')
148
+ &&
149
+ // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
150
+ (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
151
+ &&
152
+ // Prevent this code from hanging indefinitely on non-Windows;
153
+ // see https://bugs.php.net/bug.php?id=69833
154
+ (
155
+ DIRECTORY_SEPARATOR !== '/' ||
156
+ (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
157
+ )
158
+ &&
159
+ extension_loaded('mcrypt')
160
+ ) {
161
+ // See random_bytes_mcrypt.php
162
+ require_once $RandomCompatDIR . '/random_bytes_mcrypt.php';
163
+ }
164
+ $RandomCompatUrandom = null;
165
+
166
+ /**
167
+ * This is a Windows-specific fallback, for when the mcrypt extension
168
+ * isn't loaded.
169
+ */
170
+ if (
171
+ !is_callable('random_bytes')
172
+ &&
173
+ extension_loaded('com_dotnet')
174
+ &&
175
+ class_exists('COM')
176
+ ) {
177
+ $RandomCompat_disabled_classes = preg_split(
178
+ '#\s*,\s*#',
179
+ strtolower(ini_get('disable_classes'))
180
+ );
181
+
182
+ if (!in_array('com', $RandomCompat_disabled_classes)) {
183
+ try {
184
+ $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
185
+ if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
186
+ // See random_bytes_com_dotnet.php
187
+ require_once $RandomCompatDIR . '/random_bytes_com_dotnet.php';
188
+ }
189
+ } catch (com_exception $e) {
190
+ // Don't try to use it.
191
+ }
192
+ }
193
+ $RandomCompat_disabled_classes = null;
194
+ $RandomCompatCOMtest = null;
195
+ }
196
+
197
+ /**
198
+ * throw new Exception
199
+ */
200
+ if (!is_callable('random_bytes')) {
201
+ /**
202
+ * We don't have any more options, so let's throw an exception right now
203
+ * and hope the developer won't let it fail silently.
204
+ *
205
+ * @param mixed $length
206
+ * @return void
207
+ * @throws Exception
208
+ */
209
+ function random_bytes($length)
210
+ {
211
+ unset($length); // Suppress "variable not used" warnings.
212
+ throw new Exception(
213
+ 'There is no suitable CSPRNG installed on your system'
214
+ );
215
+ }
216
+ }
217
+ }
218
+
219
+ if (!is_callable('random_int')) {
220
+ require_once $RandomCompatDIR . '/random_int.php';
221
+ }
222
+
223
+ $RandomCompatDIR = null;
src/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!is_callable('random_bytes')) {
30
+ /**
31
+ * Windows with PHP < 5.3.0 will not have the function
32
+ * openssl_random_pseudo_bytes() available, so let's use
33
+ * CAPICOM to work around this deficiency.
34
+ *
35
+ * @param int $bytes
36
+ *
37
+ * @throws Exception
38
+ *
39
+ * @return string
40
+ */
41
+ function random_bytes($bytes)
42
+ {
43
+ try {
44
+ $bytes = RandomCompat_intval($bytes);
45
+ } catch (TypeError $ex) {
46
+ throw new TypeError(
47
+ 'random_bytes(): $bytes must be an integer'
48
+ );
49
+ }
50
+
51
+ if ($bytes < 1) {
52
+ throw new Error(
53
+ 'Length must be greater than 0'
54
+ );
55
+ }
56
+
57
+ $buf = '';
58
+ if (!class_exists('COM')) {
59
+ throw new Error(
60
+ 'COM does not exist'
61
+ );
62
+ }
63
+ $util = new COM('CAPICOM.Utilities.1');
64
+ $execCount = 0;
65
+
66
+ /**
67
+ * Let's not let it loop forever. If we run N times and fail to
68
+ * get N bytes of random data, then CAPICOM has failed us.
69
+ */
70
+ do {
71
+ $buf .= base64_decode($util->GetRandom($bytes, 0));
72
+ if (RandomCompat_strlen($buf) >= $bytes) {
73
+ /**
74
+ * Return our random entropy buffer here:
75
+ */
76
+ return RandomCompat_substr($buf, 0, $bytes);
77
+ }
78
+ ++$execCount;
79
+ } while ($execCount < $bytes);
80
+
81
+ /**
82
+ * If we reach here, PHP has failed us.
83
+ */
84
+ throw new Exception(
85
+ 'Could not gather sufficient random data'
86
+ );
87
+ }
88
+ }
src/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
30
+ define('RANDOM_COMPAT_READ_BUFFER', 8);
31
+ }
32
+
33
+ if (!is_callable('random_bytes')) {
34
+ /**
35
+ * Unless open_basedir is enabled, use /dev/urandom for
36
+ * random numbers in accordance with best practices
37
+ *
38
+ * Why we use /dev/urandom and not /dev/random
39
+ * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers
40
+ *
41
+ * @param int $bytes
42
+ *
43
+ * @throws Exception
44
+ *
45
+ * @return string
46
+ */
47
+ function random_bytes($bytes)
48
+ {
49
+ static $fp = null;
50
+ /**
51
+ * This block should only be run once
52
+ */
53
+ if (empty($fp)) {
54
+ /**
55
+ * We use /dev/urandom if it is a char device.
56
+ * We never fall back to /dev/random
57
+ */
58
+ $fp = fopen('/dev/urandom', 'rb');
59
+ if (!empty($fp)) {
60
+ $st = fstat($fp);
61
+ if (($st['mode'] & 0170000) !== 020000) {
62
+ fclose($fp);
63
+ $fp = false;
64
+ }
65
+ }
66
+
67
+ if (!empty($fp)) {
68
+ /**
69
+ * stream_set_read_buffer() does not exist in HHVM
70
+ *
71
+ * If we don't set the stream's read buffer to 0, PHP will
72
+ * internally buffer 8192 bytes, which can waste entropy
73
+ *
74
+ * stream_set_read_buffer returns 0 on success
75
+ */
76
+ if (is_callable('stream_set_read_buffer')) {
77
+ stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER);
78
+ }
79
+ if (is_callable('stream_set_chunk_size')) {
80
+ stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER);
81
+ }
82
+ }
83
+ }
84
+
85
+ try {
86
+ $bytes = RandomCompat_intval($bytes);
87
+ } catch (TypeError $ex) {
88
+ throw new TypeError(
89
+ 'random_bytes(): $bytes must be an integer'
90
+ );
91
+ }
92
+
93
+ if ($bytes < 1) {
94
+ throw new Error(
95
+ 'Length must be greater than 0'
96
+ );
97
+ }
98
+
99
+ /**
100
+ * This if() block only runs if we managed to open a file handle
101
+ *
102
+ * It does not belong in an else {} block, because the above
103
+ * if (empty($fp)) line is logic that should only be run once per
104
+ * page load.
105
+ */
106
+ if (!empty($fp)) {
107
+ /**
108
+ * @var int
109
+ */
110
+ $remaining = $bytes;
111
+
112
+ /**
113
+ * @var string|bool
114
+ */
115
+ $buf = '';
116
+
117
+ /**
118
+ * We use fread() in a loop to protect against partial reads
119
+ */
120
+ do {
121
+ /**
122
+ * @var string|bool
123
+ */
124
+ $read = fread($fp, $remaining);
125
+ if (!is_string($read)) {
126
+ if ($read === false) {
127
+ /**
128
+ * We cannot safely read from the file. Exit the
129
+ * do-while loop and trigger the exception condition
130
+ *
131
+ * @var string|bool
132
+ */
133
+ $buf = false;
134
+ break;
135
+ }
136
+ }
137
+ /**
138
+ * Decrease the number of bytes returned from remaining
139
+ */
140
+ $remaining -= RandomCompat_strlen($read);
141
+ /**
142
+ * @var string|bool
143
+ */
144
+ $buf = $buf . $read;
145
+ } while ($remaining > 0);
146
+
147
+ /**
148
+ * Is our result valid?
149
+ */
150
+ if (is_string($buf)) {
151
+ if (RandomCompat_strlen($buf) === $bytes) {
152
+ /**
153
+ * Return our random entropy buffer here:
154
+ */
155
+ return $buf;
156
+ }
157
+ }
158
+ }
159
+
160
+ /**
161
+ * If we reach here, PHP has failed us.
162
+ */
163
+ throw new Exception(
164
+ 'Error reading from source device'
165
+ );
166
+ }
167
+ }
src/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!is_callable('random_bytes')) {
30
+ /**
31
+ * If the libsodium PHP extension is loaded, we'll use it above any other
32
+ * solution.
33
+ *
34
+ * libsodium-php project:
35
+ * @ref https://github.com/jedisct1/libsodium-php
36
+ *
37
+ * @param int $bytes
38
+ *
39
+ * @throws Exception
40
+ *
41
+ * @return string
42
+ */
43
+ function random_bytes($bytes)
44
+ {
45
+ try {
46
+ $bytes = RandomCompat_intval($bytes);
47
+ } catch (TypeError $ex) {
48
+ throw new TypeError(
49
+ 'random_bytes(): $bytes must be an integer'
50
+ );
51
+ }
52
+
53
+ if ($bytes < 1) {
54
+ throw new Error(
55
+ 'Length must be greater than 0'
56
+ );
57
+ }
58
+
59
+ /**
60
+ * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
61
+ * generated in one invocation.
62
+ */
63
+ if ($bytes > 2147483647) {
64
+ $buf = '';
65
+ for ($i = 0; $i < $bytes; $i += 1073741824) {
66
+ $n = ($bytes - $i) > 1073741824
67
+ ? 1073741824
68
+ : $bytes - $i;
69
+ $buf .= \Sodium\randombytes_buf($n);
70
+ }
71
+ } else {
72
+ $buf = \Sodium\randombytes_buf($bytes);
73
+ }
74
+
75
+ if ($buf !== false) {
76
+ if (RandomCompat_strlen($buf) === $bytes) {
77
+ return $buf;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * If we reach here, PHP has failed us.
83
+ */
84
+ throw new Exception(
85
+ 'Could not gather sufficient random data'
86
+ );
87
+ }
88
+ }
src/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!is_callable('random_bytes')) {
30
+ /**
31
+ * If the libsodium PHP extension is loaded, we'll use it above any other
32
+ * solution.
33
+ *
34
+ * libsodium-php project:
35
+ * @ref https://github.com/jedisct1/libsodium-php
36
+ *
37
+ * @param int $bytes
38
+ *
39
+ * @throws Exception
40
+ *
41
+ * @return string
42
+ */
43
+ function random_bytes($bytes)
44
+ {
45
+ try {
46
+ $bytes = RandomCompat_intval($bytes);
47
+ } catch (TypeError $ex) {
48
+ throw new TypeError(
49
+ 'random_bytes(): $bytes must be an integer'
50
+ );
51
+ }
52
+
53
+ if ($bytes < 1) {
54
+ throw new Error(
55
+ 'Length must be greater than 0'
56
+ );
57
+ }
58
+
59
+ /**
60
+ * @var string
61
+ */
62
+ $buf = '';
63
+
64
+ /**
65
+ * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
66
+ * generated in one invocation.
67
+ */
68
+ if ($bytes > 2147483647) {
69
+ for ($i = 0; $i < $bytes; $i += 1073741824) {
70
+ $n = ($bytes - $i) > 1073741824
71
+ ? 1073741824
72
+ : $bytes - $i;
73
+ $buf .= Sodium::randombytes_buf($n);
74
+ }
75
+ } else {
76
+ $buf .= Sodium::randombytes_buf($bytes);
77
+ }
78
+
79
+ if (is_string($buf)) {
80
+ if (RandomCompat_strlen($buf) === $bytes) {
81
+ return $buf;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * If we reach here, PHP has failed us.
87
+ */
88
+ throw new Exception(
89
+ 'Could not gather sufficient random data'
90
+ );
91
+ }
92
+ }
src/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Random_* Compatibility Library
4
+ * for using the new PHP 7 random_* API in PHP 5 projects
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ * of this software and associated documentation files (the "Software"), to deal
12
+ * in the Software without restriction, including without limitation the rights
13
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ * copies of the Software, and to permit persons to whom the Software is
15
+ * furnished to do so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in
18
+ * all copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ */
28
+
29
+ if (!is_callable('random_bytes')) {
30
+ /**
31
+ * Powered by ext/mcrypt (and thankfully NOT libmcrypt)
32
+ *
33
+ * @ref https://bugs.php.net/bug.php?id=55169
34
+ * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386
35
+ *
36
+ * @param int $bytes
37
+ *
38
+ * @throws Exception
39
+ *
40
+ * @return string
41
+ */
42
+ function random_bytes($bytes)
43
+ {
44
+ try {
45
+ $bytes = RandomCompat_intval($bytes);
46
+ } catch (TypeError $ex) {
47
+ throw new TypeError(
48
+ 'random_bytes(): $bytes must be an integer'
49
+ );
50
+ }
51
+
52
+ if ($bytes < 1) {
53
+ throw new Error(
54
+ 'Length must be greater than 0'
55
+ );
56
+ }
57
+
58
+ $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
59
+ if (
60
+ $buf !== false
61
+ &&
62
+ RandomCompat_strlen($buf) === $bytes
63
+ ) {
64
+ /**
65
+ * Return our random entropy buffer here:
66
+ */
67
+ return $buf;
68
+ }
69
+
70
+ /**
71
+ * If we reach here, PHP has failed us.
72
+ */
73
+ throw new Exception(
74
+ 'Could not gather sufficient random data'
75
+ );
76
+ }
77
+ }
src/vendor/paragonie/random_compat/lib/random_int.php ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!is_callable('random_int')) {
4
+ /**
5
+ * Random_* Compatibility Library
6
+ * for using the new PHP 7 random_* API in PHP 5 projects
7
+ *
8
+ * The MIT License (MIT)
9
+ *
10
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
11
+ *
12
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ * of this software and associated documentation files (the "Software"), to deal
14
+ * in the Software without restriction, including without limitation the rights
15
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ * copies of the Software, and to permit persons to whom the Software is
17
+ * furnished to do so, subject to the following conditions:
18
+ *
19
+ * The above copyright notice and this permission notice shall be included in
20
+ * all copies or substantial portions of the Software.
21
+ *
22
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ * SOFTWARE.
29
+ */
30
+
31
+ /**
32
+ * Fetch a random integer between $min and $max inclusive
33
+ *
34
+ * @param int $min
35
+ * @param int $max
36
+ *
37
+ * @throws Exception
38
+ *
39
+ * @return int
40
+ */
41
+ function random_int($min, $max)
42
+ {
43
+ /**
44
+ * Type and input logic checks
45
+ *
46
+ * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
47
+ * (non-inclusive), it will sanely cast it to an int. If you it's equal to
48
+ * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
49
+ * lose precision, so the <= and => operators might accidentally let a float
50
+ * through.
51
+ */
52
+
53
+ try {
54
+ $min = RandomCompat_intval($min);
55
+ } catch (TypeError $ex) {
56
+ throw new TypeError(
57
+ 'random_int(): $min must be an integer'
58
+ );
59
+ }
60
+
61
+ try {
62
+ $max = RandomCompat_intval($max);
63
+ } catch (TypeError $ex) {
64
+ throw new TypeError(
65
+ 'random_int(): $max must be an integer'
66
+ );
67
+ }
68
+
69
+ /**
70
+ * Now that we've verified our weak typing system has given us an integer,
71
+ * let's validate the logic then we can move forward with generating random
72
+ * integers along a given range.
73
+ */
74
+ if ($min > $max) {
75
+ throw new Error(
76
+ 'Minimum value must be less than or equal to the maximum value'
77
+ );
78
+ }
79
+
80
+ if ($max === $min) {
81
+ return $min;
82
+ }
83
+
84
+ /**
85
+ * Initialize variables to 0
86
+ *
87
+ * We want to store:
88
+ * $bytes => the number of random bytes we need
89
+ * $mask => an integer bitmask (for use with the &) operator
90
+ * so we can minimize the number of discards
91
+ */
92
+ $attempts = $bits = $bytes = $mask = $valueShift = 0;
93
+
94
+ /**
95
+ * At this point, $range is a positive number greater than 0. It might
96
+ * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
97
+ * a float and we will lose some precision.
98
+ */
99
+ $range = $max - $min;
100
+
101
+ /**
102
+ * Test for integer overflow:
103
+ */
104
+ if (!is_int($range)) {
105
+
106
+ /**
107
+ * Still safely calculate wider ranges.
108
+ * Provided by @CodesInChaos, @oittaa
109
+ *
110
+ * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
111
+ *
112
+ * We use ~0 as a mask in this case because it generates all 1s
113
+ *
114
+ * @ref https://eval.in/400356 (32-bit)
115
+ * @ref http://3v4l.org/XX9r5 (64-bit)
116
+ */
117
+ $bytes = PHP_INT_SIZE;
118
+ $mask = ~0;
119
+
120
+ } else {
121
+
122
+ /**
123
+ * $bits is effectively ceil(log($range, 2)) without dealing with
124
+ * type juggling
125
+ */
126
+ while ($range > 0) {
127
+ if ($bits % 8 === 0) {
128
+ ++$bytes;
129
+ }
130
+ ++$bits;
131
+ $range >>= 1;
132
+ $mask = $mask << 1 | 1;
133
+ }
134
+ $valueShift = $min;
135
+ }
136
+
137
+ $val = 0;
138
+ /**
139
+ * Now that we have our parameters set up, let's begin generating
140
+ * random integers until one falls between $min and $max
141
+ */
142
+ do {
143
+ /**
144
+ * The rejection probability is at most 0.5, so this corresponds
145
+ * to a failure probability of 2^-128 for a working RNG
146
+ */
147
+ if ($attempts > 128) {
148
+ throw new Exception(
149
+ 'random_int: RNG is broken - too many rejections'
150
+ );
151
+ }
152
+
153
+ /**
154
+ * Let's grab the necessary number of random bytes
155
+ */
156
+ $randomByteString = random_bytes($bytes);
157
+
158
+ /**
159
+ * Let's turn $randomByteString into an integer
160
+ *
161
+ * This uses bitwise operators (<< and |) to build an integer
162
+ * out of the values extracted from ord()
163
+ *
164
+ * Example: [9F] | [6D] | [32] | [0C] =>
165
+ * 159 + 27904 + 3276800 + 201326592 =>
166
+ * 204631455
167
+ */
168
+ $val &= 0;
169
+ for ($i = 0; $i < $bytes; ++$i) {
170
+ $val |= ord($randomByteString[$i]) << ($i * 8);
171
+ }
172
+
173
+ /**
174
+ * Apply mask
175
+ */
176
+ $val &= $mask;
177
+ $val += $valueShift;
178
+
179
+ ++$attempts;
180
+ /**
181
+ * If $val overflows to a floating point number,
182
+ * ... or is larger than $max,
183
+ * ... or smaller than $min,
184
+ * then try again.
185
+ */
186
+ } while (!is_int($val) || $val > $max || $val < $min);
187
+
188
+ return (int)$val;
189
+ }
190
+ }
src/vendor/paragonie/random_compat/other/build_phar.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $dist = dirname(__DIR__).'/dist';
3
+ if (!is_dir($dist)) {
4
+ mkdir($dist, 0755);
5
+ }
6
+ if (file_exists($dist.'/random_compat.phar')) {
7
+ unlink($dist.'/random_compat.phar');
8
+ }
9
+ $phar = new Phar(
10
+ $dist.'/random_compat.phar',
11
+ FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME,
12
+ 'random_compat.phar'
13
+ );
14
+ rename(
15
+ dirname(__DIR__).'/lib/random.php',
16
+ dirname(__DIR__).'/lib/index.php'
17
+ );
18
+ $phar->buildFromDirectory(dirname(__DIR__).'/lib');
19
+ rename(
20
+ dirname(__DIR__).'/lib/index.php',
21
+ dirname(__DIR__).'/lib/random.php'
22
+ );
23
+
24
+ /**
25
+ * If we pass an (optional) path to a private key as a second argument, we will
26
+ * sign the Phar with OpenSSL.
27
+ *
28
+ * If you leave this out, it will produce an unsigned .phar!
29
+ */
30
+ if ($argc > 1) {
31
+ if (!@is_readable($argv[1])) {
32
+ echo 'Could not read the private key file:', $argv[1], "\n";
33
+ exit(255);
34
+ }
35
+ $pkeyFile = file_get_contents($argv[1]);
36
+
37
+ $private = openssl_get_privatekey($pkeyFile);
38
+ if ($private !== false) {
39
+ $pkey = '';
40
+ openssl_pkey_export($private, $pkey);
41
+ $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
42
+
43
+ /**
44
+ * Save the corresponding public key to the file
45
+ */
46
+ if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
47
+ $details = openssl_pkey_get_details($private);
48
+ file_put_contents(
49
+ $dist.'/random_compat.phar.pubkey',
50
+ $details['key']
51
+ );
52
+ }
53
+ } else {
54
+ echo 'An error occurred reading the private key from OpenSSL.', "\n";
55
+ exit(255);
56
+ }
57
+ }
src/vendor/paragonie/random_compat/psalm-autoload.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once 'lib/byte_safe_strings.php';
4
+ require_once 'lib/cast_to_int.php';
5
+ require_once 'lib/error_polyfill.php';
6
+ require_once 'other/ide_stubs/libsodium.php';
7
+ require_once 'lib/random.php';
8
+
9
+ $int = random_int(0, 65536);
src/vendor/paragonie/random_compat/psalm.xml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <psalm
3
+ autoloader="psalm-autoload.php"
4
+ stopOnFirstError="false"
5
+ useDocblockTypes="true"
6
+ >
7
+ <projectFiles>
8
+ <directory name="lib" />
9
+ </projectFiles>
10
+ <issueHandlers>
11
+ <InvalidOperand errorLevel="info" />
12
+ <UndefinedConstant errorLevel="info" />
13
+ <MissingReturnType errorLevel="info" />
14
+ </issueHandlers>
15
+ </psalm>