Version Description
= v160801 =
(Maintenance Release) Upgrade immediately.
Download this release
Release Info
Developer | raamdev |
Plugin | s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members) |
Version | 170524 |
Comparing to | |
See all releases |
Code changes from version 170221 to 170524
- readme.txt +34 -4
- s2member.php +5 -5
- src/includes/classes/admin-notices.inc.php +2 -2
- src/includes/classes/files-in.inc.php +1 -1
- src/includes/classes/querys.inc.php +10 -10
- src/includes/classes/registrations.inc.php +1 -1
- src/includes/classes/sc-eots-in.inc.php +3 -1
- src/includes/classes/utils-defuse.inc.php +131 -0
- src/includes/classes/utils-encryption.inc.php +224 -228
- src/includes/classes/utils-time.inc.php +11 -10
- src/includes/functions/class-autoloader.inc.php +1 -0
- src/includes/menu-pages/api-ops.inc.php +2 -0
- src/includes/menu-pages/down-ops.inc.php +2 -0
- src/includes/menu-pages/els-ops.inc.php +2 -0
- src/includes/menu-pages/gen-ops.inc.php +2 -0
- src/includes/menu-pages/help.inc.php +2 -0
- src/includes/menu-pages/integrations.inc.php +2 -0
- src/includes/menu-pages/logs.inc.php +2 -0
- src/includes/menu-pages/menu-pages-s.min.js +2 -1
- src/includes/menu-pages/menu-pages.css +105 -106
- src/includes/menu-pages/menu-pages.js +3 -3
- src/includes/menu-pages/menu-pages.min.js +1 -1
- src/includes/menu-pages/mms-ops.inc.php +2 -0
- src/includes/menu-pages/paypal-buttons.inc.php +2 -0
- src/includes/menu-pages/paypal-ops.inc.php +3 -1
- src/includes/menu-pages/res-ops.inc.php +2 -0
- src/includes/menu-pages/scripting.inc.php +4 -2
- src/includes/menu-pages/start.inc.php +2 -0
- src/includes/menu-pages/trk-ops.inc.php +2 -0
- src/includes/syscon.inc.php +19 -2
- src/includes/translations/s2member.pot +48 -48
- src/vendor/autoload.php +1 -1
- src/vendor/composer/autoload_classmap.php +14 -0
- src/vendor/composer/autoload_files.php +10 -0
- src/vendor/composer/autoload_real.php +17 -3
- src/vendor/composer/installed.json +113 -1
- src/vendor/defuse/php-encryption/LICENSE +21 -0
- src/vendor/defuse/php-encryption/dist/Makefile +37 -0
- src/vendor/defuse/php-encryption/dist/box.json +25 -0
- src/vendor/defuse/php-encryption/dist/signingkey.asc +52 -0
- src/vendor/defuse/php-encryption/src/Core.php +434 -0
- src/vendor/defuse/php-encryption/src/Crypto.php +372 -0
- src/vendor/defuse/php-encryption/src/DerivedKeys.php +37 -0
- src/vendor/defuse/php-encryption/src/Encoding.php +212 -0
- src/vendor/defuse/php-encryption/src/Exception/BadFormatException.php +7 -0
- src/vendor/defuse/php-encryption/src/Exception/CryptoException.php +7 -0
- src/vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php +7 -0
- src/vendor/defuse/php-encryption/src/Exception/IOException.php +7 -0
- src/vendor/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php +7 -0
- src/vendor/defuse/php-encryption/src/File.php +755 -0
- src/vendor/defuse/php-encryption/src/Key.php +84 -0
- src/vendor/defuse/php-encryption/src/KeyOrPassword.php +119 -0
- src/vendor/defuse/php-encryption/src/KeyProtectedByPassword.php +112 -0
- src/vendor/defuse/php-encryption/src/RuntimeTests.php +242 -0
- src/vendor/paragonie/random_compat/LICENSE +22 -0
- src/vendor/paragonie/random_compat/build-phar.sh +5 -0
- src/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey +5 -0
- src/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc +11 -0
- src/vendor/paragonie/random_compat/lib/byte_safe_strings.php +181 -0
- src/vendor/paragonie/random_compat/lib/cast_to_int.php +74 -0
- src/vendor/paragonie/random_compat/lib/error_polyfill.php +49 -0
- src/vendor/paragonie/random_compat/lib/random.php +223 -0
- src/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php +88 -0
- src/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php +167 -0
- src/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php +88 -0
- src/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php +92 -0
- src/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php +77 -0
- src/vendor/paragonie/random_compat/lib/random_int.php +190 -0
- src/vendor/paragonie/random_compat/other/build_phar.php +57 -0
- src/vendor/paragonie/random_compat/psalm-autoload.php +9 -0
- 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:
|
4 |
-
Stable tag:
|
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.
|
21 |
Requires at least: 4.2
|
22 |
|
23 |
Requires PHP: 5.2
|
24 |
-
Tested up to PHP: 7.0.
|
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:
|
24 |
-
Stable tag:
|
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.
|
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'] = '
|
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'] = '
|
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
|
87 |
}
|
88 |
else if($notice && is_string($notice))
|
89 |
{
|
90 |
if($dismiss && !empty($dismissal_link))
|
91 |
$notice = $dismissal_link.$notice;
|
92 |
-
echo '<div class="
|
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
|
53 |
*/
|
54 |
-
public static function force_query_level_access(
|
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``
|
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(
|
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
|
267 |
*/
|
268 |
-
public static function _query_level_access_sys(
|
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``
|
344 |
*
|
345 |
* @return string The revised ``$cwhere`` string.
|
346 |
*/
|
347 |
-
public static function _query_level_access_coms($cwhere = '',
|
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
|
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(
|
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 |
-
|
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(
|
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 |
-
*
|
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
|
19 |
-
|
20 |
-
|
21 |
-
if(!class_exists('c_ws_plugin__s2member_utils_encryption'))
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
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 |
-
|
178 |
-
|
179 |
-
|
180 |
-
{
|
181 |
$last_paid_access_cap_time = (integer)$_time;
|
182 |
break; // Got what we need; stop here.
|
183 |
}
|
184 |
-
|
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
|
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,"&").replace(/</g,"<").replace(/>/g,">"),string=string.replace(/"/g,""").replace(/'/g,"'")}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("⇑ normalize viewport ❙");$viewer.attr("data-state","expanded")}else{$viewer.css({height:"auto","overflow-y":"scroll"});$toggles.html("⇓ expand viewport ⇓");$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"> </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"> </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"> </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"> </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"> </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"> </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"> </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 & 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 & Punctuation ('+i+" character minimum)</option>";form+='<option value="alphanumerics-spaces-punctuation-'+i+'-e"'+((field.expected==="alphanumerics-spaces-punctuation-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics, Spaces & Punctuation (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphanumerics & Spaces Only">';for(i=1;i<=25;i++){form+='<option value="alphanumerics-spaces-'+i+'"'+((field.expected==="alphanumerics-spaces-"+i)?' selected="selected"':"")+'">Alphanumerics & Spaces ('+i+" character minimum)</option>";form+='<option value="alphanumerics-spaces-'+i+'-e"'+((field.expected==="alphanumerics-spaces-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics & Spaces (exactly '+i+" character"+((i>1)?"s":"")+")</option>"}form+="</optgroup>";form+='<option disabled="disabled"></option>';form+='<optgroup label="Alphanumerics & Punctuation Only">';for(i=1;i<=25;i++){form+='<option value="alphanumerics-punctuation-'+i+'"'+((field.expected==="alphanumerics-punctuation-"+i)?' selected="selected"':"")+'">Alphanumerics & Punctuation ('+i+" character minimum)</option>";form+='<option value="alphanumerics-punctuation-'+i+'-e"'+((field.expected==="alphanumerics-punctuation-"+i+"-e")?' selected="selected"':"")+'">Alphanumerics & 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"> </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"> </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 & totally invisible after registration)</option>';form+='<option value="no-always-invisible"'+((field.editable==="no-always-invisible")?' selected="selected"':"")+'">No (uneditable & totally invisible, both during & 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"> </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"> </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"> </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"> </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"&®Term!=="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&¤cyCode.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&¤cyCode.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"&®Term!=="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&¤cyCode.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&¤cyCode.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,"&").replace(/</g,"<").replace(/>/g,">"),e=e.replace(/"/g,""").replace(/'/g,"'")),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("⇑ normalize viewport ❙"),e.attr("data-state","expanded")):(e.css({height:"auto","overflow-y":"scroll"}),$toggles.html("⇓ expand viewport ⇓"),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"> </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"> </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"> </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"> </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"> </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"> </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"> </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 & Punctuation Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-spaces-punctuation-'+l+'"'+(m.expected==="alphanumerics-spaces-punctuation-"+l?' selected="selected"':"")+'">Alphanumerics, Spaces & Punctuation ('+l+" character minimum)</option>",a+='<option value="alphanumerics-spaces-punctuation-'+l+'-e"'+(m.expected==="alphanumerics-spaces-punctuation-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics, Spaces & Punctuation (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphanumerics & Spaces Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-spaces-'+l+'"'+(m.expected==="alphanumerics-spaces-"+l?' selected="selected"':"")+'">Alphanumerics & Spaces ('+l+" character minimum)</option>",a+='<option value="alphanumerics-spaces-'+l+'-e"'+(m.expected==="alphanumerics-spaces-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics & Spaces (exactly '+l+" character"+(l>1?"s":"")+")</option>";for(a+="</optgroup>",a+='<option disabled="disabled"></option>',a+='<optgroup label="Alphanumerics & Punctuation Only">',l=1;l<=25;l++)a+='<option value="alphanumerics-punctuation-'+l+'"'+(m.expected==="alphanumerics-punctuation-"+l?' selected="selected"':"")+'">Alphanumerics & Punctuation ('+l+" character minimum)</option>",a+='<option value="alphanumerics-punctuation-'+l+'-e"'+(m.expected==="alphanumerics-punctuation-"+l+"-e"?' selected="selected"':"")+'">Alphanumerics & 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"> </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"> </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 & totally invisible after registration)</option>',a+='<option value="no-always-invisible"'+("no-always-invisible"===m.editable?' selected="selected"':"")+'">No (uneditable & totally invisible, both during & 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"> </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"> </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"> </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"> </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 |
-
|
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 >
|
60 |
-
div.ws-menu-page >
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
{
|
62 |
font-size : inherit;
|
63 |
}
|
64 |
-
div.ws-menu-page > :not(.
|
65 |
{
|
66 |
color : #336695;
|
67 |
}
|
68 |
-
div.ws-menu-page > :not(.
|
69 |
-
div.ws-menu-page > :not(.
|
70 |
{
|
71 |
color : #027E02;
|
72 |
}
|
73 |
-
div.ws-menu-page > :not(.
|
74 |
-
div.ws-menu-page > :not(.
|
75 |
{
|
76 |
margin-top : 0;
|
77 |
}
|
78 |
-
div.ws-menu-page > :not(.
|
79 |
-
div.ws-menu-page > :not(.
|
80 |
{
|
81 |
margin-bottom : 0;
|
82 |
}
|
83 |
-
div.ws-menu-page > :not(.
|
84 |
{
|
85 |
margin-top : 0;
|
86 |
}
|
87 |
-
div.ws-menu-page > :not(.
|
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(.
|
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(.
|
146 |
{
|
147 |
padding : 0;
|
148 |
background : none;
|
149 |
}
|
150 |
-
div.ws-menu-page > :not(.
|
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(.
|
164 |
-
div.ws-menu-page > :not(.
|
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(.
|
180 |
{
|
181 |
border : 0;
|
182 |
}
|
183 |
-
div.ws-menu-page > :not(.
|
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(.
|
192 |
{
|
193 |
margin-left : 25px;
|
194 |
float : right;
|
195 |
}
|
196 |
-
div.ws-menu-page > :not(.
|
197 |
{
|
198 |
margin-right : 25px;
|
199 |
float : left;
|
200 |
}
|
201 |
-
div.ws-menu-page > :not(.
|
202 |
{
|
203 |
margin-left : auto;
|
204 |
margin-right : auto;
|
205 |
display : block;
|
206 |
}
|
207 |
-
div.ws-menu-page > :not(.
|
208 |
-
div.ws-menu-page > :not(.
|
209 |
{
|
210 |
margin-top : 8px;
|
211 |
margin-bottom : 8px;
|
212 |
}
|
213 |
-
div.ws-menu-page > :not(.
|
214 |
-
div.ws-menu-page > :not(.
|
215 |
{
|
216 |
margin-top : 0;
|
217 |
}
|
218 |
-
div.ws-menu-page > :not(.
|
219 |
-
div.ws-menu-page > :not(.
|
220 |
{
|
221 |
margin-bottom : 0;
|
222 |
}
|
223 |
-
div.ws-menu-page > :not(.
|
224 |
{
|
225 |
height : 1px;
|
226 |
line-height : 1px;
|
227 |
-
background : #
|
228 |
margin : 10px 0 10px 0;
|
229 |
}
|
230 |
-
div.ws-menu-page > :not(.
|
231 |
{
|
232 |
color : #962722;
|
233 |
}
|
234 |
-
div.ws-menu-page > :not(.
|
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(.
|
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(.
|
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(.
|
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(.
|
267 |
{
|
268 |
border : 0;
|
269 |
width : 16px;
|
270 |
height : 16px;
|
271 |
}
|
272 |
-
div.ws-menu-page > :not(.
|
273 |
{
|
274 |
font-size : inherit;
|
275 |
line-height : inherit;
|
276 |
}
|
277 |
-
div.ws-menu-page > :not(.
|
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(.
|
286 |
-
div.ws-menu-page > :not(.
|
287 |
-
div.ws-menu-page > :not(.
|
288 |
-
div.ws-menu-page > :not(.
|
289 |
-
div.ws-menu-page > :not(.
|
290 |
-
div.ws-menu-page > :not(.
|
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(.
|
303 |
-
div.ws-menu-page > :not(.
|
304 |
-
div.ws-menu-page > :not(.
|
305 |
-
div.ws-menu-page > :not(.
|
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(.
|
311 |
-
div.ws-menu-page > :not(.
|
312 |
{
|
313 |
height : auto; /* Textareas auto. */
|
314 |
white-space : pre; /* Preserve whitespace. */
|
315 |
}
|
316 |
-
div.ws-menu-page > :not(.
|
317 |
-
div.ws-menu-page > :not(.
|
318 |
-
div.ws-menu-page > :not(.
|
319 |
-
div.ws-menu-page > :not(.
|
320 |
-
div.ws-menu-page > :not(.
|
321 |
-
div.ws-menu-page > :not(.
|
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(.
|
329 |
-
div.ws-menu-page > :not(.
|
330 |
-
div.ws-menu-page > :not(.
|
331 |
{
|
332 |
color : #F7F7F7;
|
333 |
background : #73834B;
|
334 |
}
|
335 |
-
div.ws-menu-page > :not(.
|
336 |
-
div.ws-menu-page > :not(.
|
337 |
-
div.ws-menu-page > :not(.
|
338 |
{
|
339 |
background : #637041;
|
340 |
}
|
341 |
-
div.ws-menu-page > :not(.
|
342 |
{
|
343 |
padding-top : .1em;
|
344 |
font-style : italic;
|
345 |
color : rgba(255, 255, 255, 0.2);
|
346 |
}
|
347 |
-
div.ws-menu-page > :not(.
|
348 |
{
|
349 |
padding-top : .1em;
|
350 |
font-style : italic;
|
351 |
color : rgba(255, 255, 255, 0.2);
|
352 |
}
|
353 |
-
div.ws-menu-page > :not(.
|
354 |
{
|
355 |
padding-top : .1em;
|
356 |
font-style : italic;
|
357 |
color : rgba(255, 255, 255, 0.2);
|
358 |
}
|
359 |
-
div.ws-menu-page > :not(.
|
360 |
{
|
361 |
padding-top : .1em;
|
362 |
font-style : italic;
|
363 |
color : rgba(255, 255, 255, 0.2);
|
364 |
}
|
365 |
-
div.ws-menu-page > :not(.
|
366 |
-
div.ws-menu-page > :not(.
|
367 |
-
div.ws-menu-page > :not(.
|
368 |
{
|
369 |
opacity : 0.5;
|
370 |
}
|
371 |
-
div.ws-menu-page > :not(.
|
372 |
-
div.ws-menu-page > :not(.
|
373 |
-
div.ws-menu-page > :not(.
|
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(.
|
396 |
-
div.ws-menu-page > :not(.
|
397 |
-
div.ws-menu-page > :not(.
|
398 |
{
|
399 |
background : #0D1F2F;
|
400 |
}
|
401 |
-
div.ws-menu-page > :not(.
|
402 |
-
div.ws-menu-page > :not(.
|
403 |
-
div.ws-menu-page > :not(.
|
404 |
{
|
405 |
-webkit-transform : scale(0.98, 0.98);
|
406 |
transform : scale(0.98, 0.98);
|
407 |
}
|
408 |
-
div.ws-menu-page > :not(.
|
409 |
-
div.ws-menu-page > :not(.
|
410 |
{
|
411 |
font-size : 150%;
|
412 |
font-weight : 600;
|
413 |
background : #5F7523;
|
414 |
}
|
415 |
-
div.ws-menu-page > :not(.
|
416 |
-
div.ws-menu-page > :not(.
|
417 |
{
|
418 |
background : #4C6324;
|
419 |
}
|
420 |
-
div.ws-menu-page > :not(.
|
421 |
-
div.ws-menu-page > :not(.
|
422 |
{
|
423 |
width : 100%;
|
424 |
}
|
425 |
-
div.ws-menu-page > :not(.
|
426 |
{
|
427 |
width : auto !important;
|
428 |
}
|
429 |
-
div.ws-menu-page > :not(.
|
430 |
{
|
431 |
opacity : 0.5;
|
432 |
}
|
433 |
-
div.ws-menu-page > :not(.
|
434 |
-
div.ws-menu-page > :not(.
|
435 |
-
div.ws-menu-page > :not(.
|
436 |
-
div.ws-menu-page > :not(.
|
437 |
{
|
438 |
border-radius : 5px;
|
439 |
padding : 10px;
|
440 |
margin : 0 0 25px 0;
|
441 |
}
|
442 |
-
div.ws-menu-page > :not(.
|
443 |
{
|
444 |
background : #C9E0FA;
|
445 |
border : 1px solid #35558A;
|
446 |
}
|
447 |
-
div.ws-menu-page > :not(.
|
448 |
{
|
449 |
background : #FFFBCC;
|
450 |
border : 1px solid #E6DB55;
|
451 |
}
|
452 |
-
div.ws-menu-page > :not(.
|
453 |
{
|
454 |
background : #FADDAB;
|
455 |
border : 1px solid #D29A04;
|
456 |
}
|
457 |
-
div.ws-menu-page > :not(.
|
458 |
{
|
459 |
background : #FABBC6;
|
460 |
border : 1px solid #711E1E;
|
461 |
}
|
462 |
-
div.ws-menu-page > :not(.
|
463 |
{
|
464 |
font-family : 'Monaco', 'Menlo', 'Consolas', 'Courier New', monospace;
|
465 |
}
|
466 |
-
div.ws-menu-page > :not(.
|
467 |
{
|
468 |
white-space : pre;
|
469 |
}
|
470 |
-
div.ws-menu-page > :not(.
|
471 |
-
div.ws-menu-page > :not(.
|
472 |
{
|
473 |
display : table;
|
474 |
content : ' ';
|
475 |
}
|
476 |
-
div.ws-menu-page > :not(.
|
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': '#
|
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': '#
|
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
|
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 |
-
|
|
|
|
|
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 |
-
|
36 |
|
37 |
-
echo '<div class="
|
|
|
|
|
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:
|
6 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/s2member\n"
|
7 |
-
"POT-Creation-Date: 2017-
|
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:
|
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:
|
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:
|
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:
|
4553 |
msgctxt "s2member-front"
|
4554 |
msgid "Access Expires:"
|
4555 |
msgstr ""
|
4556 |
|
4557 |
-
#: src/includes/classes/sc-eots-in.inc.php:
|
4558 |
msgctxt "s2member-front"
|
4559 |
msgid "Access Expired:"
|
4560 |
msgstr ""
|
4561 |
|
4562 |
-
#: src/includes/classes/sc-eots-in.inc.php:
|
4563 |
msgctxt "s2member-front"
|
4564 |
msgid "Next Payment:"
|
4565 |
msgstr ""
|
4566 |
|
4567 |
-
#: src/includes/classes/sc-eots-in.inc.php:
|
4568 |
msgctxt "s2member-front"
|
4569 |
msgid "N/A"
|
4570 |
msgstr ""
|
4571 |
|
4572 |
-
#: src/includes/classes/sc-eots-in.inc.php:
|
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:
|
4749 |
msgctxt "s2member-front"
|
4750 |
msgid "Daily"
|
4751 |
msgstr ""
|
4752 |
|
4753 |
-
#: src/includes/classes/utils-time.inc.php:
|
4754 |
msgctxt "s2member-front"
|
4755 |
msgid "Weekly"
|
4756 |
msgstr ""
|
4757 |
|
4758 |
-
#: src/includes/classes/utils-time.inc.php:
|
4759 |
msgctxt "s2member-front"
|
4760 |
msgid "Monthly"
|
4761 |
msgstr ""
|
4762 |
|
4763 |
-
#: src/includes/classes/utils-time.inc.php:
|
4764 |
msgctxt "s2member-front"
|
4765 |
msgid "Yearly"
|
4766 |
msgstr ""
|
4767 |
|
4768 |
-
#: src/includes/classes/utils-time.inc.php:
|
4769 |
-
#: src/includes/classes/utils-time.inc.php:
|
4770 |
msgctxt "s2member-front"
|
4771 |
msgid "Lifetime"
|
4772 |
msgstr ""
|
4773 |
|
4774 |
-
#: src/includes/classes/utils-time.inc.php:
|
4775 |
msgctxt "s2member-front"
|
4776 |
msgid "Bi-Weekly"
|
4777 |
msgstr ""
|
4778 |
|
4779 |
-
#: src/includes/classes/utils-time.inc.php:
|
4780 |
msgctxt "s2member-front"
|
4781 |
msgid "Bi-Monthly"
|
4782 |
msgstr ""
|
4783 |
|
4784 |
-
#: src/includes/classes/utils-time.inc.php:
|
4785 |
msgctxt "s2member-front"
|
4786 |
msgid "Quarterly"
|
4787 |
msgstr ""
|
4788 |
|
4789 |
-
#: src/includes/classes/utils-time.inc.php:
|
4790 |
msgctxt "s2member-front"
|
4791 |
msgid "Semi-Yearly"
|
4792 |
msgstr ""
|
4793 |
|
4794 |
-
#: src/includes/classes/utils-time.inc.php:
|
4795 |
msgctxt "s2member-front"
|
4796 |
msgid "Day"
|
4797 |
msgstr ""
|
4798 |
|
4799 |
-
#: src/includes/classes/utils-time.inc.php:
|
4800 |
msgctxt "s2member-front"
|
4801 |
msgid "Week"
|
4802 |
msgstr ""
|
4803 |
|
4804 |
-
#: src/includes/classes/utils-time.inc.php:
|
4805 |
msgctxt "s2member-front"
|
4806 |
msgid "Month"
|
4807 |
msgstr ""
|
4808 |
|
4809 |
-
#: src/includes/classes/utils-time.inc.php:
|
4810 |
msgctxt "s2member-front"
|
4811 |
msgid "Year"
|
4812 |
msgstr ""
|
4813 |
|
4814 |
-
#: src/includes/classes/utils-time.inc.php:
|
4815 |
msgctxt "s2member-front"
|
4816 |
msgid "Days"
|
4817 |
msgstr ""
|
4818 |
|
4819 |
-
#: src/includes/classes/utils-time.inc.php:
|
4820 |
msgctxt "s2member-front"
|
4821 |
msgid "Weeks"
|
4822 |
msgstr ""
|
4823 |
|
4824 |
-
#: src/includes/classes/utils-time.inc.php:
|
4825 |
msgctxt "s2member-front"
|
4826 |
msgid "Months"
|
4827 |
msgstr ""
|
4828 |
|
4829 |
-
#: src/includes/classes/utils-time.inc.php:
|
4830 |
msgctxt "s2member-front"
|
4831 |
msgid "Years"
|
4832 |
msgstr ""
|
4833 |
|
4834 |
-
#: src/includes/classes/utils-time.inc.php:
|
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:
|
4842 |
-
#: src/includes/classes/utils-time.inc.php:
|
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:
|
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:
|
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:
|
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:
|
5005 |
msgctxt "s2member-front"
|
5006 |
msgid "Yes, I want to receive updates via email."
|
5007 |
msgstr ""
|
5008 |
|
5009 |
-
#: src/includes/syscon.inc.php:
|
5010 |
msgctxt "s2member-front"
|
5011 |
msgid "[%s] Username/Password"
|
5012 |
msgstr ""
|
5013 |
|
5014 |
-
#: src/includes/syscon.inc.php:
|
5015 |
msgctxt "s2member-front"
|
5016 |
msgid "[%s] New User Registration"
|
5017 |
msgstr ""
|
5018 |
|
5019 |
-
#: src/includes/syscon.inc.php:
|
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:
|
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:
|
5048 |
msgctxt "s2member-front"
|
5049 |
msgid "Thank you! Your account has been updated."
|
5050 |
msgstr ""
|
5051 |
|
5052 |
-
#: src/includes/syscon.inc.php:
|
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:
|
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:
|
5081 |
msgctxt "s2member-front"
|
5082 |
msgid "Free Subscriber"
|
5083 |
msgstr ""
|
5084 |
|
5085 |
-
#: src/includes/syscon.inc.php:
|
5086 |
msgctxt "s2member-front"
|
5087 |
msgid "Bronze Member"
|
5088 |
msgstr ""
|
5089 |
|
5090 |
-
#: src/includes/syscon.inc.php:
|
5091 |
msgctxt "s2member-front"
|
5092 |
msgid "Silver Member"
|
5093 |
msgstr ""
|
5094 |
|
5095 |
-
#: src/includes/syscon.inc.php:
|
5096 |
msgctxt "s2member-front"
|
5097 |
msgid "Gold Member"
|
5098 |
msgstr ""
|
5099 |
|
5100 |
-
#: src/includes/syscon.inc.php:
|
5101 |
msgctxt "s2member-front"
|
5102 |
msgid "Platinum Member"
|
5103 |
msgstr ""
|
5104 |
|
5105 |
-
#: src/includes/syscon.inc.php:
|
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
|
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
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit70c0498e8019a5c38acfc616c0b849f8
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
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>
|