Wordfence Login Security - Version 1.0.2

Version Description

  • May 30, 2019 =
  • Initial release
Download this release

Release Info

Developer wfryan
Plugin Icon 128x128 Wordfence Login Security
Version 1.0.2
Comparing to
See all releases

Version 1.0.2

Files changed (96) hide show
  1. classes/.htaccess +16 -0
  2. classes/controller/ajax.php +449 -0
  3. classes/controller/captcha.php +117 -0
  4. classes/controller/cron.php +1 -0
  5. classes/controller/db.php +87 -0
  6. classes/controller/notices.php +166 -0
  7. classes/controller/permissions.php +124 -0
  8. classes/controller/settings.php +380 -0
  9. classes/controller/support.php +49 -0
  10. classes/controller/time.php +185 -0
  11. classes/controller/totp.php +153 -0
  12. classes/controller/users.php +577 -0
  13. classes/controller/whitelist.php +317 -0
  14. classes/controller/wordfencels.php +771 -0
  15. classes/model/asset.php +32 -0
  16. classes/model/compat.php +10 -0
  17. classes/model/crypto.php +293 -0
  18. classes/model/crypto/base2n.php +304 -0
  19. classes/model/crypto/jwt.php +136 -0
  20. classes/model/crypto/symmetric.php +49 -0
  21. classes/model/ip.php +187 -0
  22. classes/model/notice.php +31 -0
  23. classes/model/request.php +193 -0
  24. classes/model/settings.php +21 -0
  25. classes/model/settings/db.php +122 -0
  26. classes/model/settings/wpoptions.php +69 -0
  27. classes/model/text/html.php +26 -0
  28. classes/model/text/javascript.php +38 -0
  29. classes/model/tokenbucket.php +195 -0
  30. classes/model/view.php +130 -0
  31. classes/model/view/tab.php +46 -0
  32. classes/model/view/title.php +40 -0
  33. css/admin-global.1559237323.css +1 -0
  34. css/admin.1559237323.css +1 -0
  35. css/colorbox.1559237323.css +1 -0
  36. css/font-awesome.1559237323.css +4 -0
  37. css/ionicons.1559237323.css +1 -0
  38. css/jquery-ui-timepicker-addon.1559237323.css +1 -0
  39. css/jquery-ui.min.1559237323.css +5 -0
  40. css/jquery-ui.structure.min.1559237323.css +3 -0
  41. css/jquery-ui.theme.min.1559237323.css +3 -0
  42. css/login.1559237323.css +1 -0
  43. font/fontawesome-webfont.woff +0 -0
  44. font/ionicons.woff +0 -0
  45. img/header.svg +14 -0
  46. img/lightbox-controls.png +0 -0
  47. img/loading.gif +0 -0
  48. img/loading_background.png +0 -0
  49. img/menu.svg +14 -0
  50. img/ui-icons_444444_256x240.png +0 -0
  51. img/ui-icons_555555_256x240.png +0 -0
  52. img/ui-icons_777620_256x240.png +0 -0
  53. img/ui-icons_777777_256x240.png +0 -0
  54. img/ui-icons_cc0000_256x240.png +0 -0
  55. img/ui-icons_ffffff_256x240.png +0 -0
  56. js/admin-global.1559237323.js +67 -0
  57. js/admin.1559237323.js +842 -0
  58. js/jquery-ui-timepicker-addon.1559237323.js +2291 -0
  59. js/jquery.colorbox.1559237323.js +1105 -0
  60. js/jquery.colorbox.min.1559237323.js +1 -0
  61. js/jquery.qrcode.min.1559237323.js +28 -0
  62. js/jquery.tmpl.min.1559237323.js +10 -0
  63. js/login.1559237323.js +239 -0
  64. readme.txt +62 -0
  65. views/.htaccess +16 -0
  66. views/common/modal-prompt.php +42 -0
  67. views/email/login-verification.php +22 -0
  68. views/manage/activate.php +127 -0
  69. views/manage/code.php +32 -0
  70. views/manage/deactivate.php +84 -0
  71. views/manage/regenerate.php +101 -0
  72. views/onboarding/standalone-header.php +32 -0
  73. views/options/option-captcha.php +152 -0
  74. views/options/option-ip-source.php +165 -0
  75. views/options/option-label.php +37 -0
  76. views/options/option-require-2fa.php +239 -0
  77. views/options/option-select.php +32 -0
  78. views/options/option-switch.php +43 -0
  79. views/options/option-text.php +42 -0
  80. views/options/option-textarea.php +55 -0
  81. views/options/option-toggled-boolean-switch.php +39 -0
  82. views/options/option-toggled-multiple.php +35 -0
  83. views/options/option-toggled-segmented.php +33 -0
  84. views/options/option-toggled-select.php +37 -0
  85. views/options/option-toggled-sub.php +56 -0
  86. views/options/option-toggled-textarea.php +30 -0
  87. views/options/option-toggled.php +32 -0
  88. views/options/option-token.php +39 -0
  89. views/page/manage.php +114 -0
  90. views/page/page.php +36 -0
  91. views/page/section-title.php +16 -0
  92. views/page/settings.php +23 -0
  93. views/page/tabbar.php +23 -0
  94. views/settings/options.php +125 -0
  95. views/settings/user-stats.php +57 -0
  96. wordfence-login-security.php +102 -0
classes/.htaccess ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <IfModule mod_rewrite.c>
2
+ RewriteEngine On
3
+ RewriteCond %{REQUEST_URI} \.php$
4
+ RewriteRule .* - [F,L,NC]
5
+ </IfModule>
6
+ <IfModule !mod_rewrite.c>
7
+ <FilesMatch "\.php$">
8
+ <IfModule mod_authz_core.c>
9
+ Require all denied
10
+ </IfModule>
11
+ <IfModule !mod_authz_core.c>
12
+ Order deny,allow
13
+ Deny from all
14
+ </IfModule>
15
+ </FilesMatch>
16
+ </IfModule>
classes/controller/ajax.php ADDED
@@ -0,0 +1,449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ use WordfenceLS\Crypto\Model_JWT;
6
+ use WordfenceLS\Crypto\Model_Symmetric;
7
+
8
+ class Controller_AJAX {
9
+ protected $_actions = null; //Populated on init
10
+
11
+ /**
12
+ * Returns the singleton Controller_AJAX.
13
+ *
14
+ * @return Controller_AJAX
15
+ */
16
+ public static function shared() {
17
+ static $_shared = null;
18
+ if ($_shared === null) {
19
+ $_shared = new Controller_AJAX();
20
+ }
21
+ return $_shared;
22
+ }
23
+
24
+ public function init() {
25
+ $this->_actions = array(
26
+ 'authenticate' => array(
27
+ 'handler' => array($this, '_ajax_authenticate_callback'),
28
+ 'nopriv' => true,
29
+ 'nonce' => false,
30
+ 'permissions' => array(), //Format is 'permission' => 'error message'
31
+ 'required_parameters' => array(),
32
+ ),
33
+ 'register_support' => array(
34
+ 'handler' => array($this, '_ajax_register_support_callback'),
35
+ 'nopriv' => true,
36
+ 'nonce' => false,
37
+ 'permissions' => array(),
38
+ 'required_parameters' => array('user_login', 'user_email', 'wfls-message-nonce', 'wfls-message'),
39
+ ),
40
+ 'activate' => array(
41
+ 'handler' => array($this, '_ajax_activate_callback'),
42
+ 'permissions' => array(),
43
+ 'required_parameters' => array('nonce', 'secret', 'recovery', 'code', 'user'),
44
+ ),
45
+ 'deactivate' => array(
46
+ 'handler' => array($this, '_ajax_deactivate_callback'),
47
+ 'permissions' => array(),
48
+ 'required_parameters' => array('nonce', 'user'),
49
+ ),
50
+ 'regenerate' => array(
51
+ 'handler' => array($this, '_ajax_regenerate_callback'),
52
+ 'permissions' => array(),
53
+ 'required_parameters' => array('nonce', 'user'),
54
+ ),
55
+ 'save_options' => array(
56
+ 'handler' => array($this, '_ajax_save_options_callback'),
57
+ 'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to change options.', 'wordfence-2fa')),
58
+ 'required_parameters' => array('nonce', 'changes'),
59
+ ),
60
+ 'send_grace_period_notification' => array(
61
+ 'handler' => array($this, '_ajax_send_grace_period_notification_callback'),
62
+ 'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to send notifications.', 'wordfence-2fa')),
63
+ 'required_parameters' => array('nonce'),
64
+ ),
65
+ 'update_ip_preview' => array(
66
+ 'handler' => array($this, '_ajax_update_ip_preview_callback'),
67
+ 'permissions' => array(Controller_Permissions::CAP_MANAGE_SETTINGS => __('You do not have permission to change options.', 'wordfence-2fa')),
68
+ 'required_parameters' => array('nonce', 'ip_source', 'ip_source_trusted_proxies'),
69
+ ),
70
+ 'dismiss_notice' => array(
71
+ 'handler' => array($this, '_ajax_dismiss_notice_callback'),
72
+ 'permissions' => array(),
73
+ 'required_parameters' => array('nonce', 'id'),
74
+ ),
75
+ );
76
+
77
+ $this->_init_actions();
78
+ }
79
+
80
+ public function _init_actions() {
81
+ foreach ($this->_actions as $action => $parameters) {
82
+ if (isset($parameters['nopriv']) && $parameters['nopriv']) {
83
+ add_action('wp_ajax_nopriv_wordfence_ls_' . $action, array($this, '_ajax_handler'));
84
+ }
85
+ add_action('wp_ajax_wordfence_ls_' . $action, array($this, '_ajax_handler'));
86
+ }
87
+ }
88
+
89
+ public function _ajax_handler() {
90
+ $action = (isset($_POST['action']) && is_string($_POST['action']) && $_POST['action']) ? $_POST['action'] : $_GET['action'];
91
+ if (preg_match('~wordfence_ls_([a-zA-Z_]+)$~', $action, $matches)) {
92
+ $action = $matches[1];
93
+ if (!isset($this->_actions[$action])) {
94
+ die(json_encode(array('error' => __('An unknown action was provided.', 'wordfence-2fa'))));
95
+ }
96
+
97
+ $parameters = $this->_actions[$action];
98
+ if (!empty($parameters['required_parameters'])) {
99
+ foreach ($parameters['required_parameters'] as $k) {
100
+ if (!isset($_POST[$k])) {
101
+ die(json_encode(array('error' => __('An expected parameter was not provided.', 'wordfence-2fa'))));
102
+ }
103
+ }
104
+ }
105
+
106
+ if (!isset($parameters['nonce']) || $parameters['nonce']) {
107
+ $nonce = (isset($_POST['nonce']) && is_string($_POST['nonce']) && $_POST['nonce']) ? $_POST['nonce'] : $_GET['nonce'];
108
+ if (!is_string($nonce) || !wp_verify_nonce($nonce, 'wp-ajax')) {
109
+ die(json_encode(array('error' => __('Your browser sent an invalid security token. Please try reloading this page.', 'wordfence-2fa'), 'tokenInvalid' => 1)));
110
+ }
111
+ }
112
+
113
+ if (!empty($parameters['permissions'])) {
114
+ $user = wp_get_current_user();
115
+ foreach ($parameters['permissions'] as $permission => $error) {
116
+ if (!user_can($user, $permission)) {
117
+ die(json_encode(array('error' => $error)));
118
+ }
119
+ }
120
+ }
121
+
122
+ call_user_func($parameters['handler']);
123
+ }
124
+ }
125
+
126
+ public function _ajax_authenticate_callback() {
127
+ if (!isset($_POST['log']) || !is_string($_POST['log']) || empty($_POST['log']) || !isset($_POST['pwd']) || !is_string($_POST['pwd']) || empty($_POST['pwd'])) {
128
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: A username and password must be provided. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), wp_lostpassword_url()))));
129
+ }
130
+
131
+ $legacy2FAActive = Controller_WordfenceLS::shared()->legacy_2fa_active();
132
+ if ($legacy2FAActive) { //Legacy 2FA is active, pass it on to the authenticate filter
133
+ die(json_encode(array('login' => 1)));
134
+ }
135
+
136
+ $username = $_POST['log'];
137
+ $password = $_POST['pwd'];
138
+ do_action_ref_array('wp_authenticate', array(&$username, &$password));
139
+
140
+ define('WORDFENCE_LS_AUTHENTICATION_CHECK', true); //Prevents our auth filter from recursing
141
+ $user = wp_authenticate($username, $password);
142
+ if (is_object($user) && ($user instanceof \WP_User)) {
143
+ $captcha = array();
144
+ if (defined('WORDFENCE_LS_CAPTCHA_CACHE')) {
145
+ $captcha = array('captcha' => WORDFENCE_LS_CAPTCHA_CACHE);
146
+ }
147
+
148
+ if (!Controller_Users::shared()->has_2fa_active($user) || Controller_Whitelist::shared()->is_whitelisted(Model_Request::current()->ip()) || Controller_Users::shared()->has_remembered_2fa($user)) { //Not enabled for this user, is whitelisted, or has a valid remembered cookie, pass the credentials on to the normal login flow
149
+ die(json_encode(array_merge($captcha, array('login' => 1))));
150
+ }
151
+
152
+ $encrypted = Model_Symmetric::encrypt((string) $user->ID);
153
+ if (!$encrypted) { //Can't generate payload due to host failure, pass the credentials on to the normal login flow
154
+ die(json_encode(array_merge($captcha, array('login' => 1))));
155
+ }
156
+
157
+ if (defined('WORDFENCE_LS_COMBINED_IS_VALID') && WORDFENCE_LS_COMBINED_IS_VALID) {
158
+ $nonce = Model_Crypto::random_bytes(32);
159
+ $encrypted_nonce = Model_Symmetric::encrypt($nonce);
160
+ if (!$encrypted_nonce) { //Can't generate payload due to host failure, pass the credentials on to the normal login flow
161
+ die(json_encode(array('login' => 1)));
162
+ }
163
+
164
+ update_user_meta($user->ID, 'wfls-nonce', json_encode(array('nonce' => bin2hex($nonce), 'expiration' => Controller_Time::time() + 30)));
165
+ $jwt = new Model_JWT(array('user' => $encrypted, 'nonce' => $encrypted_nonce), Controller_Time::time() + 30);
166
+ die(json_encode(array_merge($captcha, array('login' => 1, 'jwt' => (string) $jwt, 'combined' => 1))));
167
+ }
168
+
169
+ $jwt = new Model_JWT(array('user' => $encrypted), Controller_Time::time() + 300);
170
+ die(json_encode(array_merge($captcha, array('login' => 1, 'jwt' => (string) $jwt))));
171
+ }
172
+ else if (is_wp_error($user)) {
173
+ $errors = array();
174
+ $messages = array();
175
+ $reset = false;
176
+ foreach ($user->get_error_codes() as $code) {
177
+ if ($code == 'invalid_username' || $code == 'invalid_email' || $code == 'incorrect_password' || $code == 'authentication_failed') {
178
+ $errors[] = sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), wp_lostpassword_url());
179
+ }
180
+ else {
181
+ if ($code == 'wfls_twofactor_invalid') {
182
+ $reset = true;
183
+ }
184
+
185
+ $severity = $user->get_error_data($code);
186
+ foreach ($user->get_error_messages($code) as $error_message) {
187
+ if ($severity == 'message') {
188
+ $messages[] = $error_message;
189
+ }
190
+ else {
191
+ $errors[] = $error_message;
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ if (!empty($errors)) {
198
+ $errors = implode('<br>', $errors);
199
+ $errors = apply_filters('login_errors', $errors);
200
+ die(json_encode(array('error' => $errors, 'reset' => $reset)));
201
+ }
202
+
203
+ if (!empty($messages)) {
204
+ $messages = implode('<br>', $messages);
205
+ $messages = apply_filters('login_errors', $messages);
206
+ die(json_encode(array('message' => $messages, 'reset' => $reset)));
207
+ }
208
+ }
209
+
210
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: The username or password you entered is incorrect. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), wp_lostpassword_url()))));
211
+ }
212
+
213
+ public function _ajax_register_support_callback() {
214
+ if (!isset($_POST['user_login']) || !is_string($_POST['user_login']) ||
215
+ !isset($_POST['user_email']) || !is_string($_POST['user_email']) ||
216
+ !isset($_POST['wfls-message']) || !is_string($_POST['wfls-message']) ||
217
+ !isset($_POST['wfls-message-nonce']) || !is_string($_POST['wfls-message-nonce'])) {
218
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.')))));
219
+ }
220
+
221
+ $login = sanitize_user($_POST['user_login']);
222
+ $email = sanitize_email($_POST['user_email']);
223
+ $message = strip_tags($_POST['wfls-message']);
224
+ $nonce = $_POST['wfls-message-nonce'];
225
+
226
+ if (empty($login) || empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL) || empty($message)) {
227
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.')))));
228
+ }
229
+
230
+ $jwt = Model_JWT::decode_jwt($_POST['wfls-message-nonce']);
231
+ if ($jwt && isset($jwt->payload['ip']) && isset($jwt->payload['score'])) {
232
+ $decryptedIP = Model_Symmetric::decrypt($jwt->payload['ip']);
233
+ $decryptedScore = Model_Symmetric::decrypt($jwt->payload['score']);
234
+ if ($decryptedIP === false || $decryptedScore === false || Model_IP::inet_pton($decryptedIP) !== Model_IP::inet_pton(Model_Request::current()->ip())) { //JWT IP and the current request's IP don't match, refuse the message
235
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.')))));
236
+ }
237
+
238
+ $identifier = bin2hex(Model_IP::inet_pton($decryptedIP));
239
+ $tokenBucket = new Model_TokenBucket('rate:' . $identifier, 2, 1 / (6 * Model_TokenBucket::HOUR)); //Maximum of two requests, refilling at a rate of one per six hours
240
+ if (!$tokenBucket->consume(1)) {
241
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: Unable to send message. You have exceeded the maximum number of messages that may be sent at this time. Please try again later.')))));
242
+ }
243
+
244
+ $email = array(
245
+ 'to' => get_site_option('admin_email'),
246
+ 'subject' => __('Blocked User Registration Contact Form', 'wordfence-ls'),
247
+ 'body' => sprintf(__("A visitor blocked from registration sent the following message.\n\n----------------------------------------\n\nIP: %s\nUsername: %s\nEmail: %s\nreCAPTCHA Score: %f\n\n----------------------------------------\n\n%s", 'wordfence-ls'), $decryptedIP, $login, $email, $decryptedScore, $message),
248
+ 'headers' => '',
249
+ );
250
+ $success = wp_mail($email['to'], $email['subject'], $email['body'], $email['headers']);
251
+ if ($success) {
252
+ die(json_encode(array('message' => sprintf(__('<strong>MESSAGE SENT</strong>: Your message was sent to the site owner.')))));
253
+ }
254
+
255
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: An error occurred while sending the message. Please try again.')))));
256
+ }
257
+
258
+ die(json_encode(array('error' => sprintf(__('<strong>ERROR</strong>: Unable to send message. Please refresh the page and try again.')))));
259
+ }
260
+
261
+ public function _ajax_activate_callback() {
262
+ $userID = (int) @$_POST['user'];
263
+ $user = wp_get_current_user();
264
+ if ($user->ID != $userID) {
265
+ if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
266
+ die(json_encode(array('error' => __('You do not have permission to activate the given user.', 'wordfence-2fa'))));
267
+ }
268
+ else {
269
+ $user = new \WP_User($userID);
270
+ if (!$user->exists()) {
271
+ die(json_encode(array('error' => __('The given user does not exist.', 'wordfence-2fa'))));
272
+ }
273
+ }
274
+ }
275
+ else if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
276
+ die(json_encode(array('error' => __('You do not have permission to activate 2FA.', 'wordfence-2fa'))));
277
+ }
278
+
279
+ if (Controller_Users::shared()->has_2fa_active($user)) {
280
+ die(json_encode(array('error' => __('The given user already has two-factor authentication active.', 'wordfence-2fa'))));
281
+ }
282
+
283
+ $matches = (isset($_POST['secret']) && isset($_POST['code']) && is_string($_POST['secret']) && is_string($_POST['code']) && Controller_TOTP::shared()->check_code($_POST['secret'], $_POST['code']));
284
+ if ($matches === false) {
285
+ die(json_encode(array('error' => __('The code provided does not match the expected value. Please verify that the time on your authenticator device is correct and that this server\'s time is correct.', 'wordfence-2fa'))));
286
+ }
287
+
288
+ Controller_TOTP::shared()->activate_2fa($user, $_POST['secret'], $_POST['recovery'], $matches);
289
+ die(json_encode(array('activated' => 1, 'text' => sprintf(count($_POST['recovery']) == 1 ? __('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence-2fa') : __('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence-2fa'), count($_POST['recovery'])))));
290
+ }
291
+
292
+ public function _ajax_deactivate_callback() {
293
+ $userID = (int) @$_POST['user'];
294
+ $user = wp_get_current_user();
295
+ if ($user->ID != $userID) {
296
+ if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
297
+ die(json_encode(array('error' => __('You do not have permission to deactivate the given user.', 'wordfence-2fa'))));
298
+ }
299
+ else {
300
+ $user = new \WP_User($userID);
301
+ if (!$user->exists()) {
302
+ die(json_encode(array('error' => __('The user does not exist.', 'wordfence-2fa'))));
303
+ }
304
+ }
305
+ }
306
+ else if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
307
+ die(json_encode(array('error' => __('You do not have permission to deactivate 2FA.', 'wordfence-2fa'))));
308
+ }
309
+
310
+ if (!Controller_Users::shared()->has_2fa_active($user)) {
311
+ die(json_encode(array('error' => __('The user specified does not have two-factor authentication active.', 'wordfence-2fa'))));
312
+ }
313
+
314
+ Controller_Users::shared()->deactivate_2fa($user);
315
+ die(json_encode(array('deactivated' => 1)));
316
+ }
317
+
318
+ public function _ajax_regenerate_callback() {
319
+ $userID = (int) @$_POST['user'];
320
+ $user = wp_get_current_user();
321
+ if ($user->ID != $userID) {
322
+ if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
323
+ die(json_encode(array('error' => __('You do not have permission to generate new recovery codes for the given user.', 'wordfence-2fa'))));
324
+ }
325
+ else {
326
+ $user = new \WP_User($userID);
327
+ if (!$user->exists()) {
328
+ die(json_encode(array('error' => __('The user does not exist.', 'wordfence-2fa'))));
329
+ }
330
+ }
331
+ }
332
+ else if (!user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
333
+ die(json_encode(array('error' => __('You do not have permission to generate new recovery codes.', 'wordfence-2fa'))));
334
+ }
335
+
336
+ if (!Controller_Users::shared()->has_2fa_active($user)) {
337
+ die(json_encode(array('error' => __('The user specified does not have two-factor authentication active.', 'wordfence-2fa'))));
338
+ }
339
+
340
+ $codes = Controller_Users::shared()->regenerate_recovery_codes($user);
341
+ die(json_encode(array('regenerated' => 1, 'recovery' => array_map(function($r) { return implode(' ', str_split(bin2hex($r), 4)); }, $codes), 'text' => sprintf(count($codes) == 1 ? __('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence-2fa') : __('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence-2fa'), count($codes)))));
342
+ }
343
+
344
+ public function _ajax_save_options_callback() {
345
+ if (!empty($_POST['changes']) && is_string($_POST['changes']) && ($changes = json_decode(stripslashes($_POST['changes']), true)) !== false) {
346
+ try {
347
+ $errors = Controller_Settings::shared()->validate_multiple($changes);
348
+ if ($errors !== true) {
349
+ if (count($errors) == 1) {
350
+ $e = array_shift($errors);
351
+ die(json_encode(array('error' => sprintf(__('An error occurred while saving the configuration: %s', 'wordfence-2fa'), $e))));
352
+ }
353
+ else if (count($errors) > 1) {
354
+ $compoundMessage = array();
355
+ foreach ($errors as $e) {
356
+ $compoundMessage[] = esc_html($e);
357
+ }
358
+ die(json_encode(array(
359
+ 'error' => sprintf(__('Errors occurred while saving the configuration: %s', 'wordfence-2fa'), '<ul><li>' . implode('</li><li>', $compoundMessage) . '</li></ul>'),
360
+ 'html' => true,
361
+ )));
362
+ }
363
+
364
+ die(json_encode(array(
365
+ 'error' => __('Errors occurred while saving the configuration.', 'wordfence-2fa'),
366
+ )));
367
+ }
368
+
369
+ Controller_Settings::shared()->set_multiple($changes);
370
+
371
+ $response = array('success' => true);
372
+ return die(json_encode($response));
373
+ }
374
+ catch (\Exception $e) {
375
+ die(json_encode(array(
376
+ 'error' => $e->getMessage(),
377
+ )));
378
+ }
379
+ }
380
+
381
+ die(json_encode(array(
382
+ 'error' => __('No configuration changes were provided to save.', 'wordfence'),
383
+ )));
384
+ }
385
+
386
+ public function _ajax_send_grace_period_notification_callback() {
387
+ if (!Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REQUIRE_2FA_ADMIN)) {
388
+ die(json_encode(array('error' => __('Two-factor authentication is not currently required for administrators.', 'wordfence-2fa'))));
389
+ }
390
+
391
+ if (!(Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED) && \WordfenceLS\Controller_Time::time() < Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD))) {
392
+ die(json_encode(array('error' => __('A valid grace period is not configured to allow administrators time to activate two-factor authentication.', 'wordfence-2fa'))));
393
+ }
394
+
395
+ $subject = sprintf(__('2FA will soon be required on %s', 'wordfence-2fa'), home_url());
396
+ $message = sprintf(__("You do not currently have two-factor authentication active on your account, which will be required beginning %s.\n\nConfigure 2FA: %s", 'wordfence-2fa'), Controller_Time::format_local_time('F j, Y', Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD)), admin_url('admin.php?page=WFLS'));
397
+
398
+ $admins = Controller_Users::shared()->admin_users();
399
+ $sent = 0;
400
+ foreach ($admins as $a) {
401
+ /** @var \WP_User $a */
402
+ if (!Controller_Users::shared()->has_2fa_active($a)) {
403
+ continue;
404
+ }
405
+
406
+ wp_mail($a->user_email, $subject, $message);
407
+ $sent++;
408
+ }
409
+
410
+ if ($sent == 0) {
411
+ die(json_encode(array('confirmation' => __('All administrators already have two-factor authenication activated.', 'wordfence-2fa'))));
412
+ }
413
+ else if ($sent == 1) {
414
+ die(json_encode(array('confirmation' => sprintf(__('A reminder to activate two-factor authentication was sent to %d administrator.', 'wordfence-2fa'), $sent))));
415
+ }
416
+ die(json_encode(array('confirmation' => sprintf(__('A reminder to activate two-factor authentication was sent to %d administrators.', 'wordfence-2fa'), $sent))));
417
+ }
418
+
419
+ public function _ajax_update_ip_preview_callback() {
420
+ $source = $_POST['ip_source'];
421
+ $raw_proxies = $_POST['ip_source_trusted_proxies'];
422
+ if (!is_string($source) || !is_string($raw_proxies)) {
423
+ die();
424
+ }
425
+
426
+ $valid = array();
427
+ $invalid = array();
428
+ $test = preg_split('/[\r\n,]+/', $raw_proxies);
429
+ foreach ($test as $value) {
430
+ if (strlen($value) > 0) {
431
+ if (Model_IP::is_valid_ip($value) || Model_IP::is_valid_cidr_range($value)) {
432
+ $valid[] = $value;
433
+ }
434
+ else {
435
+ $invalid[] = $value;
436
+ }
437
+ }
438
+ }
439
+ $trusted_proxies = $valid;
440
+
441
+ $preview = Model_Request::current()->detected_ip_preview($source, $trusted_proxies);
442
+ $ip = Model_Request::current()->ip_for_field($source, $trusted_proxies);
443
+ die(json_encode(array('ip' => $ip[0], 'preview' => $preview)));
444
+ }
445
+
446
+ public function _ajax_dismiss_notice_callback() {
447
+ Controller_Notices::shared()->remove_notice($_POST['id'], false, wp_get_current_user());
448
+ }
449
+ }
classes/controller/captcha.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_CAPTCHA {
6
+ const RESPONSE_MODE_ALLOW = 'allow';
7
+ const RESPONSE_MODE_REQUIRE_VERIFICATION = 'verify';
8
+
9
+ const RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify';
10
+
11
+ /**
12
+ * Returns the singleton Controller_CAPTCHA.
13
+ *
14
+ * @return Controller_CAPTCHA
15
+ */
16
+ public static function shared() {
17
+ static $_shared = null;
18
+ if ($_shared === null) {
19
+ $_shared = new Controller_CAPTCHA();
20
+ }
21
+ return $_shared;
22
+ }
23
+
24
+ /**
25
+ * Returns whether or not the authentication CAPTCHA is enabled.
26
+ *
27
+ * @return bool
28
+ */
29
+ public function enabled() {
30
+ $key = $this->site_key();
31
+ $secret = $this->_secret();
32
+ return Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_ENABLE_AUTH_CAPTCHA) && !empty($key) && !empty($secret);
33
+ }
34
+
35
+ /**
36
+ * Returns the public reCAPTCHA key if set.
37
+ *
38
+ * @return string|bool
39
+ */
40
+ public function site_key() {
41
+ return Controller_Settings::shared()->get(Controller_Settings::OPTION_RECAPTCHA_SITE_KEY);
42
+ }
43
+
44
+ /**
45
+ * Returns the private reCAPTCHA secret if set.
46
+ *
47
+ * @return string|bool
48
+ */
49
+ protected function _secret() {
50
+ return Controller_Settings::shared()->get(Controller_Settings::OPTION_RECAPTCHA_SECRET);
51
+ }
52
+
53
+ /**
54
+ * Returns the bot/human threshold for comparing the score against, defaulting to 0.5.
55
+ *
56
+ * @return float
57
+ */
58
+ public function threshold() {
59
+ return Controller_Settings::shared()->get_float(Controller_Settings::OPTION_RECAPTCHA_THRESHOLD, 0.5);
60
+ }
61
+
62
+ /**
63
+ * Queries the reCAPTCHA endpoint with the given token, verifies the action matches, and returns the corresponding
64
+ * score. If validation fails, false is returned. Any other failure (e.g., mangled response or connection dropped) returns 0.0.
65
+ *
66
+ * @param string $token
67
+ * @param string $action
68
+ * @param int $timeout
69
+ * @return float|false
70
+ */
71
+ public function score($token, $action = 'login', $timeout = 10) {
72
+ try {
73
+ $payload = array(
74
+ 'secret' => $this->_secret(),
75
+ 'response' => $token,
76
+ 'remoteip' => Model_Request::current()->ip(),
77
+ );
78
+
79
+ $response = wp_remote_post(self::RECAPTCHA_ENDPOINT,
80
+ array(
81
+ 'body' => $payload,
82
+ 'headers' => array(
83
+ 'Referer' => false,
84
+ ),
85
+ 'timeout' => $timeout,
86
+ 'blocking' => true,
87
+ ));
88
+
89
+ if (!is_wp_error($response)) {
90
+ $jsonResponse = wp_remote_retrieve_body($response);
91
+ $decoded = @json_decode($jsonResponse, true);
92
+ if (is_array($decoded) && isset($decoded['success']) && isset($decoded['score']) && isset($decoded['action'])) {
93
+ if ($decoded['success'] && $decoded['action'] == $action) {
94
+ return (float) $decoded['score'];
95
+ }
96
+ return false;
97
+ }
98
+ }
99
+ }
100
+ catch (\Exception $e) {
101
+ //Fall through
102
+ }
103
+
104
+ return 0.0;
105
+ }
106
+
107
+ /**
108
+ * Returns true if the score is >= the threshold to be considered a human request.
109
+ *
110
+ * @param float $score
111
+ * @return bool
112
+ */
113
+ public function is_human($score) {
114
+ $threshold = $this->threshold();
115
+ return ($score >= $threshold || abs($score - $threshold) < 0.0001);
116
+ }
117
+ }
classes/controller/cron.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php
classes/controller/db.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_DB {
6
+ const TABLE_2FA_SECRETS = 'wfls_2fa_secrets';
7
+ const TABLE_SETTINGS = 'wfls_settings';
8
+
9
+ /**
10
+ * Returns the singleton Controller_DB.
11
+ *
12
+ * @return Controller_DB
13
+ */
14
+ public static function shared() {
15
+ static $_shared = null;
16
+ if ($_shared === null) {
17
+ $_shared = new Controller_DB();
18
+ }
19
+ return $_shared;
20
+ }
21
+
22
+ /**
23
+ * Returns the table prefix for the main site on multisites and the site itself on single site installations.
24
+ *
25
+ * @return string
26
+ */
27
+ public static function network_prefix() {
28
+ global $wpdb;
29
+ return $wpdb->base_prefix;
30
+ }
31
+
32
+ /**
33
+ * Returns the table with the site (single site installations) or network (multisite) prefix added.
34
+ *
35
+ * @param string $table
36
+ * @return string
37
+ */
38
+ public static function network_table($table) {
39
+ return self::network_prefix() . $table;
40
+ }
41
+
42
+ public function __get($key) {
43
+ switch ($key) {
44
+ case 'secrets':
45
+ return self::network_table(self::TABLE_2FA_SECRETS);
46
+ case 'settings':
47
+ return self::network_table(self::TABLE_SETTINGS);
48
+ }
49
+
50
+ throw new \OutOfBoundsException('Unknown key: ' . $key);
51
+ }
52
+
53
+ public function install() {
54
+ $this->_create_schema();
55
+
56
+ global $wpdb;
57
+ $table = $this->secrets;
58
+ $wpdb->query($wpdb->prepare("UPDATE `{$table}` SET `vtime` = LEAST(`vtime`, %d)", Controller_Time::time()));
59
+ }
60
+
61
+ protected function _create_schema() {
62
+ $tables = array(
63
+ self::TABLE_2FA_SECRETS => '(
64
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
65
+ `user_id` bigint(20) unsigned NOT NULL,
66
+ `secret` tinyblob NOT NULL,
67
+ `recovery` blob NOT NULL,
68
+ `ctime` int(10) unsigned NOT NULL,
69
+ `vtime` int(10) unsigned NOT NULL,
70
+ `mode` enum(\'authenticator\') NOT NULL DEFAULT \'authenticator\',
71
+ PRIMARY KEY (`id`),
72
+ KEY `user_id` (`user_id`)
73
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;',
74
+ self::TABLE_SETTINGS => '(
75
+ `name` varchar(191) NOT NULL DEFAULT \'\',
76
+ `value` longblob,
77
+ `autoload` enum(\'no\',\'yes\') NOT NULL DEFAULT \'yes\',
78
+ PRIMARY KEY (`name`)
79
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;',
80
+ );
81
+
82
+ foreach ($tables as $table => $def) {
83
+ global $wpdb;
84
+ $wpdb->query('CREATE TABLE IF NOT EXISTS `' . self::network_table($table) . '` ' . $def);
85
+ }
86
+ }
87
+ }
classes/controller/notices.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ use WordfenceLS\Text\Model_HTML;
6
+
7
+ class Controller_Notices {
8
+ const USER_META_KEY = 'wfls_notices';
9
+
10
+ /**
11
+ * Returns the singleton Controller_Notices.
12
+ *
13
+ * @return Controller_Notices
14
+ */
15
+ public static function shared() {
16
+ static $_shared = null;
17
+ if ($_shared === null) {
18
+ $_shared = new Controller_Notices();
19
+ }
20
+ return $_shared;
21
+ }
22
+
23
+ /**
24
+ * Adds an admin notice to the display queue. If $user is provided, it will show only for that user, otherwise it
25
+ * will show for all administrators.
26
+ *
27
+ * @param string $severity
28
+ * @param string|Model_HTML $message
29
+ * @param bool|string $category If not false, notices with the same category will be removed prior to adding this one.
30
+ * @param bool|\WP_User $user If not false, the user that the notice should show for.
31
+ */
32
+ public function add_notice($severity, $message, $category = false, $user = false) {
33
+ $notices = $this->_notices($user);
34
+ foreach ($notices as $id => $n) {
35
+ if ($category !== false && isset($n['category']) && $n['category'] == $category) { //Same category overwrites previous entry
36
+ unset($notices[$id]);
37
+ }
38
+ }
39
+
40
+ $id = Model_Crypto::uuid();
41
+ $notices[$id] = array(
42
+ 'severity' => $severity,
43
+ 'messageHTML' => Model_HTML::esc_html($message),
44
+ );
45
+
46
+ if ($category !== false) {
47
+ $notices[$id]['category'] = $category;
48
+ }
49
+
50
+ $this->_save_notices($notices, $user);
51
+ }
52
+
53
+ /**
54
+ * Removes a notice using one of two possible search methods:
55
+ *
56
+ * 1. If $id matches. $category is ignored but only notices for $user are checked.
57
+ * 2. If $category matches. Only notices for $user are checked.
58
+ *
59
+ * @param bool|int $id
60
+ * @param bool|string $category
61
+ * @param bool|\WP_User $user
62
+ */
63
+ public function remove_notice($id = false, $category = false, $user = false) {
64
+ if ($id === false && $category === false) {
65
+ return;
66
+ }
67
+ else if ($id !== false) {
68
+ $category = false;
69
+ }
70
+
71
+ $notices = $this->_notices($user);
72
+ foreach ($notices as $nid => $n) {
73
+ if ($id == $nid) { //ID match
74
+ unset($notices[$nid]);
75
+ break;
76
+ }
77
+ else if ($id !== false) {
78
+ continue;
79
+ }
80
+
81
+ if ($category !== false && isset($n['category']) && $category == $n['category']) { //Category match
82
+ unset($notices[$nid]);
83
+ }
84
+ }
85
+ $this->_save_notices($notices, $user);
86
+ }
87
+
88
+ /**
89
+ * Returns whether or not a notice exists for the given user.
90
+ *
91
+ * @param bool|\WP_User $user
92
+ * @return bool
93
+ */
94
+ public function has_notice($user) {
95
+ $notices = $this->_notices($user);
96
+ return !!count($notices);
97
+ }
98
+
99
+ /**
100
+ * Enqueues a user's notices. For administrators this also includes global notices.
101
+ *
102
+ * @return bool Whether any notices were enqueued.
103
+ */
104
+ public function enqueue_notices() {
105
+ $user = wp_get_current_user();
106
+ if ($user->ID == 0) {
107
+ return false;
108
+ }
109
+
110
+ $added = false;
111
+ $notices = array();
112
+ if (Controller_Permissions::shared()->can_manage_settings($user)) {
113
+ $globalNotices = $this->_notices(false);
114
+ $notices = array_merge($notices, $globalNotices);
115
+ }
116
+
117
+ $userNotices = $this->_notices($user);
118
+ $notices = array_merge($notices, $userNotices);
119
+
120
+ foreach ($notices as $nid => $n) {
121
+ $notice = new Model_Notice($nid, $n['severity'], $n['messageHTML']);
122
+ if (is_multisite()) {
123
+ add_action('network_admin_notices', array($notice, 'display_notice'));
124
+ }
125
+ else {
126
+ add_action('admin_notices', array($notice, 'display_notice'));
127
+ }
128
+
129
+ $added = true;
130
+ }
131
+
132
+ return $added;
133
+ }
134
+
135
+ /**
136
+ * Utility
137
+ */
138
+
139
+ /**
140
+ * Returns the notices for a user if provided, otherwise the global notices.
141
+ *
142
+ * @param bool|\WP_User $user
143
+ * @return array
144
+ */
145
+ protected function _notices($user) {
146
+ if ($user instanceof \WP_User) {
147
+ $notices = get_user_meta($user->ID, self::USER_META_KEY, true);
148
+ return array_filter((array) $notices);
149
+ }
150
+ return Controller_Settings::shared()->get_array(Controller_Settings::OPTION_GLOBAL_NOTICES);
151
+ }
152
+
153
+ /**
154
+ * Saves the notices.
155
+ *
156
+ * @param array $notices
157
+ * @param bool|\WP_User $user
158
+ */
159
+ protected function _save_notices($notices, $user) {
160
+ if ($user instanceof \WP_User) {
161
+ update_user_meta($user->ID, self::USER_META_KEY, $notices);
162
+ return;
163
+ }
164
+ Controller_Settings::shared()->set_array(Controller_Settings::OPTION_GLOBAL_NOTICES, $notices, true);
165
+ }
166
+ }
classes/controller/permissions.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_Permissions {
6
+ const CAP_ACTIVATE_2FA_SELF = 'wf2fa_activate_2fa_self'; //Activate 2FA on its own user account
7
+ const CAP_ACTIVATE_2FA_OTHERS = 'wf2fa_activate_2fa_others'; //Activate 2FA on user accounts other than its own
8
+ const CAP_MANAGE_SETTINGS = 'wf2fa_manage_settings'; //Edit settings for the plugin
9
+
10
+ /**
11
+ * Returns the singleton Controller_Permissions.
12
+ *
13
+ * @return Controller_Permissions
14
+ */
15
+ public static function shared() {
16
+ static $_shared = null;
17
+ if ($_shared === null) {
18
+ $_shared = new Controller_Permissions();
19
+ }
20
+ return $_shared;
21
+ }
22
+
23
+ public function install() {
24
+ if (is_multisite()) {
25
+ //Super Admin automatically gets all capabilities, so we don't need to explicitly add them
26
+ $this->_add_cap_multisite('administrator', self::CAP_ACTIVATE_2FA_SELF);
27
+ }
28
+ else {
29
+ $this->_add_cap('administrator', self::CAP_ACTIVATE_2FA_SELF);
30
+ $this->_add_cap('administrator', self::CAP_ACTIVATE_2FA_OTHERS);
31
+ $this->_add_cap('administrator', self::CAP_MANAGE_SETTINGS);
32
+ }
33
+ }
34
+
35
+ public function allow_2fa_self($role_name) {
36
+ if (is_multisite()) {
37
+ $this->_add_cap_multisite($role_name, self::CAP_ACTIVATE_2FA_SELF);
38
+ }
39
+ else {
40
+ $this->_add_cap($role_name, self::CAP_ACTIVATE_2FA_SELF);
41
+ }
42
+ }
43
+
44
+ public function disallow_2fa_self($role_name) {
45
+ if (is_multisite()) {
46
+ $this->_remove_cap_multisite($role_name, self::CAP_ACTIVATE_2FA_SELF);
47
+ }
48
+ else {
49
+ if ($role_name == 'administrator') {
50
+ return;
51
+ }
52
+ $this->_remove_cap($role_name, self::CAP_ACTIVATE_2FA_SELF);
53
+ }
54
+ }
55
+
56
+ public function can_manage_settings($user = false) {
57
+ if ($user === false) {
58
+ $user = wp_get_current_user();
59
+ }
60
+
61
+ if (!($user instanceof \WP_User)) {
62
+ return false;
63
+ }
64
+ return $user->has_cap(self::CAP_MANAGE_SETTINGS);
65
+ }
66
+
67
+ private function _wp_roles($site_id = null) {
68
+ require(ABSPATH . 'wp-includes/version.php'); /** @var string $wp_version */
69
+ if (version_compare($wp_version, '4.9', '>=')) {
70
+ return new \WP_Roles($site_id);
71
+ }
72
+
73
+ //\WP_Roles in WP < 4.9 initializes based on the current blog ID
74
+ global $wpdb;
75
+ $current_site = $wpdb->set_blog_id($site_id);
76
+ $wp_roles = new \WP_Roles();
77
+ $wpdb->set_blog_id($current_site);
78
+ return $wp_roles;
79
+ }
80
+
81
+ private function _add_cap_multisite($role_name, $cap) {
82
+ global $wpdb;
83
+ $blogs = $wpdb->get_col("SELECT `blog_id` FROM `{$wpdb->blogs}` WHERE `deleted` = 0");
84
+ foreach ($blogs as $id) {
85
+ $wp_roles = $this->_wp_roles($id);
86
+ $current_site = $wpdb->set_blog_id($id); //We have to set the blog ID for $wpdb because \WP_Roles does not set it prior to saving a multisite role
87
+ $this->_add_cap($role_name, $cap, $wp_roles);
88
+ $wpdb->set_blog_id($current_site);
89
+ }
90
+ }
91
+
92
+ private function _add_cap($role_name, $cap, $wp_roles = null) {
93
+ if ($wp_roles === null) { $wp_roles = $this->_wp_roles(); }
94
+ $role = $wp_roles->get_role($role_name);
95
+ if ($role === null) {
96
+ return false;
97
+ }
98
+
99
+ $wp_roles->add_cap($role_name, $cap);
100
+ return true;
101
+ }
102
+
103
+ private function _remove_cap_multisite($role_name, $cap) {
104
+ global $wpdb;
105
+ $blogs = $wpdb->get_col("SELECT `blog_id` FROM `{$wpdb->blogs}` WHERE `deleted` = 0");
106
+ foreach ($blogs as $id) {
107
+ $wp_roles = $this->_wp_roles($id);
108
+ $current_site = $wpdb->set_blog_id($id); //We have to set the blog ID for $wpdb because \WP_Roles does not set it prior to saving a multisite role
109
+ $this->_remove_cap($role_name, $cap, $wp_roles);
110
+ $wpdb->set_blog_id($current_site);
111
+ }
112
+ }
113
+
114
+ private function _remove_cap($role_name, $cap, $wp_roles = null) {
115
+ if ($wp_roles === null) { $wp_roles = $this->_wp_roles(); }
116
+ $role = $wp_roles->get_role($role_name);
117
+ if ($role === null) {
118
+ return false;
119
+ }
120
+
121
+ $wp_roles->remove_cap($role_name, $cap);
122
+ return true;
123
+ }
124
+ }
classes/controller/settings.php ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ use WordfenceLS\Settings\Model_DB;
6
+ use WordfenceLS\Settings\Model_WPOptions;
7
+
8
+ class Controller_Settings {
9
+ //Configurable
10
+ const OPTION_XMLRPC_ENABLED = 'xmlrpc-enabled';
11
+ const OPTION_2FA_WHITELISTED = 'whitelisted';
12
+ const OPTION_IP_SOURCE = 'ip-source';
13
+ const OPTION_IP_TRUSTED_PROXIES = 'ip-trusted-proxies';
14
+ const OPTION_REQUIRE_2FA_ADMIN = 'require-2fa.administrator';
15
+ const OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED = 'require-2fa-grace-period-enabled';
16
+ const OPTION_REQUIRE_2FA_GRACE_PERIOD = 'require-2fa-grace-period';
17
+ const OPTION_REMEMBER_DEVICE_ENABLED = 'remember-device';
18
+ const OPTION_REMEMBER_DEVICE_DURATION = 'remember-device-duration';
19
+ const OPTION_ALLOW_XML_RPC = 'allow-xml-rpc';
20
+ const OPTION_ENABLE_AUTH_CAPTCHA = 'enable-auth-captcha';
21
+ const OPTION_RECAPTCHA_SITE_KEY = 'recaptcha-site-key';
22
+ const OPTION_RECAPTCHA_SECRET = 'recaptcha-secret';
23
+ const OPTION_RECAPTCHA_THRESHOLD = 'recaptcha-threshold';
24
+
25
+ //Internal
26
+ const OPTION_GLOBAL_NOTICES = 'global-notices';
27
+ const OPTION_LAST_SECRET_REFRESH = 'last-secret-refresh';
28
+ const OPTION_USE_NTP = 'use-ntp';
29
+ const OPTION_NTP_OFFSET = 'ntp-offset';
30
+ const OPTION_SHARED_HASH_SECRET_KEY = 'shared-hash-secret';
31
+ const OPTION_SHARED_SYMMETRIC_SECRET_KEY = 'shared-symmetric-secret';
32
+ const OPTION_DISMISSED_FRESH_INSTALL_MODAL = 'dismissed-fresh-install-modal';
33
+
34
+ protected $_settingsStorage;
35
+
36
+ /**
37
+ * Returns the singleton Controller_Settings.
38
+ *
39
+ * @return Controller_Settings
40
+ */
41
+ public static function shared() {
42
+ static $_shared = null;
43
+ if ($_shared === null) {
44
+ $_shared = new Controller_Settings();
45
+ }
46
+ return $_shared;
47
+ }
48
+
49
+ public function __construct($settingsStorage = false) {
50
+ if (!$settingsStorage) {
51
+ $settingsStorage = new Model_DB();
52
+ }
53
+ $this->_settingsStorage = $settingsStorage;
54
+ }
55
+
56
+ public function set_defaults() {
57
+ $this->_settingsStorage->set_multiple(array(
58
+ self::OPTION_XMLRPC_ENABLED => array('value' => true, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
59
+ self::OPTION_2FA_WHITELISTED => array('value' => '', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
60
+ self::OPTION_IP_SOURCE => array('value' => Model_Request::IP_SOURCE_AUTOMATIC, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
61
+ self::OPTION_IP_TRUSTED_PROXIES => array('value' => '', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
62
+ self::OPTION_REQUIRE_2FA_ADMIN => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
63
+ self::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
64
+ self::OPTION_GLOBAL_NOTICES => array('value' => '[]', 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
65
+ self::OPTION_REMEMBER_DEVICE_ENABLED => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
66
+ self::OPTION_REMEMBER_DEVICE_DURATION => array('value' => (30 * 86400), 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
67
+ self::OPTION_ALLOW_XML_RPC => array('value' => true, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
68
+ self::OPTION_ENABLE_AUTH_CAPTCHA => array('value' => false, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
69
+ self::OPTION_RECAPTCHA_THRESHOLD => array('value' => 0.5, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
70
+ self::OPTION_LAST_SECRET_REFRESH => array('value' => 0, 'autoload' => Model_Settings::AUTOLOAD_YES, 'allowOverwrite' => false),
71
+ ));
72
+ }
73
+
74
+ public function set($key, $value, $already_validated = false) {
75
+ return $this->set_multiple(array($key => $value), $already_validated);
76
+ }
77
+
78
+ public function set_array($key, $value, $already_validated = false) {
79
+ return $this->set_multiple(array($key => json_encode($value)), $already_validated);
80
+ }
81
+
82
+ public function set_multiple($changes, $already_validated = false) {
83
+ if (!$already_validated && $this->validate_multiple($changes) !== true) {
84
+ return false;
85
+ }
86
+ $changes = $this->clean_multiple($changes);
87
+ $changes = $this->preprocess_multiple($changes);
88
+ $this->_settingsStorage->set_multiple($changes);
89
+ return true;
90
+ }
91
+
92
+ public function get($key, $default = false) {
93
+ return $this->_settingsStorage->get($key, $default);
94
+ }
95
+
96
+ public function get_bool($key, $default = false) {
97
+ return $this->_truthy_to_bool($this->get($key, $default));
98
+ }
99
+
100
+ public function get_int($key, $default = 0) {
101
+ return intval($this->get($key, $default));
102
+ }
103
+
104
+ public function get_float($key, $default = 0.0) {
105
+ return (float) $this->get($key, $default);
106
+ }
107
+
108
+ public function get_array($key, $default = array()) {
109
+ return (array) @json_decode($this->get($key, $default), true);
110
+ }
111
+
112
+ public function remove($key) {
113
+ $this->_settingsStorage->remove($key);
114
+ }
115
+
116
+ /**
117
+ * Validates whether a user-entered setting value is acceptable. Returns true if valid or an error message if not.
118
+ *
119
+ * @param string $key
120
+ * @param mixed $value
121
+ * @return bool|string
122
+ */
123
+ public function validate($key, $value) {
124
+ switch ($key) {
125
+ //Boolean
126
+ case self::OPTION_XMLRPC_ENABLED:
127
+ case self::OPTION_REQUIRE_2FA_ADMIN:
128
+ case self::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED:
129
+ case self::OPTION_REMEMBER_DEVICE_ENABLED:
130
+ case self::OPTION_ALLOW_XML_RPC:
131
+ case self::OPTION_ENABLE_AUTH_CAPTCHA:
132
+ case self::OPTION_DISMISSED_FRESH_INSTALL_MODAL:
133
+ return true;
134
+
135
+ //Int
136
+ case self::OPTION_LAST_SECRET_REFRESH:
137
+ return is_numeric($value);
138
+
139
+ //Array
140
+ case self::OPTION_GLOBAL_NOTICES:
141
+ return preg_match('/^\[.*\]$/', $value) || preg_match('/^\{.*\}$/', $value); //Only a rough JSON validation
142
+
143
+ //Special
144
+ case self::OPTION_IP_TRUSTED_PROXIES:
145
+ case self::OPTION_2FA_WHITELISTED:
146
+ $parsed = array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $value)));
147
+ foreach ($parsed as $entry) {
148
+ if (!Controller_Whitelist::shared()->is_valid_range($entry)) {
149
+ return sprintf(__('The IP/range %s is invalid.', 'wordfence-2fa'), esc_html($entry));
150
+ }
151
+ }
152
+ return true;
153
+ case self::OPTION_IP_SOURCE:
154
+ if (!in_array($value, array(Model_Request::IP_SOURCE_AUTOMATIC, Model_Request::IP_SOURCE_REMOTE_ADDR, Model_Request::IP_SOURCE_X_FORWARDED_FOR, Model_Request::IP_SOURCE_X_REAL_IP))) {
155
+ return __('An invalid IP source was provided.', 'wordfence-2fa');
156
+ }
157
+ return true;
158
+ case self::OPTION_REQUIRE_2FA_GRACE_PERIOD:
159
+ $gracePeriodEnd = strtotime($value);
160
+ if ($gracePeriodEnd <= \WordfenceLS\Controller_Time::time()) {
161
+ return __('The grace period end time must be in the future.', 'wordfence-2fa');
162
+ }
163
+ return true;
164
+ case self::OPTION_REMEMBER_DEVICE_DURATION:
165
+ return is_numeric($value) && $value > 0;
166
+ case self::OPTION_RECAPTCHA_THRESHOLD:
167
+ return is_numeric($value) && $value >= 0 && $value <= 1;
168
+ }
169
+ return true;
170
+ }
171
+
172
+ public function validate_multiple($values) {
173
+ $errors = array();
174
+ foreach ($values as $key => $value) {
175
+ $status = $this->validate($key, $value);
176
+ if ($status !== true) {
177
+ $errors[$key] = $status;
178
+ }
179
+ }
180
+
181
+ if (!empty($errors)) {
182
+ return $errors;
183
+ }
184
+
185
+ return true;
186
+ }
187
+
188
+ /**
189
+ * Cleans and normalizes a setting value for use in saving.
190
+ *
191
+ * @param string $key
192
+ * @param mixed $value
193
+ * @return mixed
194
+ */
195
+ public function clean($key, $value) {
196
+ switch ($key) {
197
+ //Boolean
198
+ case self::OPTION_XMLRPC_ENABLED:
199
+ case self::OPTION_REQUIRE_2FA_ADMIN:
200
+ case self::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED:
201
+ case self::OPTION_REMEMBER_DEVICE_ENABLED:
202
+ case self::OPTION_ALLOW_XML_RPC:
203
+ case self::OPTION_ENABLE_AUTH_CAPTCHA:
204
+ case self::OPTION_DISMISSED_FRESH_INSTALL_MODAL:
205
+ return $this->_truthy_to_bool($value);
206
+
207
+ //Int
208
+ case self::OPTION_REMEMBER_DEVICE_DURATION:
209
+ case self::OPTION_LAST_SECRET_REFRESH:
210
+ return (int) $value;
211
+
212
+ //Float
213
+ case self::OPTION_RECAPTCHA_THRESHOLD:
214
+ return (float) $value;
215
+
216
+ //Special
217
+ case self::OPTION_IP_TRUSTED_PROXIES:
218
+ case self::OPTION_2FA_WHITELISTED:
219
+ $parsed = array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $value)));
220
+ $cleaned = array();
221
+ foreach ($parsed as $item) {
222
+ $cleaned[] = $this->_sanitize_ip_range($item);
223
+ }
224
+ return implode("\n", $cleaned);
225
+ case self::OPTION_REQUIRE_2FA_GRACE_PERIOD:
226
+ $dt = $this->_parse_local_time($value);
227
+ return $dt->format('U');
228
+ case self::OPTION_RECAPTCHA_SITE_KEY:
229
+ case self::OPTION_RECAPTCHA_SECRET:
230
+ return trim($value);
231
+ }
232
+ return $value;
233
+ }
234
+
235
+ public function clean_multiple($changes) {
236
+ $cleaned = array();
237
+ foreach ($changes as $key => $value) {
238
+ $cleaned[$key] = $this->clean($key, $value);
239
+ }
240
+ return $cleaned;
241
+ }
242
+
243
+ /**
244
+ * Preprocesses the value, returning true if it was saved here (e.g., saved 2fa enabled by assigning a role
245
+ * capability) or false if it is to be saved by the backing storage.
246
+ *
247
+ * @param string $key
248
+ * @param mixed $value
249
+ * @return bool
250
+ */
251
+ public function preprocess($key, $value) {
252
+ if (preg_match('/^enabled-roles\.(.+)$/', $key, $matches)) { //Enabled roles are stored as capabilities rather than in the settings storage
253
+ $role = $matches[1];
254
+ if ($this->_truthy_to_bool($value)) {
255
+ Controller_Permissions::shared()->allow_2fa_self($role);
256
+ }
257
+ else {
258
+ Controller_Permissions::shared()->disallow_2fa_self($role);
259
+ }
260
+ return true;
261
+ }
262
+ return false;
263
+ }
264
+
265
+ public function preprocess_multiple($changes) {
266
+ $remaining = array();
267
+ foreach ($changes as $key => $value) {
268
+ if (!$this->preprocess($key, $value)) {
269
+ $remaining[$key] = $value;
270
+ }
271
+ }
272
+ return $remaining;
273
+ }
274
+
275
+ /**
276
+ * Convenience
277
+ */
278
+
279
+ /**
280
+ * Returns a cleaned array containing the whitelist entries.
281
+ *
282
+ * @return array
283
+ */
284
+ public function whitelisted_ips() {
285
+ return array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $this->get(self::OPTION_2FA_WHITELISTED, ''))));
286
+ }
287
+
288
+ /**
289
+ * Returns a cleaned array containing the trusted proxy entries.
290
+ *
291
+ * @return array
292
+ */
293
+ public function trusted_proxies() {
294
+ return array_filter(array_map(function($s) { return trim($s); }, preg_split('/[\r\n]/', $this->get(self::OPTION_IP_TRUSTED_PROXIES, ''))));
295
+ }
296
+
297
+ /**
298
+ * Utility
299
+ */
300
+
301
+ /**
302
+ * Translates a value to a boolean, correctly interpreting various textual representations.
303
+ *
304
+ * @param $value
305
+ * @return bool
306
+ */
307
+ protected function _truthy_to_bool($value) {
308
+ if ($value === true || $value === false) {
309
+ return $value;
310
+ }
311
+
312
+ if (is_numeric($value)) {
313
+ return !!$value;
314
+ }
315
+
316
+ if (preg_match('/^(?:f(?:alse)?|no?|off)$/i', $value)) {
317
+ return false;
318
+ }
319
+ else if (preg_match('/^(?:t(?:rue)?|y(?:es)?|on)$/i', $value)) {
320
+ return true;
321
+ }
322
+
323
+ return !empty($value);
324
+ }
325
+
326
+ /**
327
+ * Parses the given time string and returns its DateTime with the server's configured time zone.
328
+ *
329
+ * @param string $timestring
330
+ * @return \DateTime
331
+ */
332
+ protected function _parse_local_time($timestring) {
333
+ $utc = new \DateTimeZone('UTC');
334
+ $tz = get_option('timezone_string');
335
+ if (!empty($tz)) {
336
+ $tz = new \DateTimeZone($tz);
337
+ return new \DateTime($timestring, $tz);
338
+ }
339
+ else {
340
+ $gmt = get_option('gmt_offset');
341
+ if (!empty($gmt)) {
342
+ if (PHP_VERSION_ID < 50510) {
343
+ $timestamp = strtotime($timestring);
344
+ $dtStr = gmdate("c", (int) ($timestamp + $gmt * 3600)); //Have to do it this way because of < PHP 5.5.10
345
+ return new \DateTime($dtStr, $utc);
346
+ }
347
+ else {
348
+ $direction = ($gmt > 0 ? '+' : '-');
349
+ $gmt = abs($gmt);
350
+ $h = (int) $gmt;
351
+ $m = ($gmt - $h) * 60;
352
+ $tz = new \DateTimeZone($direction . str_pad($h, 2, '0', STR_PAD_LEFT) . str_pad($m, 2, '0', STR_PAD_LEFT));
353
+ return new \DateTime($timestring, $tz);
354
+ }
355
+ }
356
+ }
357
+ return new \DateTime($timestring);
358
+ }
359
+
360
+ /**
361
+ * Cleans a user-entered IP range of unnecessary characters and normalizes some glyphs.
362
+ *
363
+ * @param string $range
364
+ * @return string
365
+ */
366
+ protected function _sanitize_ip_range($range) {
367
+ $range = preg_replace('/\s/', '', $range); //Strip whitespace
368
+ $range = preg_replace('/[\\x{2013}-\\x{2015}]/u', '-', $range); //Non-hyphen dashes to hyphen
369
+ $range = strtolower($range);
370
+
371
+ if (preg_match('/^\d+-\d+$/', $range)) { //v5 32 bit int style format
372
+ list($start, $end) = explode('-', $range);
373
+ $start = long2ip($start);
374
+ $end = long2ip($end);
375
+ $range = "{$start}-{$end}";
376
+ }
377
+
378
+ return $range;
379
+ }
380
+ }
classes/controller/support.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_Support {
6
+ const ITEM_INDEX = 'index';
7
+
8
+ const ITEM_CHANGELOG = 'changelog';
9
+
10
+ const ITEM_VERSION_WORDPRESS = 'version-wordpress';
11
+ const ITEM_VERSION_PHP = 'version-php';
12
+ const ITEM_VERSION_OPENSSL = 'version-ssl';
13
+
14
+ const ITEM_GDPR = 'gdpr';
15
+ const ITEM_GDPR_DPA = 'gdpr-dpa';
16
+
17
+ const ITEM_MODULE_LOGIN_SECURITY = 'module-login-security';
18
+ const ITEM_MODULE_LOGIN_SECURITY_2FA = 'module-login-security-2fa';
19
+ const ITEM_MODULE_LOGIN_SECURITY_2FA_APPS = 'module-login-security-2fa-apps';
20
+ const ITEM_MODULE_LOGIN_SECURITY_CAPTCHA = 'module-login-security-captcha';
21
+
22
+ public static function esc_supportURL($item = self::ITEM_INDEX) {
23
+ return esc_url(self::supportURL($item));
24
+ }
25
+
26
+ public static function supportURL($item = self::ITEM_INDEX) {
27
+ $base = 'https://www.wordfence.com/help/';
28
+ switch ($item) {
29
+ case self::ITEM_INDEX:
30
+ return 'https://www.wordfence.com/help/';
31
+
32
+ //These all fall through to the query format
33
+
34
+ case self::ITEM_VERSION_WORDPRESS:
35
+ case self::ITEM_VERSION_PHP:
36
+ case self::ITEM_VERSION_OPENSSL:
37
+
38
+ case self::ITEM_GDPR:
39
+ case self::ITEM_GDPR_DPA:
40
+
41
+ case self::ITEM_MODULE_LOGIN_SECURITY:
42
+ case self::ITEM_MODULE_LOGIN_SECURITY_2FA:
43
+ case self::ITEM_MODULE_LOGIN_SECURITY_CAPTCHA:
44
+ return $base . '?query=' . $item;
45
+ }
46
+
47
+ return '';
48
+ }
49
+ }
classes/controller/time.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_Time {
6
+ const NTP_VERSION = 3; // https://www.ietf.org/rfc/rfc1305.txt
7
+ const NTP_EPOCH_CONVERT = 2208988800; //RFC 5905, page 13
8
+
9
+ /**
10
+ * Returns the singleton Controller_Time.
11
+ *
12
+ * @return Controller_Time
13
+ */
14
+ public static function shared() {
15
+ static $_shared = null;
16
+ if ($_shared === null) {
17
+ $_shared = new Controller_Time();
18
+ }
19
+ return $_shared;
20
+ }
21
+
22
+ public function install() {
23
+ wp_clear_scheduled_hook('wordfence_ls_ntp_cron');
24
+ if (is_main_site()) {
25
+ wp_schedule_event(time() + 10, 'hourly', 'wordfence_ls_ntp_cron');
26
+ }
27
+ }
28
+
29
+ public function uninstall() {
30
+ wp_clear_scheduled_hook('wordfence_ls_ntp_cron');
31
+ }
32
+
33
+ public function init() {
34
+ $this->_init_actions();
35
+ }
36
+
37
+ public function _init_actions() {
38
+ add_action('wordfence_ls_ntp_cron', array($this, '_wordfence_ls_ntp_cron'));
39
+ }
40
+
41
+ public function _wordfence_ls_ntp_cron() {
42
+ $ntp = self::ntp_time();
43
+ $time = time();
44
+
45
+ if ($ntp === false) {
46
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_USE_NTP, false);
47
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_NTP_OFFSET, 0);
48
+ }
49
+ else {
50
+ $useNTP = (abs($ntp - $time) > Controller_TOTP::TIME_WINDOW_LENGTH);
51
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_USE_NTP, $useNTP);
52
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_NTP_OFFSET, $ntp - $time);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Returns the current UTC timestamp, offset as needed to reflect the time retrieved from an NTP request or (if
58
+ * running in the complete plugin) offset as needed from the Wordfence server's true time.
59
+ *
60
+ * @param bool|int $time The timestamp to apply any offset to. If `false`, it will use the current timestamp.
61
+ * @return int
62
+ */
63
+ public static function time($time = false) {
64
+ if ($time === false) {
65
+ $time = time();
66
+ }
67
+
68
+ $offset = 0;
69
+ if (Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_USE_NTP)) {
70
+ $offset = Controller_Settings::shared()->get_int(Controller_Settings::OPTION_NTP_OFFSET);
71
+ }
72
+ else if (WORDFENCE_LS_FROM_CORE) {
73
+ $offset = \wfUtils::normalizedTime($time) - $time;
74
+ }
75
+
76
+ return $time + $offset;
77
+ }
78
+
79
+ /**
80
+ * Returns the current timestamp from ntp.org using the NTP protocol. If unable to (e.g., UDP connections are blocked),
81
+ * it will return false.
82
+ *
83
+ * @return bool|float
84
+ */
85
+ public static function ntp_time() {
86
+ $servers = array('0.pool.ntp.org', '1.pool.ntp.org', '2.pool.ntp.org', '3.pool.ntp.org');
87
+
88
+ //Header - RFC 5905, page 18
89
+ $header = '00'; //LI (leap indicator) - 2 bits: 00 for "no warning"
90
+ $header .= sprintf('%03d', decbin(self::NTP_VERSION)); //VN (version number) - 3 bits: 011 for version 3
91
+ $header .= '011'; //Mode (association mode) - 3 bit: 011 for "client"
92
+
93
+ $packet = chr(bindec($header));
94
+ $packet .= str_repeat("\x0", 39);
95
+
96
+ foreach ($servers as $s) {
97
+ $socket = @fsockopen('udp://' . $s, 123, $err_no, $err_str, 1);
98
+ stream_set_timeout($socket, 1);
99
+ if ($socket) {
100
+ $remote_originate = microtime(true);
101
+ $secondsNTP = ((int) $remote_originate) + self::NTP_EPOCH_CONVERT;
102
+ $fractional = sprintf('%010d', round(($remote_originate - ((int) $remote_originate)) * 0x100000000));
103
+ $packed = pack('N', $secondsNTP) . pack('N', $fractional);
104
+
105
+ if (@fwrite($socket, $packet . $packed)) {
106
+ $response = fread($socket, 48);
107
+ $local_transmitted = microtime(true);
108
+ }
109
+ @fclose($socket);
110
+
111
+ if (isset($response) && Model_Crypto::strlen($response) == 48) {
112
+ break;
113
+ }
114
+ }
115
+ }
116
+
117
+ if (isset($response) && Model_Crypto::strlen($response) == 48) {
118
+ $longs = unpack("N12", $response);
119
+
120
+ $remote_originate_seconds = sprintf('%u', $longs[7]) - self::NTP_EPOCH_CONVERT;
121
+ $remote_received_seconds = sprintf('%u', $longs[9]) - self::NTP_EPOCH_CONVERT;
122
+ $remote_transmitted_seconds = sprintf('%u', $longs[11]) - self::NTP_EPOCH_CONVERT;
123
+
124
+ $remote_originate_fraction = sprintf('%u', $longs[8]) / 0x100000000;
125
+ $remote_received_fraction = sprintf('%u', $longs[10]) / 0x100000000;
126
+ $remote_transmitted_fraction = sprintf('%u', $longs[12]) / 0x100000000;
127
+
128
+ $remote_originate = $remote_originate_seconds + $remote_originate_fraction;
129
+ $remote_received = $remote_received_seconds + $remote_received_fraction;
130
+ $remote_transmitted = $remote_transmitted_seconds + $remote_transmitted_fraction;
131
+
132
+ $delay = (($local_transmitted - $remote_originate) / 2) - ($remote_transmitted - $remote_received);
133
+
134
+ $ntp_time = $remote_transmitted - $delay;
135
+ return $ntp_time;
136
+ }
137
+
138
+ return false;
139
+ }
140
+
141
+ /**
142
+ * Formats and returns the given timestamp using the time zone set for the WordPress installation.
143
+ *
144
+ * @param string $format See the PHP docs on DateTime for the format options.
145
+ * @param int|bool $timestamp Assumed to be in UTC. If false, defaults to the current timestamp.
146
+ * @return string
147
+ */
148
+ public static function format_local_time($format, $timestamp = false) {
149
+ if ($timestamp === false) {
150
+ $timestamp = self::time();
151
+ }
152
+
153
+ $utc = new \DateTimeZone('UTC');
154
+ if (!function_exists('date_timestamp_set')) {
155
+ $dtStr = gmdate("c", (int) $timestamp); //Have to do it this way because of PHP 5.2
156
+ $dt = new \DateTime($dtStr, $utc);
157
+ }
158
+ else {
159
+ $dt = new \DateTime('now', $utc);
160
+ $dt->setTimestamp($timestamp);
161
+ }
162
+
163
+ $tz = get_option('timezone_string');
164
+ if (!empty($tz)) {
165
+ $dt->setTimezone(new \DateTimeZone($tz));
166
+ }
167
+ else {
168
+ $gmt = get_option('gmt_offset');
169
+ if (!empty($gmt)) {
170
+ if (PHP_VERSION_ID < 50510) {
171
+ $dtStr = gmdate("c", (int) ($timestamp + $gmt * 3600)); //Have to do it this way because of < PHP 5.5.10
172
+ $dt = new \DateTime($dtStr, $utc);
173
+ }
174
+ else {
175
+ $direction = ($gmt > 0 ? '+' : '-');
176
+ $gmt = abs($gmt);
177
+ $h = (int) $gmt;
178
+ $m = ($gmt - $h) * 60;
179
+ $dt->setTimezone(new \DateTimeZone($direction . str_pad($h, 2, '0', STR_PAD_LEFT) . str_pad($m, 2, '0', STR_PAD_LEFT)));
180
+ }
181
+ }
182
+ }
183
+ return $dt->format($format);
184
+ }
185
+ }
classes/controller/totp.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_TOTP {
6
+ const TIME_WINDOW_LENGTH = 30;
7
+
8
+ /**
9
+ * Returns the singleton Controller_TOTP.
10
+ *
11
+ * @return Controller_TOTP
12
+ */
13
+ public static function shared() {
14
+ static $_shared = null;
15
+ if ($_shared === null) {
16
+ $_shared = new Controller_TOTP();
17
+ }
18
+ return $_shared;
19
+ }
20
+
21
+ public function init() {
22
+
23
+ }
24
+
25
+ /**
26
+ * Activates a user with the given TOTP parameters.
27
+ *
28
+ * @param \WP_User $user
29
+ * @param string $secret The secret as a hex string.
30
+ * @param string[] $recovery An array of recovery codes as hex strings.
31
+ * @param bool|int $vtime The timestamp of the verification code or false to use the current timestamp.
32
+ */
33
+ public function activate_2fa($user, $secret, $recovery, $vtime = false) {
34
+ if ($vtime === false) {
35
+ $vtime = Controller_Time::time();
36
+ }
37
+
38
+ global $wpdb;
39
+ $table = Controller_DB::shared()->secrets;
40
+ $wpdb->query($wpdb->prepare("INSERT INTO `{$table}` (`user_id`, `secret`, `recovery`, `ctime`, `vtime`, `mode`) VALUES (%d, %s, %s, UNIX_TIMESTAMP(), %d, 'authenticator')", $user->ID, Model_Compat::hex2bin($secret), implode('', array_map(function($r) { return Model_Compat::hex2bin($r); }, $recovery)), $vtime));
41
+ }
42
+
43
+ /**
44
+ * Validates the 2FA (or recovery) code for the given user. This will return `null` if the user does not have 2FA
45
+ * enabled. This check will mark the code as used, preventing its use again.
46
+ *
47
+ * @param \WP_User $user
48
+ * @param string $code
49
+ * @return bool|null Returns null if the user does not have 2FA enabled, false if the code is invalid, and true if valid.
50
+ */
51
+ public function validate_2fa($user, $code) {
52
+ global $wpdb;
53
+ $table = Controller_DB::shared()->secrets;
54
+ $record = $wpdb->get_row($wpdb->prepare("SELECT * FROM `{$table}` WHERE `user_id` = %d FOR UPDATE", $user->ID), ARRAY_A);
55
+ if (!$record) {
56
+ return null;
57
+ }
58
+
59
+ if (preg_match('/^(?:[a-f0-9]{4}\s*){4}$/i', $code)) { //Recovery code
60
+ $code = strtolower(preg_replace('/\s/i', '', $code));
61
+ $recoveryCodes = str_split(strtolower(bin2hex($record['recovery'])), 16);
62
+
63
+ $index = array_search($code, $recoveryCodes);
64
+ if ($index !== false) {
65
+ unset($recoveryCodes[$index]);
66
+ $updatedRecoveryCodes = implode('', $recoveryCodes);
67
+ $wpdb->query($wpdb->prepare("UPDATE `{$table}` SET `recovery` = X%s WHERE `id` = %d", $updatedRecoveryCodes, $record['id']));
68
+ $wpdb->query('COMMIT');
69
+ return true;
70
+ }
71
+ }
72
+ else if (preg_match('/^(?:[0-9]{3}\s*){2}$/i', $code)) { //TOTP code
73
+ $code = preg_replace('/\s/i', '', $code);
74
+ $secret = bin2hex($record['secret']);
75
+
76
+ $matches = $this->check_code($secret, $code, floor($record['vtime'] / self::TIME_WINDOW_LENGTH));
77
+ if ($matches !== false) {
78
+ $wpdb->query($wpdb->prepare("UPDATE `{$table}` SET `vtime` = %d WHERE `id` = %d", $matches, $record['id']));
79
+ $wpdb->query('COMMIT');
80
+ return true;
81
+ }
82
+ }
83
+
84
+ $wpdb->query('ROLLBACK');
85
+ return false;
86
+ }
87
+
88
+ /**
89
+ * Checks whether or not the code is valid for the given secret. If it is, it returns the time window (as a timestamp)
90
+ * that matched. If no time windows are provided, it checks the current and one on each side.
91
+ *
92
+ * @param string $secret The secret as a hex string.
93
+ * @param string $code The code.
94
+ * @param null|int The last-used time window (as a timestamp).
95
+ * @param null|array $windows An array of time windows or null to use the default.
96
+ * @return bool|int The time window if matches, otherwise false.
97
+ */
98
+ public function check_code($secret, $code, $previous = null, $windows = null) {
99
+ $timeCode = floor(Controller_Time::time() / self::TIME_WINDOW_LENGTH);
100
+
101
+ if ($windows === null) {
102
+ $windows = array();
103
+ $validRange = array(-1, 1); //90 second range for authenticator
104
+
105
+ $lowRange = $validRange[0];
106
+ $highRange = $validRange[1];
107
+ for ($i = 0; $i >= $lowRange; $i--) {
108
+ $windows[] = $timeCode + $i;
109
+ }
110
+ for ($i = 1; $i <= $highRange; $i++) {
111
+ $windows[] = $timeCode + $i;
112
+ }
113
+ }
114
+
115
+ foreach ($windows as $w) {
116
+ if ($previous !== null && $previous >= $w) {
117
+ continue;
118
+ }
119
+
120
+ $expectedCode = $this->_generate_totp($secret, dechex($w));
121
+ if (hash_equals($expectedCode, $code)) {
122
+ return $w * self::TIME_WINDOW_LENGTH;
123
+ }
124
+ }
125
+
126
+ return false;
127
+ }
128
+
129
+ /**
130
+ * Generates a TOTP value using the provided parameters.
131
+ *
132
+ * @param $key The key in hex.
133
+ * @param $time The desired time code in hex.
134
+ * @param int $digits The number of digits.
135
+ * @return string The TOTP value.
136
+ */
137
+ private function _generate_totp($key, $time, $digits = 6)
138
+ {
139
+ $time = Model_Compat::hex2bin(str_pad($time, 16, '0', STR_PAD_LEFT));
140
+ $key = Model_Compat::hex2bin($key);
141
+ $hash = hash_hmac('sha1', $time, $key);
142
+
143
+ $offset = hexdec(substr($hash, -2)) & 0xf;
144
+ $intermediate = ( ((hexdec(substr($hash, $offset * 2, 2)) & 0x7f) << 24) |
145
+ ((hexdec(substr($hash, ($offset + 1) * 2, 2)) & 0xff) << 16) |
146
+ ((hexdec(substr($hash, ($offset + 2) * 2, 2)) & 0xff) << 8) |
147
+ ((hexdec(substr($hash, ($offset + 3) * 2, 2)) & 0xff))
148
+ );
149
+ $otp = $intermediate % pow(10, $digits);
150
+
151
+ return str_pad("{$otp}", $digits, '0', STR_PAD_LEFT);
152
+ }
153
+ }
classes/controller/users.php ADDED
@@ -0,0 +1,577 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ use WordfenceLS\Crypto\Model_JWT;
6
+ use WordfenceLS\Crypto\Model_Symmetric;
7
+
8
+ class Controller_Users {
9
+ const RECOVERY_CODE_COUNT = 5;
10
+ const RECOVERY_CODE_SIZE = 8;
11
+
12
+ /**
13
+ * Returns the singleton Controller_Users.
14
+ *
15
+ * @return Controller_Users
16
+ */
17
+ public static function shared() {
18
+ static $_shared = null;
19
+ if ($_shared === null) {
20
+ $_shared = new Controller_Users();
21
+ }
22
+ return $_shared;
23
+ }
24
+
25
+ public function init() {
26
+ $this->_init_actions();
27
+ }
28
+
29
+ /**
30
+ * Imports the array of 2FA secrets. Users that do not currently exist or are disallowed from enabling 2FA are not imported.
31
+ *
32
+ * @param array $secrets An array of secrets in the format array(<user id> => array('secret' => <secret in hex>, 'recovery' => <recovery keys in hex>, 'ctime' => <timestamp>, 'vtime' => <timestamp>, 'type' => <type>), ...)
33
+ * @return int The number imported.
34
+ */
35
+ public function import_2fa($secrets) {
36
+ global $wpdb;
37
+ $table = Controller_DB::shared()->secrets;
38
+
39
+ $count = 0;
40
+ foreach ($secrets as $id => $parameters) {
41
+ $user = new \WP_User($id);
42
+ if (!$user->exists() || !$this->can_activate_2fa($user) || $parameters['type'] != 'authenticator' || $this->has_2fa_active($user)) { continue; }
43
+ $secret = Model_Compat::hex2bin($parameters['secret']);
44
+ $recovery = Model_Compat::hex2bin($parameters['recovery']);
45
+ $ctime = (int) $parameters['ctime'];
46
+ $vtime = min((int) $parameters['vtime'], Controller_Time::time());
47
+ $type = $parameters['type'];
48
+ $wpdb->query($wpdb->prepare("INSERT INTO `{$table}` (`user_id`, `secret`, `recovery`, `ctime`, `vtime`, `mode`) VALUES (%d, %s, %s, %d, %d, %s)", $user->ID, $secret, $recovery, $ctime, $vtime, $type));
49
+ $count++;
50
+ }
51
+ return $count;
52
+ }
53
+
54
+ public function admin_users() {
55
+ //We should eventually allow for any user to be granted the manage capability, but we won't account for that now
56
+ if (is_multisite()) {
57
+ $logins = get_super_admins();
58
+ $users = array();
59
+ foreach ($logins as $l) {
60
+ $user = new \WP_User(null, $l);
61
+ if ($user->ID > 0) {
62
+ $users[] = $user;
63
+ }
64
+ }
65
+ return $users;
66
+ }
67
+
68
+ $query = new \WP_User_Query(array('role' => array('administrator'), 'number' => -1));
69
+ return $query->get_results();
70
+ }
71
+
72
+ /**
73
+ * Returns whether or not the user has a valid remembered device.
74
+ *
75
+ * @param \WP_User $user
76
+ * @return bool
77
+ */
78
+ public function has_remembered_2fa($user) {
79
+ static $_cache = array();
80
+ if (isset($_cache[$user->ID])) {
81
+ return $_cache[$user->ID];
82
+ }
83
+
84
+ if (!Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REMEMBER_DEVICE_ENABLED)) {
85
+ return false;
86
+ }
87
+
88
+ $maxExpiration = \WordfenceLS\Controller_Time::time() + Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REMEMBER_DEVICE_DURATION);
89
+
90
+ $encrypted = Model_Symmetric::encrypt((string) $user->ID);
91
+ if (!$encrypted) { //Can't generate cookie key due to host failure
92
+ return false;
93
+ }
94
+
95
+ foreach ($_COOKIE as $name => $value) {
96
+ if (!preg_match('/^wfls\-remembered\-(.+)$/', $name, $matches)) {
97
+ continue;
98
+ }
99
+
100
+ $jwt = Model_JWT::decode_jwt($value);
101
+ if (!$jwt || !isset($jwt->payload['iv'])) {
102
+ continue;
103
+ }
104
+
105
+ if (\WordfenceLS\Controller_Time::time() > min($jwt->expiration, $maxExpiration)) { //Either JWT is expired or the remember period was shortened since generating it
106
+ continue;
107
+ }
108
+
109
+ $data = Model_JWT::base64url_convert_from($matches[1]);
110
+ $iv = $jwt->payload['iv'];
111
+ $encrypted = array('data' => $data, 'iv' => $iv);
112
+ $userID = (int) Model_Symmetric::decrypt($encrypted);
113
+ if ($userID != 0 && $userID == $user->ID) {
114
+ $_cache[$user->ID] = true;
115
+ return true;
116
+ }
117
+ }
118
+
119
+ $_cache[$user->ID] = false;
120
+ return false;
121
+ }
122
+
123
+ /**
124
+ * Sets the cookie needed to remember the 2FA status.
125
+ *
126
+ * @param \WP_User $user
127
+ */
128
+ public function remember_2fa($user) {
129
+ if (!Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REMEMBER_DEVICE_ENABLED)) {
130
+ return;
131
+ }
132
+
133
+ if ($this->has_remembered_2fa($user)) {
134
+ return;
135
+ }
136
+
137
+ $encrypted = Model_Symmetric::encrypt((string) $user->ID);
138
+ if (!$encrypted) { //Can't generate cookie key due to host failure
139
+ return;
140
+ }
141
+
142
+ //Remove old cookies
143
+ foreach ($_COOKIE as $name => $value) {
144
+ if (!preg_match('/^wfls\-remembered\-(.+)$/', $name, $matches)) {
145
+ continue;
146
+ }
147
+ setcookie($name, '', \WordfenceLS\Controller_Time::time() - 86400);
148
+ }
149
+
150
+ //Set the new one
151
+ $expiration = \WordfenceLS\Controller_Time::time() + Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REMEMBER_DEVICE_DURATION);
152
+ $jwt = new Model_JWT(array('iv' => $encrypted['iv']), $expiration);
153
+ $cookieName = 'wfls-remembered-' . Model_JWT::base64url_convert_to($encrypted['data']);
154
+ $cookieValue = (string) $jwt;
155
+ setcookie($cookieName, $cookieValue, $expiration, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
156
+ }
157
+
158
+ /**
159
+ * Returns whether or not 2FA can be activated on the given user.
160
+ *
161
+ * @param \WP_User $user
162
+ * @return bool
163
+ */
164
+ public function can_activate_2fa($user) {
165
+ if (is_multisite() && !is_super_admin($user->ID)) {
166
+ $blogs = get_blogs_of_user($user->ID);
167
+ foreach ($blogs as $id => $info) {
168
+ if ($this->_user_can_for_blog($user, $id, Controller_Permissions::CAP_ACTIVATE_2FA_SELF)) {
169
+ return true;
170
+ }
171
+ }
172
+ return false;
173
+ }
174
+ return user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_SELF);
175
+ }
176
+
177
+ /**
178
+ * Implementation of current_user_can_for_blog that works for an arbitrary user.
179
+ *
180
+ * @param int $user_id
181
+ * @param int $blog_id
182
+ * @param string $capability
183
+ * @return bool
184
+ */
185
+ private function _user_can_for_blog($user_id, $blog_id, $capability) {
186
+ $switched = is_multisite() ? switch_to_blog($blog_id) : false;
187
+
188
+ $user = new \WP_User($user_id);
189
+
190
+ $args = array_slice(func_get_args(), 2);
191
+ $args = array_merge(array($capability), $args);
192
+
193
+ $can = call_user_func_array(array($user, 'has_cap'), $args);
194
+
195
+ if ($switched) {
196
+ restore_current_blog();
197
+ }
198
+
199
+ return $can;
200
+ }
201
+
202
+ /**
203
+ * Returns whether or not any user has 2FA activated.
204
+ *
205
+ * @return bool
206
+ */
207
+ public function any_2fa_active() {
208
+ global $wpdb;
209
+ $table = Controller_DB::shared()->secrets;
210
+ return !!intval($wpdb->get_var("SELECT COUNT(*) FROM `{$table}`"));
211
+ }
212
+
213
+ /**
214
+ * Returns whether or not the user has 2FA activated.
215
+ *
216
+ * @param \WP_User $user
217
+ * @return bool
218
+ */
219
+ public function has_2fa_active($user) {
220
+ global $wpdb;
221
+ $table = Controller_DB::shared()->secrets;
222
+ return $this->can_activate_2fa($user) && !!intval($wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM `{$table}` WHERE `user_id` = %d", $user->ID)));
223
+ }
224
+
225
+ /**
226
+ * Deactivates a user.
227
+ *
228
+ * @param \WP_User $user
229
+ */
230
+ public function deactivate_2fa($user) {
231
+ global $wpdb;
232
+ $table = Controller_DB::shared()->secrets;
233
+ $wpdb->query($wpdb->prepare("DELETE FROM `{$table}` WHERE `user_id` = %d", $user->ID));
234
+ }
235
+
236
+ /**
237
+ * Returns whether or not 2FA is required for the user regardless of activation status. 2FA is considered required
238
+ * when the option to require it is enabled and there is at least one administrator with it active.
239
+ *
240
+ * @param \WP_User $user
241
+ * @return bool
242
+ */
243
+ public function requires_2fa($user) {
244
+ static $_cachedRequired = null;
245
+ if ($_cachedRequired !== null) {
246
+ return $_cachedRequired;
247
+ }
248
+
249
+ if (Controller_Permissions::shared()->can_manage_settings($user) && Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REQUIRE_2FA_ADMIN)) {
250
+ if (Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED) && \WordfenceLS\Controller_Time::time() < Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD)) {
251
+ define('WFLS_WILL_BE_REQUIRED', true);
252
+ $_cachedRequired = false;
253
+ return false;
254
+ }
255
+
256
+ if ($this->has_2fa_active($user)) {
257
+ $_cachedRequired = true;
258
+ return true;
259
+ }
260
+
261
+ $activeIDs = $this->_user_ids_with_2fa_active();
262
+ foreach ($activeIDs as $id) {
263
+ if (Controller_Permissions::shared()->can_manage_settings(new \WP_User($id))) {
264
+ $_cachedRequired = true;
265
+ return true;
266
+ }
267
+ }
268
+ }
269
+ $_cachedRequired = false;
270
+ return false;
271
+ }
272
+
273
+ /**
274
+ * Returns the number of recovery codes remaining for the user or null if the user does not have 2FA active.
275
+ *
276
+ * @param \WP_User $user
277
+ * @return float|null
278
+ */
279
+ public function recovery_code_count($user) {
280
+ global $wpdb;
281
+ $table = Controller_DB::shared()->secrets;
282
+ $record = $wpdb->get_var($wpdb->prepare("SELECT `recovery` FROM `{$table}` WHERE `user_id` = %d", $user->ID));
283
+ if (!$record) {
284
+ return null;
285
+ }
286
+
287
+ return floor(Model_Crypto::strlen($record) / self::RECOVERY_CODE_SIZE);
288
+ }
289
+
290
+ /**
291
+ * Generates a new set of recovery codes and saves them to $user if provided.
292
+ *
293
+ * @param \WP_User|bool $user The user to save the codes to or false to just return codes.
294
+ * @param int $count
295
+ * @return array
296
+ */
297
+ public function regenerate_recovery_codes($user = false, $count = self::RECOVERY_CODE_COUNT) {
298
+ $codes = array();
299
+ for ($i = 0; $i < $count; $i++) {
300
+ $c = \WordfenceLS\Model_Crypto::random_bytes(self::RECOVERY_CODE_SIZE);
301
+ $codes[] = $c;
302
+ }
303
+
304
+ if ($user && Controller_Users::shared()->has_2fa_active($user)) {
305
+ global $wpdb;
306
+ $table = Controller_DB::shared()->secrets;
307
+ $wpdb->query($wpdb->prepare("UPDATE `{$table}` SET `recovery` = %s WHERE `user_id` = %d", implode('', $codes), $user->ID));
308
+ }
309
+
310
+ return $codes;
311
+ }
312
+
313
+ /**
314
+ * Returns the active and inactive user counts.
315
+ *
316
+ * @return array
317
+ */
318
+ public function user_counts() {
319
+ if (is_multisite() && function_exists('get_user_count')) {
320
+ $total_users = get_user_count();
321
+ }
322
+ else {
323
+ global $wpdb;
324
+ $total_users = (int) $wpdb->get_var("SELECT COUNT(ID) as c FROM {$wpdb->users}");
325
+ }
326
+ $active_users = $this->active_count();
327
+ return array('active_users' => $active_users, 'inactive_users' => max($total_users - $active_users, '-'));
328
+ }
329
+
330
+ public function detailed_user_counts() {
331
+ global $wpdb;
332
+
333
+ //Base counts
334
+ $counts = count_users();
335
+
336
+ //Adaptation of the source of the above call to get enabled counts
337
+ $site_id = get_current_blog_id();
338
+ $blog_prefix = $wpdb->get_blog_prefix($site_id);
339
+ $roles = new \WP_Roles();
340
+ if (is_multisite() && get_current_blog_id() != $site_id) {
341
+ switch_to_blog($site_id);
342
+ $avail_roles = $roles->get_names();
343
+ restore_current_blog();
344
+ }
345
+ else {
346
+ $avail_roles = $roles->get_names();
347
+ }
348
+
349
+ // Build a CPU-intensive query that will return concise information.
350
+ $select_count = array();
351
+ foreach ($avail_roles as $this_role => $name) {
352
+ if (!method_exists($wpdb, 'esc_like')) {
353
+ $like = addcslashes('"' . $this_role . '"', '_%\\'); //for WP < 4.0
354
+ }
355
+ else {
356
+ $like = $wpdb->esc_like('"' . $this_role . '"');
357
+ }
358
+ $select_count[] = $wpdb->prepare("COUNT(NULLIF(`meta_value` LIKE %s, false))", '%' . $like . '%');
359
+ }
360
+ $select_count[] = "COUNT(NULLIF(`meta_value` = 'a:0:{}', false))";
361
+ $select_count = implode(', ', $select_count);
362
+
363
+ // Add the meta_value index to the selection list, then run the query.
364
+ $table = Controller_DB::shared()->secrets;
365
+ $row = $wpdb->get_row("
366
+ SELECT {$select_count}, COUNT(*)
367
+ FROM {$wpdb->usermeta} um
368
+ INNER JOIN {$table} tf ON um.user_id = tf.user_id
369
+ WHERE meta_key = '{$blog_prefix}capabilities'
370
+ ", ARRAY_N);
371
+
372
+ // Run the previous loop again to associate results with role names.
373
+ $col = 0;
374
+ $role_counts = array();
375
+ foreach ($avail_roles as $this_role => $name) {
376
+ $count = (int) $row[$col++];
377
+ if ($count > 0) {
378
+ $role_counts[$this_role] = $count;
379
+ }
380
+ }
381
+
382
+ $role_counts['none'] = (int) $row[$col++];
383
+
384
+ // Get the meta_value index from the end of the result set.
385
+ $total_users = (int) $row[$col];
386
+
387
+ $counts['active_total_users'] = $total_users;
388
+ $counts['active_avail_roles'] =& $role_counts;
389
+
390
+ return $counts;
391
+ }
392
+
393
+ /**
394
+ * Returns the number of users with 2FA active.
395
+ *
396
+ * @return int
397
+ */
398
+ public function active_count() {
399
+ global $wpdb;
400
+ $table = Controller_DB::shared()->secrets;
401
+ return intval($wpdb->get_var("SELECT COUNT(*) FROM `{$table}`"));
402
+ }
403
+
404
+ /**
405
+ * WP Filters/Actions
406
+ */
407
+
408
+ protected function _init_actions() {
409
+ add_action('deleted_user', array($this, '_deleted_user'));
410
+ add_filter('manage_users_columns', array($this, '_manage_users_columns'));
411
+ add_filter('manage_users_custom_column', array($this, '_manage_users_custom_column'), 10, 3);
412
+ add_filter('manage_users_sortable_columns', array($this, '_manage_users_sortable_columns'), 10, 1);
413
+ add_filter('users_list_table_query_args', array($this, '_users_list_table_query_args'));
414
+ add_filter('user_row_actions', array($this, '_user_row_actions'), 10, 2);
415
+ add_filter('views_users', array($this, '_views_users'));
416
+
417
+ if (is_multisite()) {
418
+ add_filter('manage_users-network_columns', array($this, '_manage_users_columns'));
419
+ add_filter('manage_users-network_custom_column', array($this, '_manage_users_custom_column'), 10, 3);
420
+ add_filter('manage_users-network_sortable_columns', array($this, '_manage_users_sortable_columns'), 10, 1);
421
+ add_filter('ms_user_row_actions', array($this, '_user_row_actions'), 10, 2);
422
+ add_filter('views_users-network', array($this, '_views_users'));
423
+ }
424
+ }
425
+
426
+ public function _deleted_user($id) {
427
+ $user = new \WP_User($id);
428
+ if ($user instanceof \WP_User && !$user->exists()) {
429
+ global $wpdb;
430
+ $table = Controller_DB::shared()->secrets;
431
+ $wpdb->query($wpdb->prepare("DELETE FROM `{$table}` WHERE `user_id` = %d", $id));
432
+ }
433
+ }
434
+
435
+ public function _manage_users_columns($columns = array()) {
436
+ if (user_can(wp_get_current_user(), Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
437
+ $columns['wfls_2fa_status'] = __('2FA Status', 'wordfence-2fa');
438
+ }
439
+
440
+ if (Controller_Permissions::shared()->can_manage_settings(wp_get_current_user())) {
441
+ $columns['wfls_last_login'] = __('Last Login', 'wordfence-2fa');
442
+ if (Controller_CAPTCHA::shared()->enabled()) {
443
+ $columns['wfls_last_captcha'] = __('Last CAPTCHA', 'wordfence-2fa');
444
+ }
445
+ }
446
+ return $columns;
447
+ }
448
+
449
+ public function _manage_users_custom_column($value = '', $column_name = '', $user_id = 0) {
450
+ switch($column_name) {
451
+ case 'wfls_2fa_status':
452
+ $user = new \WP_User($user_id);
453
+ $value = __('Not Allowed', 'wordfence-2fa');
454
+ if (Controller_Users::shared()->can_activate_2fa($user)) {
455
+ $value = Controller_Users::shared()->has_2fa_active($user) ? __('Active', 'wordfence-2fa') : __('Inactive', 'wordfence-2fa');
456
+ }
457
+ break;
458
+ case 'wfls_last_login':
459
+ $value = '-';
460
+ if (($last = get_user_meta($user_id, 'wfls-last-login', true))) {
461
+ $value = Controller_Time::format_local_time(get_option('date_format') . ' ' . get_option('time_format'), $last);
462
+ }
463
+ break;
464
+ case 'wfls_last_captcha':
465
+ $user = new \WP_User($user_id);
466
+ if (Controller_Users::shared()->can_activate_2fa($user) && Controller_Users::shared()->has_2fa_active($user)) {
467
+ $value = __('(not required)', 'wordfence-2fa');
468
+ }
469
+ else {
470
+ $value = '-';
471
+ if (($last = get_user_meta($user_id, 'wfls-last-captcha-score', true))) {
472
+ $value = number_format($last, 1);
473
+ }
474
+ }
475
+ break;
476
+ }
477
+
478
+ return $value;
479
+ }
480
+
481
+ public function _manage_users_sortable_columns($sortable_columns) {
482
+ return array_merge($sortable_columns, array(
483
+ 'wfls_last_login' => 'wfls-lastlogin',
484
+ 'wfls_last_captcha' => 'wfls-lastcaptcha',
485
+ ));
486
+ }
487
+
488
+ protected function _user_ids_with_2fa_active() {
489
+ global $wpdb;
490
+ $table = Controller_DB::shared()->secrets;
491
+ return $wpdb->get_col("SELECT DISTINCT `user_id` FROM {$table}");
492
+ }
493
+
494
+ public function _users_list_table_query_args($args) {
495
+ if (isset($_REQUEST['wf2fa']) && preg_match('/^(?:in)?active$/i', $_REQUEST['wf2fa'])) {
496
+ $mode = strtolower($_REQUEST['wf2fa']);
497
+ if ($mode == 'active') {
498
+ $args['include'] = $this->_user_ids_with_2fa_active();
499
+ }
500
+ else if ($mode == 'inactive') {
501
+ unset($args['include']);
502
+ $args['exclude'] = $this->_user_ids_with_2fa_active();
503
+ }
504
+ }
505
+
506
+ if (isset($args['orderby'])) {
507
+ if (is_string($args['orderby'])) {
508
+ if ($args['orderby'] == 'wfls-lastlogin') {
509
+ $args['meta_key'] = 'wfls-last-login';
510
+ $args['orderby'] = 'meta_value';
511
+ }
512
+ else if ($args['orderby'] == 'wfls-lastcaptcha') {
513
+ $args['meta_key'] = 'wfls-last-captcha-score';
514
+ $args['orderby'] = 'meta_value';
515
+ }
516
+ }
517
+ else {
518
+ $has_one = false;
519
+ if (array_key_exists('wfls-lastlogin', $args['orderby'])) {
520
+ $args['meta_key'] = 'wfls-last-login';
521
+ $args['orderby']['meta_value'] = $args['orderby']['wfls-lastlogin'];
522
+ unset($args['orderby']['wfls-lastlogin']);
523
+ $has_one = true;
524
+ }
525
+
526
+ if (array_key_exists('wfls-lastcaptcha', $args['orderby'])) {
527
+ if (!$has_one) { //We have to discard one if both are set to sort by because $meta_key can only be a single value rather than an array
528
+ $args['meta_key'] = 'wfls-last-captcha-score';
529
+ $args['orderby']['meta_value'] = $args['orderby']['wfls-lastcaptcha'];
530
+ }
531
+ unset($args['orderby']['wfls-lastcaptcha']);
532
+ $has_one = true;
533
+ }
534
+
535
+ if (in_array('wfls-lastlogin', $args['orderby'])) {
536
+ if (!$has_one) { //We have to discard one if both are set to sort by because $meta_key can only be a single value rather than an array
537
+ $args['meta_key'] = 'wfls-last-login';
538
+ $args['orderby'][] = 'meta_value';
539
+ }
540
+ unset($args['orderby'][array_search('wfls-lastlogin', $args['orderby'])]);
541
+ $has_one = true;
542
+ }
543
+
544
+ if (in_array('wfls-lastcaptcha', $args['orderby'])) {
545
+ if (!$has_one) { //We have to discard one if both are set to sort by because $meta_key can only be a single value rather than an array
546
+ $args['meta_key'] = 'wfls-last-captcha-score';
547
+ $args['orderby'][] = 'meta_value';
548
+ }
549
+ unset($args['orderby'][array_search('wfls-lastcaptcha', $args['orderby'])]);
550
+ $has_one = true;
551
+ }
552
+ }
553
+ }
554
+ return $args;
555
+ }
556
+
557
+ public function _user_row_actions($actions, $user) {
558
+ //Format is 'view' => '<a href="https://wfpremium.dev1.ryanbritton.com/author/ryan/" aria-label="View posts by ryan">View</a>'
559
+ if (user_can(wp_get_current_user(), Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS) && (Controller_Users::shared()->can_activate_2fa($user) || Controller_Users::shared()->has_2fa_active($user))) {
560
+ $url = (is_multisite() ? network_admin_url('admin.php?page=WFLS&user=' . $user->ID) : admin_url('admin.php?page=WFLS&user=' . $user->ID));
561
+ $actions['wf2fa'] = '<a href="' . esc_url($url) . '" aria-label="' . esc_attr(sprintf(__('Edit two-factor authentication for %s', 'wordfence-2fa'), $user->user_login)) . '">' . __('2FA', 'wordfence-2fa') . '</a>';
562
+ }
563
+ return $actions;
564
+ }
565
+
566
+ public function _views_users($views) {
567
+ //Format is 'subscriber' => '<a href=\\'users.php?role=subscriber\\'>Subscriber <span class="count">(40,002)</span></a>',
568
+ include(ABSPATH . WPINC . '/version.php'); /** @var string $wp_version */
569
+ if (user_can(wp_get_current_user(), Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS) && version_compare($wp_version, '4.4.0', '>=')) {
570
+ $counts = $this->user_counts();
571
+ $views['all'] = str_replace(' class="current" aria-current="page"', '', $views['all']);
572
+ $views['wfls-active'] = '<a href="' . esc_url(add_query_arg('wf2fa', 'active', 'users.php')) . '"' . (isset($_GET['wf2fa']) && $_GET['wf2fa'] == 'active' ? ' class="current" aria-current="page"' : '') . '>' . __('2FA Active', 'wordfence-2fa') . ' <span class="count">(' . number_format($counts['active_users']) . ')</span></a>';
573
+ $views['wfls-inactive'] = '<a href="' . esc_url(add_query_arg('wf2fa', 'inactive', 'users.php')) . '"' . (isset($_GET['wf2fa']) && $_GET['wf2fa'] == 'inactive' ? ' class="current" aria-current="page"' : '') . '>' . __('2FA Inactive', 'wordfence-2fa') . ' <span class="count">(' . number_format($counts['inactive_users']) . ')</span></a>';
574
+ }
575
+ return $views;
576
+ }
577
+ }
classes/controller/whitelist.php ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Controller_Whitelist {
6
+ private $_cachedStatus = array();
7
+
8
+ /**
9
+ * Returns the singleton Controller_Whitelist.
10
+ *
11
+ * @return Controller_Whitelist
12
+ */
13
+ public static function shared() {
14
+ static $_shared = null;
15
+ if ($_shared === null) {
16
+ $_shared = new Controller_Whitelist();
17
+ }
18
+ return $_shared;
19
+ }
20
+
21
+ public function is_whitelisted($ip) {
22
+ $ipHash = hash('sha256', Model_IP::inet_pton($ip));
23
+ if (isset($this->_cachedStatus[$ipHash])) {
24
+ return $this->_cachedStatus[$ipHash];
25
+ }
26
+
27
+ $whitelist = Controller_Settings::shared()->whitelisted_ips();
28
+ foreach ($whitelist as $entry) {
29
+ if ($this->ip_in_range($ip, $entry)) {
30
+ $this->_cachedStatus[$ipHash] = true;
31
+ return true;
32
+ }
33
+ }
34
+ $this->_cachedStatus[$ipHash] = false;
35
+ return false;
36
+ }
37
+
38
+ /**
39
+ * Check if the supplied IP address is within the user supplied range.
40
+ *
41
+ * @param string $ip
42
+ * @return bool
43
+ */
44
+ public function ip_in_range($ip, $range) {
45
+ if (strpos($range, '/') !== false) { //CIDR range -- 127.0.0.1/24
46
+ return $this->_cidr_contains_ip($range, $ip);
47
+ }
48
+ else if (strpos($range, '[') !== false) { //Bracketed range -- 127.0.0.[1-100]
49
+ // IPv4 range
50
+ if (strpos($range, '.') !== false && strpos($ip, '.') !== false) {
51
+ // IPv4-mapped-IPv6
52
+ if (preg_match('/:ffff:([^:]+)$/i', $range, $matches)) {
53
+ $range = $matches[1];
54
+ }
55
+ if (preg_match('/:ffff:([^:]+)$/i', $ip, $matches)) {
56
+ $ip = $matches[1];
57
+ }
58
+
59
+ // Range check
60
+ if (preg_match('/\[\d+\-\d+\]/', $range)) {
61
+ $ipParts = explode('.', $ip);
62
+ $whiteParts = explode('.', $range);
63
+ $mismatch = false;
64
+ if (count($whiteParts) != 4 || count($ipParts) != 4) {
65
+ return false;
66
+ }
67
+
68
+ for ($i = 0; $i <= 3; $i++) {
69
+ if (preg_match('/^\[(\d+)\-(\d+)\]$/', $whiteParts[$i], $m)) {
70
+ if ($ipParts[$i] < $m[1] || $ipParts[$i] > $m[2]) {
71
+ $mismatch = true;
72
+ }
73
+ }
74
+ else if ($whiteParts[$i] != $ipParts[$i]) {
75
+ $mismatch = true;
76
+ }
77
+ }
78
+ if ($mismatch === false) {
79
+ return true; // Is whitelisted because we did not get a mismatch
80
+ }
81
+ }
82
+ else if ($range == $ip) {
83
+ return true;
84
+ }
85
+
86
+ // IPv6 range
87
+ }
88
+ else if (strpos($range, ':') !== false && strpos($ip, ':') !== false) {
89
+ $ip = strtolower(Model_IP::expand_ipv6_address($ip));
90
+ $range = strtolower($this->_expand_ipv6_range($range));
91
+ if (preg_match('/\[[a-f0-9]+\-[a-f0-9]+\]/i', $range)) {
92
+ $IPparts = explode(':', $ip);
93
+ $whiteParts = explode(':', $range);
94
+ $mismatch = false;
95
+ if (count($whiteParts) != 8 || count($IPparts) != 8) {
96
+ return false;
97
+ }
98
+
99
+ for ($i = 0; $i <= 7; $i++) {
100
+ if (preg_match('/^\[([a-f0-9]+)\-([a-f0-9]+)\]$/i', $whiteParts[$i], $m)) {
101
+ $ip_group = hexdec($IPparts[$i]);
102
+ $range_group_from = hexdec($m[1]);
103
+ $range_group_to = hexdec($m[2]);
104
+ if ($ip_group < $range_group_from || $ip_group > $range_group_to) {
105
+ $mismatch = true;
106
+ break;
107
+ }
108
+ }
109
+ else if ($whiteParts[$i] != $IPparts[$i]) {
110
+ $mismatch = true;
111
+ break;
112
+ }
113
+ }
114
+ if ($mismatch === false) {
115
+ return true; // Is whitelisted because we did not get a mismatch
116
+ }
117
+ }
118
+ else if ($range == $ip) {
119
+ return true;
120
+ }
121
+ }
122
+ }
123
+ else if (strpos($range, '-') !== false) { //Linear range -- 127.0.0.1 - 127.0.1.100
124
+ list($ip1, $ip2) = explode('-', $range);
125
+ $ip1N = Model_IP::inet_pton($ip1);
126
+ $ip2N = Model_IP::inet_pton($ip2);
127
+ $ipN = Model_IP::inet_pton($ip);
128
+ return (strcmp($ip1N, $ipN) <= 0 && strcmp($ip2N, $ipN) >= 0);
129
+ }
130
+ else { //Treat as a literal IP
131
+ $ip1 = Model_IP::inet_pton($range);
132
+ $ip2 = Model_IP::inet_pton($ip);
133
+ if ($ip1 !== false && $ip1 === $ip2) {
134
+ return true;
135
+ }
136
+ }
137
+
138
+ return false;
139
+ }
140
+
141
+ /**
142
+ * Utility
143
+ */
144
+
145
+ /**
146
+ * Returns whether or not the CIDR-formatted subnet contains $ip.
147
+ *
148
+ * @param string $subnet
149
+ * @param string $ip A human-readable IP.
150
+ * @return bool
151
+ */
152
+ protected function _cidr_contains_ip($subnet, $ip) {
153
+ list($network, $prefix) = array_pad(explode('/', $subnet, 2), 2, null);
154
+
155
+ if (filter_var($network, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
156
+ // If no prefix was supplied, 32 is implied for IPv4
157
+ if ($prefix === null) {
158
+ $prefix = 32;
159
+ }
160
+
161
+ // Validate the IPv4 network prefix
162
+ if ($prefix < 0 || $prefix > 32) {
163
+ return false;
164
+ }
165
+
166
+ // Increase the IPv4 network prefix to work in the IPv6 address space
167
+ $prefix += 96;
168
+ }
169
+ else {
170
+ // If no prefix was supplied, 128 is implied for IPv6
171
+ if ($prefix === null) {
172
+ $prefix = 128;
173
+ }
174
+
175
+ // Validate the IPv6 network prefix
176
+ if ($prefix < 1 || $prefix > 128) {
177
+ return false;
178
+ }
179
+ }
180
+
181
+ $bin_network = Model_Crypto::substr(Model_IP::inet_pton($network), 0, ceil($prefix / 8));
182
+ $bin_ip = Model_Crypto::substr(Model_IP::inet_pton($ip), 0, ceil($prefix / 8));
183
+ if ($prefix % 8 != 0) { //Adjust the last relevant character to fit the mask length since the character's bits are split over it
184
+ $pos = intval($prefix / 8);
185
+ $adjustment = chr(((0xff << (8 - ($prefix % 8))) & 0xff));
186
+ $bin_network[$pos] = ($bin_network[$pos] & $adjustment);
187
+ $bin_ip[$pos] = ($bin_ip[$pos] & $adjustment);
188
+ }
189
+
190
+ return ($bin_network === $bin_ip);
191
+ }
192
+
193
+ /**
194
+ * Expands a compressed printable range representation of an IPv6 address.
195
+ *
196
+ * @param string $range
197
+ * @return string
198
+ */
199
+ protected function _expand_ipv6_range($range) {
200
+ $colon_count = substr_count($range, ':');
201
+ $dbl_colon_count = substr_count($range, '::');
202
+ if ($dbl_colon_count > 1) {
203
+ return false;
204
+ }
205
+ $dbl_colon_pos = strpos($range, '::');
206
+ if ($dbl_colon_pos !== false) {
207
+ $range = str_replace('::', str_repeat(':0000', (($dbl_colon_pos === 0 || $dbl_colon_pos === strlen($range) - 2) ? 9 : 8) - $colon_count) . ':', $range);
208
+ $range = trim($range, ':');
209
+ }
210
+ $colon_count = substr_count($range, ':');
211
+ if ($colon_count != 7) {
212
+ return false;
213
+ }
214
+
215
+ $groups = explode(':', $range);
216
+ $expanded = '';
217
+ foreach ($groups as $group) {
218
+ if (preg_match('/\[([a-f0-9]{1,4})\-([a-f0-9]{1,4})\]/i', $group, $matches)) {
219
+ $expanded .= sprintf('[%s-%s]', str_pad(strtolower($matches[1]), 4, '0', STR_PAD_LEFT), str_pad(strtolower($matches[2]), 4, '0', STR_PAD_LEFT)) . ':';
220
+ }
221
+ else if (preg_match('/[a-f0-9]{1,4}/i', $group)) {
222
+ $expanded .= str_pad(strtolower($group), 4, '0', STR_PAD_LEFT) . ':';
223
+ }
224
+ else {
225
+ return false;
226
+ }
227
+ }
228
+ return trim($expanded, ':');
229
+ }
230
+
231
+ /**
232
+ * @return bool
233
+ */
234
+ public function is_valid_range($range) {
235
+ return $this->_is_valid_cidr_range($range) || $this->_is_valid_bracketed_range($range) || $this->_is_valid_linear_range($range) || Model_IP::is_valid_ip($range);
236
+ }
237
+
238
+ protected function _is_valid_cidr_range($range) { //e.g., 192.0.2.1/24
239
+ if (preg_match('/[^0-9a-f:\/\.]/i', $range)) { return false; }
240
+ $components = explode('/', $range);
241
+ if (count($components) != 2) { return false; }
242
+
243
+ list($ip, $prefix) = $components;
244
+ if (!Model_IP::is_valid_ip($ip)) { return false; }
245
+
246
+ if (!preg_match('/^\d+$/', $prefix)) { return false; }
247
+
248
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
249
+ if ($prefix < 0 || $prefix > 32) { return false; }
250
+ }
251
+ else {
252
+ if ($prefix < 1 || $prefix > 128) { return false; }
253
+ }
254
+
255
+ return true;
256
+ }
257
+
258
+ protected function _is_valid_bracketed_range($range) { //e.g., 192.0.2.[1-10]
259
+ if (preg_match('/[^0-9a-f:\.\[\]\-]/i', $range)) { return false; }
260
+ if (strpos($range, '.') !== false) { //IPv4
261
+ if (preg_match_all('/(\d+)/', $range, $matches) > 0) {
262
+ foreach ($matches[1] as $match) {
263
+ $group = (int) $match;
264
+ if ($group > 255 || $group < 0) {
265
+ return false;
266
+ }
267
+ }
268
+ }
269
+
270
+ $group_regex = '([0-9]{1,3}|\[[0-9]{1,3}\-[0-9]{1,3}\])';
271
+ return preg_match('/^' . str_repeat("{$group_regex}\\.", 3) . $group_regex . '$/i', $range) > 0;
272
+ }
273
+
274
+ //IPv6
275
+ if (strpos($range, '::') !== false) {
276
+ $range = $this->_expand_ipv6_range($range);
277
+ }
278
+
279
+ if (!$range) {
280
+ return false;
281
+ }
282
+ $group_regex = '([a-f0-9]{1,4}|\[[a-f0-9]{1,4}\-[a-f0-9]{1,4}\])';
283
+ return preg_match('/^' . str_repeat($group_regex . ':', 7) . $group_regex . '$/i', $range) > 0;
284
+ }
285
+
286
+ protected function _is_valid_linear_range($range) { //e.g., 192.0.2.1-192.0.2.100
287
+ if (preg_match('/[^0-9a-f:\.\-]/i', $range)) { return false; }
288
+ list($ip1, $ip2) = explode("-", $range);
289
+ $ip1N = Model_IP::inet_pton($ip1);
290
+ $ip2N = Model_IP::inet_pton($ip2);
291
+
292
+ if ($ip1N === false || !Model_IP::is_valid_ip($ip1) || $ip2N === false || !Model_IP::is_valid_ip($ip2)) {
293
+ return false;
294
+ }
295
+
296
+ return strcmp($ip1N, $ip2N) <= 0;
297
+ }
298
+
299
+ protected function _is_mixed_range($range) { //e.g., 192.0.2.1-2001:db8::ffff
300
+ if (preg_match('/[^0-9a-f:\.\-]/i', $range)) { return false; }
301
+ list($ip1, $ip2) = explode("-", $range);
302
+
303
+ $ipv4Count = 0;
304
+ $ipv4Count += filter_var($ip1, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false ? 1 : 0;
305
+ $ipv4Count += filter_var($ip2, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false ? 1 : 0;
306
+
307
+ $ipv6Count = 0;
308
+ $ipv6Count += filter_var($ip1, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false ? 1 : 0;
309
+ $ipv6Count += filter_var($ip2, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false ? 1 : 0;
310
+
311
+ if ($ipv4Count != 2 && $ipv6Count != 2) {
312
+ return true;
313
+ }
314
+
315
+ return false;
316
+ }
317
+ }
classes/controller/wordfencels.php ADDED
@@ -0,0 +1,771 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ use WordfenceLS\Crypto\Model_JWT;
6
+ use WordfenceLS\Crypto\Model_Symmetric;
7
+ use WordfenceLS\Text\Model_HTML;
8
+ use WordfenceLS\View\Model_Tab;
9
+ use WordfenceLS\View\Model_Title;
10
+
11
+ class Controller_WordfenceLS {
12
+ const VERSION_KEY = 'wordfence_ls_version';
13
+
14
+ /**
15
+ * Returns the singleton Controller_Wordfence2FA.
16
+ *
17
+ * @return Controller_WordfenceLS
18
+ */
19
+ public static function shared() {
20
+ static $_shared = null;
21
+ if ($_shared === null) {
22
+ $_shared = new Controller_WordfenceLS();
23
+ }
24
+ return $_shared;
25
+ }
26
+
27
+ public function init() {
28
+ $this->_init_actions();
29
+ Controller_AJAX::shared()->init();
30
+ Controller_Users::shared()->init();
31
+ Controller_Time::shared()->init();
32
+ }
33
+
34
+ protected function _init_actions() {
35
+ register_activation_hook(WORDFENCE_LS_FCPATH, array($this, '_install_plugin'));
36
+ register_deactivation_hook(WORDFENCE_LS_FCPATH, array($this, '_uninstall_plugin'));
37
+
38
+ $versionInOptions = ((is_multisite() && function_exists('get_network_option')) ? get_network_option(null, self::VERSION_KEY, false) : get_option(self::VERSION_KEY, false));
39
+ if (!$versionInOptions || version_compare(WORDFENCE_LS_VERSION, $versionInOptions, '>')) { //Either there is no version in options or the version in options is greater and we need to run the upgrade
40
+ $this->_install();
41
+ }
42
+
43
+ if (!Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_ALLOW_XML_RPC)) {
44
+ add_filter('xmlrpc_enabled', array($this, '_block_xml_rpc'));
45
+ }
46
+
47
+ add_action('admin_init', array($this, '_admin_init'));
48
+ add_action('login_enqueue_scripts', array($this, '_login_enqueue_scripts'));
49
+ add_filter('authenticate', array($this, '_authenticate'), 25, 3);
50
+ add_action('set_logged_in_cookie', array($this, '_set_logged_in_cookie'), 25, 4);
51
+ add_action('wp_login', array($this, '_record_login'), 999, 1);
52
+ add_action('register_post', array($this, '_register_post'), 25, 3);
53
+ add_filter('wp_login_errors', array($this, '_wp_login_errors'), 25, 3);
54
+
55
+ $useSubmenu = WORDFENCE_LS_FROM_CORE;
56
+ if (is_multisite() && !is_network_admin()) {
57
+ $useSubmenu = false;
58
+ }
59
+
60
+ add_action('admin_menu', array($this, '_admin_menu'), $useSubmenu ? 55 : 10);
61
+ if (is_multisite()) {
62
+ add_action('network_admin_menu', array($this, '_admin_menu'), $useSubmenu ? 55 : 10);
63
+ }
64
+ add_action('admin_enqueue_scripts', array($this, '_admin_enqueue_scripts'));
65
+
66
+ add_action('show_user_profile', array($this, '_edit_user_profile'), 0); //We can't add it to the password section directly -- priority 0 is as close as we can get
67
+ add_action('edit_user_profile', array($this, '_edit_user_profile'), 0);
68
+ }
69
+
70
+ public function _admin_init() {
71
+ if (WORDFENCE_LS_FROM_CORE) {
72
+ \wfModuleController::shared()->addOptionIndex('wfls-option-enable-2fa-roles', __('Login Security: Enable 2FA for these roles', 'wordfence-2fa'));
73
+ \wfModuleController::shared()->addOptionIndex('wfls-option-allow-remember', __('Login Security: Allow remembering device for 30 days', 'wordfence-2fa'));
74
+ \wfModuleController::shared()->addOptionIndex('wfls-option-require-2fa-xml-rpc', __('Login Security: Require 2FA for XML-RPC call authentication', 'wordfence-2fa'));
75
+ \wfModuleController::shared()->addOptionIndex('wfls-option-disable-xml-rpc', __('Login Security: Disable XML-RPC authentication', 'wordfence-2fa'));
76
+ \wfModuleController::shared()->addOptionIndex('wfls-option-whitelist-2fa', __('Login Security: Whitelisted IP addresses that bypass 2FA', 'wordfence-2fa'));
77
+ \wfModuleController::shared()->addOptionIndex('wfls-option-enable-captcha', __('Login Security: Enable reCAPTCHA on the login and user registration pages', 'wordfence-2fa'));
78
+
79
+ $title = __('Login Security Options', 'wordfence-ls');
80
+ $description = __('Login Security options are available on the Login Security options page', 'wordfence-ls');
81
+ $url = esc_url(network_admin_url('admin.php?page=WFLS#top#settings'));
82
+ $link = __('Login Security Options', 'wordfence');;
83
+ \wfModuleController::shared()->addOptionBlock(<<<END
84
+ <div class="wf-row">
85
+ <div class="wf-col-xs-12">
86
+ <div class="wf-block wf-always-active" data-persistence-key="">
87
+ <div class="wf-block-header">
88
+ <div class="wf-block-header-content">
89
+ <div class="wf-block-title">
90
+ <strong>{$title}</strong>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ <div class="wf-block-content">
95
+ <ul class="wf-block-list">
96
+ <li>
97
+ <ul class="wf-flex-horizontal wf-flex-vertical-xs wf-flex-full-width wf-add-top wf-add-bottom">
98
+ <li>{$description}</li>
99
+ <li class="wf-right wf-left-xs wf-padding-add-top-xs-small">
100
+ <a href="{$url}" class="wf-btn wf-btn-primary wf-btn-callout-subtle" id="wf-login-security-options">{$link}</a>
101
+ </li>
102
+ </ul>
103
+ <input type="hidden" id="wfls-option-enable-2fa-roles">
104
+ <input type="hidden" id="wfls-option-allow-remember">
105
+ <input type="hidden" id="wfls-option-require-2fa-xml-rpc">
106
+ <input type="hidden" id="wfls-option-disable-xml-rpc">
107
+ <input type="hidden" id="wfls-option-whitelist-2fa">
108
+ <input type="hidden" id="wfls-option-enable-captcha">
109
+ </li>
110
+ </ul>
111
+ </div>
112
+ </div>
113
+ </div>
114
+ </div> <!-- end ls options -->
115
+ END
116
+ );
117
+ }
118
+
119
+ if ((is_plugin_active('jetpack/jetpack.php') || (is_multisite() && is_plugin_active_for_network('jetpack/jetpack.php'))) && !Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_ALLOW_XML_RPC) && Controller_Permissions::shared()->can_manage_settings()) {
120
+ if (is_multisite()) {
121
+ add_action('network_admin_notices', array($this, '_jetpack_xml_rpc_notice'));
122
+ }
123
+ else {
124
+ add_action('admin_notices', array($this, '_jetpack_xml_rpc_notice'));
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Notices
131
+ */
132
+
133
+ public function _jetpack_xml_rpc_notice() {
134
+ echo '<div class="notice notice-warning"><p>' . sprintf(__('XML-RPC authentication is disabled. Jetpack is currently active and requires XML-RPC authentication to work correctly. <a href="%s">Manage Settings</a>', 'wordfence-2fa'), esc_url(network_admin_url('admin.php?page=WFLS#top#settings'))) . '</p></div>';
135
+ }
136
+
137
+ /**
138
+ * Installation/Uninstallation
139
+ */
140
+
141
+ public function _install_plugin() {
142
+ $this->_install();
143
+ }
144
+
145
+ public function _uninstall_plugin() {
146
+ Controller_Time::shared()->uninstall();
147
+
148
+ foreach (array(self::VERSION_KEY) as $opt) {
149
+ if (is_multisite() && function_exists('delete_network_option')) {
150
+ delete_network_option(null, $opt);
151
+ }
152
+ delete_option($opt);
153
+ }
154
+ }
155
+
156
+ protected function _install() {
157
+ static $_runInstallCalled = false;
158
+ if ($_runInstallCalled) { return; }
159
+ $_runInstallCalled = true;
160
+
161
+ if (function_exists('ignore_user_abort')) {
162
+ ignore_user_abort(true);
163
+ }
164
+
165
+ if (!defined('DONOTCACHEDB')) { define('DONOTCACHEDB', true); }
166
+
167
+ $previousVersion = ((is_multisite() && function_exists('get_network_option')) ? get_network_option(null, self::VERSION_KEY, '0.0.0') : get_option(self::VERSION_KEY, '0.0.0'));
168
+ if (is_multisite() && function_exists('update_network_option')) {
169
+ update_network_option(null, self::VERSION_KEY, WORDFENCE_LS_VERSION); //In case we have a fatal error we don't want to keep running install.
170
+ }
171
+ else {
172
+ update_option(self::VERSION_KEY, WORDFENCE_LS_VERSION); //In case we have a fatal error we don't want to keep running install.
173
+ }
174
+
175
+ Controller_DB::shared()->install();
176
+ Controller_Settings::shared()->set_defaults();
177
+
178
+ if (\WordfenceLS\Controller_Time::time() > Controller_Settings::shared()->get_int(Controller_Settings::OPTION_LAST_SECRET_REFRESH) + 180 * 86400) {
179
+ Model_Crypto::refresh_secrets();
180
+ }
181
+
182
+ Controller_Time::shared()->install();
183
+ Controller_Permissions::shared()->install();
184
+ }
185
+
186
+ public function _block_xml_rpc() {
187
+ /**
188
+ * Fires just prior to blocking an XML-RPC request. After firing this action hook the XML-RPC request is blocked.
189
+ *
190
+ * @param int $source The source code of the block.
191
+ */
192
+ do_action('wfls_xml_rpc_blocked', 2);
193
+ return false;
194
+ }
195
+
196
+ /**
197
+ * Login Page
198
+ */
199
+
200
+ public function _login_enqueue_scripts() {
201
+ $useCAPTCHA = Controller_CAPTCHA::shared()->enabled();
202
+ if ($useCAPTCHA) {
203
+ wp_enqueue_script('wordfence-ls-recaptcha', 'https://www.google.com/recaptcha/api.js?render=' . urlencode(Controller_Settings::shared()->get(Controller_Settings::OPTION_RECAPTCHA_SITE_KEY)));
204
+ }
205
+
206
+ if ($useCAPTCHA || Controller_Users::shared()->any_2fa_active()) {
207
+ $verification = '';
208
+ if (isset($_REQUEST['wfls-email-verification']) && is_string($_REQUEST['wfls-email-verification'])) {
209
+ $jwt = Model_JWT::decode_jwt($_REQUEST['wfls-email-verification']);
210
+ if ($jwt && isset($jwt->payload['user'])) {
211
+ $verification = $_REQUEST['wfls-email-verification'];
212
+ }
213
+ }
214
+
215
+ wp_enqueue_script('wordfence-ls-login', Model_Asset::js('login.js'), array('jquery'), WORDFENCE_LS_VERSION);
216
+ wp_enqueue_style('wordfence-ls-login', Model_Asset::css('login.css'), array(), WORDFENCE_LS_VERSION);
217
+ wp_localize_script('wordfence-ls-login', 'WFLSVars', array(
218
+ 'ajaxurl' => admin_url('admin-ajax.php'),
219
+ 'nonce' => wp_create_nonce('wp-ajax'),
220
+ 'recaptchasitekey' => Controller_Settings::shared()->get(Controller_Settings::OPTION_RECAPTCHA_SITE_KEY),
221
+ 'useCAPTCHA' => $useCAPTCHA,
222
+ 'allowremember' => Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REMEMBER_DEVICE_ENABLED),
223
+ 'verification' => $verification,
224
+ ));
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Admin Pages
230
+ */
231
+ public function _admin_enqueue_scripts() {
232
+ if (isset($_GET['page']) && $_GET['page'] == 'WFLS') {
233
+ wp_enqueue_script('wordfence-ls-jquery.qrcode', Model_Asset::js('jquery.qrcode.min.js'), array('jquery'), WORDFENCE_LS_VERSION);
234
+ wp_enqueue_script('wordfence-ls-jquery.tmpl', Model_Asset::js('jquery.tmpl.min.js'), array('jquery'), WORDFENCE_LS_VERSION);
235
+ wp_enqueue_script('wordfence-ls-jquery.colorbox', Model_Asset::js('jquery.colorbox.min.js'), array('jquery'), WORDFENCE_LS_VERSION);
236
+ if (Controller_Permissions::shared()->can_manage_settings()) {
237
+ wp_enqueue_script('wordfence-ls-jquery-ui.timepicker', Model_Asset::js('jquery-ui-timepicker-addon.js'), array('jquery', 'jquery-ui-datepicker', 'jquery-ui-slider'), WORDFENCE_LS_VERSION);
238
+
239
+ wp_enqueue_style('wordfence-ls-jquery-ui-css', Model_Asset::css('jquery-ui.min.css'), array(), WORDFENCE_LS_VERSION);
240
+ wp_enqueue_style('wordfence-ls-jquery-ui-css.structure', Model_Asset::css('jquery-ui.structure.min.css'), array(), WORDFENCE_LS_VERSION);
241
+ wp_enqueue_style('wordfence-ls-jquery-ui-css.theme', Model_Asset::css('jquery-ui.theme.min.css'), array(), WORDFENCE_LS_VERSION);
242
+ wp_enqueue_style('wordfence-ls-jquery-ui-css.timepicker', Model_Asset::css('jquery-ui-timepicker-addon.css'), array(), WORDFENCE_LS_VERSION);
243
+ }
244
+ wp_enqueue_script('wordfence-ls-admin', Model_Asset::js('admin.js'), array('jquery'), WORDFENCE_LS_VERSION);
245
+ wp_enqueue_style('wordfence-ls-admin', Model_Asset::css('admin.css'), array(), WORDFENCE_LS_VERSION);
246
+ wp_enqueue_style('wordfence-ls-colorbox', Model_Asset::css('colorbox.css'), array(), WORDFENCE_LS_VERSION);
247
+ wp_enqueue_style('wordfence-ls-ionicons', Model_Asset::css('ionicons.css'), array(), WORDFENCE_LS_VERSION);
248
+ wp_localize_script('wordfence-ls-admin', 'WFLSVars', array(
249
+ 'ajaxurl' => admin_url('admin-ajax.php'),
250
+ 'nonce' => wp_create_nonce('wp-ajax'),
251
+ 'modalTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}', 'primaryButton' => array('id' => 'wfls-generic-modal-close', 'label' => __('Close', 'wordfence'), 'link' => '#')))->render(),
252
+ 'tokenInvalidTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '${message}', 'primaryButton' => array('id' => 'wfls-token-invalid-modal-reload', 'label' => __('Reload', 'wordfence'), 'link' => '#')))->render(),
253
+ 'modalHTMLTemplate' => Model_View::create('common/modal-prompt', array('title' => '${title}', 'message' => '{{html message}}', 'primaryButton' => array('id' => 'wfls-generic-modal-close', 'label' => __('Close', 'wordfence'), 'link' => '#')))->render(),
254
+ ));
255
+ }
256
+ else {
257
+ wp_enqueue_style('wordfence-ls-admin-global', Model_Asset::css('admin-global.css'), array(), WORDFENCE_LS_VERSION);
258
+ }
259
+
260
+ if (Controller_Notices::shared()->has_notice(wp_get_current_user())) {
261
+ wp_enqueue_script('wordfence-ls-admin-global', Model_Asset::js('admin-global.js'), array('jquery'), WORDFENCE_LS_VERSION);
262
+
263
+ wp_localize_script('wordfence-ls-admin-global', 'GWFLSVars', array(
264
+ 'ajaxurl' => admin_url('admin-ajax.php'),
265
+ 'nonce' => wp_create_nonce('wp-ajax'),
266
+ ));
267
+ }
268
+ }
269
+
270
+ public function _edit_user_profile($user) {
271
+ if ($user->ID == get_current_user_id() || !current_user_can(Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
272
+ $manageURL = admin_url('admin.php?page=WFLS');
273
+ }
274
+ else {
275
+ $manageURL = admin_url('admin.php?page=WFLS&user=' . ((int) $user->ID));
276
+ }
277
+
278
+ if (is_multisite() && is_super_admin()) {
279
+ if ($user->ID == get_current_user_id()) {
280
+ $manageURL = network_admin_url('admin.php?page=WFLS');
281
+ }
282
+ else {
283
+ $manageURL = network_admin_url('admin.php?page=WFLS&user=' . ((int) $user->ID));
284
+ }
285
+ }
286
+
287
+ if (Controller_Users::shared()->can_activate_2fa($user) && $user->ID == get_current_user_id()):
288
+ ?>
289
+ <h2><?php _e('Wordfence Login Security', 'wordfence-2fa'); ?></h2>
290
+ <table class="form-table">
291
+ <tr id="wordfence-ls">
292
+ <th><label for="wordfence-ls-btn"><?php _e('2FA Status'); ?></label></th>
293
+ <td>
294
+ <p><strong><?php echo (Controller_Users::shared()->has_2fa_active($user) ? __('Active', 'wordfence-2fa') : __('Inactive', 'wordfence-2fa')); ?>:</strong> <?php echo (Controller_Users::shared()->has_2fa_active($user) ? __('Wordfence 2FA is active.', 'wordfence-2fa') : __('Wordfence 2FA is inactive.', 'wordfence-2fa')); ?> <a href="<?php echo Controller_Support::esc_supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA); ?>" target="_blank" rel="noopener noreferrer"><?php _e('Learn More', 'wordfence-2fa'); ?></a></p>
295
+ <p><a href="<?php echo esc_url($manageURL); ?>" class="button" id="wordfence-ls-btn"><?php echo (Controller_Users::shared()->has_2fa_active($user) ? __('Manage 2FA', 'wordfence-2fa') : __('Activate 2FA', 'wordfence-2fa')); ?></a></p>
296
+ </td>
297
+ </tr>
298
+ </table>
299
+ <?php
300
+ elseif (current_user_can(Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)):
301
+ ?>
302
+ <h2><?php _e('Wordfence Login Security', 'wordfence-2fa'); ?></h2>
303
+ <table class="form-table">
304
+ <tr id="wordfence-ls">
305
+ <th><label for="wordfence-ls-btn"><?php _e('2FA Status'); ?></label></th>
306
+ <td>
307
+ <?php if (Controller_Users::shared()->can_activate_2fa($user)): ?>
308
+ <p><strong><?php echo (Controller_Users::shared()->has_2fa_active($user) ? __('Active', 'wordfence-2fa') : __('Inactive', 'wordfence-2fa')); ?>:</strong> <?php echo (Controller_Users::shared()->has_2fa_active($user) ? __('Wordfence 2FA is active.', 'wordfence-2fa') : __('Wordfence 2FA is inactive.', 'wordfence-2fa')); ?> <a href="<?php echo Controller_Support::esc_supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA); ?>" target="_blank" rel="noopener noreferrer"><?php _e('Learn More', 'wordfence-2fa'); ?></a></p>
309
+ <?php if (Controller_Users::shared()->has_2fa_active($user)): ?><p><a href="<?php echo esc_url($manageURL); ?>" class="button" id="wordfence-ls-btn"><?php echo __('Manage 2FA', 'wordfence-2fa'); ?></a></p><?php endif; ?>
310
+ <?php else: ?>
311
+ <p><strong><?php _e('Disabled', 'wordfence-2fa'); ?>:</strong> <?php _e('Two-factor authentication is not currently enabled for this account type. To enable it, visit the Wordfence 2FA Settings page.', 'wordfence-2fa'); ?> <a href="#"><?php _e('Learn More', 'wordfence-2fa'); ?></a></p>
312
+ <p><a href="<?php echo esc_url(is_multisite() ? network_admin_url('admin.php?page=WFLS#top#settings') : admin_url('admin.php?page=WFLS#top#settings')); ?>" class="button" id="wordfence-ls-btn"><?php _e('Manage 2FA Settings', 'wordfence-2fa'); ?></a></p>
313
+ <?php endif; ?>
314
+ </td>
315
+ </tr>
316
+ </table>
317
+ <?php
318
+ endif;
319
+ }
320
+
321
+ /**
322
+ * Authentication
323
+ */
324
+
325
+ public function _authenticate($user, $username, $password) {
326
+ if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST && !Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_XMLRPC_ENABLED)) { //XML-RPC call and we're not enforcing 2FA on it
327
+ return $user;
328
+ }
329
+
330
+ if (Controller_Whitelist::shared()->is_whitelisted(Model_Request::current()->ip())) { //Whitelisted, so we're not enforcing 2FA
331
+ return $user;
332
+ }
333
+
334
+ /*
335
+ * CAPTCHA Check
336
+ *
337
+ * It will be enforced so long as:
338
+ *
339
+ * 1. It's enabled and keys are set.
340
+ * 2. This is not an XML-RPC request. An XML-RPC request is de facto an automated request, so a CAPTCHA makes
341
+ * no sense.
342
+ * 3. A filter does not override it. This is to allow plugins with REST endpoints that handle authentication
343
+ * themselves to opt out of the requirement.
344
+ * 4. The user does not have 2FA enabled. 2FA exempts the user from requiring email verification if the score is
345
+ * below the threshold.
346
+ */
347
+ if (!empty($username)) { //Login attempt, not just a wp-login.php page load
348
+ $requireCAPTCHA = Controller_CAPTCHA::shared()->enabled() && !(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST); //CAPTCHA is enabled, not an XML-RPC request
349
+ $requireCAPTCHA = apply_filters('wordfence_ls_require_captcha', $requireCAPTCHA);
350
+
351
+ $performVerification = false;
352
+ $token = (isset($_POST['wfls-captcha-token']) && is_string($_POST['wfls-captcha-token']) ? $_POST['wfls-captcha-token'] : '');
353
+ if ($requireCAPTCHA && empty($token)) { //No CAPTCHA token means forced additional verification (if 2FA is not active)
354
+ $performVerification = true;
355
+ }
356
+
357
+ if ($requireCAPTCHA && !$performVerification) {
358
+ if (isset($_POST['wfls-captcha-jwt']) && is_string($_POST['wfls-captcha-jwt']) && is_object($user) && $user instanceof \WP_User) {
359
+ $jwt = Model_JWT::decode_jwt($_POST['wfls-captcha-jwt']);
360
+ if ($jwt && isset($jwt->payload['nonce'])) {
361
+ $encryptedNonce = $jwt->payload['nonce'];
362
+ $nonce = Model_Symmetric::decrypt($encryptedNonce);
363
+ if ($nonce) {
364
+ $cachedJSON = get_user_meta($user->ID, 'wfls-captcha-nonce', true);
365
+ $cached = @json_decode($cachedJSON, true); //Expected: nonce, score, token, expiration
366
+ if (is_array($cached) && isset($cached['expiration']) && Controller_Time::time() <= $cached['expiration'] && hash_equals($cached['token'], $token) && hash_equals(bin2hex($nonce), $cached['nonce'])) {
367
+ $score = (float) $cached['score'];
368
+ }
369
+ delete_user_meta($user->ID, 'wfls-captcha-nonce');
370
+ }
371
+ //else - unable to decrypt, probably a host error, so let it fall through to a re-check
372
+ }
373
+ //else - invalid JWT or host error, so let it fall through to a re-check
374
+ }
375
+
376
+ if (!isset($score)) {
377
+ $score = Controller_CAPTCHA::shared()->score($token);
378
+ if ($score === false) { //An invalid token will require additional verification (if 2FA is not active)
379
+ $performVerification = true;
380
+ }
381
+ }
382
+ }
383
+
384
+ if (!isset($score)) { $score = false; }
385
+
386
+ if (is_object($user) && $user instanceof \WP_User) {
387
+ if (Controller_Users::shared()->has_2fa_active($user)) { //CAPTCHA enforcement skipped for users with 2FA active
388
+ $requireCAPTCHA = false;
389
+ $performVerification = false;
390
+ }
391
+ else { //Cache the score/token combo for this specific user
392
+ $nonce = Model_Crypto::random_bytes(32);
393
+ $encryptedNonce = Model_Symmetric::encrypt($nonce);
394
+ if ($encryptedNonce) {
395
+ update_user_meta($user->ID, 'wfls-captcha-nonce', json_encode(array('nonce' => bin2hex($nonce), 'score' => $score, 'token' => $token, 'expiration' => Controller_Time::time() + 30)));
396
+ $jwt = new Model_JWT(array('nonce' => $encryptedNonce), Controller_Time::time() + 30);
397
+ if (!defined('WORDFENCE_LS_CAPTCHA_CACHE')) { define('WORDFENCE_LS_CAPTCHA_CACHE', (string) $jwt); }
398
+ }
399
+ // else Can't generate payload, so we'll end up re-querying the reCAPTCHA token next hit
400
+ }
401
+
402
+ update_user_meta($user->ID, 'wfls-last-captcha-score', $score);
403
+
404
+ if (isset($_REQUEST['wfls-email-verification']) && !empty($_REQUEST['wfls-email-verification']) && is_string($_REQUEST['wfls-email-verification'])) {
405
+ $jwt = Model_JWT::decode_jwt($_REQUEST['wfls-email-verification']);
406
+ if ($jwt && isset($jwt->payload['user'])) {
407
+ $decryptedUser = Model_Symmetric::decrypt($jwt->payload['user']);
408
+ if (!$decryptedUser || $decryptedUser == $user->ID) { //Skip the CAPTCHA check if the user in the JWT matches or decryption failed due to a server error
409
+ $requireCAPTCHA = false;
410
+ $performVerification = false;
411
+ }
412
+ }
413
+ }
414
+
415
+ if ($requireCAPTCHA && !$performVerification) {
416
+ if (!Controller_CAPTCHA::shared()->is_human($score)) { //Score is below the human threshold, require email verification
417
+ $performVerification = true;
418
+ }
419
+ }
420
+
421
+ if ($requireCAPTCHA && $performVerification) {
422
+ $encrypted = Model_Symmetric::encrypt((string) $user->ID);
423
+ if ($encrypted) {
424
+ $jwt = new Model_JWT(array('user' => $encrypted), Controller_Time::time() + 60 * 15 /* minutes */);
425
+ $view = new Model_View('email/login-verification', array(
426
+ 'siteName' => get_bloginfo('name', 'raw'),
427
+ 'siteURL' => rtrim(site_url(), '/') . '/',
428
+ 'verificationURL' => add_query_arg(array('wfls-email-verification' => (string) $jwt), wp_login_url()),
429
+ 'ip' => Model_Request::current()->ip(),
430
+ 'canEnable2FA' => Controller_Users::shared()->can_activate_2fa($user),
431
+ ));
432
+ wp_mail($user->user_email, __('Login Verification Required', 'wordfence-ls'), $view->render(), "Content-Type: text/html");
433
+
434
+ return new \WP_Error('wfls_captcha_verify', __('<strong>VERIFICATION REQUIRED</strong>: Additional verification is required for login. Please check the email address associated with the account for a verification link.', 'wordfence-ls'));
435
+ }
436
+ //else -- Can't generate payload due to host failure, allow it to proceed
437
+ }
438
+ }
439
+ }
440
+
441
+ /*
442
+ * Check 1
443
+ *
444
+ * If we have a valid JWT that authenticates the account _and_ code, fetch and return that user.
445
+ */
446
+ if (isset($_POST['wfls-token-jwt']) && is_string($_POST['wfls-token-jwt'])) {
447
+ $jwt = Model_JWT::decode_jwt($_POST['wfls-token-jwt']);
448
+ if (!$jwt) { //Possibly user-corrupted or expired JWT
449
+ return new \WP_Error('wfls_twofactor_invalid', __('<strong>VALIDATION FAILED</strong>: The 2FA code could not be validated. Please try logging in again.', 'wordfence-2fa'));
450
+ }
451
+
452
+ if (!isset($jwt->payload['user'])) { //Possibly user-corrupted JWT
453
+ return new \WP_Error('wfls_twofactor_invalid', __('<strong>VALIDATION FAILED</strong>: The 2FA code could not be validated. Please try logging in again.', 'wordfence-2fa'));
454
+ }
455
+
456
+ $decryptedUser = Model_Symmetric::decrypt($jwt->payload['user']);
457
+ if (!$decryptedUser) {
458
+ return $user; //Likely a server failure, allow authentication without our authenticate filter
459
+ }
460
+
461
+ if (isset($jwt->payload['nonce'])) { //JWT includes previous token validation
462
+ $decryptedNonce = Model_Symmetric::decrypt($jwt->payload['nonce']);
463
+ if (!$decryptedNonce) {
464
+ return $user; //Likely a server failure, allow authentication without our authenticate filter
465
+ }
466
+
467
+ $expectedNonceJSON = get_user_meta((int) $decryptedUser, 'wfls-nonce', true);
468
+ $expectedNonce = @json_decode($expectedNonceJSON, true);
469
+ if ($expectedNonce && $expectedNonce['expiration'] > Controller_Time::time() && hash_equals($decryptedNonce, Model_Compat::hex2bin($expectedNonce['nonce']))) {
470
+ delete_user_meta((int) $decryptedUser, 'wfls-nonce');
471
+ $user = new \WP_User((int) $decryptedUser);
472
+ return $user;
473
+ }
474
+
475
+ //Invalid nonce or expired nonce
476
+ return new \WP_Error('wfls_twofactor_invalid', __('<strong>VALIDATION FAILED</strong>: The 2FA code could not be validated. Please try logging in again.', 'wordfence-2fa'));
477
+ }
478
+ }
479
+
480
+ /*
481
+ * Check 2
482
+ *
483
+ * If we don't have a valid $user at this point, it means the $username/$password combo is invalid. We'll check
484
+ * to see if the user has provided a combined password in the format `<password><code>`, populating $user from
485
+ * that if so.
486
+ */
487
+ if (!defined('WORDFENCE_LS_CHECKING_COMBINED') && (!isset($_POST['wfls-token']) || !is_string($_POST['wfls-token'])) && (!is_object($user) || !($user instanceof \WP_User))) {
488
+ //Compatibility with WF legacy 2FA
489
+ $combinedTOTPRegex = '/((?:[0-9]{3}\s*){2})$/i';
490
+ $combinedRecoveryRegex = '/((?:[a-f0-9]{4}\s*){4})$/i';
491
+ if ($this->legacy_2fa_active()) {
492
+ $combinedTOTPRegex = '/(?<! wf)((?:[0-9]{3}\s*){2})$/i';
493
+ $combinedRecoveryRegex = '/(?<! wf)((?:[a-f0-9]{4}\s*){4})$/i';
494
+ }
495
+
496
+ if (preg_match($combinedTOTPRegex, $password, $matches)) { //Possible TOTP code
497
+ if (strlen($password) > strlen($matches[1])) {
498
+ $revisedPassword = substr($password, 0, strlen($password) - strlen($matches[1]));
499
+ $code = $matches[1];
500
+ }
501
+ }
502
+ else if (preg_match($combinedRecoveryRegex, $password, $matches)) { //Possible recovery code
503
+ if (strlen($password) > strlen($matches[1])) {
504
+ $revisedPassword = substr($password, 0, strlen($password) - strlen($matches[1]));
505
+ $code = $matches[1];
506
+ }
507
+ }
508
+
509
+ if (isset($revisedPassword)) {
510
+ define('WORDFENCE_LS_CHECKING_COMBINED', true); //Avoid recursing into this block
511
+ if (!defined('WORDFENCE_LS_AUTHENTICATION_CHECK')) { define('WORDFENCE_LS_AUTHENTICATION_CHECK', true); }
512
+ $revisedUser = wp_authenticate($username, $revisedPassword);
513
+ if (is_object($revisedUser) && ($revisedUser instanceof \WP_User) && Controller_TOTP::shared()->validate_2fa($revisedUser, $code)) {
514
+ define('WORDFENCE_LS_COMBINED_IS_VALID', true); //AJAX call will use this to generate a different JWT that authenticates for the account _and_ code
515
+ return $revisedUser;
516
+ }
517
+ }
518
+ }
519
+
520
+ /*
521
+ * Check 3
522
+ *
523
+ * If we have a valid JWT user and the user has provided a code, check to see if the code is valid. If it is,
524
+ * the JWT user is returned.
525
+ */
526
+ if (isset($decryptedUser) && isset($_POST['wfls-token']) && is_string($_POST['wfls-token'])) {
527
+ $jwtUser = new \WP_User((int) $decryptedUser);
528
+ if (Controller_Users::shared()->has_2fa_active($jwtUser)) {
529
+ if (Controller_TOTP::shared()->validate_2fa($jwtUser, $_POST['wfls-token'])) {
530
+ define('WORDFENCE_LS_COMBINED_IS_VALID', true); //AJAX call will use this to generate a different JWT that authenticates for the account _and_ code
531
+ return $jwtUser;
532
+ }
533
+
534
+ return new \WP_Error('wfls_twofactor_failed', __('<strong>CODE INVALID</strong>: The 2FA code provided is either expired or invalid. Please try again.', 'wordfence-2fa'));
535
+ }
536
+ }
537
+
538
+ if (defined('WORDFENCE_LS_AUTHENTICATION_CHECK') && WORDFENCE_LS_AUTHENTICATION_CHECK) { //Checking for the purpose of prompting for 2FA, don't enforce it here -- AJAX calls will halt here, POST will continue
539
+ return $user;
540
+ }
541
+
542
+ /*
543
+ * Check 4
544
+ *
545
+ * If we have a user from a previous filter, check to see if it has 2FA enabled or a remembered 2FA. If it does, it has not
546
+ * provided a code, so block its login.
547
+ */
548
+ if (is_object($user) && ($user instanceof \WP_User)) {
549
+ if (Controller_Users::shared()->has_remembered_2fa($user)) {
550
+ return $user;
551
+ }
552
+
553
+ if (Controller_Users::shared()->has_2fa_active($user)) {
554
+ $legacy2FAActive = Controller_WordfenceLS::shared()->legacy_2fa_active();
555
+ if ($legacy2FAActive) {
556
+ return new \WP_Error('wfls_twofactor_required', __('<strong>CODE REQUIRED</strong>: Please enter your 2FA code immediately after your password in the same field.', 'wordfence-2fa'));
557
+ }
558
+ return new \WP_Error('wfls_twofactor_required', __('<strong>CODE REQUIRED</strong>: Please provide your 2FA code when prompted.', 'wordfence-2fa'));
559
+ }
560
+ else if (Controller_Users::shared()->requires_2fa($user)) {
561
+ return new \WP_Error('wfls_twofactor_blocked', __('<strong>LOGIN BLOCKED</strong>: 2FA is required to be active on all administrator accounts.', 'wordfence-2fa'));
562
+ }
563
+ else if (defined('WFLS_WILL_BE_REQUIRED') && WFLS_WILL_BE_REQUIRED) {
564
+ Controller_Notices::shared()->add_notice(Model_Notice::SEVERITY_CRITICAL, new Model_HTML(sprintf(__('You do not currently have two-factor authentication active on your account, which will be required beginning %s. <a href="%s">Configure 2FA</a>', 'wordfence-2fa'), Controller_Time::format_local_time('F j, Y', Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD)), esc_url(admin_url('admin.php?page=WFLS')))), 'wfls-will-be-required', $user);
565
+ }
566
+ }
567
+
568
+ return $user;
569
+ }
570
+
571
+ public function _set_logged_in_cookie($logged_in_cookie, $expire, $expiration, $user_id) {
572
+ $user = new \WP_User($user_id);
573
+ if (Controller_Users::shared()->has_2fa_active($user) && isset($_POST['wfls-remember-device']) && $_POST['wfls-remember-device']) {
574
+ Controller_Users::shared()->remember_2fa($user);
575
+ }
576
+ delete_user_meta($user_id, 'wfls-captcha-nonce');
577
+ }
578
+
579
+ public function _record_login($user_login/*, $user -- we'd like to use the second parameter instead, but too many plugins call this hook and only provide one of the two required parameters*/) {
580
+ $user = get_user_by('login', $user_login);
581
+ if (is_object($user) && $user instanceof \WP_User && $user->exists()) {
582
+ update_user_meta($user->ID, 'wfls-last-login', Controller_Time::time());
583
+ }
584
+ }
585
+
586
+ public function _register_post($sanitized_user_login, $user_email, $errors) {
587
+ if (Controller_Whitelist::shared()->is_whitelisted(Model_Request::current()->ip())) { //Whitelisted, so we're not enforcing 2FA
588
+ return;
589
+ }
590
+
591
+ /*
592
+ * CAPTCHA Check
593
+ *
594
+ * It will be enforced so long as:
595
+ *
596
+ * 1. It's enabled and keys are set.
597
+ * 2. This is not an XML-RPC request. An XML-RPC request is de facto an automated request, so a CAPTCHA makes
598
+ * no sense.
599
+ * 3. A filter does not override it. This is to allow plugins with REST endpoints that handle authentication
600
+ * themselves to opt out of the requirement.
601
+ */
602
+ $requireCAPTCHA = Controller_CAPTCHA::shared()->enabled() && !(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST); //CAPTCHA is enabled, not an XML-RPC request
603
+ $requireCAPTCHA = apply_filters('wordfence_ls_require_captcha', $requireCAPTCHA);
604
+
605
+ if ($requireCAPTCHA && (!isset($_POST['wfls-captcha-token']) || !is_string($_POST['wfls-captcha-token'])) && !empty($sanitized_user_login)) { //A CAPTCHA token must be provided for the login attempt to proceed past this point
606
+ $errors->add('wfls_captcha_required', __('<strong>REGISTRATION ATTEMPT BLOCKED</strong>: This site requires a security token created when the page loads for all registration attempts. Please ensure JavaScript is enabled and try again.', 'wordfence-ls'));
607
+ return;
608
+ }
609
+
610
+ $score = false;
611
+ if ($requireCAPTCHA) {
612
+ $score = Controller_CAPTCHA::shared()->score($_POST['wfls-captcha-token']);
613
+ if ($score === false) { //The token must be valid
614
+ $errors->add('wfls_captcha_required', __('<strong>REGISTRATION ATTEMPT BLOCKED</strong>: The security token for the login attempt was invalid or expired. Please reload the page and try again.', 'wordfence-ls'));
615
+ return;
616
+ }
617
+ }
618
+
619
+ if ($requireCAPTCHA) {
620
+ if (!Controller_CAPTCHA::shared()->is_human($score)) { //Score is below the human threshold, block the user registration
621
+ $encryptedIP = Model_Symmetric::encrypt(Model_Request::current()->ip());
622
+ $encryptedScore = Model_Symmetric::encrypt($score);
623
+ if ($encryptedIP && $encryptedScore && filter_var(get_site_option('admin_email'), FILTER_VALIDATE_EMAIL)) {
624
+ $jwt = new Model_JWT(array('ip' => $encryptedIP, 'score' => $encryptedScore), Controller_Time::time() + 600);
625
+ $token = (string) $jwt;
626
+
627
+ $message = sprintf(__('<strong>REGISTRATION BLOCKED</strong>: The registration request was blocked because it was flagged as spam. Please try again or <a href="#" class="wfls-registration-captcha-contact" data-token="%s">contact the site owner</a> for help.', 'wordfence-ls'), esc_attr($token));
628
+ }
629
+ else {
630
+ $message = __('<strong>REGISTRATION BLOCKED</strong>: The registration request was blocked because it was flagged as spam. Please try again or contact the site owner for help.', 'wordfence-ls');
631
+ }
632
+
633
+ /**
634
+ * Fires just prior to blocking user registration due to a failed CAPTCHA. After firing this action hook
635
+ * the registration attempt is blocked.
636
+ *
637
+ * @param int $source The source code of the block.
638
+ */
639
+ do_action('wfls_registration_blocked', 1);
640
+
641
+ /**
642
+ * Filters the message to show if registration is blocked due to a captcha rejection.
643
+ *
644
+ * @since 1.0.0
645
+ *
646
+ * @param string $message The message to display, HTML allowed.
647
+ */
648
+ $message = apply_filters('wfls_registration_blocked_message', $message);
649
+ $errors->add('wfls_registration_blocked', $message);
650
+ return;
651
+ }
652
+ }
653
+ }
654
+
655
+ /**
656
+ * @param \WP_Error $errors
657
+ * @param string $redirect_to
658
+ * @return \WP_Error
659
+ */
660
+ public function _wp_login_errors($errors, $redirect_to) {
661
+ $has_errors = (method_exists($errors, 'has_errors') ? $errors->has_errors() : !empty($errors->errors)); //has_errors was added in WP 5.1
662
+ if (!$has_errors && isset($_REQUEST['wfls-email-verification']) && is_string($_REQUEST['wfls-email-verification'])) {
663
+ $jwt = Model_JWT::decode_jwt($_REQUEST['wfls-email-verification']);
664
+ if ($jwt && isset($jwt->payload['user'])) {
665
+ $errors->add('wfls_email_verified', __('Email verification succeeded. Please continue logging in.', 'wordfence-2fa'), 'message');
666
+ }
667
+ else {
668
+ $errors->add('wfls_email_not_verified', __('Email verification invalid or expired. Please try again.', 'wordfence-2fa'), 'message');
669
+ }
670
+ }
671
+ return $errors;
672
+ }
673
+
674
+ public function legacy_2fa_active() {
675
+ $wfLegacy2FAActive = false;
676
+ if (class_exists('wfConfig') && \wfConfig::get('isPaid')) {
677
+ $twoFactorUsers = \wfConfig::get_ser('twoFactorUsers', array());
678
+ if (is_array($twoFactorUsers) && count($twoFactorUsers) > 0) {
679
+ foreach ($twoFactorUsers as $t) {
680
+ if ($t[3] == 'activated') {
681
+ $testUser = get_user_by('ID', $t[0]);
682
+ if (is_object($testUser) && $testUser instanceof \WP_User && \wfUtils::isAdmin($testUser)) {
683
+ $wfLegacy2FAActive = true;
684
+ break;
685
+ }
686
+ }
687
+ }
688
+ }
689
+
690
+ if ($wfLegacy2FAActive && class_exists('wfCredentialsController') && method_exists('wfCredentialsController', 'useLegacy2FA') && !\wfCredentialsController::useLegacy2FA()) {
691
+ $wfLegacy2FAActive = false;
692
+ }
693
+ }
694
+ return $wfLegacy2FAActive;
695
+ }
696
+
697
+ /**
698
+ * Menu
699
+ */
700
+
701
+ public function _admin_menu() {
702
+ $user = wp_get_current_user();
703
+ if (Controller_Notices::shared()->has_notice($user)) {
704
+ if (!Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REQUIRE_2FA_ADMIN) || !(Controller_Settings::shared()->get_bool(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED) && Controller_Time::time() < Controller_Settings::shared()->get_int(Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD))) {
705
+ Controller_Notices::shared()->remove_notice(false, 'wfls-will-be-required', $user);
706
+ }
707
+ }
708
+
709
+ Controller_Notices::shared()->enqueue_notices();
710
+
711
+ $useSubmenu = WORDFENCE_LS_FROM_CORE && current_user_can('activate_plugins');
712
+ if (is_multisite() && !is_network_admin()) {
713
+ $useSubmenu = false;
714
+
715
+ if (is_super_admin()) {
716
+ return;
717
+ }
718
+ }
719
+
720
+ if ($useSubmenu) {
721
+ add_submenu_page('Wordfence', __('Login Security', 'wordfence-2fa'), __('Login Security', 'wordfence-2fa'), Controller_Permissions::CAP_ACTIVATE_2FA_SELF, 'WFLS', array($this, '_menu'));
722
+ }
723
+ else {
724
+ add_menu_page(__('Login Security', 'wordfence-2fa'), __('Login Security', 'wordfence-2fa'), Controller_Permissions::CAP_ACTIVATE_2FA_SELF, 'WFLS', array($this, '_menu'), Model_Asset::img('menu.svg'));
725
+ }
726
+ }
727
+
728
+ public function _menu() {
729
+ $user = wp_get_current_user();
730
+ $administrator = false;
731
+ $canEditUsers = false;
732
+ if (Controller_Permissions::shared()->can_manage_settings($user)) {
733
+ $administrator = true;
734
+ }
735
+
736
+ if (user_can($user, Controller_Permissions::CAP_ACTIVATE_2FA_OTHERS)) {
737
+ $canEditUsers = true;
738
+ if (isset($_GET['user'])) {
739
+ $user = new \WP_User((int) $_GET['user']);
740
+ if (!$user->exists()) {
741
+ $user = wp_get_current_user();
742
+ }
743
+ }
744
+ }
745
+
746
+ $sections = array(
747
+ array(
748
+ 'tab' => new Model_Tab('manage', 'manage', __('Two-Factor Authentication', 'wordfence-2fa'), __('Two-Factor Authentication', 'wordfence-2fa')),
749
+ 'title' => new Model_Title('manage', __('Two-Factor Authentication', 'wordfence-2fa'), Controller_Support::supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA), new Model_HTML(__('Learn more<span class="wfls-hidden-xs"> about Two-Factor Authentication</span>', 'wordfence'))),
750
+ 'content' => new Model_View('page/manage', array(
751
+ 'user' => $user,
752
+ 'canEditUsers' => $canEditUsers,
753
+ )),
754
+ ),
755
+ );
756
+
757
+ if ($administrator) {
758
+ $sections[] = array(
759
+ 'tab' => new Model_Tab('settings', 'settings', __('Settings', 'wordfence-2fa'), __('Settings', 'wordfence-2fa')),
760
+ 'title' => new Model_Title('settings', __('Login Security Settings', 'wordfence-2fa'), Controller_Support::supportURL(Controller_Support::ITEM_MODULE_LOGIN_SECURITY), new Model_HTML(__('Learn more<span class="wfls-hidden-xs"> about Login Security</span>', 'wordfence'))),
761
+ 'content' => new Model_View('page/settings', array(
762
+ )),
763
+ );
764
+ }
765
+
766
+ $view = new Model_View('page/page', array(
767
+ 'sections' => $sections,
768
+ ));
769
+ echo $view->render();
770
+ }
771
+ }
classes/model/asset.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ abstract class Model_Asset {
6
+ public static function js($file) {
7
+ return self::_pluginBaseURL() . 'js/' . self::_versionedFileName($file);
8
+ }
9
+
10
+ public static function css($file) {
11
+ return self::_pluginBaseURL() . 'css/' . self::_versionedFileName($file);
12
+ }
13
+
14
+ public static function img($file) {
15
+ return self::_pluginBaseURL() . 'img/' . $file;
16
+ }
17
+
18
+ protected static function _pluginBaseURL() {
19
+ return plugins_url('', WORDFENCE_LS_FCPATH) . '/';
20
+ }
21
+
22
+ protected static function _versionedFileName($subpath) {
23
+ $version = WORDFENCE_LS_BUILD_NUMBER;
24
+ if ($version != 'WORDFENCE_LS_BUILD_NUMBER' && preg_match('/^(.+?)(\.[^\.]+)$/', $subpath, $matches)) {
25
+ $prefix = $matches[1];
26
+ $suffix = $matches[2];
27
+ return $prefix . '.' . $version . $suffix;
28
+ }
29
+
30
+ return $subpath;
31
+ }
32
+ }
classes/model/compat.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WordfenceLS;
3
+
4
+ class Model_Compat {
5
+ public static function hex2bin($string) { //Polyfill for PHP < 5.4
6
+ if (!is_string($string)) { return false; }
7
+ if (strlen($string) % 2 == 1) { return false; }
8
+ return pack('H*', $string);
9
+ }
10
+ }
classes/model/crypto.php ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ abstract class Model_Crypto {
6
+ /**
7
+ * Refreshes the secrets used by the plugin.
8
+ */
9
+ public static function refresh_secrets() {
10
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_SHARED_HASH_SECRET_KEY, bin2hex(self::random_bytes(32)));
11
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_SHARED_SYMMETRIC_SECRET_KEY, bin2hex(self::random_bytes(32)));
12
+ Controller_Settings::shared()->set(Controller_Settings::OPTION_LAST_SECRET_REFRESH, Controller_Time::time(), true);
13
+ }
14
+
15
+ /**
16
+ * Returns the secret for hashing.
17
+ *
18
+ * @return string
19
+ */
20
+ public static function shared_hash_secret() {
21
+ return Controller_Settings::shared()->get(Controller_Settings::OPTION_SHARED_HASH_SECRET_KEY);
22
+ }
23
+
24
+ /**
25
+ * Returns the secret for symmetric encryption.
26
+ *
27
+ * @return string
28
+ */
29
+ public static function shared_symmetric_secret() {
30
+ return Controller_Settings::shared()->get(Controller_Settings::OPTION_SHARED_SYMMETRIC_SECRET_KEY);
31
+ }
32
+
33
+ /**
34
+ * Returns whether or not the installation has the required crypto support for this to work.
35
+ *
36
+ * @return bool
37
+ */
38
+ public static function has_required_crypto_functions() {
39
+ if (function_exists('openssl_get_publickey') && function_exists('openssl_get_cipher_methods')) {
40
+ $ciphers = openssl_get_cipher_methods();
41
+ return array_search('aes-256-cbc', $ciphers) !== false;
42
+ }
43
+ return false;
44
+ }
45
+
46
+ /**
47
+ * Utility
48
+ */
49
+
50
+ public static function random_bytes($bytes) {
51
+ $bytes = (int) $bytes;
52
+ if (function_exists('random_bytes')) {
53
+ try {
54
+ $rand = random_bytes($bytes);
55
+ if (is_string($rand) && self::strlen($rand) === $bytes) {
56
+ return $rand;
57
+ }
58
+ } catch (\Exception $e) {
59
+ // Fall through
60
+ } catch (\TypeError $e) {
61
+ // Fall through
62
+ } catch (\Error $e) {
63
+ // Fall through
64
+ }
65
+ }
66
+ if (function_exists('mcrypt_create_iv')) {
67
+ $rand = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
68
+ if (is_string($rand) && self::strlen($rand) === $bytes) {
69
+ return $rand;
70
+ }
71
+ }
72
+ if (function_exists('openssl_random_pseudo_bytes')) {
73
+ $rand = @openssl_random_pseudo_bytes($bytes, $strong);
74
+ if (is_string($rand) && self::strlen($rand) === $bytes) {
75
+ return $rand;
76
+ }
77
+ }
78
+ // Last resort is insecure
79
+ $return = '';
80
+ for ($i = 0; $i < $bytes; $i++) {
81
+ $return .= chr(mt_rand(0, 255));
82
+ }
83
+ return $return;
84
+ }
85
+
86
+ /**
87
+ * Polyfill for random_int.
88
+ *
89
+ * @param int $min
90
+ * @param int $max
91
+ * @return int
92
+ */
93
+ public static function random_int($min = 0, $max = 0x7FFFFFFF) {
94
+ if (function_exists('random_int')) {
95
+ try {
96
+ return random_int($min, $max);
97
+ } catch (\Exception $e) {
98
+ // Fall through
99
+ } catch (\TypeError $e) {
100
+ // Fall through
101
+ } catch (\Error $e) {
102
+ // Fall through
103
+ }
104
+ }
105
+ $diff = $max - $min;
106
+ $bytes = self::random_bytes(4);
107
+ if ($bytes === false || self::strlen($bytes) != 4) {
108
+ throw new \RuntimeException("Unable to get 4 bytes");
109
+ }
110
+ $val = @unpack("Nint", $bytes);
111
+ $val = $val['int'] & 0x7FFFFFFF;
112
+ $fp = (float) $val / 2147483647.0; // convert to [0,1]
113
+ return (int) (round($fp * $diff) + $min);
114
+ }
115
+
116
+ public static function uuid() {
117
+ return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
118
+ // 32 bits for "time_low"
119
+ self::random_int(0, 0xffff), self::random_int(0, 0xffff),
120
+
121
+ // 16 bits for "time_mid"
122
+ self::random_int(0, 0xffff),
123
+
124
+ // 16 bits for "time_hi_and_version",
125
+ // four most significant bits holds version number 4
126
+ self::random_int(0, 0x0fff) | 0x4000,
127
+
128
+ // 16 bits, 8 bits for "clk_seq_hi_res",
129
+ // 8 bits for "clk_seq_low",
130
+ // two most significant bits holds zero and one for variant DCE1.1
131
+ self::random_int(0, 0x3fff) | 0x8000,
132
+
133
+ // 48 bits for "node"
134
+ self::random_int(0, 0xffff), self::random_int(0, 0xffff), self::random_int(0, 0xffff)
135
+ );
136
+ }
137
+
138
+ /**
139
+ * Set the mbstring internal encoding to a binary safe encoding when func_overload
140
+ * is enabled.
141
+ *
142
+ * When mbstring.func_overload is in use for multi-byte encodings, the results from
143
+ * strlen() and similar functions respect the utf8 characters, causing binary data
144
+ * to return incorrect lengths.
145
+ *
146
+ * This function overrides the mbstring encoding to a binary-safe encoding, and
147
+ * resets it to the users expected encoding afterwards through the
148
+ * `reset_mbstring_encoding` function.
149
+ *
150
+ * It is safe to recursively call this function, however each
151
+ * `_mbstring_binary_safe_encoding()` call must be followed up with an equal number
152
+ * of `_reset_mbstring_encoding()` calls.
153
+ *
154
+ * @see Model_Crypto::_reset_mbstring_encoding
155
+ *
156
+ * @staticvar array $encodings
157
+ * @staticvar bool $overloaded
158
+ *
159
+ * @param bool $reset Optional. Whether to reset the encoding back to a previously-set encoding.
160
+ * Default false.
161
+ */
162
+ protected static function _mbstring_binary_safe_encoding($reset = false) {
163
+ static $encodings = array();
164
+ static $overloaded = null;
165
+
166
+ if (is_null($overloaded))
167
+ $overloaded = function_exists('mb_internal_encoding') && (ini_get('mbstring.func_overload') & 2);
168
+
169
+ if (false === $overloaded)
170
+ return;
171
+
172
+ if (!$reset) {
173
+ $encoding = mb_internal_encoding();
174
+ array_push($encodings, $encoding);
175
+ mb_internal_encoding('ISO-8859-1');
176
+ }
177
+
178
+ if ($reset && $encodings) {
179
+ $encoding = array_pop($encodings);
180
+ mb_internal_encoding($encoding);
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Reset the mbstring internal encoding to a users previously set encoding.
186
+ *
187
+ * @see Model_Crypto::_mbstring_binary_safe_encoding
188
+ */
189
+ protected static function _reset_mbstring_encoding() {
190
+ self::_mbstring_binary_safe_encoding(true);
191
+ }
192
+
193
+ /**
194
+ * @param callable $function
195
+ * @param array $args
196
+ * @return mixed
197
+ */
198
+ protected static function _call_mb_string_function($function, $args) {
199
+ self::_mbstring_binary_safe_encoding();
200
+ $return = call_user_func_array($function, $args);
201
+ self::_reset_mbstring_encoding();
202
+ return $return;
203
+ }
204
+
205
+ /**
206
+ * Multibyte safe strlen.
207
+ *
208
+ * @param $binary
209
+ * @return int
210
+ */
211
+ public static function strlen($binary) {
212
+ $args = func_get_args();
213
+ return self::_call_mb_string_function('strlen', $args);
214
+ }
215
+
216
+ /**
217
+ * @param $haystack
218
+ * @param $needle
219
+ * @param int $offset
220
+ * @return int
221
+ */
222
+ public static function stripos($haystack, $needle, $offset = 0) {
223
+ $args = func_get_args();
224
+ return self::_call_mb_string_function('stripos', $args);
225
+ }
226
+
227
+ /**
228
+ * @param $string
229
+ * @return mixed
230
+ */
231
+ public static function strtolower($string) {
232
+ $args = func_get_args();
233
+ return self::_call_mb_string_function('strtolower', $args);
234
+ }
235
+
236
+ /**
237
+ * @param $string
238
+ * @param $start
239
+ * @param $length
240
+ * @return mixed
241
+ */
242
+ public static function substr($string, $start, $length = null) {
243
+ if ($length === null) { $length = self::strlen($string); }
244
+ return self::_call_mb_string_function('substr', array(
245
+ $string, $start, $length
246
+ ));
247
+ }
248
+
249
+ /**
250
+ * @param $haystack
251
+ * @param $needle
252
+ * @param int $offset
253
+ * @return mixed
254
+ */
255
+ public static function strpos($haystack, $needle, $offset = 0) {
256
+ $args = func_get_args();
257
+ return self::_call_mb_string_function('strpos', $args);
258
+ }
259
+
260
+ /**
261
+ * @param string $haystack
262
+ * @param string $needle
263
+ * @param int $offset
264
+ * @param int $length
265
+ * @return mixed
266
+ */
267
+ public static function substr_count($haystack, $needle, $offset = 0, $length = null) {
268
+ if ($length === null) { $length = self::strlen($haystack); }
269
+ return self::_call_mb_string_function('substr_count', array(
270
+ $haystack, $needle, $offset, $length
271
+ ));
272
+ }
273
+
274
+ /**
275
+ * @param $string
276
+ * @return mixed
277
+ */
278
+ public static function strtoupper($string) {
279
+ $args = func_get_args();
280
+ return self::_call_mb_string_function('strtoupper', $args);
281
+ }
282
+
283
+ /**
284
+ * @param string $haystack
285
+ * @param string $needle
286
+ * @param int $offset
287
+ * @return mixed
288
+ */
289
+ public static function strrpos($haystack, $needle, $offset = 0) {
290
+ $args = func_get_args();
291
+ return self::_call_mb_string_function('strrpos', $args);
292
+ }
293
+ }
classes/model/crypto/base2n.php ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Crypto;
4
+ /**
5
+ * Binary-to-text PHP Utilities
6
+ *
7
+ * @package binary-to-text-php
8
+ * @link https://github.com/ademarre/binary-to-text-php
9
+ * @author Andre DeMarre
10
+ * @copyright 2009-2013 Andre DeMarre
11
+ * @license http://opensource.org/licenses/MIT MIT
12
+ */
13
+
14
+ /**
15
+ * Class for binary-to-text encoding with a base of 2^n
16
+ *
17
+ * The Base2n class is for binary-to-text conversion. It employs a
18
+ * generalization of the algorithms used by many encoding schemes that
19
+ * use a fixed number of bits to encode each character. In other words,
20
+ * the base is a power of 2.
21
+ *
22
+ * Earlier versions of this class were named
23
+ * FixedBitNotation and FixedBitEncoding.
24
+ *
25
+ * @package binary-to-text-php
26
+ */
27
+ class Model_Base2n
28
+ {
29
+ protected $_chars;
30
+ protected $_bitsPerCharacter;
31
+ protected $_radix;
32
+ protected $_rightPadFinalBits;
33
+ protected $_padFinalGroup;
34
+ protected $_padCharacter;
35
+ protected $_caseSensitive;
36
+ protected $_charmap;
37
+
38
+ /**
39
+ * Constructor
40
+ *
41
+ * @param integer $bitsPerCharacter Bits to use for each encoded character
42
+ * @param string $chars Base character alphabet
43
+ * @param boolean $caseSensitive To decode in a case-sensitive manner
44
+ * @param boolean $rightPadFinalBits How to encode last character
45
+ * @param boolean $padFinalGroup Add padding to end of encoded output
46
+ * @param string $padCharacter Character to use for padding
47
+ *
48
+ * @throws InvalidArgumentException for incompatible parameters
49
+ */
50
+ public function __construct(
51
+ $bitsPerCharacter,
52
+ $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
53
+ $caseSensitive = TRUE, $rightPadFinalBits = FALSE,
54
+ $padFinalGroup = FALSE, $padCharacter = '=')
55
+ {
56
+ // Ensure validity of $chars
57
+ if (!is_string($chars) || ($charLength = strlen($chars)) < 2) {
58
+ throw new \InvalidArgumentException('$chars must be a string of at least two characters');
59
+ }
60
+
61
+ // Ensure validity of $padCharacter
62
+ if ($padFinalGroup) {
63
+ if (!is_string($padCharacter) || !isset($padCharacter[0])) {
64
+ throw new \InvalidArgumentException('$padCharacter must be a string of one character');
65
+ }
66
+
67
+ if ($caseSensitive) {
68
+ $padCharFound = strpos($chars, $padCharacter[0]);
69
+ } else {
70
+ $padCharFound = stripos($chars, $padCharacter[0]);
71
+ }
72
+
73
+ if ($padCharFound !== FALSE) {
74
+ throw new \InvalidArgumentException('$padCharacter can not be a member of $chars');
75
+ }
76
+ }
77
+
78
+ // Ensure validity of $bitsPerCharacter
79
+ if (!is_int($bitsPerCharacter)) {
80
+ throw new \InvalidArgumentException('$bitsPerCharacter must be an integer');
81
+ }
82
+
83
+ if ($bitsPerCharacter < 1) {
84
+ // $bitsPerCharacter must be at least 1
85
+ throw new \InvalidArgumentException('$bitsPerCharacter can not be less than 1');
86
+
87
+ } elseif ($charLength < 1 << $bitsPerCharacter) {
88
+ // Character length of $chars is too small for $bitsPerCharacter
89
+ // Find greatest acceptable value of $bitsPerCharacter
90
+ $bitsPerCharacter = 1;
91
+ $radix = 2;
92
+
93
+ while ($charLength >= ($radix <<= 1) && $bitsPerCharacter < 8) {
94
+ $bitsPerCharacter++;
95
+ }
96
+
97
+ $radix >>= 1;
98
+ throw new \InvalidArgumentException(
99
+ '$bitsPerCharacter can not be more than ' . $bitsPerCharacter
100
+ . ' given $chars length of ' . $charLength
101
+ . ' (max radix ' . $radix . ')');
102
+
103
+ } elseif ($bitsPerCharacter > 8) {
104
+ // $bitsPerCharacter must not be greater than 8
105
+ throw new \InvalidArgumentException('$bitsPerCharacter can not be greater than 8');
106
+
107
+ } else {
108
+ $radix = 1 << $bitsPerCharacter;
109
+ }
110
+
111
+ $this->_chars = $chars;
112
+ $this->_bitsPerCharacter = $bitsPerCharacter;
113
+ $this->_radix = $radix;
114
+ $this->_rightPadFinalBits = $rightPadFinalBits;
115
+ $this->_padFinalGroup = $padFinalGroup;
116
+ $this->_padCharacter = $padCharacter[0];
117
+ $this->_caseSensitive = $caseSensitive;
118
+ }
119
+
120
+ /**
121
+ * Encode a string
122
+ *
123
+ * @param string $rawString Binary data to encode
124
+ * @return string
125
+ */
126
+ public function encode($rawString)
127
+ {
128
+ // Unpack string into an array of bytes
129
+ $bytes = unpack('C*', $rawString);
130
+ $byteCount = count($bytes);
131
+
132
+ $encodedString = '';
133
+ $byte = array_shift($bytes);
134
+ $bitsRead = 0;
135
+ $oldBits = 0;
136
+
137
+ $chars = $this->_chars;
138
+ $bitsPerCharacter = $this->_bitsPerCharacter;
139
+ $rightPadFinalBits = $this->_rightPadFinalBits;
140
+ $padFinalGroup = $this->_padFinalGroup;
141
+ $padCharacter = $this->_padCharacter;
142
+
143
+ $charsPerByte = 8 / $bitsPerCharacter;
144
+ $encodedLength = $byteCount * $charsPerByte;
145
+
146
+ // Generate encoded output; each loop produces one encoded character
147
+ for ($c = 0; $c < $encodedLength; $c++) {
148
+
149
+ // Get the bits needed for this encoded character
150
+ if ($bitsRead + $bitsPerCharacter > 8) {
151
+ // Not enough bits remain in this byte for the current character
152
+ // Save the remaining bits before getting the next byte
153
+ $oldBitCount = 8 - $bitsRead;
154
+ $oldBits = $byte ^ ($byte >> $oldBitCount << $oldBitCount);
155
+ $newBitCount = $bitsPerCharacter - $oldBitCount;
156
+
157
+ if (!$bytes) {
158
+ // Last bits; match final character and exit loop
159
+ if ($rightPadFinalBits) $oldBits <<= $newBitCount;
160
+ $encodedString .= $chars[$oldBits];
161
+
162
+ if ($padFinalGroup) {
163
+ // Array of the lowest common multiples of $bitsPerCharacter and 8, divided by 8
164
+ $lcmMap = array(1 => 1, 2 => 1, 3 => 3, 4 => 1, 5 => 5, 6 => 3, 7 => 7, 8 => 1);
165
+ $bytesPerGroup = $lcmMap[$bitsPerCharacter];
166
+ $pads = $bytesPerGroup * $charsPerByte - ceil((strlen($rawString) % $bytesPerGroup) * $charsPerByte);
167
+ $encodedString .= str_repeat($padCharacter, $pads);
168
+ }
169
+
170
+ break;
171
+ }
172
+
173
+ // Get next byte
174
+ $byte = array_shift($bytes);
175
+ $bitsRead = 0;
176
+
177
+ } else {
178
+ $oldBitCount = 0;
179
+ $newBitCount = $bitsPerCharacter;
180
+ }
181
+
182
+ // Read only the needed bits from this byte
183
+ $bits = $byte >> 8 - ($bitsRead + ($newBitCount));
184
+ $bits ^= $bits >> $newBitCount << $newBitCount;
185
+ $bitsRead += $newBitCount;
186
+
187
+ if ($oldBitCount) {
188
+ // Bits come from seperate bytes, add $oldBits to $bits
189
+ $bits = ($oldBits << $newBitCount) | $bits;
190
+ }
191
+
192
+ $encodedString .= $chars[$bits];
193
+ }
194
+
195
+ return $encodedString;
196
+ }
197
+
198
+ /**
199
+ * Decode a string
200
+ *
201
+ * @param string $encodedString Data to decode
202
+ * @param boolean $strict Returns NULL if $encodedString contains an undecodable character
203
+ * @return string
204
+ */
205
+ public function decode($encodedString, $strict = FALSE)
206
+ {
207
+ if (!$encodedString || !is_string($encodedString)) {
208
+ // Empty string, nothing to decode
209
+ return '';
210
+ }
211
+
212
+ $chars = $this->_chars;
213
+ $bitsPerCharacter = $this->_bitsPerCharacter;
214
+ $radix = $this->_radix;
215
+ $rightPadFinalBits = $this->_rightPadFinalBits;
216
+ $padFinalGroup = $this->_padFinalGroup;
217
+ $padCharacter = $this->_padCharacter;
218
+ $caseSensitive = $this->_caseSensitive;
219
+
220
+ // Get index of encoded characters
221
+ if ($this->_charmap) {
222
+ $charmap = $this->_charmap;
223
+
224
+ } else {
225
+ $charmap = array();
226
+
227
+ for ($i = 0; $i < $radix; $i++) {
228
+ $charmap[$chars[$i]] = $i;
229
+ }
230
+
231
+ $this->_charmap = $charmap;
232
+ }
233
+
234
+ // The last encoded character is $encodedString[$lastNotatedIndex]
235
+ $lastNotatedIndex = strlen($encodedString) - 1;
236
+
237
+ // Remove trailing padding characters
238
+ if ($padFinalGroup) {
239
+ while ($encodedString[$lastNotatedIndex] === $padCharacter) {
240
+ $encodedString = substr($encodedString, 0, $lastNotatedIndex);
241
+ $lastNotatedIndex--;
242
+ }
243
+ }
244
+
245
+ $rawString = '';
246
+ $byte = 0;
247
+ $bitsWritten = 0;
248
+
249
+ // Convert each encoded character to a series of unencoded bits
250
+ for ($c = 0; $c <= $lastNotatedIndex; $c++) {
251
+
252
+ if (!$caseSensitive && !isset($charmap[$encodedString[$c]])) {
253
+ // Encoded character was not found; try other case
254
+ if (isset($charmap[$cUpper = strtoupper($encodedString[$c])])) {
255
+ $charmap[$encodedString[$c]] = $charmap[$cUpper];
256
+
257
+ } elseif (isset($charmap[$cLower = strtolower($encodedString[$c])])) {
258
+ $charmap[$encodedString[$c]] = $charmap[$cLower];
259
+ }
260
+ }
261
+
262
+ if (isset($charmap[$encodedString[$c]])) {
263
+ $bitsNeeded = 8 - $bitsWritten;
264
+ $unusedBitCount = $bitsPerCharacter - $bitsNeeded;
265
+
266
+ // Get the new bits ready
267
+ if ($bitsNeeded > $bitsPerCharacter) {
268
+ // New bits aren't enough to complete a byte; shift them left into position
269
+ $newBits = $charmap[$encodedString[$c]] << $bitsNeeded - $bitsPerCharacter;
270
+ $bitsWritten += $bitsPerCharacter;
271
+
272
+ } elseif ($c !== $lastNotatedIndex || $rightPadFinalBits) {
273
+ // Zero or more too many bits to complete a byte; shift right
274
+ $newBits = $charmap[$encodedString[$c]] >> $unusedBitCount;
275
+ $bitsWritten = 8; //$bitsWritten += $bitsNeeded;
276
+
277
+ } else {
278
+ // Final bits don't need to be shifted
279
+ $newBits = $charmap[$encodedString[$c]];
280
+ $bitsWritten = 8;
281
+ }
282
+
283
+ $byte |= $newBits;
284
+
285
+ if ($bitsWritten === 8 || $c === $lastNotatedIndex) {
286
+ // Byte is ready to be written
287
+ $rawString .= pack('C', $byte);
288
+
289
+ if ($c !== $lastNotatedIndex) {
290
+ // Start the next byte
291
+ $bitsWritten = $unusedBitCount;
292
+ $byte = ($charmap[$encodedString[$c]] ^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten;
293
+ }
294
+ }
295
+
296
+ } elseif ($strict) {
297
+ // Unable to decode character; abort
298
+ return NULL;
299
+ }
300
+ }
301
+
302
+ return $rawString;
303
+ }
304
+ }
classes/model/crypto/jwt.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Crypto;
4
+
5
+ use WordfenceLS\Controller_Time;
6
+ use WordfenceLS\Model_Crypto;
7
+
8
+ /**
9
+ * Class Model_JWT
10
+ * @package Wordfence2FA\Crypto
11
+ * @property array $payload
12
+ * @property int $expiration
13
+ */
14
+ class Model_JWT {
15
+ private $_payload;
16
+ private $_expiration;
17
+
18
+ /**
19
+ * Decodes and returns the payload of a JWT. This also validates the signature and expiration. Currently assumes HS256 JWTs.
20
+ *
21
+ * @param string $token
22
+ * @return Model_JWT|bool The decoded JWT or false if the token is invalid or fails validation.
23
+ */
24
+ public static function decode_jwt($token) {
25
+ $components = explode('.', $token);
26
+ if (count($components) != 3) {
27
+ return false;
28
+ }
29
+
30
+ $key = Model_Crypto::shared_hash_secret();
31
+ $body = $components[0] . '.' . $components[1];
32
+ $signature = hash_hmac('sha256', $body, $key, true);
33
+ $testSignature = self::base64url_decode($components[2]);
34
+ if (!hash_equals($signature, $testSignature)) {
35
+ return false;
36
+ }
37
+
38
+ $json = self::base64url_decode($components[1]);
39
+ $payload = @json_decode($json, true);
40
+ $expiration = false;
41
+ if (isset($payload['_exp'])) {
42
+ $expiration = $payload['_exp'];
43
+
44
+ if ($payload['_exp'] < Controller_Time::time()) {
45
+ return false;
46
+ }
47
+
48
+ unset($payload['_exp']);
49
+ }
50
+
51
+ return new self($payload, $expiration);
52
+ }
53
+
54
+ /**
55
+ * Model_JWT constructor.
56
+ *
57
+ * @param array $payload
58
+ * @param bool|int $expiration
59
+ */
60
+ public function __construct($payload, $expiration = false) {
61
+ $this->_payload = $payload;
62
+ $this->_expiration = $expiration;
63
+ }
64
+
65
+ public function __toString() {
66
+ $payload = $this->_payload;
67
+ if ($this->_expiration !== false) {
68
+ $payload['_exp'] = $this->_expiration;
69
+ }
70
+ $key = Model_Crypto::shared_hash_secret();
71
+ $header = '{"alg":"HS256","typ":"JWT"}';
72
+ $body = self::base64url_encode($header) . '.' . self::base64url_encode(json_encode($payload));
73
+ $signature = hash_hmac('sha256', $body, $key, true);
74
+ return $body . '.' . self::base64url_encode($signature);
75
+ }
76
+
77
+ public function __isset($key) {
78
+ switch ($key) {
79
+ case 'payload':
80
+ case 'expiration':
81
+ return true;
82
+ }
83
+
84
+ throw new \OutOfBoundsException('Invalid key: ' . $key);
85
+ }
86
+
87
+ public function __get($key) {
88
+ switch ($key) {
89
+ case 'payload':
90
+ return $this->_payload;
91
+ case 'expiration':
92
+ return $this->_expiration;
93
+ }
94
+
95
+ throw new \OutOfBoundsException('Invalid key: ' . $key);
96
+ }
97
+
98
+ /**
99
+ * Utility
100
+ */
101
+
102
+ /**
103
+ * Base64URL-encodes the given payload. This is identical to base64_encode except it substitutes characters
104
+ * not safe for use in URLs.
105
+ *
106
+ * @param string $payload
107
+ * @return string
108
+ */
109
+ public static function base64url_encode($payload) {
110
+ return self::base64url_convert_to(base64_encode($payload));
111
+ }
112
+
113
+ public static function base64url_convert_to($base64) {
114
+ $intermediate = rtrim($base64, '=');
115
+ $intermediate = str_replace('+', '-', $intermediate);
116
+ $intermediate = str_replace('/', '_', $intermediate);
117
+ return $intermediate;
118
+ }
119
+
120
+ /**
121
+ * Base64URL-decodes the given payload. This is identical to base64_encode except it allows for the characters
122
+ * substituted by base64url_encode.
123
+ *
124
+ * @param string $payload
125
+ * @return string
126
+ */
127
+ public static function base64url_decode($payload) {
128
+ return base64_decode(self::base64url_convert_from($payload));
129
+ }
130
+
131
+ public static function base64url_convert_from($base64url) {
132
+ $intermediate = str_replace('_', '/', $base64url);
133
+ $intermediate = str_replace('-', '+', $intermediate);
134
+ return $intermediate;
135
+ }
136
+ }
classes/model/crypto/symmetric.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Crypto;
4
+
5
+ use WordfenceLS\Model_Crypto;
6
+
7
+ abstract class Model_Symmetric {
8
+ /**
9
+ * Returns $data encrypted with the shared symmetric key or false if unable to do so.
10
+ *
11
+ * @param string $data
12
+ * @return bool|array
13
+ */
14
+ public static function encrypt($data) {
15
+ if (!Model_Crypto::has_required_crypto_functions()) {
16
+ return false;
17
+ }
18
+
19
+ $symmetricKey = Model_Crypto::shared_symmetric_secret();
20
+ $iv = Model_Crypto::random_bytes(16);
21
+ $encrypted = @openssl_encrypt($data, 'aes-256-cbc', $symmetricKey, OPENSSL_RAW_DATA, $iv);
22
+ if ($encrypted) {
23
+ return array('data' => base64_encode($encrypted), 'iv' => base64_encode($iv));
24
+ }
25
+ return false;
26
+ }
27
+
28
+ /**
29
+ * Returns the decrypted value of a payload encrypted by Model_Symmetric::encrypt
30
+ *
31
+ * @param array $encrypted
32
+ * @return bool|string
33
+ */
34
+ public static function decrypt($encrypted) {
35
+ if (!Model_Crypto::has_required_crypto_functions()) {
36
+ return false;
37
+ }
38
+
39
+ if (!isset($encrypted['data']) || !isset($encrypted['iv'])) {
40
+ return false;
41
+ }
42
+
43
+ $symmetricKey = Model_Crypto::shared_symmetric_secret();
44
+ $iv = base64_decode($encrypted['iv']);
45
+ $encrypted = base64_decode($encrypted['data']);
46
+ $data = @openssl_decrypt($encrypted, 'aes-256-cbc', $symmetricKey, OPENSSL_RAW_DATA, $iv);
47
+ return $data;
48
+ }
49
+ }
classes/model/ip.php ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Model_IP {
6
+ /**
7
+ * Returns the human-readable representation of a packed binary IP address.
8
+ *
9
+ * @param string $ip
10
+ * @return bool|string
11
+ */
12
+ public static function inet_ntop($ip) {
13
+ if (Model_Crypto::strlen($ip) == 16 && Model_Crypto::substr($ip, 0, 12) == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") {
14
+ $ip = Model_Crypto::substr($ip, 12, 4);
15
+ }
16
+
17
+ if (self::has_ipv6()) {
18
+ return @inet_ntop($ip);
19
+ }
20
+
21
+ // IPv4
22
+ if (Model_Crypto::strlen($ip) === 4) {
23
+ return ord($ip[0]) . '.' . ord($ip[1]) . '.' . ord($ip[2]) . '.' . ord($ip[3]);
24
+ }
25
+
26
+ // IPv6
27
+ if (Model_Crypto::strlen($ip) === 16) {
28
+ // IPv4 mapped IPv6
29
+ if (Model_Crypto::substr($ip, 0, 12) == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") {
30
+ return "::ffff:" . ord($ip[12]) . '.' . ord($ip[13]) . '.' . ord($ip[14]) . '.' . ord($ip[15]);
31
+ }
32
+
33
+ $hex = bin2hex($ip);
34
+ $groups = str_split($hex, 4);
35
+ $in_collapse = false;
36
+ $done_collapse = false;
37
+ foreach ($groups as $index => $group) {
38
+ if ($group == '0000' && !$done_collapse) {
39
+ if ($in_collapse) {
40
+ $groups[$index] = '';
41
+ continue;
42
+ }
43
+ $groups[$index] = ':';
44
+ $in_collapse = true;
45
+ continue;
46
+ }
47
+ if ($in_collapse) {
48
+ $done_collapse = true;
49
+ }
50
+ $groups[$index] = ltrim($groups[$index], '0');
51
+ if (strlen($groups[$index]) === 0) {
52
+ $groups[$index] = '0';
53
+ }
54
+ }
55
+ $ip = join(':', array_filter($groups, 'strlen'));
56
+ $ip = str_replace(':::', '::', $ip);
57
+ return $ip == ':' ? '::' : $ip;
58
+ }
59
+
60
+ return false;
61
+ }
62
+
63
+ /**
64
+ * Returns the packed binary representation of an IP address from the human readable version.
65
+ *
66
+ * @param string $ip
67
+ * @return string
68
+ */
69
+ public static function inet_pton($ip) {
70
+ if (self::has_ipv6()) {
71
+ $pton = @inet_pton($ip);
72
+ if ($pton === false) {
73
+ return false;
74
+ }
75
+ }
76
+ else {
77
+ if (preg_match('/^(?:\d{1,3}(?:\.|$)){4}/', $ip)) { // IPv4
78
+ $octets = explode('.', $ip);
79
+ $pton = chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]);
80
+ }
81
+ else if (preg_match('/^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/i', $ip)) { // IPv6
82
+ if ($ip === '::') {
83
+ $pton = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
84
+ }
85
+ else {
86
+ $colon_count = substr_count($ip, ':');
87
+ $dbl_colon_pos = strpos($ip, '::');
88
+ if ($dbl_colon_pos !== false) {
89
+ $ip = str_replace('::', str_repeat(':0000', (($dbl_colon_pos === 0 || $dbl_colon_pos === strlen($ip) - 2) ? 9 : 8) - $colon_count) . ':', $ip);
90
+ $ip = trim($ip, ':');
91
+ }
92
+
93
+ $ip_groups = explode(':', $ip);
94
+ $ipv6_bin = '';
95
+ foreach ($ip_groups as $ip_group) {
96
+ $ipv6_bin .= pack('H*', str_pad($ip_group, 4, '0', STR_PAD_LEFT));
97
+ }
98
+
99
+ if (Model_Crypto::strlen($ipv6_bin) == 16) {
100
+ $pton = $ipv6_bin;
101
+ }
102
+ else {
103
+ return false;
104
+ }
105
+ }
106
+ }
107
+ else if (preg_match('/^(?:\:(?:\:0{1,4}){0,4}\:|(?:0{1,4}\:){5})ffff\:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $ip, $matches)) { // IPv4 mapped IPv6
108
+ $octets = explode('.', $matches[1]);
109
+ $pton = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff" . chr($octets[0]) . chr($octets[1]) . chr($octets[2]) . chr($octets[3]);
110
+ }
111
+ else {
112
+ return false;
113
+ }
114
+ }
115
+
116
+ $pton = str_pad($pton, 16, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00", STR_PAD_LEFT);
117
+ return $pton;
118
+ }
119
+
120
+ /**
121
+ * Verify PHP was compiled with IPv6 support.
122
+ *
123
+ * Some hosts appear to not have inet_ntop, and others appear to have inet_ntop but are unable to process IPv6 addresses.
124
+ *
125
+ * @return bool
126
+ */
127
+ public static function has_ipv6() {
128
+ return defined('AF_INET6');
129
+ }
130
+
131
+ /**
132
+ * Expands a compressed printable representation of an IPv6 address.
133
+ *
134
+ * @param string $ip
135
+ * @return string
136
+ */
137
+ public static function expand_ipv6_address($ip) {
138
+ $hex = bin2hex(self::inet_pton($ip));
139
+ $ip = substr(preg_replace("/([a-f0-9]{4})/i", "$1:", $hex), 0, -1);
140
+ return $ip;
141
+ }
142
+
143
+ /**
144
+ * Returns whether or not the IP is a valid format.
145
+ *
146
+ * @param string $ip
147
+ * @return bool
148
+ */
149
+ public static function is_valid_ip($ip) {
150
+ return filter_var($ip, FILTER_VALIDATE_IP) !== false;
151
+ }
152
+
153
+ /**
154
+ * Returns whether or not the range is a valid CIDR range.
155
+ *
156
+ * @param string $range
157
+ * @return bool
158
+ */
159
+ public static function is_valid_cidr_range($range) {
160
+ $components = explode('/', $range);
161
+ if (count($components) != 2) { return false; }
162
+
163
+ list($ip, $prefix) = $components;
164
+ if (!self::is_valid_ip($ip)) { return false; }
165
+
166
+ if (!preg_match('/^\d+$/', $prefix)) { return false; }
167
+
168
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
169
+ if ($prefix < 0 || $prefix > 32) { return false; }
170
+ }
171
+ else {
172
+ if ($prefix < 1 || $prefix > 128) { return false; }
173
+ }
174
+
175
+ return true;
176
+ }
177
+
178
+ /**
179
+ * Returns whether or not the IP is in the IPv6-mapped-IPv4 format.
180
+ *
181
+ * @param string $ip
182
+ * @return bool
183
+ */
184
+ public static function is_ipv6_mapped_ipv4($ip) {
185
+ return preg_match('/^(?:\:(?:\:0{1,4}){0,4}\:|(?:0{1,4}\:){5})ffff\:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/i', $ip) > 0;
186
+ }
187
+ }
classes/model/notice.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Model_Notice {
6
+ const SEVERITY_CRITICAL = 'critical';
7
+ const SEVERITY_WARNING = 'warning';
8
+ const SEVERITY_INFO = 'info';
9
+
10
+ private $_id;
11
+ private $_severity;
12
+ private $_messageHTML;
13
+
14
+ public function __construct($id, $severity, $messageHTML) {
15
+ $this->_id = $id;
16
+ $this->_severity = $severity;
17
+ $this->_messageHTML = $messageHTML;
18
+ }
19
+
20
+ public function display_notice() {
21
+ $severityClass = 'notice-info';
22
+ if ($this->_severity == self::SEVERITY_CRITICAL) {
23
+ $severityClass = 'notice-error';
24
+ }
25
+ else if ($this->_severity == self::SEVERITY_WARNING) {
26
+ $severityClass = 'notice-warning';
27
+ }
28
+
29
+ echo '<div class="wfls-notice notice ' . $severityClass . '" data-notice-id="' . esc_attr($this->_id) . '"><p>' . $this->_messageHTML . '</p><p>' . sprintf(__('<a class="wfls-btn wfls-btn-default wfls-btn-sm wfls-dismiss-link" href="#" onclick="GWFLS.dismiss_notice(\'%s\'); return false;">Dismiss</a>', 'wordfence-2fa'), esc_attr($this->_id)) . '</p></div>';
30
+ }
31
+ }
classes/model/request.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Model_Request {
6
+ const IP_SOURCE_AUTOMATIC = '';
7
+ const IP_SOURCE_REMOTE_ADDR = 'REMOTE_ADDR';
8
+ const IP_SOURCE_X_FORWARDED_FOR = 'HTTP_X_FORWARDED_FOR';
9
+ const IP_SOURCE_X_REAL_IP = 'HTTP_X_REAL_IP';
10
+
11
+ private $_cachedIP;
12
+
13
+ public static function current() {
14
+ return new Model_Request();
15
+ }
16
+
17
+ public function detected_ip_preview($source = null, $trusted_proxies = null) {
18
+ if ($source === null) {
19
+ $source = Controller_Settings::shared()->get(Controller_Settings::OPTION_IP_SOURCE);
20
+ }
21
+
22
+ $record = $this->_ip($source);
23
+ if (is_array($record)) {
24
+ list($ip, $variable) = $record;
25
+ if (isset($_SERVER[$variable]) && strpos($_SERVER[$variable], ',') !== false) {
26
+ $items = preg_replace('/[\s,]/', '', explode(',', $_SERVER[$variable]));
27
+ $output = '';
28
+ foreach ($items as $i) {
29
+ if ($ip == $i) {
30
+ $output .= ', <strong>' . esc_html($i) . '</strong>';
31
+ }
32
+ else {
33
+ $output .= ', ' . esc_html($i);
34
+ }
35
+ }
36
+
37
+ return substr($output, 2);
38
+ }
39
+ return '<strong>' . esc_html($ip) . '</strong>';
40
+ }
41
+ return false;
42
+ }
43
+
44
+ public function ip($refreshCache = false) {
45
+ if (WORDFENCE_LS_FROM_CORE) {
46
+ return \wfUtils::getIP($refreshCache);
47
+ }
48
+
49
+ if (!isset($this->_cachedIP) || $refreshCache) {
50
+ $this->_cachedIP = $this->_ip(Controller_Settings::shared()->get(Controller_Settings::OPTION_IP_SOURCE), Controller_Settings::shared()->trusted_proxies());
51
+ }
52
+
53
+ return $this->_cachedIP[0]; //Format is array(<text IP>, <field found in>)
54
+ }
55
+
56
+ public function ip_for_field($source, $trusted_proxies) {
57
+ return $this->_ip($source, $trusted_proxies);
58
+ }
59
+
60
+ protected function _ip($source = null, $trusted_proxies = null) {
61
+ if ($source === null) {
62
+ $source = Controller_Settings::shared()->get(Controller_Settings::OPTION_IP_SOURCE);
63
+ }
64
+
65
+ $possible_ips = $this->_possible_ips($source);
66
+ if ($trusted_proxies === null) { $trusted_proxies = array(); }
67
+ return $this->_find_preferred_ip($possible_ips, $trusted_proxies);
68
+ }
69
+
70
+ protected function _possible_ips($source = null) {
71
+ $defaultIP = (is_array($_SERVER) && isset($_SERVER[self::IP_SOURCE_REMOTE_ADDR])) ? array($_SERVER[self::IP_SOURCE_REMOTE_ADDR], self::IP_SOURCE_REMOTE_ADDR) : array('127.0.0.1', self::IP_SOURCE_REMOTE_ADDR);
72
+
73
+ if ($source) {
74
+ if ($source == self::IP_SOURCE_REMOTE_ADDR) {
75
+ return array($defaultIP);
76
+ }
77
+
78
+ $check = array(
79
+ array((isset($_SERVER[$source]) ? $_SERVER[$source] : ''), $source),
80
+ $defaultIP,
81
+ );
82
+ return $check;
83
+ }
84
+
85
+ $check = array($defaultIP);
86
+ if (isset($_SERVER[self::IP_SOURCE_X_FORWARDED_FOR])) {
87
+ $check[] = array($_SERVER[self::IP_SOURCE_X_FORWARDED_FOR], self::IP_SOURCE_X_FORWARDED_FOR);
88
+ }
89
+ if (isset($_SERVER[self::IP_SOURCE_X_REAL_IP])) {
90
+ $check[] = array($_SERVER[self::IP_SOURCE_X_REAL_IP], self::IP_SOURCE_X_REAL_IP);
91
+ }
92
+ return $check;
93
+ }
94
+
95
+ protected function _find_preferred_ip($possible_ips, $trusted_proxies) {
96
+ $privates = array();
97
+ foreach ($possible_ips as $entry) {
98
+ list($value, $var) = $entry;
99
+ if (is_array($value)) { // An array of IPs
100
+ foreach ($value as $index => $j) {
101
+ if (!Model_IP::is_valid_ip($j)) {
102
+ $j = preg_replace('/:\d+$/', '', $j); //Strip off port if present
103
+ }
104
+
105
+ if (Model_IP::is_valid_ip($j)) {
106
+ if (Model_IP::is_ipv6_mapped_ipv4($j)) {
107
+ $j = Model_IP::inet_ntop(Model_IP::inet_pton($j));
108
+ }
109
+
110
+ foreach ($trusted_proxies as $proxy) {
111
+ if (!empty($proxy)) {
112
+ if (Controller_Whitelist::shared()->ip_in_range($j, $proxy) && $index < count($value) - 1) {
113
+ continue 2;
114
+ }
115
+ }
116
+ }
117
+
118
+ if (filter_var($j, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
119
+ $privates[] = array($j, $var);
120
+ }
121
+ else {
122
+ return array($j, $var);
123
+ }
124
+ }
125
+ }
126
+ continue;
127
+ }
128
+
129
+ $skipToNext = false;
130
+ $separators = array(',', ' ', "\t");
131
+ foreach ($separators as $char) { // A list of IPs separated by <separator>: 192.0.2.15,192.0.2.35,192.0.2.254
132
+ if (strpos($value, $char) !== false) {
133
+ $sp = explode($char, $value);
134
+ $sp = array_reverse($sp);
135
+ foreach ($sp as $index => $j) {
136
+ $j = trim($j);
137
+ if (!Model_IP::is_valid_ip($j)) {
138
+ $j = preg_replace('/:\d+$/', '', $j); //Strip off port
139
+ }
140
+
141
+ if (Model_IP::is_valid_ip($j)) {
142
+ if (Model_IP::is_ipv6_mapped_ipv4($j)) {
143
+ $j = Model_IP::inet_ntop(Model_IP::inet_pton($j));
144
+ }
145
+
146
+ foreach ($trusted_proxies as $proxy) {
147
+ if (!empty($proxy)) {
148
+ if (Controller_Whitelist::shared()->ip_in_range($j, $proxy) && $index < count($sp) - 1) {
149
+ continue 2;
150
+ }
151
+ }
152
+ }
153
+
154
+ if (filter_var($j, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
155
+ $privates[] = array($j, $var);
156
+ }
157
+ else {
158
+ return array($j, $var);
159
+ }
160
+ }
161
+ }
162
+ $skipToNext = true;
163
+ break;
164
+ }
165
+ }
166
+ if ($skipToNext) { continue; } //Skip to next item because this one had a comma/space/tab, but we didn't find a valid, non-private address
167
+
168
+ // A literal IP
169
+ if (!Model_IP::is_valid_ip($value)) {
170
+ $value = preg_replace('/:\d+$/', '', $value); //Strip off port
171
+ }
172
+
173
+ if (Model_IP::is_valid_ip($value)) {
174
+ if (Model_IP::is_ipv6_mapped_ipv4($value)) {
175
+ $value = Model_IP::inet_ntop(Model_IP::inet_pton($value));
176
+ }
177
+
178
+ if (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
179
+ $privates[] = array($value, $var);
180
+ }
181
+ else {
182
+ return array($value, $var);
183
+ }
184
+ }
185
+ }
186
+
187
+ if (count($privates) > 0) {
188
+ return $privates[0];
189
+ }
190
+
191
+ return false;
192
+ }
193
+ }
classes/model/settings.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ abstract class Model_Settings {
6
+ const AUTOLOAD_YES = 'yes';
7
+ const AUTOLOAD_NO = 'no';
8
+
9
+ /**
10
+ * Sets $value to $key.
11
+ *
12
+ * @param string $key
13
+ * @param mixed $value
14
+ * @param string $autoload Whether or not the key/value pair should autoload in storages that do that.
15
+ * @param bool $allowOverwrite If false, only sets the value if key does not already exist.
16
+ */
17
+ abstract public function set($key, $value, $autoload = self::AUTOLOAD_YES, $allowOverwrite = true);
18
+ abstract public function set_multiple($values);
19
+ abstract public function get($key, $default);
20
+ abstract public function remove($key);
21
+ }
classes/model/settings/db.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Settings;
4
+
5
+ use WordfenceLS\Controller_DB;
6
+ use WordfenceLS\Model_Settings;
7
+
8
+ class Model_DB extends Model_Settings {
9
+ const AUTOLOAD_NO = 'no';
10
+ const AUTOLOAD_YES = 'yes';
11
+
12
+ public function set($key, $value, $autoload = self::AUTOLOAD_YES, $allowOverwrite = true) {
13
+ global $wpdb;
14
+ $table = Controller_DB::shared()->settings;
15
+ if (!$allowOverwrite) {
16
+ if ($this->_has_cached($key)) {
17
+ return;
18
+ }
19
+
20
+ $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM `{$table}` WHERE `name` = %s", $key), ARRAY_A);
21
+ if (is_array($row)) {
22
+ return;
23
+ }
24
+ }
25
+
26
+ if ($wpdb->query($wpdb->prepare("INSERT INTO `{$table}` (`name`, `value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), `autoload` = VALUES(`autoload`)", $key, $value, $autoload)) !== false && $autoload != self::AUTOLOAD_NO) {
27
+ $this->_update_cached($key, $value);
28
+ }
29
+ }
30
+
31
+ public function set_multiple($values) {
32
+ foreach ($values as $key => $value) {
33
+ if (is_array($value)) {
34
+ $this->set($key, $value['value'], $value['autoload'], $value['allowOverwrite']);
35
+ }
36
+ else {
37
+ $this->set($key, $value);
38
+ }
39
+ }
40
+ }
41
+
42
+ public function get($key, $default = false) {
43
+ global $wpdb;
44
+
45
+ if ($this->_has_cached($key)) {
46
+ return $this->_cached_value($key);
47
+ }
48
+
49
+ $table = Controller_DB::shared()->settings;
50
+ if (!($setting = $wpdb->get_row($wpdb->prepare("SELECT `name`, `value`, `autoload` FROM `{$table}` WHERE `name` = %s", $key)))) {
51
+ return $default;
52
+ }
53
+
54
+ if ($setting->autoload != self::AUTOLOAD_NO) {
55
+ $this->_update_cached($key, $setting->value);
56
+ }
57
+ return $setting->value;
58
+ }
59
+
60
+ public function remove($key) {
61
+ global $wpdb;
62
+ $table = Controller_DB::shared()->settings;
63
+ $wpdb->query($wpdb->prepare("DELETE FROM `{$table}` WHERE `name` = %s", $key));
64
+ $this->_remove_cached($key);
65
+ }
66
+
67
+ private function _cached() {
68
+ global $wpdb;
69
+
70
+ $settings = wp_cache_get('allsettings', 'wordfence-ls');
71
+ if (!$settings) {
72
+ $table = Controller_DB::shared()->settings;
73
+ $suppress = $wpdb->suppress_errors();
74
+ $raw = $wpdb->get_results("SELECT `name`, `value` FROM `{$table}` WHERE `autoload` = 'yes'");
75
+ $wpdb->suppress_errors($suppress);
76
+ $settings = array();
77
+ foreach ((array) $raw as $o) {
78
+ $settings[$o->name] = $o->value;
79
+ }
80
+
81
+ wp_cache_add_non_persistent_groups('wordfence-ls');
82
+ wp_cache_add('allsettings', $settings, 'wordfence-ls');
83
+ }
84
+
85
+ return $settings;
86
+ }
87
+
88
+ private function _update_cached($key, $value) {
89
+ $settings = $this->_cached();
90
+ $settings[$key] = $value;
91
+ wp_cache_set('allsettings', $settings, 'wordfence-ls');
92
+ }
93
+
94
+ private function _remove_cached($key) {
95
+ $settings = $this->_cached();
96
+ if (isset($settings[$key])) {
97
+ unset($settings[$key]);
98
+ wp_cache_set('allsettings', $settings, 'wordfence-ls');
99
+ }
100
+ }
101
+
102
+ private function _cached_value($key) {
103
+ global $wpdb;
104
+
105
+ $settings = $this->_cached();
106
+ if (isset($settings[$key])) {
107
+ return $settings[$key];
108
+ }
109
+
110
+ $table = Controller_DB::shared()->settings;
111
+ $value = $wpdb->get_var($wpdb->prepare("SELECT `value` FROM `{$table}` WHERE name = %s", $key));
112
+ if ($value !== null) {
113
+ $settings[$key] = $value;
114
+ wp_cache_set('allsettings', $settings, 'wordfence-ls');
115
+ }
116
+ return $value;
117
+ }
118
+ public function _has_cached($key) {
119
+ $settings = $this->_cached();
120
+ return isset($settings[$key]);
121
+ }
122
+ }
classes/model/settings/wpoptions.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Settings;
4
+
5
+ use WordfenceLS\Model_Settings;
6
+
7
+ class Model_WPOptions extends Model_Settings {
8
+ protected $_prefix;
9
+
10
+ public function __construct($prefix = '') {
11
+ $this->_prefix = $prefix;
12
+ }
13
+
14
+ protected function _translate_key($key) {
15
+ return strtolower(preg_replace('/[^a-z0-9]/i', '_', $key));
16
+ }
17
+
18
+ public function set($key, $value, $autoload = self::AUTOLOAD_YES, $allowOverwrite = true) {
19
+ $key = $this->_translate_key($this->_prefix . $key);
20
+ if (!$allowOverwrite) {
21
+ if (is_multisite()) {
22
+ add_network_option(null, $key, $value);
23
+ }
24
+ else {
25
+ add_option($key, $value, '', $autoload);
26
+ }
27
+ }
28
+ else {
29
+ if (is_multisite()) {
30
+ update_network_option(null, $key, $value);
31
+ }
32
+ else {
33
+ update_option($key, $value, $autoload);
34
+ }
35
+ }
36
+ }
37
+
38
+ public function set_multiple($values) {
39
+ foreach ($values as $key => $value) {
40
+ if (is_array($value)) {
41
+ $this->set($key, $value['value'], $value['autoload'], $value['allowOverwrite']);
42
+ }
43
+ else {
44
+ $this->set($key, $value);
45
+ }
46
+ }
47
+ }
48
+
49
+ public function get($key, $default = false) {
50
+ $key = $this->_translate_key($this->_prefix . $key);
51
+ if (is_multisite()) {
52
+ $value = get_network_option($key, $default);
53
+ }
54
+ else {
55
+ $value = get_option($key, $default);
56
+ }
57
+ return $value;
58
+ }
59
+
60
+ public function remove($key) {
61
+ $key = $this->_translate_key($this->_prefix . $key);
62
+ if (is_multisite()) {
63
+ delete_network_option(null, $key);
64
+ }
65
+ else {
66
+ delete_option($key);
67
+ }
68
+ }
69
+ }
classes/model/text/html.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Text;
4
+
5
+ /**
6
+ * Represents text that is already HTML-safe and should not be encoded again.
7
+ * @package Wordfence2FA\Text
8
+ */
9
+ class Model_HTML {
10
+ private $_html;
11
+
12
+ public static function esc_html($content) {
13
+ if (is_object($content) && ($content instanceof Model_HTML)) {
14
+ return (string) $content;
15
+ }
16
+ return esc_html($content);
17
+ }
18
+
19
+ public function __construct($html) {
20
+ $this->_html = $html;
21
+ }
22
+
23
+ public function __toString() {
24
+ return $this->_html;
25
+ }
26
+ }
classes/model/text/javascript.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\Text;
4
+
5
+ /**
6
+ * Represents text that is already JavaScript-safe and should not be encoded again.
7
+ * @package Wordfence2FA\Text
8
+ */
9
+ class Model_JavaScript {
10
+ private $_javaScript;
11
+
12
+ /**
13
+ * Returns a string escaped for use in JavaScript. This is almost identical in behavior to esc_js except that
14
+ * we don't call _wp_specialchars and keep \r rather than stripping it.
15
+ *
16
+ * @param string|Model_JavaScript $content
17
+ * @return string
18
+ */
19
+ public static function esc_js($content) {
20
+ if (is_object($content) && ($content instanceof Model_HTML)) {
21
+ return (string) $content;
22
+ }
23
+
24
+ $safe_text = wp_check_invalid_utf8($content);
25
+ $safe_text = preg_replace('/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes($safe_text));
26
+ $safe_text = str_replace("\r", '\\r', $safe_text);
27
+ $safe_text = str_replace("\n", '\\n', addslashes($safe_text));
28
+ return apply_filters('js_escape', $safe_text, $content);
29
+ }
30
+
31
+ public function __construct($javaScript) {
32
+ $this->_javaScript = $javaScript;
33
+ }
34
+
35
+ public function __toString() {
36
+ return $this->_javaScript;
37
+ }
38
+ }
classes/model/tokenbucket.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Model_TokenBucket {
6
+ /* Constants to map from tokens per unit to tokens per second */
7
+ const MICROSECOND = 0.000001;
8
+ const MILLISECOND = 0.001;
9
+ const SECOND = 1;
10
+ const MINUTE = 60;
11
+ const HOUR = 3600;
12
+ const DAY = 86400;
13
+ const WEEK = 604800;
14
+ const MONTH = 2629743.83;
15
+ const YEAR = 31556926;
16
+
17
+ const BACKING_REDIS = 'redis';
18
+ const BACKING_WP_OPTIONS = 'wpoptions';
19
+
20
+ private $_identifier;
21
+ private $_bucketSize;
22
+ private $_tokensPerSecond;
23
+
24
+ private $_backing;
25
+ private $_redis;
26
+
27
+ /**
28
+ * Model_TokenBucket constructor.
29
+ *
30
+ * @param string $identifier The identifier for the bucket record in the database
31
+ * @param int $bucketSize The maximum capacity of the bucket.
32
+ * @param double $tokensPerSecond The number of tokens per second added to the bucket.
33
+ * @param string $backing The backing storage to use.
34
+ */
35
+ public function __construct($identifier, $bucketSize, $tokensPerSecond, $backing = self::BACKING_WP_OPTIONS) {
36
+ $this->_identifier = $identifier;
37
+ $this->_bucketSize = $bucketSize;
38
+ $this->_tokensPerSecond = $tokensPerSecond;
39
+ $this->_backing = $backing;
40
+
41
+ if ($backing == self::BACKING_REDIS) {
42
+ $this->_redis = new \Redis();
43
+ $this->_redis->pconnect('127.0.0.1');
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Attempts to acquire a lock for the bucket.
49
+ *
50
+ * @param int $timeout
51
+ * @return bool Whether or not the lock was acquired.
52
+ */
53
+ private function _lock($timeout = 30) {
54
+ if ($this->_backing == self::BACKING_WP_OPTIONS) {
55
+ $start = microtime(true);
56
+ while (!$this->_wp_options_create_lock($this->_identifier)) {
57
+ if (microtime(true) - $start > $timeout) {
58
+ return false;
59
+ }
60
+ usleep(5000); // 5 ms
61
+ }
62
+ return true;
63
+ }
64
+ else if ($this->_backing == self::BACKING_REDIS) {
65
+ if ($this->_redis === false) {
66
+ return false;
67
+ }
68
+
69
+ $start = microtime(true);
70
+ while (!$this->_redis->setnx('lock:' . $this->_identifier, '1')) {
71
+ if (microtime(true) - $start > $timeout) {
72
+ return false;
73
+ }
74
+ usleep(5000); // 5 ms
75
+ }
76
+ $this->_redis->expire('lock:' . $this->_identifier, 30);
77
+ return true;
78
+ }
79
+ return false;
80
+ }
81
+
82
+ private function _unlock() {
83
+ if ($this->_backing == self::BACKING_WP_OPTIONS) {
84
+ $this->_wp_options_release_lock($this->_identifier);
85
+ }
86
+ else if ($this->_backing == self::BACKING_REDIS) {
87
+ if ($this->_redis === false) {
88
+ return;
89
+ }
90
+
91
+ $this->_redis->del('lock:' . $this->_identifier);
92
+ }
93
+ }
94
+
95
+ private function _wp_options_create_lock($name, $timeout = null) { //Our own version of WP_Upgrader::create_lock
96
+ global $wpdb;
97
+
98
+ if (!$timeout) {
99
+ $timeout = 3600;
100
+ }
101
+
102
+ $lock_option = 'wfls_' . $name . '.lock';
103
+ $lock_result = $wpdb->query($wpdb->prepare("INSERT IGNORE INTO `{$wpdb->options}` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, 'no')", $lock_option, time()));
104
+
105
+ if (!$lock_result) {
106
+ $lock_result = get_option($lock_option);
107
+ if (!$lock_result) {
108
+ return false;
109
+ }
110
+
111
+ if ($lock_result > (time() - $timeout)) {
112
+ return false;
113
+ }
114
+
115
+ $this->_wp_options_release_lock($name);
116
+ return $this->_wp_options_create_lock($name, $timeout);
117
+ }
118
+
119
+ return true;
120
+ }
121
+
122
+ private function _wp_options_release_lock($name) {
123
+ return delete_option('wfls_' . $name . '.lock');
124
+ }
125
+
126
+ /**
127
+ * Atomically checks the available token count, creating the initial record if needed, and updates the available token count if the requested number of tokens is available.
128
+ *
129
+ * @param int $tokenCount
130
+ * @return bool Whether or not there were enough tokens to satisfy the request.
131
+ */
132
+ public function consume($tokenCount = 1) {
133
+ if (!$this->_lock()) { return false; }
134
+
135
+ if ($this->_backing == self::BACKING_WP_OPTIONS) {
136
+ $record = get_transient('wflsbucket:' . $this->_identifier);
137
+ }
138
+ else if ($this->_backing == self::BACKING_REDIS) {
139
+ $record = $this->_redis->get('bucket:' . $this->_identifier);
140
+ }
141
+ else {
142
+ return false;
143
+ }
144
+
145
+ if ($record === false) {
146
+ if ($tokenCount > $this->_bucketSize) {
147
+ $this->_unlock();
148
+ return false;
149
+ }
150
+
151
+ $this->_bootstrap($this->_bucketSize - $tokenCount);
152
+ $this->_unlock();
153
+ return true;
154
+ }
155
+
156
+ $tokens = min($this->_secondsToTokens(microtime(true) - (float) $record), $this->_bucketSize);
157
+ if ($tokenCount > $tokens) {
158
+ $this->_unlock();
159
+ return false;
160
+ }
161
+
162
+ if ($this->_backing == self::BACKING_WP_OPTIONS) {
163
+ set_transient('wflsbucket:' . $this->_identifier, (string) (microtime(true) - $this->_tokensToSeconds($tokens - $tokenCount)), ceil($this->_tokensToSeconds($this->_bucketSize)));
164
+ }
165
+ else if ($this->_backing == self::BACKING_REDIS) {
166
+ $this->_redis->set('bucket:' . $this->_identifier, (string) (microtime(true) - $this->_tokensToSeconds($tokens - $tokenCount)));
167
+ }
168
+
169
+ $this->_unlock();
170
+ return true;
171
+ }
172
+
173
+ /**
174
+ * Creates an initial record with the given number of tokens.
175
+ *
176
+ * @param int $initialTokens
177
+ */
178
+ protected function _bootstrap($initialTokens) {
179
+ $microtime = microtime(true) - $this->_tokensToSeconds($initialTokens);
180
+ if ($this->_backing == self::BACKING_WP_OPTIONS) {
181
+ set_transient('wflsbucket:' . $this->_identifier, (string) $microtime, ceil($this->_tokensToSeconds($this->_bucketSize)));
182
+ }
183
+ else if ($this->_backing == self::BACKING_REDIS) {
184
+ $this->_redis->set('bucket:' . $this->_identifier, (string) $microtime);
185
+ }
186
+ }
187
+
188
+ protected function _tokensToSeconds($tokens) {
189
+ return $tokens / $this->_tokensPerSecond;
190
+ }
191
+
192
+ protected function _secondsToTokens($seconds) {
193
+ return (int) $seconds * $this->_tokensPerSecond;
194
+ }
195
+ }
classes/model/view.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS;
4
+
5
+ class Model_View {
6
+ /**
7
+ * @var string
8
+ */
9
+ protected $path;
10
+
11
+ /**
12
+ * @var string
13
+ */
14
+ protected $file_extension = '.php';
15
+
16
+ /**
17
+ * @var string
18
+ */
19
+ protected $view;
20
+
21
+ /**
22
+ * @var array
23
+ */
24
+ protected $data;
25
+
26
+ /**
27
+ * Equivalent to the constructor but allows for call chaining.
28
+ *
29
+ * @param string $view
30
+ * @param array $data
31
+ * @return Model_View
32
+ */
33
+ public static function create($view, $data = array()) {
34
+ return new self($view, $data);
35
+ }
36
+
37
+ /**
38
+ * @param string $view
39
+ * @param array $data
40
+ */
41
+ public function __construct($view, $data = array()) {
42
+ $this->path = WORDFENCE_LS_PATH . 'views';
43
+ $this->view = $view;
44
+ $this->data = $data;
45
+ }
46
+
47
+ /**
48
+ * @return string
49
+ * @throws ViewNotFoundException
50
+ */
51
+ public function render() {
52
+ $view = preg_replace('/\.{2,}/', '.', $this->view);
53
+ $path = $this->path . '/' . $view . $this->file_extension;
54
+ if (!file_exists($path)) {
55
+ throw new ViewNotFoundException('The view ' . $path . ' does not exist or is not readable.');
56
+ }
57
+
58
+ extract($this->data, EXTR_SKIP);
59
+
60
+ ob_start();
61
+ /** @noinspection PhpIncludeInspection */
62
+ include $path;
63
+ return ob_get_clean();
64
+ }
65
+
66
+ /**
67
+ * @return string
68
+ */
69
+ public function __toString() {
70
+ try {
71
+ return $this->render();
72
+ }
73
+ catch (ViewNotFoundException $e) {
74
+ return defined('WP_DEBUG') && WP_DEBUG ? $e->getMessage() : 'The view could not be loaded.';
75
+ }
76
+ }
77
+
78
+ /**
79
+ * @param $data
80
+ * @return $this
81
+ */
82
+ public function addData($data) {
83
+ $this->data = array_merge($data, $this->data);
84
+ return $this;
85
+ }
86
+
87
+ /**
88
+ * @return array
89
+ */
90
+ public function getData() {
91
+ return $this->data;
92
+ }
93
+
94
+ /**
95
+ * @param array $data
96
+ * @return $this
97
+ */
98
+ public function setData($data) {
99
+ $this->data = $data;
100
+ return $this;
101
+ }
102
+
103
+ /**
104
+ * @return string
105
+ */
106
+ public function getView() {
107
+ return $this->view;
108
+ }
109
+
110
+ /**
111
+ * @param string $view
112
+ * @return $this
113
+ */
114
+ public function setView($view) {
115
+ $this->view = $view;
116
+ return $this;
117
+ }
118
+
119
+ /**
120
+ * Prevent POP
121
+ */
122
+ public function __wakeup() {
123
+ $this->path = WORDFENCE_LS_PATH . 'views';
124
+ $this->view = null;
125
+ $this->data = array();
126
+ $this->file_extension = '.php';
127
+ }
128
+ }
129
+
130
+ class ViewNotFoundException extends \Exception { }
classes/model/view/tab.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\View;
4
+
5
+ /**
6
+ * Represents a tab in the UI.
7
+ *
8
+ * @package Wordfence2FA\View
9
+ * @property string $id
10
+ * @property string $a
11
+ * @property string $tabTitle
12
+ * @property string $pageTitle
13
+ * @property bool $active
14
+ */
15
+ class Model_Tab {
16
+ protected $_id;
17
+ protected $_a;
18
+ protected $_tabTitle;
19
+ protected $_pageTitle;
20
+ protected $_active;
21
+
22
+ public function __construct($id, $a, $tabTitle, $pageTitle, $active = false) {
23
+ $this->_id = $id;
24
+ $this->_a = $a;
25
+ $this->_tabTitle = $tabTitle;
26
+ $this->_pageTitle = $pageTitle;
27
+ $this->_active = $active;
28
+ }
29
+
30
+ public function __get($name) {
31
+ switch ($name) {
32
+ case 'id':
33
+ return $this->_id;
34
+ case 'a':
35
+ return $this->_a;
36
+ case 'tabTitle':
37
+ return $this->_tabTitle;
38
+ case 'pageTitle':
39
+ return $this->_pageTitle;
40
+ case 'active':
41
+ return $this->_active;
42
+ }
43
+
44
+ throw new \OutOfBoundsException('Invalid key: ' . $name);
45
+ }
46
+ }
classes/model/view/title.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WordfenceLS\View;
4
+
5
+ /**
6
+ * Class Model_Title
7
+ * @package Wordfence2FA\Page
8
+ * @var string $id A valid DOM ID for the title.
9
+ * @var string|Model_HTML $title The title text or HTML.
10
+ * @var string $helpURL The help URL.
11
+ * @var string|Model_HTML $helpLink The text/HTML of the help link.
12
+ */
13
+ class Model_Title {
14
+ private $_id;
15
+ private $_title;
16
+ private $_helpURL;
17
+ private $_helpLink;
18
+
19
+ public function __construct($id, $title, $helpURL, $helpLink) {
20
+ $this->_id = $id;
21
+ $this->_title = $title;
22
+ $this->_helpURL = $helpURL;
23
+ $this->_helpLink = $helpLink;
24
+ }
25
+
26
+ public function __get($name) {
27
+ switch ($name) {
28
+ case 'id':
29
+ return $this->_id;
30
+ case 'title':
31
+ return $this->_title;
32
+ case 'helpURL':
33
+ return $this->_helpURL;
34
+ case 'helpLink':
35
+ return $this->_helpLink;
36
+ }
37
+
38
+ throw new \OutOfBoundsException('Invalid key: ' . $name);
39
+ }
40
+ }
css/admin-global.1559237323.css ADDED
@@ -0,0 +1 @@
 
1
+ .wfls-clearfix:before,.wfls-clearfix:after{content:" ";display:table}.wfls-clearfix:after{clear:both}.wfls-btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;text-transform:uppercase;padding:.4rem 1rem;font-size:.875rem;line-height:1.3125rem;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media (min-width: 768px){.wfls-btn{padding:.5rem 1.25rem;font-size:.875rem;line-height:1.3125rem;border-radius:4px}}.wfls-btn:focus,.wfls-btn.wfls-focus,.wfls-btn:active:focus,.wfls-btn:active.wfls-focus,.wfls-btn.wfls-active:focus,.wfls-btn.wfls-active.wfls-focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.wfls-btn:hover,.wfls-btn:focus,.wfls-btn.wfls-focus{color:#00709e;text-decoration:none !important}.wfls-btn:active,.wfls-btn.wfls-active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.wfls-btn.wfls-disabled,.wfls-btn[disabled],.wfls-btn[readonly],fieldset[disabled] .wfls-btn{cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none}a.wfls-btn{text-decoration:none}a.wfls-btn.wfls-disabled,fieldset[disabled] a.wfls-btn{cursor:not-allowed;pointer-events:none}.wfls-btn-default{color:#00709e;background-color:#fff;border-color:#00709e}.wfls-btn-default:focus,.wfls-btn-default.focus{color:#00709e;background-color:#e6e6e6;border-color:#00161f}.wfls-btn-default:hover{color:#00709e;background-color:#e6e6e6;border-color:#004561}.wfls-btn-default:active,.wfls-btn-default.active,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle{color:#00709e;background-color:#e6e6e6;border-color:#004561}.wfls-btn-default:active:hover,.wfls-btn-default:active:focus,.wfls-btn-default:active.focus,.wfls-btn-default.active:hover,.wfls-btn-default.active:focus,.wfls-btn-default.active.focus,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle.focus{color:#00709e;background-color:#d4d4d4;border-color:#00161f}.wfls-btn-default:active,.wfls-btn-default.wfls-active,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle{background-image:none}.wfls-btn-default.wfls-disabled,.wfls-btn-default[disabled],.wfls-btn-default[readonly],fieldset[disabled] .wfls-btn-default{color:#777;background-color:#fff;border-color:#e2e2e2;cursor:not-allowed;opacity:0.75}.wfls-btn-default.wfls-disabled:hover,.wfls-btn-default.wfls-disabled:focus,.wfls-btn-default.wfls-disabled.wfls-focus,.wfls-btn-default[disabled]:hover,.wfls-btn-default[disabled]:focus,.wfls-btn-default[disabled].wfls-focus,.wfls-btn-default[readonly]:hover,.wfls-btn-default[readonly]:focus,.wfls-btn-default[readonly].wfls-focus,fieldset[disabled] .wfls-btn-default:hover,fieldset[disabled] .wfls-btn-default:focus,fieldset[disabled] .wfls-btn-default.wfls-focus{background-color:#fff;border-color:#00709e}.wfls-btn-default .wfls-badge{color:#fff;background-color:#00709e}.wfls-btn-primary{color:#fff;background-color:#00709e;border-color:#005e85}.wfls-btn-primary:focus,.wfls-btn-primary.focus{color:#fff;background-color:#004c6b;border-color:#000405}.wfls-btn-primary:hover{color:#fff;background-color:#004c6b;border-color:#003347}.wfls-btn-primary:active,.wfls-btn-primary.active,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle{color:#fff;background-color:#004c6b;border-color:#003347}.wfls-btn-primary:active:hover,.wfls-btn-primary:active:focus,.wfls-btn-primary:active.focus,.wfls-btn-primary.active:hover,.wfls-btn-primary.active:focus,.wfls-btn-primary.active.focus,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle.focus{color:#fff;background-color:#003347;border-color:#000405}.wfls-btn-primary:active,.wfls-btn-primary.wfls-active,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle{background-image:none}.wfls-btn-primary.wfls-disabled,.wfls-btn-primary[disabled],.wfls-btn-primary[readonly],fieldset[disabled] .wfls-btn-primary{color:#fff;background-color:#59a2c0;border-color:#5996b0;cursor:not-allowed;opacity:0.75}.wfls-btn-primary.wfls-disabled:hover,.wfls-btn-primary.wfls-disabled:focus,.wfls-btn-primary.wfls-disabled.wfls-focus,.wfls-btn-primary[disabled]:hover,.wfls-btn-primary[disabled]:focus,.wfls-btn-primary[disabled].wfls-focus,.wfls-btn-primary[readonly]:hover,.wfls-btn-primary[readonly]:focus,.wfls-btn-primary[readonly].wfls-focus,fieldset[disabled] .wfls-btn-primary:hover,fieldset[disabled] .wfls-btn-primary:focus,fieldset[disabled] .wfls-btn-primary.wfls-focus{background-color:#00709e;border-color:#005e85}.wfls-btn-primary .wfls-badge{color:#00709e;background-color:#fff}.wfls-btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.wfls-btn-success:focus,.wfls-btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.wfls-btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.wfls-btn-success:active,.wfls-btn-success.active,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle{color:#fff;background-color:#449d44;border-color:#398439}.wfls-btn-success:active:hover,.wfls-btn-success:active:focus,.wfls-btn-success:active.focus,.wfls-btn-success.active:hover,.wfls-btn-success.active:focus,.wfls-btn-success.active.focus,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle.focus{color:#fff;background-color:#398439;border-color:#255625}.wfls-btn-success:active,.wfls-btn-success.wfls-active,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle{background-image:none}.wfls-btn-success.wfls-disabled,.wfls-btn-success[disabled],.wfls-btn-success[readonly],fieldset[disabled] .wfls-btn-success{color:#fff;background-color:#95d195;border-color:#8bca8b;cursor:not-allowed;opacity:0.75}.wfls-btn-success.wfls-disabled:hover,.wfls-btn-success.wfls-disabled:focus,.wfls-btn-success.wfls-disabled.wfls-focus,.wfls-btn-success[disabled]:hover,.wfls-btn-success[disabled]:focus,.wfls-btn-success[disabled].wfls-focus,.wfls-btn-success[readonly]:hover,.wfls-btn-success[readonly]:focus,.wfls-btn-success[readonly].wfls-focus,fieldset[disabled] .wfls-btn-success:hover,fieldset[disabled] .wfls-btn-success:focus,fieldset[disabled] .wfls-btn-success.wfls-focus{background-color:#5cb85c;border-color:#4cae4c}.wfls-btn-success .wfls-badge{color:#5cb85c;background-color:#fff}.wfls-btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.wfls-btn-info:focus,.wfls-btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.wfls-btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.wfls-btn-info:active,.wfls-btn-info.active,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#269abc}.wfls-btn-info:active:hover,.wfls-btn-info:active:focus,.wfls-btn-info:active.focus,.wfls-btn-info.active:hover,.wfls-btn-info.active:focus,.wfls-btn-info.active.focus,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.wfls-btn-info:active,.wfls-btn-info.wfls-active,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle{background-image:none}.wfls-btn-info.wfls-disabled,.wfls-btn-info[disabled],.wfls-btn-info[readonly],fieldset[disabled] .wfls-btn-info{color:#fff;background-color:#94d6ea;border-color:#87d1e7;cursor:not-allowed;opacity:0.75}.wfls-btn-info.wfls-disabled:hover,.wfls-btn-info.wfls-disabled:focus,.wfls-btn-info.wfls-disabled.wfls-focus,.wfls-btn-info[disabled]:hover,.wfls-btn-info[disabled]:focus,.wfls-btn-info[disabled].wfls-focus,.wfls-btn-info[readonly]:hover,.wfls-btn-info[readonly]:focus,.wfls-btn-info[readonly].wfls-focus,fieldset[disabled] .wfls-btn-info:hover,fieldset[disabled] .wfls-btn-info:focus,fieldset[disabled] .wfls-btn-info.wfls-focus{background-color:#5bc0de;border-color:#46b8da}.wfls-btn-info .wfls-badge{color:#5bc0de;background-color:#fff}.wfls-btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.wfls-btn-warning:focus,.wfls-btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.wfls-btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.wfls-btn-warning:active,.wfls-btn-warning.active,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle{color:#fff;background-color:#ec971f;border-color:#d58512}.wfls-btn-warning:active:hover,.wfls-btn-warning:active:focus,.wfls-btn-warning:active.focus,.wfls-btn-warning.active:hover,.wfls-btn-warning.active:focus,.wfls-btn-warning.active.focus,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.wfls-btn-warning:active,.wfls-btn-warning.wfls-active,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle{background-image:none}.wfls-btn-warning.wfls-disabled,.wfls-btn-warning[disabled],.wfls-btn-warning[readonly],fieldset[disabled] .wfls-btn-warning{color:#fff;background-color:#f5ca8c;border-color:#f4c37c;cursor:not-allowed;opacity:0.75}.wfls-btn-warning.wfls-disabled:hover,.wfls-btn-warning.wfls-disabled:focus,.wfls-btn-warning.wfls-disabled.wfls-focus,.wfls-btn-warning[disabled]:hover,.wfls-btn-warning[disabled]:focus,.wfls-btn-warning[disabled].wfls-focus,.wfls-btn-warning[readonly]:hover,.wfls-btn-warning[readonly]:focus,.wfls-btn-warning[readonly].wfls-focus,fieldset[disabled] .wfls-btn-warning:hover,fieldset[disabled] .wfls-btn-warning:focus,fieldset[disabled] .wfls-btn-warning.wfls-focus{background-color:#f0ad4e;border-color:#eea236}.wfls-btn-warning .wfls-badge{color:#f0ad4e;background-color:#fff}.wfls-btn-danger{color:#fff;background-color:#930000;border-color:#7a0000}.wfls-btn-danger:focus,.wfls-btn-danger.focus{color:#fff;background-color:#600000;border-color:#000}.wfls-btn-danger:hover{color:#fff;background-color:#600000;border-color:#3c0000}.wfls-btn-danger:active,.wfls-btn-danger.active,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle{color:#fff;background-color:#600000;border-color:#3c0000}.wfls-btn-danger:active:hover,.wfls-btn-danger:active:focus,.wfls-btn-danger:active.focus,.wfls-btn-danger.active:hover,.wfls-btn-danger.active:focus,.wfls-btn-danger.active.focus,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle.focus{color:#fff;background-color:#3c0000;border-color:#000}.wfls-btn-danger:active,.wfls-btn-danger.wfls-active,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle{background-image:none}.wfls-btn-danger.wfls-disabled,.wfls-btn-danger[disabled],.wfls-btn-danger[readonly],fieldset[disabled] .wfls-btn-danger{color:#fff;background-color:#b95959;border-color:#a95959;cursor:not-allowed;opacity:0.75}.wfls-btn-danger.wfls-disabled:hover,.wfls-btn-danger.wfls-disabled:focus,.wfls-btn-danger.wfls-disabled.wfls-focus,.wfls-btn-danger[disabled]:hover,.wfls-btn-danger[disabled]:focus,.wfls-btn-danger[disabled].wfls-focus,.wfls-btn-danger[readonly]:hover,.wfls-btn-danger[readonly]:focus,.wfls-btn-danger[readonly].wfls-focus,fieldset[disabled] .wfls-btn-danger:hover,fieldset[disabled] .wfls-btn-danger:focus,fieldset[disabled] .wfls-btn-danger.wfls-focus{background-color:#930000;border-color:#7a0000}.wfls-btn-danger .wfls-badge{color:#930000;background-color:#fff}.wfls-btn-callout{font-weight:600;text-transform:uppercase}.wfls-btn-callout-subtle{font-weight:400;text-transform:uppercase}.wfls-btn-link{color:#00709e;font-weight:normal;border-radius:0}.wfls-btn-link,.wfls-btn-link:active,.wfls-btn-link.wfls-active,.wfls-btn-link[disabled],fieldset[disabled] .wfls-btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.wfls-btn-link,.wfls-btn-link:hover,.wfls-btn-link:focus,.wfls-btn-link:active{border-color:transparent}.wfls-btn-link:hover,.wfls-btn-link:focus{color:#003a52;text-decoration:underline;background-color:transparent}.wfls-btn-link[disabled]:hover,.wfls-btn-link[disabled]:focus,fieldset[disabled] .wfls-btn-link:hover,fieldset[disabled] .wfls-btn-link:focus{color:#777;text-decoration:none}.wfls-btn-lg,.wfls-btn-group-lg>.wfls-btn{padding:10px 16px;font-size:18px;line-height:1.33333;border-radius:6px}.wfls-btn-sm,.wfls-btn-group-sm>.wfls-btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.wfls-btn-xs,.wfls-btn-group-xs>.wfls-btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.wfls-btn-block{display:block;width:100%}.wfls-btn-block+.wfls-btn-block{margin-top:5px}input[type="submit"].wfls-btn-block,input[type="reset"].wfls-btn-block,input[type="button"].wfls-btn-block{width:100%}.wfls-btn-group,.wfls-btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.wfls-btn-group>.wfls-btn,.wfls-btn-group-vertical>.wfls-btn{position:relative;float:left}.wfls-btn-group>.wfls-btn:hover,.wfls-btn-group>.wfls-btn:focus,.wfls-btn-group>.wfls-btn:active,.wfls-btn-group>.wfls-btn.wfls-active,.wfls-btn-group-vertical>.wfls-btn:hover,.wfls-btn-group-vertical>.wfls-btn:focus,.wfls-btn-group-vertical>.wfls-btn:active,.wfls-btn-group-vertical>.wfls-btn.wfls-active{z-index:2}.wfls-btn-group .wfls-btn+.wfls-btn,.wfls-btn-group .wfls-btn+.wfls-btn-group,.wfls-btn-group .wfls-btn-group+.wfls-btn,.wfls-btn-group .wfls-btn-group+.wfls-btn-group{margin-left:-1px}.wfls-btn-toolbar{margin-left:-5px}.wfls-btn-toolbar:before,.wfls-btn-toolbar:after{content:" ";display:table}.wfls-btn-toolbar:after{clear:both}.wfls-btn-toolbar .wfls-btn,.wfls-btn-toolbar .wfls-btn-group,.wfls-btn-toolbar .wfls-input-group{float:left}.wfls-btn-toolbar>.wfls-btn,.wfls-btn-toolbar>.wfls-btn-group,.wfls-btn-toolbar>.wfls-input-group{margin-left:5px}.wfls-btn-group>.wfls-btn:not(:first-child):not(:last-child):not(.wfls-dropdown-toggle){border-radius:0}.wfls-btn-group>.wfls-btn:first-child{margin-left:0}.wfls-btn-group>.wfls-btn:first-child:not(:last-child):not(.wfls-dropdown-toggle){-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group>.wfls-btn:last-child:not(:first-child),.wfls-btn-group>.wfls-dropdown-toggle:not(:first-child){-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.wfls-btn-group>.wfls-btn-group{float:left}.wfls-btn-group>.wfls-btn-group:not(:first-child):not(:last-child)>.wfls-btn{border-radius:0}.wfls-btn-group>.wfls-btn-group:first-child:not(:last-child)>.wfls-btn:last-child,.wfls-btn-group>.wfls-btn-group:first-child:not(:last-child)>.wfls-dropdown-toggle{-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group>.wfls-btn-group:last-child:not(:first-child)>.wfls-btn:first-child{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.wfls-btn-group .wfls-dropdown-toggle:active,.wfls-btn-group.wfls-open .wfls-dropdown-toggle{outline:0}.wfls-btn-group>.wfls-btn+.wfls-dropdown-toggle{padding-left:8px;padding-right:8px}.wfls-btn-group>.wfls-btn-lg+.wfls-dropdown-toggle,.wfls-btn-group-lg.wfls-btn-group>.wfls-btn+.wfls-dropdown-toggle{padding-left:12px;padding-right:12px}.wfls-btn-group.open .wfls-dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.wfls-btn-group.open .wfls-dropdown-toggle.wfls-btn-link{-webkit-box-shadow:none;box-shadow:none}.wfls-btn .wfls-caret{margin-left:0}.wfls-btn-lg .wfls-caret,.wfls-btn-group-lg>.wfls-btn .wfls-caret{border-width:5px 5px 0;border-bottom-width:0}.wfls-dropup .wfls-btn-lg .wfls-caret,.wfls-dropup .wfls-btn-group-lg>.wfls-btn .wfls-caret{border-width:0 5px 5px}.wfls-btn-group-vertical>.wfls-btn,.wfls-btn-group-vertical>.wfls-btn-group,.wfls-btn-group-vertical>.wfls-btn-group>.wfls-btn{display:block;float:none;width:100%;max-width:100%}.wfls-btn-group-vertical>.wfls-btn-group:before,.wfls-btn-group-vertical>.wfls-btn-group:after{content:" ";display:table}.wfls-btn-group-vertical>.wfls-btn-group:after{clear:both}.wfls-btn-group-vertical>.wfls-btn-group>.wfls-btn{float:none}.wfls-btn-group-vertical>.wfls-btn+.wfls-btn,.wfls-btn-group-vertical>.wfls-btn+.wfls-btn-group,.wfls-btn-group-vertical>.wfls-btn-group+.wfls-btn,.wfls-btn-group-vertical>.wfls-btn-group+.wfls-btn-group{margin-top:-1px;margin-left:0}.wfls-btn-group-vertical>.wfls-btn:not(:first-child):not(:last-child){border-radius:0}.wfls-btn-group-vertical>.wfls-btn:first-child:not(:last-child){-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group-vertical>.wfls-btn:last-child:not(:first-child){-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.wfls-btn-group-vertical>.wfls-btn-group:not(:first-child):not(:last-child)>.wfls-btn{border-radius:0}.wfls-btn-group-vertical>.wfls-btn-group:first-child:not(:last-child)>.wfls-btn:last-child,.wfls-btn-group-vertical>.wfls-btn-group:first-child:not(:last-child)>.wfls-dropdown-toggle{-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group-vertical>.wfls-btn-group:last-child:not(:first-child)>.wfls-btn:first-child{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0}.wfls-btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.wfls-btn-group-justified>.wfls-btn,.wfls-btn-group-justified>.wfls-btn-group{float:none;display:table-cell;width:1%}.wfls-btn-group-justified>.wfls-btn-group .wfls-btn{width:100%}.wfls-btn-group-justified>.wfls-btn-group .wfls-dropdown-menu{left:auto}[data-toggle="buttons"]>.wfls-btn input[type="radio"],[data-toggle="buttons"]>.wfls-btn input[type="checkbox"],[data-toggle="buttons"]>.wfls-btn-group>.wfls-btn input[type="radio"],[data-toggle="buttons"]>.wfls-btn-group>.wfls-btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.wfls-pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.wfls-pagination>li{display:inline}.wfls-pagination>li>a,.wfls-pagination>li>span{position:relative;float:left;padding:.5rem 1.25rem;line-height:1.42857;text-decoration:none;color:#00709e;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.wfls-pagination>li:first-child>a,.wfls-pagination>li:first-child>span{margin-left:0;-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.wfls-pagination>li:last-child>a,.wfls-pagination>li:last-child>span{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.wfls-pagination>li>a:hover,.wfls-pagination>li>a:focus,.wfls-pagination>li>span:hover,.wfls-pagination>li>span:focus{z-index:2;color:#003a52;background-color:#e2e2e2;border-color:#ddd}.wfls-pagination>.wfls-active>a,.wfls-pagination>.wfls-active>a:hover,.wfls-pagination>.wfls-active>a:focus,.wfls-pagination>.wfls-active>span,.wfls-pagination>.wfls-active>span:hover,.wfls-pagination>.wfls-active>span:focus{z-index:3;color:#fff;background-color:#00709e;border-color:#00709e;cursor:default}.wfls-pagination>.wfls-disabled>span,.wfls-pagination>.wfls-disabled>span:hover,.wfls-pagination>.wfls-disabled>span:focus,.wfls-pagination>.wfls-disabled>a,.wfls-pagination>.wfls-disabled>a:hover,.wfls-pagination>.wfls-disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.wfls-pagination-lg>li>a,.wfls-pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.33333}.wfls-pagination-lg>li:first-child>a,.wfls-pagination-lg>li:first-child>span{-moz-border-radius-topleft:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px}.wfls-pagination-lg>li:last-child>a,.wfls-pagination-lg>li:last-child>span{-moz-border-radius-topright:6px;-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-moz-border-radius-bottomright:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px}.wfls-pagination-sm>li>a,.wfls-pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.wfls-pagination-sm>li:first-child>a,.wfls-pagination-sm>li:first-child>span{-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px}.wfls-pagination-sm>li:last-child>a,.wfls-pagination-sm>li:last-child>span{-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-moz-border-radius-bottomright:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}#wfls-notices{margin-top:15px}#wfls-notices .wfls-admin-notice{margin-left:0px;margin-right:0px}.wfls-success-text,.wfls-notice-text{display:inline-block;vertical-align:middle;line-height:1.3;font-size:16px;font-weight:bold;font-style:italic}.wfls-notice{margin:12px 0;padding:8px;background-color:#ffffe0;border:1px solid #ffd975;border-width:1px 1px 1px 10px}.wfls-notice-text{color:#6d798c}.wfls-success{margin:12px 0;padding:8px;background-color:#ffffff;border:1px solid #16bc9b;border-width:1px 1px 1px 10px}.wfls-success-text{color:#11967a}.wfls-premium-callout{border:1px solid #dfdfdf;background-color:#ffffff;padding:16px;margin:20px 0 0;text-align:center}.wfls-premium-callout ul{margin:8px 0;padding:0 0 0 15px}.wfls-premium-callout ul li{list-style-type:disc;margin:0;padding:0}.wfls-premium-callout .center{text-align:center;margin:0}.wfls-premium-callout .button-primary{text-align:center;text-transform:uppercase;font-weight:bold;background-color:#00709e}#toplevel_page_WFLS .wp-menu-image img{max-width:16px;max-height:16px}
css/admin.1559237323.css ADDED
@@ -0,0 +1 @@
 
1
+ .wfls-clearfix:before,.wfls-clearfix:after{content:" ";display:table}.wfls-clearfix:after{clear:both}.wfls-btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;text-transform:uppercase;padding:.4rem 1rem;font-size:.875rem;line-height:1.3125rem;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media (min-width: 768px){.wfls-btn{padding:.5rem 1.25rem;font-size:.875rem;line-height:1.3125rem;border-radius:4px}}.wfls-btn:focus,.wfls-btn.wfls-focus,.wfls-btn:active:focus,.wfls-btn:active.wfls-focus,.wfls-btn.wfls-active:focus,.wfls-btn.wfls-active.wfls-focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.wfls-btn:hover,.wfls-btn:focus,.wfls-btn.wfls-focus{color:#00709e;text-decoration:none !important}.wfls-btn:active,.wfls-btn.wfls-active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.wfls-btn.wfls-disabled,.wfls-btn[disabled],.wfls-btn[readonly],fieldset[disabled] .wfls-btn{cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none}a.wfls-btn{text-decoration:none}a.wfls-btn.wfls-disabled,fieldset[disabled] a.wfls-btn{cursor:not-allowed;pointer-events:none}.wfls-btn-default{color:#00709e;background-color:#fff;border-color:#00709e}.wfls-btn-default:focus,.wfls-btn-default.focus{color:#00709e;background-color:#e6e6e6;border-color:#00161f}.wfls-btn-default:hover{color:#00709e;background-color:#e6e6e6;border-color:#004561}.wfls-btn-default:active,.wfls-btn-default.active,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle{color:#00709e;background-color:#e6e6e6;border-color:#004561}.wfls-btn-default:active:hover,.wfls-btn-default:active:focus,.wfls-btn-default:active.focus,.wfls-btn-default.active:hover,.wfls-btn-default.active:focus,.wfls-btn-default.active.focus,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle.focus{color:#00709e;background-color:#d4d4d4;border-color:#00161f}.wfls-btn-default:active,.wfls-btn-default.wfls-active,.wfls-open>.wfls-btn-default.wfls-dropdown-toggle{background-image:none}.wfls-btn-default.wfls-disabled,.wfls-btn-default[disabled],.wfls-btn-default[readonly],fieldset[disabled] .wfls-btn-default{color:#777;background-color:#fff;border-color:#e2e2e2;cursor:not-allowed;opacity:0.75}.wfls-btn-default.wfls-disabled:hover,.wfls-btn-default.wfls-disabled:focus,.wfls-btn-default.wfls-disabled.wfls-focus,.wfls-btn-default[disabled]:hover,.wfls-btn-default[disabled]:focus,.wfls-btn-default[disabled].wfls-focus,.wfls-btn-default[readonly]:hover,.wfls-btn-default[readonly]:focus,.wfls-btn-default[readonly].wfls-focus,fieldset[disabled] .wfls-btn-default:hover,fieldset[disabled] .wfls-btn-default:focus,fieldset[disabled] .wfls-btn-default.wfls-focus{background-color:#fff;border-color:#00709e}.wfls-btn-default .wfls-badge{color:#fff;background-color:#00709e}.wfls-btn-primary{color:#fff;background-color:#00709e;border-color:#005e85}.wfls-btn-primary:focus,.wfls-btn-primary.focus{color:#fff;background-color:#004c6b;border-color:#000405}.wfls-btn-primary:hover{color:#fff;background-color:#004c6b;border-color:#003347}.wfls-btn-primary:active,.wfls-btn-primary.active,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle{color:#fff;background-color:#004c6b;border-color:#003347}.wfls-btn-primary:active:hover,.wfls-btn-primary:active:focus,.wfls-btn-primary:active.focus,.wfls-btn-primary.active:hover,.wfls-btn-primary.active:focus,.wfls-btn-primary.active.focus,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle.focus{color:#fff;background-color:#003347;border-color:#000405}.wfls-btn-primary:active,.wfls-btn-primary.wfls-active,.wfls-open>.wfls-btn-primary.wfls-dropdown-toggle{background-image:none}.wfls-btn-primary.wfls-disabled,.wfls-btn-primary[disabled],.wfls-btn-primary[readonly],fieldset[disabled] .wfls-btn-primary{color:#fff;background-color:#59a2c0;border-color:#5996b0;cursor:not-allowed;opacity:0.75}.wfls-btn-primary.wfls-disabled:hover,.wfls-btn-primary.wfls-disabled:focus,.wfls-btn-primary.wfls-disabled.wfls-focus,.wfls-btn-primary[disabled]:hover,.wfls-btn-primary[disabled]:focus,.wfls-btn-primary[disabled].wfls-focus,.wfls-btn-primary[readonly]:hover,.wfls-btn-primary[readonly]:focus,.wfls-btn-primary[readonly].wfls-focus,fieldset[disabled] .wfls-btn-primary:hover,fieldset[disabled] .wfls-btn-primary:focus,fieldset[disabled] .wfls-btn-primary.wfls-focus{background-color:#00709e;border-color:#005e85}.wfls-btn-primary .wfls-badge{color:#00709e;background-color:#fff}.wfls-btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.wfls-btn-success:focus,.wfls-btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.wfls-btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.wfls-btn-success:active,.wfls-btn-success.active,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle{color:#fff;background-color:#449d44;border-color:#398439}.wfls-btn-success:active:hover,.wfls-btn-success:active:focus,.wfls-btn-success:active.focus,.wfls-btn-success.active:hover,.wfls-btn-success.active:focus,.wfls-btn-success.active.focus,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle.focus{color:#fff;background-color:#398439;border-color:#255625}.wfls-btn-success:active,.wfls-btn-success.wfls-active,.wfls-open>.wfls-btn-success.wfls-dropdown-toggle{background-image:none}.wfls-btn-success.wfls-disabled,.wfls-btn-success[disabled],.wfls-btn-success[readonly],fieldset[disabled] .wfls-btn-success{color:#fff;background-color:#95d195;border-color:#8bca8b;cursor:not-allowed;opacity:0.75}.wfls-btn-success.wfls-disabled:hover,.wfls-btn-success.wfls-disabled:focus,.wfls-btn-success.wfls-disabled.wfls-focus,.wfls-btn-success[disabled]:hover,.wfls-btn-success[disabled]:focus,.wfls-btn-success[disabled].wfls-focus,.wfls-btn-success[readonly]:hover,.wfls-btn-success[readonly]:focus,.wfls-btn-success[readonly].wfls-focus,fieldset[disabled] .wfls-btn-success:hover,fieldset[disabled] .wfls-btn-success:focus,fieldset[disabled] .wfls-btn-success.wfls-focus{background-color:#5cb85c;border-color:#4cae4c}.wfls-btn-success .wfls-badge{color:#5cb85c;background-color:#fff}.wfls-btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.wfls-btn-info:focus,.wfls-btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.wfls-btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.wfls-btn-info:active,.wfls-btn-info.active,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#269abc}.wfls-btn-info:active:hover,.wfls-btn-info:active:focus,.wfls-btn-info:active.focus,.wfls-btn-info.active:hover,.wfls-btn-info.active:focus,.wfls-btn-info.active.focus,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.wfls-btn-info:active,.wfls-btn-info.wfls-active,.wfls-open>.wfls-btn-info.wfls-dropdown-toggle{background-image:none}.wfls-btn-info.wfls-disabled,.wfls-btn-info[disabled],.wfls-btn-info[readonly],fieldset[disabled] .wfls-btn-info{color:#fff;background-color:#94d6ea;border-color:#87d1e7;cursor:not-allowed;opacity:0.75}.wfls-btn-info.wfls-disabled:hover,.wfls-btn-info.wfls-disabled:focus,.wfls-btn-info.wfls-disabled.wfls-focus,.wfls-btn-info[disabled]:hover,.wfls-btn-info[disabled]:focus,.wfls-btn-info[disabled].wfls-focus,.wfls-btn-info[readonly]:hover,.wfls-btn-info[readonly]:focus,.wfls-btn-info[readonly].wfls-focus,fieldset[disabled] .wfls-btn-info:hover,fieldset[disabled] .wfls-btn-info:focus,fieldset[disabled] .wfls-btn-info.wfls-focus{background-color:#5bc0de;border-color:#46b8da}.wfls-btn-info .wfls-badge{color:#5bc0de;background-color:#fff}.wfls-btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.wfls-btn-warning:focus,.wfls-btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.wfls-btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.wfls-btn-warning:active,.wfls-btn-warning.active,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle{color:#fff;background-color:#ec971f;border-color:#d58512}.wfls-btn-warning:active:hover,.wfls-btn-warning:active:focus,.wfls-btn-warning:active.focus,.wfls-btn-warning.active:hover,.wfls-btn-warning.active:focus,.wfls-btn-warning.active.focus,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.wfls-btn-warning:active,.wfls-btn-warning.wfls-active,.wfls-open>.wfls-btn-warning.wfls-dropdown-toggle{background-image:none}.wfls-btn-warning.wfls-disabled,.wfls-btn-warning[disabled],.wfls-btn-warning[readonly],fieldset[disabled] .wfls-btn-warning{color:#fff;background-color:#f5ca8c;border-color:#f4c37c;cursor:not-allowed;opacity:0.75}.wfls-btn-warning.wfls-disabled:hover,.wfls-btn-warning.wfls-disabled:focus,.wfls-btn-warning.wfls-disabled.wfls-focus,.wfls-btn-warning[disabled]:hover,.wfls-btn-warning[disabled]:focus,.wfls-btn-warning[disabled].wfls-focus,.wfls-btn-warning[readonly]:hover,.wfls-btn-warning[readonly]:focus,.wfls-btn-warning[readonly].wfls-focus,fieldset[disabled] .wfls-btn-warning:hover,fieldset[disabled] .wfls-btn-warning:focus,fieldset[disabled] .wfls-btn-warning.wfls-focus{background-color:#f0ad4e;border-color:#eea236}.wfls-btn-warning .wfls-badge{color:#f0ad4e;background-color:#fff}.wfls-btn-danger{color:#fff;background-color:#930000;border-color:#7a0000}.wfls-btn-danger:focus,.wfls-btn-danger.focus{color:#fff;background-color:#600000;border-color:#000}.wfls-btn-danger:hover{color:#fff;background-color:#600000;border-color:#3c0000}.wfls-btn-danger:active,.wfls-btn-danger.active,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle{color:#fff;background-color:#600000;border-color:#3c0000}.wfls-btn-danger:active:hover,.wfls-btn-danger:active:focus,.wfls-btn-danger:active.focus,.wfls-btn-danger.active:hover,.wfls-btn-danger.active:focus,.wfls-btn-danger.active.focus,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle:hover,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle:focus,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle.focus{color:#fff;background-color:#3c0000;border-color:#000}.wfls-btn-danger:active,.wfls-btn-danger.wfls-active,.wfls-open>.wfls-btn-danger.wfls-dropdown-toggle{background-image:none}.wfls-btn-danger.wfls-disabled,.wfls-btn-danger[disabled],.wfls-btn-danger[readonly],fieldset[disabled] .wfls-btn-danger{color:#fff;background-color:#b95959;border-color:#a95959;cursor:not-allowed;opacity:0.75}.wfls-btn-danger.wfls-disabled:hover,.wfls-btn-danger.wfls-disabled:focus,.wfls-btn-danger.wfls-disabled.wfls-focus,.wfls-btn-danger[disabled]:hover,.wfls-btn-danger[disabled]:focus,.wfls-btn-danger[disabled].wfls-focus,.wfls-btn-danger[readonly]:hover,.wfls-btn-danger[readonly]:focus,.wfls-btn-danger[readonly].wfls-focus,fieldset[disabled] .wfls-btn-danger:hover,fieldset[disabled] .wfls-btn-danger:focus,fieldset[disabled] .wfls-btn-danger.wfls-focus{background-color:#930000;border-color:#7a0000}.wfls-btn-danger .wfls-badge{color:#930000;background-color:#fff}.wfls-btn-callout{font-weight:600;text-transform:uppercase}.wfls-btn-callout-subtle{font-weight:400;text-transform:uppercase}.wfls-btn-link{color:#00709e;font-weight:normal;border-radius:0}.wfls-btn-link,.wfls-btn-link:active,.wfls-btn-link.wfls-active,.wfls-btn-link[disabled],fieldset[disabled] .wfls-btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.wfls-btn-link,.wfls-btn-link:hover,.wfls-btn-link:focus,.wfls-btn-link:active{border-color:transparent}.wfls-btn-link:hover,.wfls-btn-link:focus{color:#003a52;text-decoration:underline;background-color:transparent}.wfls-btn-link[disabled]:hover,.wfls-btn-link[disabled]:focus,fieldset[disabled] .wfls-btn-link:hover,fieldset[disabled] .wfls-btn-link:focus{color:#777;text-decoration:none}.wfls-btn-lg,.wfls-btn-group-lg>.wfls-btn{padding:10px 16px;font-size:18px;line-height:1.33333;border-radius:6px}.wfls-btn-sm,.wfls-btn-group-sm>.wfls-btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.wfls-btn-xs,.wfls-btn-group-xs>.wfls-btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.wfls-btn-block{display:block;width:100%}.wfls-btn-block+.wfls-btn-block{margin-top:5px}input[type="submit"].wfls-btn-block,input[type="reset"].wfls-btn-block,input[type="button"].wfls-btn-block{width:100%}.wfls-btn-group,.wfls-btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.wfls-btn-group>.wfls-btn,.wfls-btn-group-vertical>.wfls-btn{position:relative;float:left}.wfls-btn-group>.wfls-btn:hover,.wfls-btn-group>.wfls-btn:focus,.wfls-btn-group>.wfls-btn:active,.wfls-btn-group>.wfls-btn.wfls-active,.wfls-btn-group-vertical>.wfls-btn:hover,.wfls-btn-group-vertical>.wfls-btn:focus,.wfls-btn-group-vertical>.wfls-btn:active,.wfls-btn-group-vertical>.wfls-btn.wfls-active{z-index:2}.wfls-btn-group .wfls-btn+.wfls-btn,.wfls-btn-group .wfls-btn+.wfls-btn-group,.wfls-btn-group .wfls-btn-group+.wfls-btn,.wfls-btn-group .wfls-btn-group+.wfls-btn-group{margin-left:-1px}.wfls-btn-toolbar{margin-left:-5px}.wfls-btn-toolbar:before,.wfls-btn-toolbar:after{content:" ";display:table}.wfls-btn-toolbar:after{clear:both}.wfls-btn-toolbar .wfls-btn,.wfls-btn-toolbar .wfls-btn-group,.wfls-btn-toolbar .wfls-input-group{float:left}.wfls-btn-toolbar>.wfls-btn,.wfls-btn-toolbar>.wfls-btn-group,.wfls-btn-toolbar>.wfls-input-group{margin-left:5px}.wfls-btn-group>.wfls-btn:not(:first-child):not(:last-child):not(.wfls-dropdown-toggle){border-radius:0}.wfls-btn-group>.wfls-btn:first-child{margin-left:0}.wfls-btn-group>.wfls-btn:first-child:not(:last-child):not(.wfls-dropdown-toggle){-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group>.wfls-btn:last-child:not(:first-child),.wfls-btn-group>.wfls-dropdown-toggle:not(:first-child){-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.wfls-btn-group>.wfls-btn-group{float:left}.wfls-btn-group>.wfls-btn-group:not(:first-child):not(:last-child)>.wfls-btn{border-radius:0}.wfls-btn-group>.wfls-btn-group:first-child:not(:last-child)>.wfls-btn:last-child,.wfls-btn-group>.wfls-btn-group:first-child:not(:last-child)>.wfls-dropdown-toggle{-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group>.wfls-btn-group:last-child:not(:first-child)>.wfls-btn:first-child{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0}.wfls-btn-group .wfls-dropdown-toggle:active,.wfls-btn-group.wfls-open .wfls-dropdown-toggle{outline:0}.wfls-btn-group>.wfls-btn+.wfls-dropdown-toggle{padding-left:8px;padding-right:8px}.wfls-btn-group>.wfls-btn-lg+.wfls-dropdown-toggle,.wfls-btn-group-lg.wfls-btn-group>.wfls-btn+.wfls-dropdown-toggle{padding-left:12px;padding-right:12px}.wfls-btn-group.open .wfls-dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.wfls-btn-group.open .wfls-dropdown-toggle.wfls-btn-link{-webkit-box-shadow:none;box-shadow:none}.wfls-btn .wfls-caret{margin-left:0}.wfls-btn-lg .wfls-caret,.wfls-btn-group-lg>.wfls-btn .wfls-caret{border-width:5px 5px 0;border-bottom-width:0}.wfls-dropup .wfls-btn-lg .wfls-caret,.wfls-dropup .wfls-btn-group-lg>.wfls-btn .wfls-caret{border-width:0 5px 5px}.wfls-btn-group-vertical>.wfls-btn,.wfls-btn-group-vertical>.wfls-btn-group,.wfls-btn-group-vertical>.wfls-btn-group>.wfls-btn{display:block;float:none;width:100%;max-width:100%}.wfls-btn-group-vertical>.wfls-btn-group:before,.wfls-btn-group-vertical>.wfls-btn-group:after{content:" ";display:table}.wfls-btn-group-vertical>.wfls-btn-group:after{clear:both}.wfls-btn-group-vertical>.wfls-btn-group>.wfls-btn{float:none}.wfls-btn-group-vertical>.wfls-btn+.wfls-btn,.wfls-btn-group-vertical>.wfls-btn+.wfls-btn-group,.wfls-btn-group-vertical>.wfls-btn-group+.wfls-btn,.wfls-btn-group-vertical>.wfls-btn-group+.wfls-btn-group{margin-top:-1px;margin-left:0}.wfls-btn-group-vertical>.wfls-btn:not(:first-child):not(:last-child){border-radius:0}.wfls-btn-group-vertical>.wfls-btn:first-child:not(:last-child){-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group-vertical>.wfls-btn:last-child:not(:first-child){-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.wfls-btn-group-vertical>.wfls-btn-group:not(:first-child):not(:last-child)>.wfls-btn{border-radius:0}.wfls-btn-group-vertical>.wfls-btn-group:first-child:not(:last-child)>.wfls-btn:last-child,.wfls-btn-group-vertical>.wfls-btn-group:first-child:not(:last-child)>.wfls-dropdown-toggle{-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0}.wfls-btn-group-vertical>.wfls-btn-group:last-child:not(:first-child)>.wfls-btn:first-child{-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0}.wfls-btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.wfls-btn-group-justified>.wfls-btn,.wfls-btn-group-justified>.wfls-btn-group{float:none;display:table-cell;width:1%}.wfls-btn-group-justified>.wfls-btn-group .wfls-btn{width:100%}.wfls-btn-group-justified>.wfls-btn-group .wfls-dropdown-menu{left:auto}[data-toggle="buttons"]>.wfls-btn input[type="radio"],[data-toggle="buttons"]>.wfls-btn input[type="checkbox"],[data-toggle="buttons"]>.wfls-btn-group>.wfls-btn input[type="radio"],[data-toggle="buttons"]>.wfls-btn-group>.wfls-btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.wfls-pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.wfls-pagination>li{display:inline}.wfls-pagination>li>a,.wfls-pagination>li>span{position:relative;float:left;padding:.5rem 1.25rem;line-height:1.42857;text-decoration:none;color:#00709e;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.wfls-pagination>li:first-child>a,.wfls-pagination>li:first-child>span{margin-left:0;-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.wfls-pagination>li:last-child>a,.wfls-pagination>li:last-child>span{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.wfls-pagination>li>a:hover,.wfls-pagination>li>a:focus,.wfls-pagination>li>span:hover,.wfls-pagination>li>span:focus{z-index:2;color:#003a52;background-color:#e2e2e2;border-color:#ddd}.wfls-pagination>.wfls-active>a,.wfls-pagination>.wfls-active>a:hover,.wfls-pagination>.wfls-active>a:focus,.wfls-pagination>.wfls-active>span,.wfls-pagination>.wfls-active>span:hover,.wfls-pagination>.wfls-active>span:focus{z-index:3;color:#fff;background-color:#00709e;border-color:#00709e;cursor:default}.wfls-pagination>.wfls-disabled>span,.wfls-pagination>.wfls-disabled>span:hover,.wfls-pagination>.wfls-disabled>span:focus,.wfls-pagination>.wfls-disabled>a,.wfls-pagination>.wfls-disabled>a:hover,.wfls-pagination>.wfls-disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.wfls-pagination-lg>li>a,.wfls-pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.33333}.wfls-pagination-lg>li:first-child>a,.wfls-pagination-lg>li:first-child>span{-moz-border-radius-topleft:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px}.wfls-pagination-lg>li:last-child>a,.wfls-pagination-lg>li:last-child>span{-moz-border-radius-topright:6px;-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-moz-border-radius-bottomright:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px}.wfls-pagination-sm>li>a,.wfls-pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.wfls-pagination-sm>li:first-child>a,.wfls-pagination-sm>li:first-child>span{-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px}.wfls-pagination-sm>li:last-child>a,.wfls-pagination-sm>li:last-child>span{-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-moz-border-radius-bottomright:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}@-ms-viewport{width:device-width}.wfls-visible-xs{display:none !important}.wfls-visible-sm{display:none !important}.wfls-visible-md{display:none !important}.wfls-visible-lg{display:none !important}.wfls-visible-xs-block,.wfls-visible-xs-inline,.wfls-visible-xs-inline-block,.wfls-visible-sm-block,.wfls-visible-sm-inline,.wfls-visible-sm-inline-block,.wfls-visible-md-block,.wfls-visible-md-inline,.wfls-visible-md-inline-block,.wfls-visible-lg-block,.wfls-visible-lg-inline,.wfls-visible-lg-inline-block{display:none !important}@media (max-width: 767px){.wfls-visible-xs{display:block !important}table.wfls-visible-xs{display:table !important}tr.wfls-visible-xs{display:table-row !important}th.wfls-visible-xs,td.wfls-visible-xs{display:table-cell !important}}@media (max-width: 767px){.wfls-visible-xs-block{display:block !important}}@media (max-width: 767px){.wfls-visible-xs-inline{display:inline !important}}@media (max-width: 767px){.wfls-visible-xs-inline-block{display:inline-block !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-visible-sm{display:block !important}table.wfls-visible-sm{display:table !important}tr.wfls-visible-sm{display:table-row !important}th.wfls-visible-sm,td.wfls-visible-sm{display:table-cell !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-visible-sm-block{display:block !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-visible-sm-inline{display:inline !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-visible-sm-inline-block{display:inline-block !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-visible-md{display:block !important}table.wfls-visible-md{display:table !important}tr.wfls-visible-md{display:table-row !important}th.wfls-visible-md,td.wfls-visible-md{display:table-cell !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-visible-md-block{display:block !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-visible-md-inline{display:inline !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-visible-md-inline-block{display:inline-block !important}}@media (min-width: 1200px){.wfls-visible-lg{display:block !important}table.wfls-visible-lg{display:table !important}tr.wfls-visible-lg{display:table-row !important}th.wfls-visible-lg,td.wfls-visible-lg{display:table-cell !important}}@media (min-width: 1200px){.wfls-visible-lg-block{display:block !important}}@media (min-width: 1200px){.wfls-visible-lg-inline{display:inline !important}}@media (min-width: 1200px){.wfls-visible-lg-inline-block{display:inline-block !important}}@media (max-width: 767px){.wfls-hidden-xs{display:none !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-hidden-sm{display:none !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-hidden-md{display:none !important}}@media (min-width: 1200px){.wfls-hidden-lg{display:none !important}}.wfls-visible-print{display:none !important}@media print{.wfls-visible-print{display:block !important}table.wfls-visible-print{display:table !important}tr.wfls-visible-print{display:table-row !important}th.wfls-visible-print,td.wfls-visible-print{display:table-cell !important}}.wfls-visible-print-block{display:none !important}@media print{.wfls-visible-print-block{display:block !important}}.wfls-visible-print-inline{display:none !important}@media print{.wfls-visible-print-inline{display:inline !important}}.wfls-visible-print-inline-block{display:none !important}@media print{.wfls-visible-print-inline-block{display:inline-block !important}}@media print{.wfls-hidden-print{display:none !important}}.wfls-container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.wfls-container:before,.wfls-container:after{content:" ";display:table}.wfls-container:after{clear:both}@media (min-width: 768px){.wfls-container{width:750px}}@media (min-width: 992px){.wfls-container{width:970px}}@media (min-width: 1200px){.wfls-container{width:1170px}}.wfls-container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.wfls-container-fluid:before,.wfls-container-fluid:after{content:" ";display:table}.wfls-container-fluid:after{clear:both}.wfls-row{margin-left:-15px;margin-right:-15px}.wfls-row:before,.wfls-row:after{content:" ";display:table}.wfls-row:after{clear:both}.wfls-col-xs-1,.wfls-col-sm-1,.wfls-col-md-1,.wfls-col-lg-1,.wfls-col-xs-2,.wfls-col-sm-2,.wfls-col-md-2,.wfls-col-lg-2,.wfls-col-xs-3,.wfls-col-sm-3,.wfls-col-md-3,.wfls-col-lg-3,.wfls-col-xs-4,.wfls-col-sm-4,.wfls-col-md-4,.wfls-col-lg-4,.wfls-col-xs-5,.wfls-col-sm-5,.wfls-col-md-5,.wfls-col-lg-5,.wfls-col-xs-6,.wfls-col-sm-6,.wfls-col-md-6,.wfls-col-lg-6,.wfls-col-xs-7,.wfls-col-sm-7,.wfls-col-md-7,.wfls-col-lg-7,.wfls-col-xs-8,.wfls-col-sm-8,.wfls-col-md-8,.wfls-col-lg-8,.wfls-col-xs-9,.wfls-col-sm-9,.wfls-col-md-9,.wfls-col-lg-9,.wfls-col-xs-10,.wfls-col-sm-10,.wfls-col-md-10,.wfls-col-lg-10,.wfls-col-xs-11,.wfls-col-sm-11,.wfls-col-md-11,.wfls-col-lg-11,.wfls-col-xs-12,.wfls-col-sm-12,.wfls-col-md-12,.wfls-col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px;box-sizing:border-box}.wfls-col-xs-1,.wfls-col-xs-2,.wfls-col-xs-3,.wfls-col-xs-4,.wfls-col-xs-5,.wfls-col-xs-6,.wfls-col-xs-7,.wfls-col-xs-8,.wfls-col-xs-9,.wfls-col-xs-10,.wfls-col-xs-11,.wfls-col-xs-12{float:left}.wfls-col-xs-1{width:8.33333%}.wfls-col-xs-2{width:16.66667%}.wfls-col-xs-3{width:25%}.wfls-col-xs-4{width:33.33333%}.wfls-col-xs-5{width:41.66667%}.wfls-col-xs-6{width:50%}.wfls-col-xs-7{width:58.33333%}.wfls-col-xs-8{width:66.66667%}.wfls-col-xs-9{width:75%}.wfls-col-xs-10{width:83.33333%}.wfls-col-xs-11{width:91.66667%}.wfls-col-xs-12{width:100%}.wfls-col-xs-pull-0{right:auto}.wfls-col-xs-pull-1{right:8.33333%}.wfls-col-xs-pull-2{right:16.66667%}.wfls-col-xs-pull-3{right:25%}.wfls-col-xs-pull-4{right:33.33333%}.wfls-col-xs-pull-5{right:41.66667%}.wfls-col-xs-pull-6{right:50%}.wfls-col-xs-pull-7{right:58.33333%}.wfls-col-xs-pull-8{right:66.66667%}.wfls-col-xs-pull-9{right:75%}.wfls-col-xs-pull-10{right:83.33333%}.wfls-col-xs-pull-11{right:91.66667%}.wfls-col-xs-pull-12{right:100%}.wfls-col-xs-push-0{left:auto}.wfls-col-xs-push-1{left:8.33333%}.wfls-col-xs-push-2{left:16.66667%}.wfls-col-xs-push-3{left:25%}.wfls-col-xs-push-4{left:33.33333%}.wfls-col-xs-push-5{left:41.66667%}.wfls-col-xs-push-6{left:50%}.wfls-col-xs-push-7{left:58.33333%}.wfls-col-xs-push-8{left:66.66667%}.wfls-col-xs-push-9{left:75%}.wfls-col-xs-push-10{left:83.33333%}.wfls-col-xs-push-11{left:91.66667%}.wfls-col-xs-push-12{left:100%}.wfls-col-xs-offset-0{margin-left:0%}.wfls-col-xs-offset-1{margin-left:8.33333%}.wfls-col-xs-offset-2{margin-left:16.66667%}.wfls-col-xs-offset-3{margin-left:25%}.wfls-col-xs-offset-4{margin-left:33.33333%}.wfls-col-xs-offset-5{margin-left:41.66667%}.wfls-col-xs-offset-6{margin-left:50%}.wfls-col-xs-offset-7{margin-left:58.33333%}.wfls-col-xs-offset-8{margin-left:66.66667%}.wfls-col-xs-offset-9{margin-left:75%}.wfls-col-xs-offset-10{margin-left:83.33333%}.wfls-col-xs-offset-11{margin-left:91.66667%}.wfls-col-xs-offset-12{margin-left:100%}.wfls-col-xs-half-padding-left{padding-left:8px}.wfls-col-xs-half-padding-right{padding-right:7px}@media (min-width: 768px){.wfls-col-sm-1,.wfls-col-sm-2,.wfls-col-sm-3,.wfls-col-sm-4,.wfls-col-sm-5,.wfls-col-sm-6,.wfls-col-sm-7,.wfls-col-sm-8,.wfls-col-sm-9,.wfls-col-sm-10,.wfls-col-sm-11,.wfls-col-sm-12{float:left}.wfls-col-sm-1{width:8.33333%}.wfls-col-sm-2{width:16.66667%}.wfls-col-sm-3{width:25%}.wfls-col-sm-4{width:33.33333%}.wfls-col-sm-5{width:41.66667%}.wfls-col-sm-6{width:50%}.wfls-col-sm-7{width:58.33333%}.wfls-col-sm-8{width:66.66667%}.wfls-col-sm-9{width:75%}.wfls-col-sm-10{width:83.33333%}.wfls-col-sm-11{width:91.66667%}.wfls-col-sm-12{width:100%}.wfls-col-sm-pull-0{right:auto}.wfls-col-sm-pull-1{right:8.33333%}.wfls-col-sm-pull-2{right:16.66667%}.wfls-col-sm-pull-3{right:25%}.wfls-col-sm-pull-4{right:33.33333%}.wfls-col-sm-pull-5{right:41.66667%}.wfls-col-sm-pull-6{right:50%}.wfls-col-sm-pull-7{right:58.33333%}.wfls-col-sm-pull-8{right:66.66667%}.wfls-col-sm-pull-9{right:75%}.wfls-col-sm-pull-10{right:83.33333%}.wfls-col-sm-pull-11{right:91.66667%}.wfls-col-sm-pull-12{right:100%}.wfls-col-sm-push-0{left:auto}.wfls-col-sm-push-1{left:8.33333%}.wfls-col-sm-push-2{left:16.66667%}.wfls-col-sm-push-3{left:25%}.wfls-col-sm-push-4{left:33.33333%}.wfls-col-sm-push-5{left:41.66667%}.wfls-col-sm-push-6{left:50%}.wfls-col-sm-push-7{left:58.33333%}.wfls-col-sm-push-8{left:66.66667%}.wfls-col-sm-push-9{left:75%}.wfls-col-sm-push-10{left:83.33333%}.wfls-col-sm-push-11{left:91.66667%}.wfls-col-sm-push-12{left:100%}.wfls-col-sm-offset-0{margin-left:0%}.wfls-col-sm-offset-1{margin-left:8.33333%}.wfls-col-sm-offset-2{margin-left:16.66667%}.wfls-col-sm-offset-3{margin-left:25%}.wfls-col-sm-offset-4{margin-left:33.33333%}.wfls-col-sm-offset-5{margin-left:41.66667%}.wfls-col-sm-offset-6{margin-left:50%}.wfls-col-sm-offset-7{margin-left:58.33333%}.wfls-col-sm-offset-8{margin-left:66.66667%}.wfls-col-sm-offset-9{margin-left:75%}.wfls-col-sm-offset-10{margin-left:83.33333%}.wfls-col-sm-offset-11{margin-left:91.66667%}.wfls-col-sm-offset-12{margin-left:100%}.wfls-col-sm-half-padding-left{padding-left:8px}.wfls-col-sm-half-padding-right{padding-right:7px}}@media (min-width: 992px){.wfls-col-md-1,.wfls-col-md-2,.wfls-col-md-3,.wfls-col-md-4,.wfls-col-md-5,.wfls-col-md-6,.wfls-col-md-7,.wfls-col-md-8,.wfls-col-md-9,.wfls-col-md-10,.wfls-col-md-11,.wfls-col-md-12{float:left}.wfls-col-md-1{width:8.33333%}.wfls-col-md-2{width:16.66667%}.wfls-col-md-3{width:25%}.wfls-col-md-4{width:33.33333%}.wfls-col-md-5{width:41.66667%}.wfls-col-md-6{width:50%}.wfls-col-md-7{width:58.33333%}.wfls-col-md-8{width:66.66667%}.wfls-col-md-9{width:75%}.wfls-col-md-10{width:83.33333%}.wfls-col-md-11{width:91.66667%}.wfls-col-md-12{width:100%}.wfls-col-md-pull-0{right:auto}.wfls-col-md-pull-1{right:8.33333%}.wfls-col-md-pull-2{right:16.66667%}.wfls-col-md-pull-3{right:25%}.wfls-col-md-pull-4{right:33.33333%}.wfls-col-md-pull-5{right:41.66667%}.wfls-col-md-pull-6{right:50%}.wfls-col-md-pull-7{right:58.33333%}.wfls-col-md-pull-8{right:66.66667%}.wfls-col-md-pull-9{right:75%}.wfls-col-md-pull-10{right:83.33333%}.wfls-col-md-pull-11{right:91.66667%}.wfls-col-md-pull-12{right:100%}.wfls-col-md-push-0{left:auto}.wfls-col-md-push-1{left:8.33333%}.wfls-col-md-push-2{left:16.66667%}.wfls-col-md-push-3{left:25%}.wfls-col-md-push-4{left:33.33333%}.wfls-col-md-push-5{left:41.66667%}.wfls-col-md-push-6{left:50%}.wfls-col-md-push-7{left:58.33333%}.wfls-col-md-push-8{left:66.66667%}.wfls-col-md-push-9{left:75%}.wfls-col-md-push-10{left:83.33333%}.wfls-col-md-push-11{left:91.66667%}.wfls-col-md-push-12{left:100%}.wfls-col-md-offset-0{margin-left:0%}.wfls-col-md-offset-1{margin-left:8.33333%}.wfls-col-md-offset-2{margin-left:16.66667%}.wfls-col-md-offset-3{margin-left:25%}.wfls-col-md-offset-4{margin-left:33.33333%}.wfls-col-md-offset-5{margin-left:41.66667%}.wfls-col-md-offset-6{margin-left:50%}.wfls-col-md-offset-7{margin-left:58.33333%}.wfls-col-md-offset-8{margin-left:66.66667%}.wfls-col-md-offset-9{margin-left:75%}.wfls-col-md-offset-10{margin-left:83.33333%}.wfls-col-md-offset-11{margin-left:91.66667%}.wfls-col-md-offset-12{margin-left:100%}.wfls-col-md-half-padding-left{padding-left:8px}.wfls-col-md-half-padding-right{padding-right:7px}}@media (min-width: 1200px){.wfls-col-lg-1,.wfls-col-lg-2,.wfls-col-lg-3,.wfls-col-lg-4,.wfls-col-lg-5,.wfls-col-lg-6,.wfls-col-lg-7,.wfls-col-lg-8,.wfls-col-lg-9,.wfls-col-lg-10,.wfls-col-lg-11,.wfls-col-lg-12{float:left}.wfls-col-lg-1{width:8.33333%}.wfls-col-lg-2{width:16.66667%}.wfls-col-lg-3{width:25%}.wfls-col-lg-4{width:33.33333%}.wfls-col-lg-5{width:41.66667%}.wfls-col-lg-6{width:50%}.wfls-col-lg-7{width:58.33333%}.wfls-col-lg-8{width:66.66667%}.wfls-col-lg-9{width:75%}.wfls-col-lg-10{width:83.33333%}.wfls-col-lg-11{width:91.66667%}.wfls-col-lg-12{width:100%}.wfls-col-lg-pull-0{right:auto}.wfls-col-lg-pull-1{right:8.33333%}.wfls-col-lg-pull-2{right:16.66667%}.wfls-col-lg-pull-3{right:25%}.wfls-col-lg-pull-4{right:33.33333%}.wfls-col-lg-pull-5{right:41.66667%}.wfls-col-lg-pull-6{right:50%}.wfls-col-lg-pull-7{right:58.33333%}.wfls-col-lg-pull-8{right:66.66667%}.wfls-col-lg-pull-9{right:75%}.wfls-col-lg-pull-10{right:83.33333%}.wfls-col-lg-pull-11{right:91.66667%}.wfls-col-lg-pull-12{right:100%}.wfls-col-lg-push-0{left:auto}.wfls-col-lg-push-1{left:8.33333%}.wfls-col-lg-push-2{left:16.66667%}.wfls-col-lg-push-3{left:25%}.wfls-col-lg-push-4{left:33.33333%}.wfls-col-lg-push-5{left:41.66667%}.wfls-col-lg-push-6{left:50%}.wfls-col-lg-push-7{left:58.33333%}.wfls-col-lg-push-8{left:66.66667%}.wfls-col-lg-push-9{left:75%}.wfls-col-lg-push-10{left:83.33333%}.wfls-col-lg-push-11{left:91.66667%}.wfls-col-lg-push-12{left:100%}.wfls-col-lg-offset-0{margin-left:0%}.wfls-col-lg-offset-1{margin-left:8.33333%}.wfls-col-lg-offset-2{margin-left:16.66667%}.wfls-col-lg-offset-3{margin-left:25%}.wfls-col-lg-offset-4{margin-left:33.33333%}.wfls-col-lg-offset-5{margin-left:41.66667%}.wfls-col-lg-offset-6{margin-left:50%}.wfls-col-lg-offset-7{margin-left:58.33333%}.wfls-col-lg-offset-8{margin-left:66.66667%}.wfls-col-lg-offset-9{margin-left:75%}.wfls-col-lg-offset-10{margin-left:83.33333%}.wfls-col-lg-offset-11{margin-left:91.66667%}.wfls-col-lg-offset-12{margin-left:100%}.wfls-col-lg-half-padding-left{padding-left:8px}.wfls-col-lg-half-padding-right{padding-right:7px}}hr.wfls-half{border:0 !important;border-bottom:1px solid #e4e4e4 !important;width:50%;margin:1.25rem auto}.wrap.wordfence-ls{direction:ltr}@media (min-width: 768px){.wrap.wordfence-ls{max-width:750px}}@media (min-width: 992px){.wrap.wordfence-ls{max-width:970px}}@media (min-width: 1200px){.wrap.wordfence-ls{max-width:1170px}}.wrap.wordfence-ls>.wfls-container-fluid{padding-left:0px;padding-right:0px}.wrap.wordfence-ls .button-primary{text-align:center;text-transform:uppercase;font-weight:bold;background-color:#00709e}.wrap.wordfence-ls a{text-decoration:none}.wrap.wordfence-ls a:hover{text-decoration:underline}.wrap.wordfence-ls a.wfls-btn:hover{text-decoration:none}.wrap.wordfence-ls p,.wrap.wordfence-ls td,.wrap.wordfence-ls li{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:.875rem;color:#2d2d2d;line-height:1.3125;font-weight:normal}.wrap.wordfence-ls p strong,.wrap.wordfence-ls td strong,.wrap.wordfence-ls li strong{font-weight:600}.wrap.wordfence-ls p em,.wrap.wordfence-ls td em,.wrap.wordfence-ls li em{font-weight:normal}.wrap.wordfence-ls h1,.wrap.wordfence-ls h2,.wrap.wordfence-ls h3,.wrap.wordfence-ls h4,.wrap.wordfence-ls h5,.wrap.wordfence-ls h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;color:#2d2d2d;font-weight:700}.wrap.wordfence-ls h2{font-size:1.3125rem;line-height:1.5}.wrap.wordfence-ls h3{font-size:1.125rem}.wrap.wordfence-ls h4{font-size:1rem}a{color:#00709e}.wfls-inline-help{color:#9f9fa0}.wfls-inline-help:hover{color:#00709e}.wordfenceWrap{margin:20px 0 0 20px}#wfHeading:after{content:'.';visibility:hidden;display:block;clear:both;height:0px}.wfls-header-icon{background-image:url(../img/header.svg);width:32px;height:32px;background-position:0 0;background-repeat:no-repeat;padding:0;margin:0 5px 0 0;float:left}a.wfhelp{margin:0 3px 0 3px;text-decoration:none;display:inline-block;vertical-align:middle;font:normal normal normal 14px/1 FontAwesome;text-rendering:auto;-webkit-font-smoothing:antialiased}a.wfhelp:before{content:'\f29c'}.wordfence .resulticon{display:block;float:left;width:16px;height:16px;background-position:0 0;background-repeat:no-repeat;border-width:0;padding:0;margin:0 3px 0 0;background-image:url(../img/icons/bullet_yellow.png)}.wordfenceBoldTD{font-weight:bold}.wfAjax24{display:none;width:24px;height:24px;background-image:url(../img/icons/ajax24.gif);margin:0;padding:0}div.wfLoadingWhite32{width:32px;height:32px;background-image:url(../img/icons/ajaxWhite32x32.gif);margin:0;padding:0}.wfTabsContainer{background-color:#FFF;overflow:hidden;border:1px solid #CCC;padding:15px;min-height:200px;-webkit-font-smoothing:antialiased}#wfTabs::after{content:".";display:block;height:0;width:0;line-height:0;clear:both;visibility:hidden}#wfTabs a{float:left;z-index:10;height:18px;margin:0 5px -1px 0;padding:5px 8px;border:1px solid #CCC;text-decoration:none;background-color:#EFEFEF;color:#21759B;-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px}#wfTabs a.selected{border-bottom:1px solid #FFF;background-color:#FFF;color:#777}.wordfenceTopTab{display:none;margin-top:15px}.wordfenceTopTab.active{display:block}.wordfenceHelpLink{margin-top:15px}.wfAjaxLight128{background-image:url(../img/icons/ajax3.gif)}.wfStrong{font-weight:bold}.wordfenceModeElem{width:1px;height:1px;opacity:0}.wfWarn{color:#F00}img.wfFlag{vertical-align:middle;margin:-3px 4px 0 0}.wfHitTime{font-style:italic}.wfAvatar img{vertical-align:middle;margin-right:0.5rem}.wfls-hex-sequence{color:#587ECB}.wfLoadMoreButton.disabled,.wfLoadMoreButton[disabled]{pointer-events:none;opacity:0.65}table.wfConfigForm th{font-weight:normal;text-align:left;padding:2px 3px 1px 0;vertical-align:middle}table.wfConfigForm td{vertical-align:middle}table.wfConfigForm td.align-top{vertical-align:top}table th.wfConfigEnable{font-weight:bold;min-width:25%}.wfSavedMsg{display:none;color:#A00}table th.wfSubheading{font-weight:bold;padding-top:10px}h3.wfConfigHeading{font-size:22px;color:#777;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:italic;font-weight:normal}.wfTipText{color:#777;font-family:Georgia,Times New Roman,Times,serif;font-style:italic}.wfBlackCursor{color:#FFF}.wfls-spinner{display:inline-block;width:4px}.wferror{color:#F00}#wordfenceWorking{padding:10px 40px 6px 16px;z-index:100000;position:fixed;right:16px;bottom:0px;background-color:#fcb214;border:5px solid #fcb214;border-width:6px 15px 6px 6px;color:#525355;font-size:12px;font-weight:bold;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;background-image:url("../img/icons/working-indicator.gif");background-position:100% 50%;background-repeat:no-repeat}@media (max-width: 960px){#wordfenceWorking{left:auto;right:0px}}#paidWrap{position:relative}.paidInnerMsg{width:500px;margin:150px auto 0 auto;color:#000;font-size:18px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:1.8em;text-align:center;-webkit-font-smoothing:antialiased}.wfMarker{height:1px;width:1px}.wfPaidOnlyNotice{width:500px;background-color:#FFFFE0;border:1px solid #000;padding:10px;margin:20px}.wfOnOffSwitch{display:inline-block;position:relative !important;width:69px !important;-webkit-user-select:none !important;-moz-user-select:none !important;-ms-user-select:none !important;user-select:none !important}.wfOnOffSwitch-checkbox{display:none !important}.wfOnOffSwitch-label{display:block !important;overflow:hidden !important;cursor:pointer !important;border:2px solid #999999 !important;border-radius:19px !important;margin:0}.wfOnOffSwitch-inner{width:200% !important;margin-left:-100% !important;-webkit-transition:margin 0.3s ease-in !important;-o-transition:margin 0.3s ease-in !important;transition:margin 0.3s ease-in !important;-webkit-transition-delay:0s !important;transition-delay:0s !important}.wfOnOffSwitch-inner:before,.wfOnOffSwitch-inner:after{float:left !important;width:50% !important;height:19px !important;padding:0 !important;line-height:19px !important;font-size:14px !important;color:white !important;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;font-weight:bold !important;-webkit-box-sizing:border-box !important;-moz-box-sizing:border-box !important;box-sizing:border-box !important;-moz-border-radius:19px !important;-webkit-border-radius:19px;border-radius:19px !important;-webkit-box-shadow:0 9.5px 0 rgba(0,0,0,0.08) inset !important;box-shadow:0 9.5px 0 rgba(0,0,0,0.08) inset !important}.wfOnOffSwitch-inner:before{content:"ON" !important;padding-left:10px !important;background-color:#30D965 !important;color:#FFFFFF !important;-moz-border-radius:19px 0 0 19px !important;-webkit-border-radius:19px;border-radius:19px 0 0 19px !important}.wfOnOffSwitch-inner:after{content:"OFF" !important;padding-right:10px !important;background-color:#EEEEEE !important;color:#999999 !important;text-align:right !important;-moz-border-radius:0 19px 19px 0 !important;-webkit-border-radius:0;border-radius:0 19px 19px 0 !important}.wfOnOffSwitch-switch{width:19px !important;margin:0 !important;background:#FFFFFF !important;border:2px solid #999999 !important;-moz-border-radius:19px !important;-webkit-border-radius:19px;border-radius:19px !important;position:absolute !important;top:0 !important;bottom:0 !important;right:46px !important;-webkit-transition:all 0.3s ease-in !important;-o-transition:all 0.3s ease-in !important;transition:all 0.3s ease-in !important;-webkit-transition-delay:0s !important;transition-delay:0s !important;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjEiLz48c3RvcCBvZmZzZXQ9IjgwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=') !important;background-size:100%;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0,0,0,0.1)),color-stop(80%, rgba(0,0,0,0))) !important;background-image:-moz-linear-gradient(center top, rgba(0,0,0,0.1) 0%,rgba(0,0,0,0) 80%) !important;background-image:-webkit-linear-gradient(center top, rgba(0,0,0,0.1) 0%,rgba(0,0,0,0) 80%) !important;background-image:linear-gradient(to center bottom, rgba(0,0,0,0.1) 0%,rgba(0,0,0,0) 80%) !important;box-shadow:0 1px 1px white inset !important}.wfOnOffSwitch-checkbox:checked+.wfOnOffSwitch-label .wfOnOffSwitch-inner{margin-left:0 !important}.wfOnOffSwitch-checkbox:checked+.wfOnOffSwitch-label .wfOnOffSwitch-switch{right:0 !important}#wordfenceConfigWarning,#wordfenceAdminEmailWarning{clear:left;margin-top:5px}.wfls-striped-table{width:100%;max-width:100%;border-collapse:collapse}.wfls-striped-table th{border-left:1px solid #bdbdbd}.wfls-striped-table th:first-of-type{border-left:0}.wfls-striped-table th,.wfls-striped-table td{padding:1rem}.wfls-striped-table thead th,.wfls-striped-table thead td,.wfls-striped-table tfoot th,.wfls-striped-table tfoot td,.wfls-striped-table tbody.thead th,.wfls-striped-table tbody.thead td{background-color:#ebebeb;color:#777;font-weight:bold;text-align:left}.wfls-striped-table tbody tr.even td,.wfls-striped-table tbody tr:nth-child(2n) td{background-color:#ffffff}.wfls-striped-table tbody tr td,.wfls-striped-table tbody tr.odd td{background-color:#fafafa}.wfls-striped-table tbody tr:hover>td{background-color:#fffbd8}.wfls-striped-table tbody.empty-row tr td{border-width:0;padding:8px 0;background-color:transparent}.wfls-striped-table .wfls-result-error,.wfls-block-list .wfls-result-error{color:#d0514c !important;font-weight:bold}.wfls-striped-table .wfls-result-error:before,.wfls-block-list .wfls-result-error:before{content:"\2718"}.wfls-striped-table .wfls-result-success{max-width:20%}.wfls-striped-table .wfls-result-success,.wfls-block-list .wfls-result-success{color:#008c10 !important;font-weight:bold}.wfls-striped-table .wfls-result-success:before,.wfls-block-list .wfls-result-success:before{content:"\2713"}.wfls-striped-table .wfls-result-success:before,.wfls-block-list .wfls-result-success:before,.wfls-striped-table .wfls-result-error:before,.wfls-block-list .wfls-result-error:before{font-size:16px;display:inline-block;margin:0px 8px 0px 0px}.wfls-striped-table .wfls-result-inactive,.wfls-block-list .wfls-result-inactive{font-weight:bold;color:#666666 !important}.wfls-fixed-table{table-layout:fixed}pre.wfls-pre{margin:8px 0 20px;padding:12px;background:#ffffff;border:1px solid #999999;overflow:auto}.wfls-center{text-align:center}#wfConfigForm,.wfls-diagnostics-wrapper{max-width:1035px}.wfls-hidden{display:none !important}.wfls-card{position:relative;margin:0 auto .625rem;padding:1rem;box-sizing:border-box;background:#fff;box-shadow:0 0 0 1px rgba(200,215,225,0.5),0 1px 2px #e9eff3}.wfls-card .wfls-card-inner{min-height:76px;width:100%;padding:8px;box-sizing:border-box;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;position:relative}.wfls-card .wfls-card-inner .wfls-card-content{max-width:75%}.wfls-card .wfls-card-inner .wfls-card-content .wfls-card-title{font-size:1.125rem;width:100%}.wfls-card .wfls-card-inner .wfls-card-content .wfls-card-subtitle{margin-top:.125rem;margin-bottom:.125rem;font-size:.875rem;color:#4f748e}.wfls-card .wfls-card-inner .wfls-card-action{position:absolute;top:0;right:0;height:100%;background:none;border:0;outline:0;width:48px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;vertical-align:middle;transition:transform 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275),color 0.2s ease-in}.wfls-card .wfls-card-inner .wfls-card-action .wfls-card-action-chevron{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJjaGV2cm9uLW9iamVjdCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyNCAyNCIKCSB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHBhdGggaWQ9ImNoZXZyb24iIGQ9Ik0yMCA5bC04IDgtOC04IDEuNDE0LTEuNDE0TDEyIDE0LjE3Mmw2LjU4Ni02LjU4NiIvPgo8L3N2Zz4K");background-repeat:no-repeat;background-position:center center;width:24px;height:24px;fill:#87a6bc}.wfls-card .wfls-card-inner .wfls-card-action .wfls-card-action-checkbox{background-image:url(../img/checkbox.png);background-repeat:no-repeat;background-position:left center;width:29px;height:29px}.wfls-card .wfls-card-inner .wfls-card-action .wfls-card-action-checkbox.checked{background-position:right center}.wfls-card .wfls-card-extra{display:none;padding:0.5rem;margin-top:1rem;border-top:1px solid #f3f6f8}@media (min-width: 768px){.wfls-card .wfls-card-extra{padding:1rem}}.wfls-card.active .wfls-card-extra{display:block}.wfls-card.wfls-card-left .wfls-card-content{margin-left:48px}.wfls-card.wfls-card-left .wfls-card-action{right:auto;left:0px}.wfls-card.disabled .wfls-card-content .wfls-card-title{color:#aaaaaa}.wfls-card.disabled .wfls-card-content .wfls-card-subtitle{color:#8ea6be}.wfls-inline-block{display:inline-block}@media (max-width: 767px){.wfls-inline-block-xs{display:inline-block}}.wfls-full-width{width:100%;max-width:100%}.wfls-no-top{margin-top:0 !important}.wfls-add-top{margin-top:1rem !important}.wfls-add-top-large{margin-top:1.5rem !important}.wfls-add-top-medium{margin-top:0.75rem !important}.wfls-add-top-small{margin-top:0.5rem !important}.wfls-add-top-smaller{margin-top:0.25rem !important}.wfls-no-bottom{margin-bottom:0 !important}.wfls-add-bottom{margin-bottom:1rem !important}.wfls-add-bottom-large{margin-bottom:1.5rem !important}.wfls-add-bottom-medium{margin-bottom:0.75rem !important}.wfls-add-bottom-small{margin-bottom:0.5rem !important}.wfls-add-bottom-smaller{margin-bottom:0.25rem !important}.wfls-padding-no-top{padding-top:0 !important}.wfls-no-right{margin-right:0 !important}.wfls-padding-no-bottom{padding-bottom:0 !important}.wfls-padding-no-left{padding-left:0 !important}.wfls-padding-no-right{padding-right:0 !important}.wfls-padding-add-top{padding-top:1rem !important}.wfls-padding-add-top-small{padding-top:0.5rem !important}.wfls-padding-add-top-medium{padding-top:0.75rem !important}.wfls-padding-add-top-large{padding-top:1.5rem !important}.wfls-padding-add-top-responsive{padding-top:1rem !important}@media (min-width: 768px){.wfls-padding-add-top-responsive{padding-top:1.5rem !important}}.wfls-padding-add-bottom{padding-bottom:1rem !important}.wfls-padding-add-bottom-small{padding-bottom:0.5rem !important}.wfls-padding-add-bottom-medium{padding-bottom:0.75rem !important}.wfls-padding-add-bottom-large{padding-bottom:1.5rem !important}.wfls-padding-add-bottom-responsive{padding-bottom:1rem !important}@media (min-width: 768px){.wfls-padding-add-bottom-responsive{padding-bottom:1.5rem !important}}.wfls-padding-no-bottom{padding-bottom:0 !important}.wfls-padding-add-left{padding-left:1rem !important}.wfls-padding-add-left-small{padding-left:0.5rem !important}.wfls-padding-add-left-medium{padding-left:0.75rem !important}.wfls-padding-add-left-large{padding-left:1.5rem !important}.wfls-padding-add-left-responsive{padding-left:1rem !important}@media (min-width: 768px){.wfls-padding-add-left-responsive{padding-left:1.5rem !important}}.wfls-padding-add-right{padding-right:1rem !important}.wfls-padding-add-right-small{padding-right:0.5rem !important}.wfls-padding-add-right-medium{padding-right:0.75rem !important}.wfls-padding-add-right-large{padding-right:1.5rem !important}.wfls-padding-add-right-responsive{padding-right:1rem !important}@media (min-width: 768px){.wfls-padding-add-right-responsive{padding-right:1.5rem !important}}.wfls-left{text-align:left !important}.wfls-center{text-align:center !important}.wfls-block-center{margin:0 auto}.wfls-right{text-align:right !important}.wfls-block-right{margin:0 0 0 auto}@media (max-width: 767px){.wfls-left-xs{text-align:left !important}.wfls-center-xs{text-align:center !important}.wfls-padding-add-top-xs{padding-top:1rem !important}.wfls-padding-add-top-xs-small{padding-top:0.5rem !important}.wfls-padding-add-top-xs-large{padding-top:1.5rem !important}.wfls-padding-add-bottom-xs{padding-bottom:1rem !important}.wfls-padding-add-bottom-xs-small{padding-bottom:0.5rem !important}.wfls-padding-add-bottom-xs-large{padding-bottom:1.5rem !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-left-sm{text-align:left !important}.wfls-center-sm{text-align:center !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-left-md{text-align:left !important}.wfls-center-md{text-align:center !important}}@media (min-width: 1200px){.wfls-left-lg{text-align:left !important}.wfls-center-lg{text-align:center !important}}.wfls-border-no-top{border-top:none !important}.wfls-border-no-right{border-right:none !important}.wfls-border-no-bottom{border-bottom:none !important}.wfls-border-no-left{border-left:none !important}.wfls-overflow-x-auto{overflow-x:auto}.wfls-overflow-y-auto{overflow-y:auto}@media (max-width: 767px){.wfls-overflow-x-auto-xs{overflow-x:auto}.wfls-overflow-y-auto-xs{overflow-y:auto}}.wfls-blue{color:#00709e !important}.wfls-blue-light{color:#008cc1 !important}.wfls-gray-dark{color:#2d2d2d !important}.wfls-gray-blue{color:#3f596b !important}.wfls-green-dark{color:#11967a !important}.wfls-green-light{color:#16bc9b !important}.wfls-red-dark{color:#930000 !important}.wfls-red-light{color:#c10000 !important}.wfls-yellow-dark{color:#fcb214 !important}.wfls-yellow-light{color:#ffd10a !important}.wfls-gray{color:#525355 !important}.wfls-gray-light{color:#9f9fa0 !important}.wfls-nowrap{white-space:nowrap}.wfls-tip{color:#fcb214;font-size:1.1rem;margin-right:0.25rem}.wfls-text-small{font-size:85% !important}.wfls-text-plain{font-weight:400 !important}.wfls-scroll-x::-webkit-scrollbar,.wfls-scroll-y::-webkit-scrollbar{-webkit-appearance:none;width:7px;height:7px}.wfls-scroll-x::-webkit-scrollbar-thumb,.wfls-scroll-y::-webkit-scrollbar-thumb{border-radius:4px;background-color:rgba(0,0,0,0.194);-webkit-box-shadow:0 0 1px rgba(255,255,255,0.5)}.wfls-split-word{word-wrap:break-word;word-break:break-all}@media (max-width: 767px){.wfls-split-word-xs{word-wrap:break-word;word-break:break-all;white-space:normal !important}}.wfselect2-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;min-width:200px}@media (min-width: 768px){.wfselect2-container{min-width:280px}}@media (min-width: 992px){.wfselect2-container{min-width:320px}}@media (max-width: 767px){.wfselect2-container .wfselect2-search.wfselect2-search--inline{margin:0 !important}}.wfls-select2-placeholder-fix .wfselect2-search__field{width:auto !important}.wfls-page-title{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;margin-top:0.5rem}.wfls-page-title>*{-webkit-flex-grow:0;flex-grow:0;min-width:0}.wfls-page-title>*:first-child{-webkit-flex-grow:0;flex-grow:0;min-width:32px;-webkit-flex-basis:32px;flex-basis:32px;padding-right:0.25rem}.wfls-page-title .wordfence-icon32{margin:0;margin-right:0.5rem}.wfls-page-title h2{padding:0 !important}.wfls-page-title .wfOnOffSwitch{-webkit-flex-basis:69px;flex-basis:69px;-webkit-flex-shrink:0;flex-shrink:0;margin-left:0.5rem}.wfls-tab-container{background-color:#fff}@media (min-width: 768px){.wfls-tab-container{background-color:unset}}.wfls-page-tabs,.wfls-page-fixed-tabs{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;border-bottom:1px solid #d0d0d0;margin:0;margin-top:0.5rem;margin-left:-10px;margin-right:-10px}@media (min-width: 768px){.wfls-page-tabs,.wfls-page-fixed-tabs{margin-left:0;margin-right:0}}.wfls-page-tabs>*,.wfls-page-fixed-tabs>*{-webkit-flex-grow:0;flex-grow:0;min-width:0}.wfls-page-tabs>*:first-child,.wfls-page-fixed-tabs>*:first-child{-webkit-flex-grow:0;flex-grow:0;min-width:32px;-webkit-flex-basis:32px;flex-basis:32px}.wfls-page-tabs .wordfence-icon32,.wfls-page-fixed-tabs .wordfence-icon32{margin:0;margin-right:0.5rem;margin-left:0.5rem}@media (min-width: 768px){.wfls-page-tabs .wordfence-icon32,.wfls-page-fixed-tabs .wordfence-icon32{margin-left:0}}.wfls-page-tabs .wfls-text-tab,.wfls-page-fixed-tabs .wfls-text-tab{margin:0;margin-left:0.5rem;color:#333}.wfls-page-tabs .wfls-tab,.wfls-page-fixed-tabs .wfls-tab{border:1px solid #fff;border-top-right-radius:0.5rem;border-top-left-radius:0.5rem;border-bottom:none;margin-bottom:-1px;margin-right:0.5rem;color:#333}@media (min-width: 768px){.wfls-page-tabs .wfls-tab,.wfls-page-fixed-tabs .wfls-tab{border:1px solid #d0d0d0;background:#e6e6e6}}.wfls-page-tabs .wfls-tab a,.wfls-page-fixed-tabs .wfls-tab a{display:block;padding:0.5rem 1rem;font-size:14px;line-height:24px;text-decoration:none;font-weight:bold;color:#333}.wfls-page-tabs .wfls-tab.wfls-active,.wfls-page-tabs .wfls-tab:hover,.wfls-page-fixed-tabs .wfls-tab.wfls-active,.wfls-page-fixed-tabs .wfls-tab:hover{border-bottom:1px solid #f1f1f1;background:#f1f1f1;color:#00709e;-webkit-box-shadow:none;box-shadow:none}.wfls-page-tabs .wfls-tab.wfls-active a,.wfls-page-tabs .wfls-tab:hover a,.wfls-page-fixed-tabs .wfls-tab.wfls-active a,.wfls-page-fixed-tabs .wfls-tab:hover a{color:#00709e}.wfls-tab-content{display:none;margin-top:15px}.wfls-tab-content.wfls-active{display:block}.wfls-fixed-tab-content{margin-top:15px}.wfls-section-title{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start}.wfls-section-title>*{-webkit-flex-grow:0;flex-grow:0;min-width:0}.wfls-section-title>h1,.wfls-section-title>h2,.wfls-section-title>h3,.wfls-section-title>h4,.wfls-section-title>h5,.wfls-section-title>h6{-webkit-flex-grow:1;flex-grow:1;color:#2d2d2d !important;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;line-height:1.5rem !important;font-weight:700 !important;padding:0 !important;margin:0 !important}@media (min-width: 768px){.wfls-section-title>h1,.wfls-section-title>h2,.wfls-section-title>h3,.wfls-section-title>h4,.wfls-section-title>h5,.wfls-section-title>h6{padding-right:0.25rem !important}}.wfls-section-title h2{font-size:1.3125rem;line-height:1.5}.wfls-section-title h3{font-size:1.125rem}.wfls-section-title h4{font-size:1rem}.wfls-section-title .wordfence-icon32{margin:0;margin-right:0.5rem}.wfls-status-circular{position:relative}.wfls-status-circular-text{position:absolute;left:50%;top:50%;padding:0;margin:0;transform:translate(-50%, -50%);color:#aaa;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:1.3125rem;font-weight:300;line-height:1.5}.wfls-status-circular .wfls-status-overlay-text{position:absolute;left:50%;top:50%;padding:0;margin:0;width:200%;text-align:center;transform:translate(-50%, -50%);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:.875rem;font-weight:normal;line-height:1.3125;opacity:0.0;color:#777}.wfls-status-warning,.wfls-status-critical,.wfls-status-payment-expiring,.wfls-status-renewing{width:100px;height:100px;margin-bottom:1rem}.wfls-status-warning svg path{fill:#fcb214}.wfls-status-critical svg path{fill:#930000}.wfls-status-payment-expiring svg rect,.wfls-status-payment-expiring svg path{fill:#930000}.wfls-status-renewing svg rect,.wfls-status-renewing svg path{fill:#11967a}#howGetIPs-preview{color:#8c8c8c}#howGetIPs-preview strong{color:#666}.wfls-scrollTop{background:#424242;bottom:30px;right:15px;position:fixed;z-index:999;display:none}.wfls-scrollTop a{background:#959595;display:block;padding:4px 5px;line-height:32px;width:32px;color:#ffffff;text-align:center}.wfls-back-icon{color:#00709e;margin-right:0.75rem;font-size:1.5rem !important}.wfls-back-link-chevron{margin-left:1rem}.wfls-back-link-chevron:first-of-type{margin-left:0}.wfls-back-link{font-weight:bold;text-decoration:none}.wfls-premium-link{font-weight:bold}.wfls-boolean-switch{border:1px solid #aaa;display:block;cursor:pointer;width:54px;height:30px;min-width:54px;min-height:30px;-moz-border-radius:15px;-webkit-border-radius:15px;border-radius:15px;line-height:30px !important;background-color:#ffffff;position:relative;box-sizing:border-box;transition:background-color 0.2s ease-in-out, border-color 0.2s ease-in-out}@media (min-width: 768px){.wfls-boolean-switch{width:34px;height:20px;min-width:34px;min-height:20px;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px;line-height:20px !important}}.wfls-boolean-switch .wfls-boolean-switch-handle{position:relative;display:block;border:1px solid #aaa;background-color:#fff;width:30px;height:30px;min-width:30px;min-height:30px;-moz-border-radius:15px;-webkit-border-radius:15px;border-radius:15px;margin-top:-1px;box-sizing:border-box;left:-1px;transition:border-color 0.2s ease-in-out, left 0.2s ease-in-out}@media (min-width: 768px){.wfls-boolean-switch .wfls-boolean-switch-handle{width:20px;height:20px;min-width:20px;min-height:20px;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px}}.wfls-boolean-switch.wfls-active{border:1px solid #00709e;background-color:#00709e}.wfls-boolean-switch.wfls-active .wfls-boolean-switch-handle{border:1px solid #00709e;left:25px}@media (min-width: 768px){.wfls-boolean-switch.wfls-active .wfls-boolean-switch-handle{left:15px}}.wfls-boolean-switch.wfls-disabled{pointer-events:none;border-color:#e2e2e2}.wfls-boolean-switch.wfls-disabled .wfls-boolean-switch-handle{border-color:#e2e2e2}.wfls-boolean-switch.wfls-disabled.wfls-active{border-color:#e2e2e2;background-color:#e2e2e2}.wfls-boolean-switch.wfls-disabled.wfls-active .wfls-boolean-switch-handle{border-color:#e2e2e2}.wfls-option-checkbox,[type=checkbox].wfls-option-checkbox+label:before{content:"";font-family:"Ionicons" !important;display:block;cursor:pointer;width:30px;height:30px;min-width:30px;min-height:30px;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;line-height:30px !important;text-align:center !important;background-color:#ffffff !important;box-shadow:0px 0px 0px 1px #aaa;color:#ffffff !important;font-size:30px !important;font-weight:normal !important}@media (min-width: 768px){.wfls-option-checkbox,[type=checkbox].wfls-option-checkbox+label:before{width:20px;height:20px;min-width:20px;min-height:20px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;line-height:21px !important;font-size:25px !important}}@media (min-width: 768px){.wfls-option-checkbox{position:relative}.wfls-option-checkbox>*{position:absolute;top:9px;left:50%;transform:translateX(-50%) translateY(-50%)}}.wfls-option-radio,[type=radio].wfls-option-radio+label:before{content:"\f401";font-family:"Ionicons" !important;display:block;cursor:pointer;width:30px;height:30px;min-width:30px;min-height:30px;line-height:30px !important;text-align:center !important;color:#ccc !important;font-size:30px !important;font-weight:normal !important}@media (min-width: 768px){.wfls-option-radio,[type=radio].wfls-option-radio+label:before{width:20px;height:20px;min-width:20px;min-height:20px;-moz-border-radius:10px;-webkit-border-radius:10px;border-radius:10px;line-height:20px !important}}[type=checkbox].wfls-option-checkbox.wfls-small+label:before{width:20px;height:20px;min-width:20px;min-height:20px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;line-height:21px !important;font-size:20px !important}[type=radio].wfls-option-radio.wfls-small+label:before{width:20px;height:20px;min-width:20px;min-height:20px;line-height:21px !important;font-size:20px !important}[type=checkbox].wfls-option-checkbox+label:before,[type=radio].wfls-option-radio+label:before{text-align:center !important;text-indent:0px;display:inline-block;vertical-align:-6px;margin:0px 5px 0px 0px;font-weight:normal;font-style:normal}[type=checkbox].wfls-option-checkbox.wfls-small+label:before,[type=radio].wfls-option-radio.wfls-small+label:before{text-indent:0px;vertical-align:-3px}.wfls-option-checkbox.wfls-checked,[type=checkbox].wfls-option-checkbox:checked+label:before{color:#ffffff !important;box-shadow:0px 0px 0px 1px #00709e !important;background-color:#00709e !important}.wfls-option-checkbox.wfls-disabled,[type=checkbox].wfls-option-checkbox:disabled+label:before{color:#f1f1f1 !important;box-shadow:0px 0px 0px 1px #e2e2e2 !important;background-color:#f1f1f1 !important}.wfls-option-checkbox.wfls-checked.wfls-disabled,[type=checkbox].wfls-option-checkbox:disabled:checked+label:before{color:#777 !important;box-shadow:0px 0px 0px 1px #e2e2e2 !important;background-color:#f1f1f1 !important}.wfls-option-radio.wfls-checked,[type=radio].wfls-option-radio:checked+label:before{content:"\f3a7";color:#00709e !important}.wfls-option-checkbox[type=checkbox],.wfls-option-checkbox[type=radio],.wfls-option-radio[type=checkbox],.wfls-option-radio[type=radio]{position:absolute;left:-9999px}.wfls-option-text input[type="text"],input.wfls-input-text{text-align:left;width:100%;height:40px;border-radius:0;border:0;background-color:#ffffff;box-shadow:1px 1px 1px 2px rgba(215,215,215,0.65)}.wfls-option-text input[type="text"]:placeholder-shown,input.wfls-input-text:placeholder-shown{font-style:italic;color:#bfbfbf}::-webkit-input-placeholder{color:#bfbfbf}:-moz-placeholder{color:#bfbfbf;opacity:1}::-moz-placeholder{color:#bfbfbf;opacity:1}:-ms-input-placeholder{color:#bfbfbf}::-ms-input-placeholder{color:#bfbfbf}::placeholder{color:#bfbfbf}.wfls-option-premium .wfls-option-title,.wfls-option-premium .wfls-option-title>ul>li,.wfls-option.wfls-disabled .wfls-option-title,.wfls-option.wfls-disabled .wfls-option-title>ul>li{color:#aaa !important}.wfls-option-premium .wfls-option-checkbox,.wfls-option-premium .wfls-option-radio,.wfls-option.wfls-disabled .wfls-option-checkbox,.wfls-option.wfls-disabled .wfls-option-radio{opacity:0.5}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status .wfls-block-labeled-value-value{padding-top:0}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status .wfls-block-labeled-value-value .wfls-fa{font-size:8rem}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status .wfls-block-labeled-value-value svg{width:160px}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status .wfls-block-labeled-value-label{font-size:1.35rem;font-weight:300;padding-bottom:0}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status-premium .wfls-block-labeled-value-value{color:#9f9fa0}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status-premium .wfls-block-labeled-value-value svg{fill:#9f9fa0}.wfls-block .wfls-block-content .wfls-block-labeled-value.wfls-protection-status-premium .wfls-block-labeled-value-label{color:#9f9fa0}.wfls-indeterminate-progress{-webkit-animation:wfls-indeterminate-progress-keyframes 1s steps(8, end) infinite;-o-animation:wfls-indeterminate-progress-keyframes 1s steps(8, end) infinite;animation:wfls-indeterminate-progress-keyframes 1s steps(8, end) infinite}.wfls-indeterminate-progress path{fill:#00709e}@-moz-keyframes wfls-indeterminate-progress-keyframes{to{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes wfls-indeterminate-progress-keyframes{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes wfls-indeterminate-progress-keyframes{to{-moz-transform:rotate(360deg);-ms-transform:rotate(360deg);-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.wfls-flex-row{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.wfls-flex-row .wfls-flex-row-1{-webkit-flex-grow:1;flex-grow:1}.wfls-flex-row .wfls-flex-row-0{-webkit-flex-grow:0;flex-grow:0}.wfls-flex-row.wfls-flex-row-wrappable,.wfls-flex-row.wfls-flex-row-xs-wrappable{-webkit-flex-wrap:wrap;flex-wrap:wrap}.wfls-flex-row.wfls-flex-row-equal-heights{-webkit-align-items:stretch;align-items:stretch}.wfls-flex-row .wfls-flex-item-full-width{width:100%}.wfls-flex-row .wfls-flex-item-xs-100{-webkit-flex-basis:100%;flex-basis:100%}@media (min-width: 768px){.wfls-flex-row.wfls-flex-row-xs-wrappable{-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.wfls-flex-row .wfls-flex-item-sm-50{-webkit-flex-basis:50%;flex-basis:50%}}.wfls-switch{display:-webkit-flex !important;display:flex !important;-webkit-align-items:stretch !important;align-items:stretch !important;-webkit-justify-content:flex-start !important;justify-content:flex-start !important;-webkit-flex-direction:row !important;flex-direction:row !important;margin:0;padding:0}.wfls-switch>li{margin:0 !important;padding:0.5rem 0.7rem !important;text-transform:uppercase;cursor:pointer;color:#aaa;font-weight:400;border-top:1px solid #bfbfbf;border-bottom:1px solid #bfbfbf;border-right:1px solid #bfbfbf}.wfls-switch>li:first-of-type{border-left:1px solid #bfbfbf;-moz-border-radius-topleft:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px}.wfls-switch>li:last-of-type{-moz-border-radius-topright:6px;-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-moz-border-radius-bottomright:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px}.wfls-switch>li.wfls-active{color:#ffffff;background-color:#00709e}.wfls-tooltip,.ui-widget.wfls-tooltip{max-width:600px;font-size:0.75rem;overflow-wrap:break-word}.wfls-widget-learning-mode{border-top:1px solid #eee;margin:0 -1rem;padding:1rem;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;-webkit-flex-direction:row;flex-direction:row}@media (min-width: 768px){.wfls-widget-learning-mode{padding:1.5rem}}.wfls-widget-learning-mode svg{width:18px}.wfls-widget-learning-mode svg path{fill:#aaa}.wfls-widget-learning-mode span{padding-left:0.5rem;font-size:.875rem;line-height:1.3125;font-weight:600}.wfls-drawer-overlay{position:fixed;top:0px;right:0px;bottom:0px;left:160px;background-color:rgba(0,0,0,0.5);z-index:9980;padding:5rem 0}.folded .wfls-drawer-overlay{left:36px}@media only screen and (max-width: 960px){.auto-fold .wfls-drawer-overlay{left:36px}}.rtl .wfls-drawer-overlay{right:160px;left:0px}.rtl .folded .wfls-drawer-overlay{right:36px}@media only screen and (max-width: 960px){.rtl .auto-fold .wfls-drawer-overlay{right:36px}}@media screen and (max-width: 782px){.wfls-drawer-overlay,.folded .wfls-drawer-overlay,.auto-fold .wfls-drawer-overlay,.rtl .wfls-drawer-overlay,.rtl .folded .wfls-drawer-overlay,.rtl .auto-fold .wfls-drawer-overlay{left:0px;right:0px}}.wfls-drawer{background-color:#ffffff;position:fixed;top:32px;bottom:0px;right:0px;z-index:9981}.wfls-drawer .wfls-modal{display:-webkit-flex;display:flex;-webkit-align-items:stretch;align-items:stretch;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:column;flex-direction:column;height:100%}.wfls-drawer .wfls-modal ul,.wfls-drawer .wfls-modal li{padding:0;margin:0}.wfls-drawer .wfls-modal .wfls-modal-header{-webkit-flex-shrink:0;flex-shrink:0;min-height:44px;padding:1rem;width:100%;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;position:relative;background-color:#00709e;color:#ffffff}.wfls-drawer .wfls-modal .wfls-modal-header .wfls-modal-header-content{max-width:75%}.wfls-drawer .wfls-modal .wfls-modal-header .wfls-modal-header-content .wfls-modal-title{font-size:1.3125rem;line-height:1.5;font-weight:300;width:100%;transition:color 0.2s ease-in}.wfls-drawer .wfls-modal .wfls-modal-header .wfls-modal-header-content .wfls-modal-subtitle{margin-top:.125rem;margin-bottom:.125rem;font-size:.575rem;color:#4f748e}.wfls-drawer .wfls-modal .wfls-modal-content{-webkit-flex-grow:1;flex-grow:1;display:-webkit-flex;display:flex;-webkit-align-items:stretch;align-items:stretch;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:column;flex-direction:column;padding:1rem}.wfls-drawer .wfls-modal .wfls-modal-content>*:first-child{margin-top:0}.wfls-drawer .wfls-modal .wfls-modal-content select,.wfls-drawer .wfls-modal .wfls-modal-content select option,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default{font-size:0.7rem;font-weight:bold}@media (min-width: 768px){.wfls-drawer .wfls-modal .wfls-modal-content select,.wfls-drawer .wfls-modal .wfls-modal-content select option,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default{font-size:0.8rem}}@media (min-width: 992px){.wfls-drawer .wfls-modal .wfls-modal-content select,.wfls-drawer .wfls-modal .wfls-modal-content select option,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default{font-size:0.9rem}}.wfls-drawer .wfls-modal .wfls-modal-content .wfls-option-select-option,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection--single{text-align:left;height:40px;border-radius:0;border:0;background-color:#ffffff;box-shadow:1px 1px 1px 2px rgba(215,215,215,0.35)}.wfls-drawer .wfls-modal .wfls-modal-content .wfls-option-select-option .wfselect2-selection__rendered,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection__rendered,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__rendered{color:#333;line-height:40px}.wfls-drawer .wfls-modal .wfls-modal-content .wfls-option-select-option .wfselect2-selection__arrow,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection__arrow,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow{height:38px}.wfls-drawer .wfls-modal .wfls-modal-content .wfls-option-select-option.wfselect2-container--disabled .wfselect2-selection__rendered,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default.wfselect2-container--disabled .wfselect2-selection__rendered,.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection--single.wfselect2-container--disabled .wfselect2-selection__rendered{color:#aaa}.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow b{border-color:#333 transparent transparent}.wfls-drawer .wfls-modal .wfls-modal-content .wfselect2-container--default.wfselect2-container--open .wfselect2-selection--single .wfselect2-selection__arrow b{border-color:transparent transparent #333}.wfls-drawer .wfls-modal .wfls-modal-footer{-webkit-flex-shrink:0;flex-shrink:0;min-height:44px;padding:1rem;width:100%;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;position:relative;background-color:#f1f1f1;border-top:1px solid #d9d9d9}.wfls-mobile-menu-overlay{position:fixed;top:0px;right:0px;bottom:0px;left:0px;background-color:rgba(0,0,0,0.5);z-index:100000}.wfls-mobile-menu-overlay>.wfls-mobile-menu-tap-hint{position:absolute;top:25%;left:50%;transform:translateX(-50%);color:#ffffff;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:1.3125rem;font-weight:300;line-height:1.5}.wfls-mobile-menu{position:fixed;left:50%;transform:translateX(-50%);z-index:100001}.wfls-mobile-menu>.wfls-mobile-menu-items{margin:0;padding:0 0 0.25rem 0;list-style:none}.wfls-mobile-menu>.wfls-mobile-menu-items>li{margin:0;padding:0.25rem 0}.wfls-mobile-menu>.wfls-mobile-menu-items>li>a{box-sizing:border-box}.wfls-callout-warning{background-color:#feecc4;padding:0.8rem 1.25rem}.wfls-tip-light-bulb{color:#fcb214;font-size:1.5rem;font-weight:bold}.wfls-tip-info-message{padding-left:0.5rem !important;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:.875rem;color:#2d2d2d;line-height:1.3125;font-weight:normal}#wfls-qr-code{width:175px;height:175px;margin:0 auto}@media (min-width: 500px){#wfls-qr-code{width:256px;height:256px}}#wfls-activate-field{margin:0 auto;font-size:1.5rem;display:block;text-align:center}.wfls-recovery-codes{list-style-type:none}.wfls-recovery-codes li{font-family:monospace !important;text-align:center}#wfls-recovery-download .dashicons,#wfls-recovery-new-download .dashicons{line-height:26px}#wfls-ip-source-trusted-proxies{display:none}ul.wfls-option.wfls-option-howgetips .wfls-option-ip-source-details{display:-webkit-flex;display:flex;-webkit-align-items:flex-start;align-items:flex-start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:column;flex-direction:column;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.8rem;margin-top:0.5rem}#wfls-ip-source-preview{color:#8c8c8c}#wfls-ip-source-preview strong{color:#666}.wfls-block{display:-webkit-flex;display:flex;-webkit-align-items:stretch;align-items:stretch;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:column;flex-direction:column;position:relative;margin:0 auto 0.5rem;box-sizing:border-box;background-color:#fff;box-shadow:0 0 0 1px rgba(200,215,225,0.25),0 1px 2px #e9eff3}.wfls-block.wfls-block-transparent{background-color:transparent;box-shadow:none}.wfls-block .wfls-block-banner{min-height:44px;margin:0 -1rem;padding:0;box-sizing:border-box;position:relative;background-color:#fcb214;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-direction:row;flex-direction:row}.wfls-block .wfls-block-banner>li{margin:0;padding:0.75rem 1rem}@media (min-width: 768px){.wfls-block .wfls-block-banner{margin:0 -1.5rem}.wfls-block .wfls-block-banner>li{padding:0.75rem 1.5rem}}.wfls-block .wfls-block-header{-webkit-flex-basis:44px;flex-basis:44px;-webkit-flex-shrink:0;flex-shrink:0;-webkit-flex-grow:0;flex-grow:0;min-height:44px;padding:1rem 0;width:100%;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;position:relative}.wfls-block .wfls-block-header.wfls-block-header-border-bottom{padding:0 1rem;border-bottom:1px solid #e2e2e2}@media (min-width: 768px){.wfls-block .wfls-block-header.wfls-block-header-border-bottom{padding:0 1.5rem}}.wfls-block .wfls-block-header .wfls-block-header-content{max-width:75%}.wfls-block .wfls-block-header .wfls-block-header-content .wfls-block-title{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.9rem;width:100%;transition:color 0.2s ease-in}.wfls-block .wfls-block-header .wfls-block-header-content .wfls-block-subtitle{margin-top:.125rem;margin-bottom:.125rem;font-size:0.775rem}.wfls-block .wfls-block-header .wfls-block-header-action{position:absolute;top:0;right:0;height:100%;background:none;border:0;outline:0;width:48px;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end;vertical-align:middle;transition:transform 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275),color 0.2s ease-in}.wfls-block .wfls-block-header .wfls-block-header-action.wfls-block-header-action-text{width:auto}.wfls-block .wfls-block-header .wfls-block-header-action.wfls-block-header-action-text.wfls-block-header-action-text-success{color:#11967a}.wfls-block .wfls-block-header .wfls-block-header-action.wfls-block-header-action-text.wfls-block-header-action-text-warning{color:#930000}.wfls-block .wfls-block-header .wfls-block-header-action.wfls-block-header-action-text.wfls-block-header-action-text-warning a{color:#930000}.wfls-block .wfls-block-header .wfls-block-header-action .wfls-block-header-action-chevron{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJjaGV2cm9uLW9iamVjdCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiCgkgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAyNCAyNCIKCSB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHBhdGggaWQ9ImNoZXZyb24iIGQ9Ik0yMCA5bC04IDgtOC04IDEuNDE0LTEuNDE0TDEyIDE0LjE3Mmw2LjU4Ni02LjU4NiIvPgo8L3N2Zz4K");background-repeat:no-repeat;background-position:center center;width:24px;height:24px}.wfls-block .wfls-block-header .wfls-block-header-action .wfls-block-header-action-disclosure{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJkaXNjbG9zdXJlLWNsb3NlZC1vYmplY3QiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjEycHgiIHZpZXdCb3g9IjAgMCAxMiAxMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTIgMTIiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIGlkPSJkaXNjbG9zdXJlLWNsb3NlZCIgZD0iTSA2IDAgbCA2IDYgLTYgNiAwIC0xMiIgZmlsbD0iIzc3NyIvPgo8L3N2Zz4=");background-repeat:no-repeat;background-position:center center;width:12px;height:12px;transition:transform 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275),background 0.2s ease-in}.wfls-block .wfls-block-header .wfls-block-header-action .wfls-block-header-action-checkbox{background-image:url(../img/checkbox.png);background-repeat:no-repeat;background-position:left center;width:29px;height:29px}.wfls-block .wfls-block-header .wfls-block-header-action .wfls-block-header-action-checkbox.wfls-checked{background-position:right center}.wfls-block .wfls-block-content{-webkit-flex-grow:1;flex-grow:1;display:none;padding:0 1rem}@media (min-width: 768px){.wfls-block .wfls-block-content{padding:0 1.5rem}}.wfls-block .wfls-block-content .wfls-block-list{margin:0 -1rem;padding:0;list-style:none}@media (min-width: 768px){.wfls-block .wfls-block-content .wfls-block-list{margin:0 -1.5rem}}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-striped>li:nth-of-type(odd){background-color:#f9f9f9}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-striped>li:nth-of-type(even){background-color:#ffffff}.wfls-block .wfls-block-content .wfls-block-list>li{display:block;min-height:44px;padding:0 1rem;margin:0;border-top:1px solid #e2e2e2;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between}@media (min-width: 768px){.wfls-block .wfls-block-content .wfls-block-list>li{padding:0 1.5rem}}.wfls-block .wfls-block-content .wfls-block-list>li>*:first-child{-webkit-flex-grow:1;flex-grow:1;min-width:0}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal{box-sizing:border-box;margin-top:-1px;display:-webkit-flex;display:flex;-webkit-align-items:stretch;align-items:stretch;-webkit-align-content:flex-start;align-content:flex-start;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-wrap:wrap;flex-wrap:wrap}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal>li{-webkit-flex-grow:1;flex-grow:1;-webkit-flex-basis:100%;flex-basis:100%;border-left:1px solid #e2e2e2}@media (min-width: 768px){.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal>li{-webkit-flex-basis:50%;flex-basis:50%}}@media (min-width: 992px){.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal>li{-webkit-flex-basis:25%;flex-basis:25%}}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal.wfls-block-list-nowrap{overflow-y:auto;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal.wfls-block-list-nowrap>li{-webkit-flex-shrink:0;flex-shrink:0}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal.wfls-block-list-horizontal-5>li{-webkit-flex-grow:1;flex-grow:1;-webkit-flex-basis:20%;flex-basis:20%}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal>*:first-child{border-left:0}@media (min-width: 768px){.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal.wfls-block-list-equal>li{max-width:50%}}@media (min-width: 992px){.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal.wfls-block-list-equal>li{max-width:25%}}.wfls-block .wfls-block-content .wfls-block-list.wfls-block-list-horizontal.wfls-block-list-horizontal-5.wfls-block-list-equal>li{max-width:20%}.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-state{text-align:center}@media (min-width: 1200px){.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-state{text-align:left}}.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-state-enabled .wfls-fa{color:#11967a}.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-state-disabled .wfls-fa{color:#525355}.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-state-premium{color:#9f9fa0}.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-dismiss{padding-left:2rem;font-size:1.25rem}.wfls-block .wfls-block-content .wfls-block-list .wfls-block-list-dismiss a{color:#525355}.wfls-block .wfls-block-content:first-child>.wfls-block-list>li:first-child{border-top:none}.wfls-block .wfls-block-content .wfls-block-left-right{margin:0 -1rem;padding:0;list-style:none;display:-webkit-flex;display:flex;-webkit-align-items:stretch;align-items:stretch;-webkit-align-content:flex-start;align-content:flex-start;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-wrap:wrap;flex-wrap:wrap}@media (min-width: 768px){.wfls-block .wfls-block-content .wfls-block-left-right{margin:0 -1.5rem}}.wfls-block .wfls-block-content .wfls-block-left-right.wfls-block-left-right-nowrap{-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.wfls-block .wfls-block-content .wfls-block-left-right>li{display:block;min-height:44px;padding:0;margin:0;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between}.wfls-block .wfls-block-content .wfls-block-left-right>li>*:first-child{-webkit-flex-grow:1;flex-grow:1;min-width:0}.wfls-block .wfls-block-content .wfls-block-left-right>li.wfls-left{text-align:left}.wfls-block .wfls-block-content .wfls-block-left-right>li.wfls-right{text-align:right}.wfls-block .wfls-block-content .wfls-block-left-center-right{margin:0 -1rem;padding:0;list-style:none;display:-webkit-flex;display:flex;-webkit-align-items:stretch;align-items:stretch;-webkit-align-content:center;align-content:center;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.wfls-block .wfls-block-content .wfls-block-left-center-right>li{display:block;min-height:44px;padding:0;margin:0;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-grow:1;flex-grow:1;-webkit-flex-basis:33.3333%;flex-basis:33.3333%;max-width:33.3333%}.wfls-block .wfls-block-content .wfls-block-left-center-right>li a{text-decoration:none;font-size:.875rem}.wfls-block .wfls-block-content .wfls-block-left-center-right>li.wfls-left{text-align:left}.wfls-block .wfls-block-content .wfls-block-left-center-right>li.wfls-center{text-align:center;-webkit-justify-content:center;justify-content:center}.wfls-block .wfls-block-content .wfls-block-left-center-right>li.wfls-center .wordfence-icon32{margin:0}.wfls-block .wfls-block-content .wfls-block-left-center-right>li.wfls-right{text-align:right;-webkit-justify-content:flex-end;justify-content:flex-end}.wfls-block .wfls-block-content .wfls-block-labeled-value{box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-direction:column;flex-direction:column;margin:0 -1rem;padding:1rem}@media (min-width: 768px){.wfls-block .wfls-block-content .wfls-block-labeled-value{margin:0 -1.5rem;padding:1.5rem}}.wfls-block .wfls-block-content .wfls-block-labeled-value-value{font-size:3rem;line-height:3rem;color:#9f9fa0;padding:1rem}.wfls-block .wfls-block-content .wfls-block-labeled-value-label{font-size:0.75rem;color:#9f9fa0;padding:0 1rem 1rem 1rem}.wfls-block .wfls-block-footer{-webkit-flex-shrink:0;flex-shrink:0;-webkit-flex-grow:0;flex-grow:0;min-height:44px;padding:1rem;width:100%;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;position:relative;background-color:#e4e4e4}.wfls-block .wfls-block-footer .wfls-block-footer-content{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;width:100%}.wfls-block .wfls-block-footer .wfls-block-footer-content>*{-webkit-flex-grow:1;flex-grow:1}.wfls-block .wfls-block-footer .wfls-block-footer-content .wfls-block-title{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.9rem;width:100%;transition:color 0.2s ease-in}.wfls-block .wfls-block-footer .wfls-block-footer-content .wfls-block-subtitle{margin-top:.125rem;margin-bottom:.125rem;font-size:0.775rem}.wfls-block .wfls-block-footer .wfls-block-footer-action{-webkit-flex-grow:0;flex-grow:0;background:none;border:0;outline:0;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end;vertical-align:middle}.wfls-block.wfls-block-no-header .wfls-block-content .wfls-block-list>li{border-top:none}.wfls-block.wfls-active .wfls-block-content,.wfls-block.wfls-always-active .wfls-block-content{display:block}.wfls-block.wfls-active>.wfls-block-header>.wfls-block-header-content>.wfls-block-title{color:#00709e}.wfls-block.wfls-active>.wfls-block-header>.wfls-block-header-content>.wfls-block-header-action>.wfls-block-header-action-disclosure{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJkaXNjbG9zdXJlLWNsb3NlZC1vYmplY3QiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjEycHgiIHZpZXdCb3g9IjAgMCAxMiAxMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTIgMTIiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIGlkPSJkaXNjbG9zdXJlLWNsb3NlZCIgZD0iTSA2IDAgbCA2IDYgLTYgNiAwIC0xMiIgZmlsbD0iIzAwNzA5ZSIvPgo8L3N2Zz4=") !important;transform:rotate(90deg)}.wfls-block.wfls-disabled>.wfls-block-header>.wfls-block-header-content>.wfls-block-title,.wfls-block.wfls-disabled>.wfls-block-header>.wfls-block-header-content>.wfls-block-subtitle{color:#bfbfbf !important}.wfls-block.wfls-disabled>.wfls-block-header>.wfls-block-header-content>.wfls-block-header-action>.wfls-block-header-action-disclosure{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJkaXNjbG9zdXJlLWNsb3NlZC1vYmplY3QiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIxMnB4IiBoZWlnaHQ9IjEycHgiIHZpZXdCb3g9IjAgMCAxMiAxMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTIgMTIiCgkgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxwYXRoIGlkPSJkaXNjbG9zdXJlLWNsb3NlZCIgZD0iTSA2IDAgbCA2IDYgLTYgNiAwIC0xMiIgZmlsbD0iI2JkYmRiZCIvPgo8L3N2Zz4=") !important;transform:rotate(0deg)}.wfls-block.wfls-disabled>.wfls-block-content{display:none !important}.wfls-block.wfls-block-header-left .wfls-block-header-content{margin-left:48px}.wfls-block.wfls-block-header-left .wfls-block-header-action{right:auto;left:0px}.wfls-block.wfls-disabled .wfls-dashboard-item-content .wfls-block-title{color:#aaaaaa}.wfls-block.wfls-disabled .wfls-dashboard-item-content .wfls-block-subtitle{color:#8ea6be}.wfls-section-title{margin-bottom:1rem}.wfls-status-detail{box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-direction:column;flex-direction:column;margin:0 -1rem;padding:1rem}.wfls-status-detail p{margin:0 0 0.45rem 0}.wfls-status-detail .wfls-status-circular{margin-bottom:1rem}.wfls-status-detail .wfls-status-detail-title{font-weight:700 !important;font-size:1rem !important;line-height:1.3125 !important}.wfls-status-detail .wfls-status-detail-subtitle{font-size:.875rem !important;line-height:1.3125 !important;font-weight:normal !important;text-align:center}.wfls-status-detail .wfls-status-detail-link>a{font-weight:600 !important;font-size:0.85rem !important}.wfls-block-navigation-option{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-align-content:flex-start;align-content:flex-start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.wfls-block-navigation-option svg.wfls-block-navigation-option-icon{width:50px;min-width:50px;fill:#9f9fa0}.wfls-block-navigation-option:hover{cursor:pointer}.wfls-block-navigation-option:hover a{text-decoration:underline}.wfls-block-navigation-option:hover svg.wfls-block-navigation-option-icon{fill:#00709e}.wfls-select-group{display:-webkit-flex !important;display:flex !important;-webkit-align-items:center !important;align-items:center !important;-webkit-justify-content:flex-start !important;justify-content:flex-start !important;-webkit-flex-direction:row !important;flex-direction:row !important;-webkit-flex-grow:0 !important;flex-grow:0 !important}.wfls-select-group .wfselect2-container{min-width:200px}@media (max-width: 767px){.wfls-select-group .wfselect2-container{max-width:100px}}.wfls-select-group .wfselect2-container--default .wfselect2-selection--single{display:block;width:100%;height:38px;padding:.5rem 1.25rem;font-size:14px;line-height:1.42857;color:#2b2b2b;background-color:#fff;background-image:none;border:1px solid #ddd;border-radius:4px;border-top-right-radius:0;border-bottom-right-radius:0;border-right:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;-o-transition:border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;transition:border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s}.wfls-select-group .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__rendered{color:#2b2b2b;line-height:inherit}.wfls-select-group .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow{height:38px}.wfls-select-group .wfls-form-control{display:inline-block;width:auto;border-top-left-radius:0;border-bottom-left-radius:0;margin-left:0}.wfls-flex-horizontal{display:-webkit-flex !important;display:flex !important;-webkit-align-items:center !important;align-items:center !important;-webkit-justify-content:flex-start !important;justify-content:flex-start !important;-webkit-flex-direction:row !important;flex-direction:row !important}.wfls-flex-horizontal>*:first-child{-webkit-flex-grow:0 !important;flex-grow:0 !important}.wfls-flex-horizontal.wfls-flex-align-left{-webkit-align-items:flex-start !important;align-items:flex-start !important}.wfls-flex-horizontal.wfls-flex-align-right{-webkit-justify-content:flex-end !important;justify-content:flex-end !important}.wfls-flex-horizontal.wfls-flex-full-width{width:100%}.wfls-flex-horizontal.wfls-flex-full-width>*:last-child{-webkit-flex-grow:1 !important;flex-grow:1 !important}.wfls-flex-horizontal.wfls-flex-full-width.wfls-flex-grow-first>*:first-child{-webkit-flex-grow:1 !important;flex-grow:1 !important}.wfls-flex-horizontal.wfls-flex-full-width.wfls-flex-grow-first>*:last-child{-webkit-flex-grow:0 !important;flex-grow:0 !important}.wfls-flex-horizontal.wfls-flex-full-width.wfls-flex-grow-all>*:first-child,.wfls-flex-horizontal.wfls-flex-full-width.wfls-flex-grow-all>*{-webkit-flex-grow:1 !important;flex-grow:1 !important}.wfls-flex-horizontal>li{padding:0;margin:0}.wfls-flex-vertical{display:-webkit-flex !important;display:flex !important;-webkit-align-items:center !important;align-items:center !important;-webkit-justify-content:flex-start !important;justify-content:flex-start !important;-webkit-flex-direction:column !important;flex-direction:column !important}.wfls-flex-vertical>*:first-child{-webkit-flex-grow:0 !important;flex-grow:0 !important}.wfls-flex-vertical.wfls-flex-align-left{-webkit-align-items:flex-start !important;align-items:flex-start !important}.wfls-flex-vertical.wfls-flex-align-right{-webkit-align-items:flex-end !important;align-items:flex-end !important}.wfls-flex-vertical.wfls-flex-full-width{-webkit-align-items:stretch !important;align-items:stretch !important}@media (max-width: 767px){.wfls-flex-vertical.wfls-flex-align-left-xs{-webkit-align-items:flex-start !important;align-items:flex-start !important}}@media (min-width: 768px) and (max-width: 991px){.wfls-flex-vertical.wfls-flex-align-left-sm{-webkit-align-items:flex-start !important;align-items:flex-start !important}}@media (min-width: 992px) and (max-width: 1199px){.wfls-flex-vertical.wfls-flex-align-left-md{-webkit-align-items:flex-start !important;align-items:flex-start !important}}@media (min-width: 1200px){.wfls-flex-vertical.wfls-flex-align-left-lg{-webkit-align-items:flex-start !important;align-items:flex-start !important}}.wfls-flex-vertical>li{padding:0;margin:0}@media (max-width: 767px){.wfls-flex-vertical-xs{display:-webkit-flex !important;display:flex !important;-webkit-align-items:center !important;align-items:center !important;-webkit-justify-content:flex-start !important;justify-content:flex-start !important;-webkit-flex-direction:column !important;flex-direction:column !important}.wfls-flex-vertical-xs>*:first-child{-webkit-flex-grow:0 !important;flex-grow:0 !important}.wfls-flex-vertical-xs.wfls-flex-align-left{-webkit-align-items:flex-start !important;align-items:flex-start !important}.wfls-flex-vertical-xs.wfls-flex-align-right{-webkit-align-items:flex-end !important;align-items:flex-end !important}.wfls-flex-vertical-xs.wfls-flex-full-width{-webkit-align-items:stretch !important;align-items:stretch !important}}ul.wfls-option,.wfls-form-field{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;flex-wrap:nowrap;padding:1rem 0;position:relative}ul.wfls-option li,.wfls-form-field li{margin:0;padding:0}ul.wfls-option.wfls-option-no-spacing,.wfls-form-field.wfls-option-no-spacing{padding:0;margin:0}ul.wfls-option.wfls-option-toggled>*:last-child,ul.wfls-option.wfls-option-toggled-boolean-switch>*:last-child,ul.wfls-option.wfls-option-toggled-select>*:last-child,ul.wfls-option.wfls-option-select>*:last-child,ul.wfls-option.wfls-option-text>*:last-child,ul.wfls-option.wfls-option-textarea>*:last-child,ul.wfls-option.wfls-option-switch>*:last-child,ul.wfls-option.wfls-option-footer>*:last-child,.wfls-form-field.wfls-option-toggled>*:last-child,.wfls-form-field.wfls-option-toggled-boolean-switch>*:last-child,.wfls-form-field.wfls-option-toggled-select>*:last-child,.wfls-form-field.wfls-option-select>*:last-child,.wfls-form-field.wfls-option-text>*:last-child,.wfls-form-field.wfls-option-textarea>*:last-child,.wfls-form-field.wfls-option-switch>*:last-child,.wfls-form-field.wfls-option-footer>*:last-child{margin-right:1rem}@media (max-width: 768px){ul.wfls-option.wfls-option-footer,.wfls-form-field.wfls-option-footer{-webkit-flex-direction:column;flex-direction:column}}ul.wfls-option>.wfls-option-content,.wfls-form-field>.wfls-option-content{-webkit-flex-grow:1;flex-grow:1}ul.wfls-option>.wfls-option-content>ul,.wfls-form-field>.wfls-option-content>ul{display:-webkit-flex;display:flex;-webkit-align-items:flex-start;align-items:flex-start;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:column;flex-direction:column;-webkit-flex-wrap:nowrap;flex-wrap:nowrap;width:100%}ul.wfls-option>.wfls-option-content>ul>*:first-child,.wfls-form-field>.wfls-option-content>ul>*:first-child{-webkit-flex-grow:1;flex-grow:1}@media (min-width: 768px){ul.wfls-option>.wfls-option-content>ul,.wfls-form-field>.wfls-option-content>ul{-webkit-flex-direction:row;flex-direction:row;-webkit-align-items:center;align-items:center}}ul.wfls-option.wfls-option-toggled-segmented *,.wfls-form-field.wfls-option-toggled-segmented *{-webkit-flex-grow:0;flex-grow:0}ul.wfls-option.wfls-option-toggled-segmented *:first-child,.wfls-form-field.wfls-option-toggled-segmented *:first-child{-webkit-flex-grow:1;flex-grow:1}ul.wfls-option.wfls-option-toggled-segmented>*:last-child,.wfls-form-field.wfls-option-toggled-segmented>*:last-child{margin-left:1rem}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-title,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-title{font-size:.8rem}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-align-content:stretch;align-content:stretch;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label{-webkit-flex-grow:1;flex-grow:1;-webkit-flex-basis:50%;flex-basis:50%;display:block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;text-transform:uppercase;padding:.5rem 1.25rem;font-size:14px;line-height:1.42857;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#00709e;background-color:#fff;border-color:#00709e;border-radius:0}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.focus{color:#00709e;background-color:#e6e6e6;border-color:#00161f}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:hover{color:#00709e;background-color:#e6e6e6;border-color:#004561}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:active,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.active,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:active,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.active,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle{color:#00709e;background-color:#e6e6e6;border-color:#004561}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:active:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:active:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:active.focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.active:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.active:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.active.focus,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle:hover,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle:focus,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle.focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:active:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:active:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:active.focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.active:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.active:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.active.focus,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle:hover,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle:focus,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle.focus{color:#00709e;background-color:#d4d4d4;border-color:#00161f}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:active,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-active,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:active,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-active,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-dropdown-toggle{background-image:none}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[disabled],ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[readonly],fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[disabled],.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[readonly],fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label{color:#777;background-color:#fff;border-color:#e2e2e2;cursor:not-allowed;opacity:0.75}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled.wfls-focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[disabled]:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[disabled]:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[disabled].wfls-focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[readonly]:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[readonly]:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label[readonly].wfls-focus,fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:hover,fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label:focus,fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-disabled.wfls-focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[disabled]:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[disabled]:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[disabled].wfls-focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[readonly]:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[readonly]:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label[readonly].wfls-focus,fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:hover,fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label:focus,fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-focus{background-color:#fff;border-color:#00709e}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label .wfls-badge,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label .wfls-badge{color:#fff;background-color:#00709e}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-segment-first,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-segment-first{border-radius:4px 0 0 4px}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments label.wfls-segment-last,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments label.wfls-segment-last{border-radius:0 4px 4px 0}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio],.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]{position:absolute;left:-9999px}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label{color:#fff;background-color:#00709e;border-color:#005e85}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.focus{color:#fff;background-color:#004c6b;border-color:#000405}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:hover{color:#fff;background-color:#004c6b;border-color:#003347}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle{color:#fff;background-color:#004c6b;border-color:#003347}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active.focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active.focus,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle:hover,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle:focus,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle.focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active.focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.active.focus,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle:hover,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle:focus,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle.focus{color:#fff;background-color:#003347;border-color:#000405}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-active,.wfls-open>ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:active,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-active,.wfls-open>.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-dropdown-toggle{background-image:none}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled],ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly],fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled],.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly],fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label{color:#fff;background-color:#59a2c0;border-color:#5996b0;cursor:not-allowed;opacity:0.75}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled.wfls-focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled]:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled]:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled].wfls-focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly]:hover,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly]:focus,ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly].wfls-focus,fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:hover,fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:focus,fieldset[disabled] ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-disabled.wfls-focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled]:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled]:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[disabled].wfls-focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly]:hover,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly]:focus,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label[readonly].wfls-focus,fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:hover,fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label:focus,fieldset[disabled] .wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label.wfls-focus{background-color:#00709e;border-color:#005e85}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label .wfls-badge,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:checked+label .wfls-badge{color:#00709e;background-color:#fff}ul.wfls-option.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:disabled+label,.wfls-form-field.wfls-option-toggled-segmented .wfls-option-segments [type=radio]:disabled+label{cursor:not-allowed;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=65);opacity:.65}ul.wfls-option.wfls-option-toggled-multiple,.wfls-form-field.wfls-option-toggled-multiple{-webkit-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;align-items:flex-start}ul.wfls-option.wfls-option-toggled-multiple>.wfls-option-title,.wfls-form-field.wfls-option-toggled-multiple>.wfls-option-title{font-weight:600}ul.wfls-option>.wfls-option-spacer,.wfls-form-field>.wfls-option-spacer{-webkit-flex-grow:0;flex-grow:0;-webkit-flex-shrink:0;flex-shrink:0;margin:0 1rem 0 0;width:30px;height:30px}@media (min-width: 768px){ul.wfls-option>.wfls-option-spacer,.wfls-form-field>.wfls-option-spacer{width:20px;height:20px}}ul.wfls-option>.wfls-option-premium-lock,.wfls-form-field>.wfls-option-premium-lock{-webkit-flex-grow:0;flex-grow:0;-webkit-flex-shrink:0;flex-shrink:0;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzMHB4IiB2aWV3Qm94PSIwIDAgMjQgMzAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxwYXRoIGQ9Ik0yMy45NDksMTQuMjMzYy0wLjM3OSwtMC4zOSAtMC45MDQsLTAuNjA2IC0xLjQ0OCwtMC41OTVsLTAuNjgzLDBsMCwtNC4wOTJjMC4wMzIsLTIuNTM1IC0wLjk4NiwtNC45NzMgLTIuODEyLC02LjczMWMtMS43NTksLTEuODI4IC00LjE5OCwtMi44NDcgLTYuNzM0LC0yLjgxNWMtMi41MzYsLTAuMDMyIC00Ljk3NiwwLjk4NyAtNi43MzQsMi44MTVjLTEuODI2LDEuNzU4IC0yLjg0NCw0LjE5NiAtMi44MTIsNi43MzFsMCw0LjA4OWwtMC42OCwwYy0wLjU0NCwtMC4wMTEgLTEuMDY5LDAuMjA1IC0xLjQ0OCwwLjU5NWMtMC4zOTUsMC4zODIgLTAuNjEyLDAuOTEyIC0wLjU5OCwxLjQ2MWwwLDEyLjI2NmMtMC4wMTEsMC41NDQgMC4yMDQsMS4wNjkgMC41OTUsMS40NDhjMC4zNzksMC4zOTEgMC45MDQsMC42MDYgMS40NDgsMC41OTVsMjAuNDU4LDBjMC4wMDMsMCAwLjAwNiwwIDAuMDEsMGMxLjExNywwIDIuMDM2LC0wLjkxOSAyLjAzNiwtMi4wMzdjMCwtMC4wMDMgMCwtMC4wMDYgMCwtMC4wMDlsMCwtMTIuMjYzYzAuMDExLC0wLjU0NCAtMC4yMDYsLTEuMDY5IC0wLjU5OCwtMS40NDhsMCwtMC4wMVptLTYuMjExLC0wLjU5NWwtMTAuOTE5LDBsMCwtNC4wOTJjLTAuMDIyLC0xLjQ1MSAwLjU1NywtMi44NDggMS41OTksLTMuODU4YzEuMDA5LC0xLjA0MiAyLjQwNywtMS42MjEgMy44NTcsLTEuNTk4YzEuNDUxLC0wLjAyMyAyLjg0OCwwLjU1NiAzLjg1OCwxLjU5OGMxLjA0MiwxLjAwOSAxLjYyMSwyLjQwNyAxLjU5OCwzLjg1OGwwLjAwNyw0LjA5MloiIGZpbGw9IiNkMWQxZDEiLz4KPC9zdmc+");background-repeat:no-repeat;background-position:center center;background-size:contain;margin:0 1rem 0 0;width:30px;height:30px}@media (min-width: 768px){ul.wfls-option>.wfls-option-premium-lock,.wfls-form-field>.wfls-option-premium-lock{margin:0 2rem 0 1rem;width:20px;height:20px}}ul.wfls-option>.wfls-option-checkbox,.wfls-form-field>.wfls-option-checkbox{-webkit-flex-grow:0;flex-grow:0;-webkit-flex-shrink:0;flex-shrink:0;margin:0 1rem 0 0}ul.wfls-option>.wfls-boolean-switch,.wfls-form-field>.wfls-boolean-switch{-webkit-flex-grow:0;flex-grow:0;-webkit-flex-shrink:0;flex-shrink:0;margin:0 1rem 0 0}@media (min-width: 768px){ul.wfls-option>.wfls-boolean-switch,.wfls-form-field>.wfls-boolean-switch{margin:0 1rem 0 1rem}}ul.wfls-option.wfls-option-no-spacing>.wfls-boolean-switch,.wfls-form-field.wfls-option-no-spacing>.wfls-boolean-switch{margin:0}ul.wfls-option>.wfls-option-radio-container,.wfls-form-field>.wfls-option-radio-container{-webkit-flex-grow:0;flex-grow:0;-webkit-flex-shrink:0;flex-shrink:0;margin:0 1rem 0 0}@media (min-width: 768px){ul.wfls-option>.wfls-option-radio-container,.wfls-form-field>.wfls-option-radio-container{margin:0 2rem 0 1rem}}ul.wfls-option>.wfls-option-radio-container [type=radio].wfls-option-radio+label:before,.wfls-form-field>.wfls-option-radio-container [type=radio].wfls-option-radio+label:before{margin:0}ul.wfls-option>li>.wfls-option-title,ul.wfls-option>.wfls-option-title,ul.wfls-option>.wfls-option-content>ul>.wfls-option-title,.wfls-form-field>li>.wfls-option-title,.wfls-form-field>.wfls-option-title,.wfls-form-field>.wfls-option-content>ul>.wfls-option-title{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.9rem;color:#2b2b2b;padding-right:0.5rem}ul.wfls-option>li>.wfls-option-title.wfls-option-title-top,ul.wfls-option>.wfls-option-title.wfls-option-title-top,ul.wfls-option>.wfls-option-content>ul>.wfls-option-title.wfls-option-title-top,.wfls-form-field>li>.wfls-option-title.wfls-option-title-top,.wfls-form-field>.wfls-option-title.wfls-option-title-top,.wfls-form-field>.wfls-option-content>ul>.wfls-option-title.wfls-option-title-top{-webkit-align-self:flex-start;align-self:flex-start}ul.wfls-option>li>.wfls-option-title.wfls-option-title-bottom,ul.wfls-option>.wfls-option-title.wfls-option-title-bottom,ul.wfls-option>.wfls-option-content>ul>.wfls-option-title.wfls-option-title-bottom,.wfls-form-field>li>.wfls-option-title.wfls-option-title-bottom,.wfls-form-field>.wfls-option-title.wfls-option-title-bottom,.wfls-form-field>.wfls-option-content>ul>.wfls-option-title.wfls-option-title-bottom{-webkit-align-self:flex-end;align-self:flex-end}ul.wfls-option .wfls-option-subtitle,.wfls-form-field .wfls-option-subtitle{padding-top:0.25rem;font-size:0.75rem}ul.wfls-option .wfls-flex-vertical .wfls-option-title,.wfls-form-field .wfls-flex-vertical .wfls-option-title{padding-bottom:0.75rem}ul.wfls-option.wfls-flex-vertical>.wfls-option-subtitle,.wfls-form-field.wfls-flex-vertical>.wfls-option-subtitle{padding-top:0.25rem !important;font-size:0.75rem !important}ul.wfls-option .wfls-option-checkboxes,ul.wfls-option .wfls-option-checkboxes>ul,.wfls-form-field .wfls-option-checkboxes,.wfls-form-field .wfls-option-checkboxes>ul{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}ul.wfls-option .wfls-option-checkboxes.wfls-option-checkboxes-wrap,ul.wfls-option .wfls-option-checkboxes>ul.wfls-option-checkboxes-wrap,.wfls-form-field .wfls-option-checkboxes.wfls-option-checkboxes-wrap,.wfls-form-field .wfls-option-checkboxes>ul.wfls-option-checkboxes-wrap{-webkit-flex-wrap:wrap;flex-wrap:wrap}ul.wfls-option .wfls-option-checkboxes,.wfls-form-field .wfls-option-checkboxes{margin-top:0.5rem}ul.wfls-option .wfls-option-checkboxes>ul,.wfls-form-field .wfls-option-checkboxes>ul{margin-top:0.5rem;margin-right:1rem}@media (min-width: 768px){ul.wfls-option .wfls-option-checkboxes>ul,.wfls-form-field .wfls-option-checkboxes>ul{margin-right:1.5rem}}ul.wfls-option .wfls-option-checkboxes>ul:last-of-type,.wfls-form-field .wfls-option-checkboxes>ul:last-of-type{margin-right:0}ul.wfls-option .wfls-option-checkboxes>ul>.wfls-option-checkbox,.wfls-form-field .wfls-option-checkboxes>ul>.wfls-option-checkbox{margin:0 1rem 0 0}ul.wfls-option li.wfls-option-text,ul.wfls-option li.wfls-option-textarea,ul.wfls-option td.wfls-option-text,.wfls-form-field li.wfls-option-text,.wfls-form-field li.wfls-option-textarea,.wfls-form-field td.wfls-option-text{padding-top:0.5rem}@media (min-width: 768px){ul.wfls-option li.wfls-option-text,ul.wfls-option li.wfls-option-textarea,ul.wfls-option td.wfls-option-text,.wfls-form-field li.wfls-option-text,.wfls-form-field li.wfls-option-textarea,.wfls-form-field td.wfls-option-text{-webkit-flex-grow:1;flex-grow:1;text-align:right;padding-left:1rem;padding-top:0}}ul.wfls-option li.wfls-option-text>input[type="text"],.wfls-form-field li.wfls-option-text>input[type="text"]{max-width:240px}@media (min-width: 768px){ul.wfls-option li.wfls-option-text>input[type="text"],.wfls-form-field li.wfls-option-text>input[type="text"]{max-width:280px}}@media (min-width: 992px){ul.wfls-option li.wfls-option-text>input[type="text"],.wfls-form-field li.wfls-option-text>input[type="text"]{max-width:340px}}ul.wfls-option li.wfls-option-text.wfls-option-full-width>input[type="text"],.wfls-form-field li.wfls-option-text.wfls-option-full-width>input[type="text"]{max-width:100%;width:100%}ul.wfls-option li.wfls-option-textarea,.wfls-form-field li.wfls-option-textarea{min-width:150px;max-width:240px}@media (min-width: 768px){ul.wfls-option li.wfls-option-textarea,.wfls-form-field li.wfls-option-textarea{min-width:200px;max-width:400px}}@media (min-width: 992px){ul.wfls-option li.wfls-option-textarea,.wfls-form-field li.wfls-option-textarea{min-width:250px;max-width:500px}}ul.wfls-option li.wfls-option-textarea>textarea,.wfls-form-field li.wfls-option-textarea>textarea{width:100%;height:80px;min-width:150px;max-width:240px}@media (min-width: 768px){ul.wfls-option li.wfls-option-textarea>textarea,.wfls-form-field li.wfls-option-textarea>textarea{min-width:200px;max-width:280px}}@media (min-width: 992px){ul.wfls-option li.wfls-option-textarea>textarea,.wfls-form-field li.wfls-option-textarea>textarea{min-width:250px;max-width:340px}}ul.wfls-option li.wfls-option-textarea>.wfls-flex-vertical>li>textarea,.wfls-form-field li.wfls-option-textarea>.wfls-flex-vertical>li>textarea{width:100%;height:80px;box-sizing:border-box}ul.wfls-option li.wfls-option-textarea>.wfls-flex-vertical>li.wfls-option-subtitle,.wfls-form-field li.wfls-option-textarea>.wfls-flex-vertical>li.wfls-option-subtitle{width:100%;text-align:left}ul.wfls-option li.wfls-option-switch,.wfls-form-field li.wfls-option-switch{-webkit-flex-grow:1;flex-grow:1}ul.wfls-option li.wfls-option-switch.wfls-right .wfls-switch,.wfls-form-field li.wfls-option-switch.wfls-right .wfls-switch{justify-content:flex-end !important}ul.wfls-option li.wfls-option-select,.wfls-form-field li.wfls-option-select{-webkit-flex-grow:1;flex-grow:1;text-align:right}ul.wfls-option li.wfls-option-select select,ul.wfls-option li.wfls-option-select select option,ul.wfls-option li.wfls-option-select .wfselect2-container--default,.wfls-form-field li.wfls-option-select select,.wfls-form-field li.wfls-option-select select option,.wfls-form-field li.wfls-option-select .wfselect2-container--default{font-size:0.7rem;font-weight:bold}@media (min-width: 768px){ul.wfls-option li.wfls-option-select select,ul.wfls-option li.wfls-option-select select option,ul.wfls-option li.wfls-option-select .wfselect2-container--default,.wfls-form-field li.wfls-option-select select,.wfls-form-field li.wfls-option-select select option,.wfls-form-field li.wfls-option-select .wfselect2-container--default{font-size:0.8rem}}@media (min-width: 992px){ul.wfls-option li.wfls-option-select select,ul.wfls-option li.wfls-option-select select option,ul.wfls-option li.wfls-option-select .wfselect2-container--default,.wfls-form-field li.wfls-option-select select,.wfls-form-field li.wfls-option-select select option,.wfls-form-field li.wfls-option-select .wfselect2-container--default{font-size:0.9rem}}ul.wfls-option li.wfls-option-select .wfls-option-select-option,ul.wfls-option li.wfls-option-select .wfselect2-container--default,ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single,.wfls-form-field li.wfls-option-select .wfls-option-select-option,.wfls-form-field li.wfls-option-select .wfselect2-container--default,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single{text-align:left;height:40px;border-radius:0;border:0;background-color:#fff;box-shadow:1px 1px 1px 2px rgba(215,215,215,0.35)}ul.wfls-option li.wfls-option-select .wfls-option-select-option .wfselect2-selection__rendered,ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection__rendered,ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__rendered,.wfls-form-field li.wfls-option-select .wfls-option-select-option .wfselect2-selection__rendered,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection__rendered,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__rendered{color:#333;line-height:40px}ul.wfls-option li.wfls-option-select .wfls-option-select-option .wfselect2-selection__arrow,ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection__arrow,ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow,.wfls-form-field li.wfls-option-select .wfls-option-select-option .wfselect2-selection__arrow,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection__arrow,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow{height:38px}ul.wfls-option li.wfls-option-select .wfls-option-select-option.wfselect2-container--disabled .wfselect2-selection__rendered,ul.wfls-option li.wfls-option-select .wfselect2-container--default.wfselect2-container--disabled .wfselect2-selection__rendered,ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single.wfselect2-container--disabled .wfselect2-selection__rendered,.wfls-form-field li.wfls-option-select .wfls-option-select-option.wfselect2-container--disabled .wfselect2-selection__rendered,.wfls-form-field li.wfls-option-select .wfselect2-container--default.wfselect2-container--disabled .wfselect2-selection__rendered,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single.wfselect2-container--disabled .wfselect2-selection__rendered{color:#aaa}ul.wfls-option li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow b,.wfls-form-field li.wfls-option-select .wfselect2-container--default .wfselect2-selection--single .wfselect2-selection__arrow b{border-color:#333 transparent transparent}ul.wfls-option li.wfls-option-select .wfselect2-container--default.wfselect2-container--open .wfselect2-selection--single .wfselect2-selection__arrow b,.wfls-form-field li.wfls-option-select .wfselect2-container--default.wfselect2-container--open .wfselect2-selection--single .wfselect2-selection__arrow b{border-color:transparent transparent #333}ul.wfls-option.wfls-option-token select,.wfls-form-field.wfls-option-token select{width:240px}@media (min-width: 768px){ul.wfls-option.wfls-option-token select,.wfls-form-field.wfls-option-token select{width:280px}}@media (min-width: 992px){ul.wfls-option.wfls-option-token select,.wfls-form-field.wfls-option-token select{width:320px}}ul.wfls-option.wfls-option-token .wfselect2-container--default,ul.wfls-option.wfls-option-token .wfselect2-container--default .wfselect2-selection--multiple,.wfls-form-field.wfls-option-token .wfselect2-container--default,.wfls-form-field.wfls-option-token .wfselect2-container--default .wfselect2-selection--multiple{border-color:#e2e2e2}ul.wfls-option.wfls-option-token .wfselect2-container--default .wfselect2-selection__choice,ul.wfls-option.wfls-option-token .wfselect2-container--default .wfselect2-selection--multiple .wfselect2-selection__choice,.wfls-form-field.wfls-option-token .wfselect2-container--default .wfselect2-selection__choice,.wfls-form-field.wfls-option-token .wfselect2-container--default .wfselect2-selection--multiple .wfselect2-selection__choice{background-color:#fff;border-color:#e2e2e2;padding:0.5rem}ul.wfls-option.wfls-option-token .wfselect2-container--default .wfselect2-search__field,ul.wfls-option.wfls-option-token .wfselect2-container--default .wfselect2-selection--multiple .wfselect2-search__field,.wfls-form-field.wfls-option-token .wfselect2-container--default .wfselect2-search__field,.wfls-form-field.wfls-option-token .wfselect2-container--default .wfselect2-selection--multiple .wfselect2-search__field{margin-right:5px;margin-top:5px;padding:0.5rem 0}#wfls-option-require-2fa{margin-top:1rem}#wfls-option-require-2fa>li>ul{margin-left:1rem}@media (min-width: 768px){#wfls-option-require-2fa>li>ul{margin-left:1.5rem}}#wfls-option-require-2fa>li>ul:first-of-type{margin-left:0}#wfls-option-require-2fa>li>ul>.wfls-option-checkbox{margin:0 1rem 0 0}.wfls-option-sub{padding-left:2rem !important;margin-left:30px !important}.wfls-select2-suppress-dropdown .wfselect2-results,.wfls-select2-suppress-dropdown .wfselect2-dropdown{display:none}.wfls-options-controls{direction:ltr;background:#ffffff;border-bottom:1px solid #e2e2e2;position:absolute;left:160px;right:0px;top:46px;z-index:900;padding-left:15px;padding-right:15px}@media (min-width: 616px){.wfls-options-controls{position:fixed}}.wfls-options-controls .wfls-block{margin:0}@media (min-width: 782px){.wfls-options-controls .wfls-block{margin:0.5rem 0}}.wfls-options-controls,.sticky-menu .wfls-options-controls{top:32px}.folded .wfls-options-controls{left:36px}@media only screen and (max-width: 960px){.auto-fold .wfls-options-controls{left:36px}}.rtl .wfls-options-controls{right:160px;left:0px}.rtl .folded .wfls-options-controls{right:36px}@media only screen and (max-width: 960px){.rtl .auto-fold .wfls-options-controls{right:36px}}@media screen and (max-width: 782px){.wfls-options-controls,.folded .wfls-options-controls,.auto-fold .wfls-options-controls,.rtl .wfls-options-controls,.rtl .folded .wfls-options-controls,.rtl .auto-fold .wfls-options-controls{left:-10px;right:0px}}.wfls-options-controls-spacer{height:45px}@media (min-width: 782px){.wfls-options-controls-spacer{height:75px}}.wfls-options-controls-spacer,.sticky-menu .wfls-options-controls-spacer{top:61px}.wordfence .wfselect2-container .wfselect2-selection--single{border:1px solid #dadada;font-weight:normal;font-size:0.8rem}#wfls-notices{margin-top:15px}#wfls-notices .wfls-admin-notice{margin-left:0px;margin-right:0px}.wfls-success-text,.wfls-notice-text{display:inline-block;vertical-align:middle;line-height:1.3;font-size:16px;font-weight:bold;font-style:italic}.wfls-notice{margin:12px 0;padding:8px;background-color:#ffffe0;border:1px solid #ffd975;border-width:1px 1px 1px 10px}.wfls-notice-text{color:#6d798c}.wfls-success{margin:12px 0;padding:8px;background-color:#ffffff;border:1px solid #16bc9b;border-width:1px 1px 1px 10px}.wfls-success-text{color:#11967a}.wfls-premium-callout{border:1px solid #dfdfdf;background-color:#ffffff;padding:16px;margin:20px 0 0;text-align:center}.wfls-premium-callout ul{margin:8px 0;padding:0 0 0 15px}.wfls-premium-callout ul li{list-style-type:disc;margin:0;padding:0}.wfls-premium-callout .center{text-align:center;margin:0}.wfls-premium-callout .button-primary{text-align:center;text-transform:uppercase;font-weight:bold;background-color:#00709e}table.wfls-table{background-color:transparent;border-collapse:collapse;border-spacing:0}table.wfls-table td,table.wfls-table th{padding:0}.wfls-table caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}.wfls-table th{text-align:left}.wfls-table{width:100%;max-width:100%;margin-bottom:20px}.wfls-table>thead>tr>th,.wfls-table>thead>tr>td,.wfls-table>tbody>tr>th,.wfls-table>tbody>tr>td,.wfls-table>tfoot>tr>th,.wfls-table>tfoot>tr>td{padding:8px;line-height:1.42857;vertical-align:top;border-top:1px solid #ddd}.wfls-table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.wfls-table>caption+thead>tr:first-child>th,.wfls-table>caption+thead>tr:first-child>td,.wfls-table>colgroup+thead>tr:first-child>th,.wfls-table>colgroup+thead>tr:first-child>td,.wfls-table>thead:first-child>tr:first-child>th,.wfls-table>thead:first-child>tr:first-child>td{border-top:0}.wfls-table>tbody+tbody{border-top:2px solid #ddd}.wfls-table .wfls-table{background-color:#fff}.wfls-table-header-separators>thead>tr>th{border-left:2px solid #ddd}.wfls-table-header-separators>thead>tr>th:first-child{border-left:0}.wfls-table-condensed>thead>tr>th,.wfls-table-condensed>thead>tr>td,.wfls-table-condensed>tbody>tr>th,.wfls-table-condensed>tbody>tr>td,.wfls-table-condensed>tfoot>tr>th,.wfls-table-condensed>tfoot>tr>td{padding:5px}.wfls-table-expanded>thead>tr>th,.wfls-table-expanded>thead>tr>td,.wfls-table-expanded>tbody>tr>th,.wfls-table-expanded>tbody>tr>td,.wfls-table-expanded>tfoot>tr>th,.wfls-table-expanded>tfoot>tr>td{padding:0.5rem 1rem}@media (min-width: 768px){.wfls-table-expanded>thead>tr>th,.wfls-table-expanded>thead>tr>td,.wfls-table-expanded>tbody>tr>th,.wfls-table-expanded>tbody>tr>td,.wfls-table-expanded>tfoot>tr>th,.wfls-table-expanded>tfoot>tr>td{padding:1rem 1.5rem}}.wfls-table-bordered{border:1px solid #ddd}.wfls-table-bordered>thead>tr>th,.wfls-table-bordered>thead>tr>td,.wfls-table-bordered>tbody>tr>th,.wfls-table-bordered>tbody>tr>td,.wfls-table-bordered>tfoot>tr>th,.wfls-table-bordered>tfoot>tr>td{border:1px solid #ddd}.wfls-table-bordered>thead>tr>th,.wfls-table-bordered>thead>tr>td{border-bottom-width:2px}.wfls-table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.wfls-table-hover>tbody>tr:hover{background-color:#f5f5f5}table.wfls-table col[class*="col-"]{position:static;float:none;display:table-column}table.wfls-table td[class*="col-"],table.wfls-table th[class*="col-"]{position:static;float:none;display:table-cell}.wfls-table>thead>tr>td.active,.wfls-table>thead>tr>th.active,.wfls-table>thead>tr.active>td,.wfls-table>thead>tr.active>th,.wfls-table>tbody>tr>td.active,.wfls-table>tbody>tr>th.active,.wfls-table>tbody>tr.active>td,.wfls-table>tbody>tr.active>th,.wfls-table>tfoot>tr>td.active,.wfls-table>tfoot>tr>th.active,.wfls-table>tfoot>tr.active>td,.wfls-table>tfoot>tr.active>th{background-color:#f5f5f5}.wfls-table-hover>tbody>tr>td.active:hover,.wfls-table-hover>tbody>tr>th.active:hover,.wfls-table-hover>tbody>tr.active:hover>td,.wfls-table-hover>tbody>tr:hover>.active,.wfls-table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.wfls-table>thead>tr>td.success,.wfls-table>thead>tr>th.success,.wfls-table>thead>tr.success>td,.wfls-table>thead>tr.success>th,.wfls-table>tbody>tr>td.success,.wfls-table>tbody>tr>th.success,.wfls-table>tbody>tr.success>td,.wfls-table>tbody>tr.success>th,.wfls-table>tfoot>tr>td.success,.wfls-table>tfoot>tr>th.success,.wfls-table>tfoot>tr.success>td,.wfls-table>tfoot>tr.success>th{background-color:#dff0d8}.wfls-table-hover>tbody>tr>td.success:hover,.wfls-table-hover>tbody>tr>th.success:hover,.wfls-table-hover>tbody>tr.success:hover>td,.wfls-table-hover>tbody>tr:hover>.success,.wfls-table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.wfls-table>thead>tr>td.info,.wfls-table>thead>tr>th.info,.wfls-table>thead>tr.info>td,.wfls-table>thead>tr.info>th,.wfls-table>tbody>tr>td.info,.wfls-table>tbody>tr>th.info,.wfls-table>tbody>tr.info>td,.wfls-table>tbody>tr.info>th,.wfls-table>tfoot>tr>td.info,.wfls-table>tfoot>tr>th.info,.wfls-table>tfoot>tr.info>td,.wfls-table>tfoot>tr.info>th{background-color:#d9edf7}.wfls-table-hover>tbody>tr>td.info:hover,.wfls-table-hover>tbody>tr>th.info:hover,.wfls-table-hover>tbody>tr.info:hover>td,.wfls-table-hover>tbody>tr:hover>.info,.wfls-table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.wfls-table>thead>tr>td.warning,.wfls-table>thead>tr>th.warning,.wfls-table>thead>tr.warning>td,.wfls-table>thead>tr.warning>th,.wfls-table>tbody>tr>td.warning,.wfls-table>tbody>tr>th.warning,.wfls-table>tbody>tr.warning>td,.wfls-table>tbody>tr.warning>th,.wfls-table>tfoot>tr>td.warning,.wfls-table>tfoot>tr>th.warning,.wfls-table>tfoot>tr.warning>td,.wfls-table>tfoot>tr.warning>th{background-color:#fcf8e3}.wfls-table-hover>tbody>tr>td.warning:hover,.wfls-table-hover>tbody>tr>th.warning:hover,.wfls-table-hover>tbody>tr.warning:hover>td,.wfls-table-hover>tbody>tr:hover>.warning,.wfls-table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.wfls-table>thead>tr>td.danger,.wfls-table>thead>tr>th.danger,.wfls-table>thead>tr.danger>td,.wfls-table>thead>tr.danger>th,.wfls-table>tbody>tr>td.danger,.wfls-table>tbody>tr>th.danger,.wfls-table>tbody>tr.danger>td,.wfls-table>tbody>tr.danger>th,.wfls-table>tfoot>tr>td.danger,.wfls-table>tfoot>tr>th.danger,.wfls-table>tfoot>tr.danger>td,.wfls-table>tfoot>tr.danger>th{background-color:#f2dede}.wfls-table-hover>tbody>tr>td.danger:hover,.wfls-table-hover>tbody>tr>th.danger:hover,.wfls-table-hover>tbody>tr.danger:hover>td,.wfls-table-hover>tbody>tr:hover>.danger,.wfls-table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.wfls-table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width: 767px){.wfls-table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.wfls-table-responsive>.wfls-table{margin-bottom:0}.wfls-table-responsive>.wfls-table>thead>tr>th,.wfls-table-responsive>.wfls-table>thead>tr>td,.wfls-table-responsive>.wfls-table>tbody>tr>th,.wfls-table-responsive>.wfls-table>tbody>tr>td,.wfls-table-responsive>.wfls-table>tfoot>tr>th,.wfls-table-responsive>.wfls-table>tfoot>tr>td{white-space:nowrap}.wfls-table-responsive>.wfls-table-bordered{border:0}.wfls-table-responsive>.wfls-table-bordered>thead>tr>th:first-child,.wfls-table-responsive>.wfls-table-bordered>thead>tr>td:first-child,.wfls-table-responsive>.wfls-table-bordered>tbody>tr>th:first-child,.wfls-table-responsive>.wfls-table-bordered>tbody>tr>td:first-child,.wfls-table-responsive>.wfls-table-bordered>tfoot>tr>th:first-child,.wfls-table-responsive>.wfls-table-bordered>tfoot>tr>td:first-child{border-left:0}.wfls-table-responsive>.wfls-table-bordered>thead>tr>th:last-child,.wfls-table-responsive>.wfls-table-bordered>thead>tr>td:last-child,.wfls-table-responsive>.wfls-table-bordered>tbody>tr>th:last-child,.wfls-table-responsive>.wfls-table-bordered>tbody>tr>td:last-child,.wfls-table-responsive>.wfls-table-bordered>tfoot>tr>th:last-child,.wfls-table-responsive>.wfls-table-bordered>tfoot>tr>td:last-child{border-right:0}.wfls-table-responsive>.wfls-table-bordered>tbody>tr:last-child>th,.wfls-table-responsive>.wfls-table-bordered>tbody>tr:last-child>td,.wfls-table-responsive>.wfls-table-bordered>tfoot>tr:last-child>th,.wfls-table-responsive>.wfls-table-bordered>tfoot>tr:last-child>td{border-bottom:0}}.wfls-sortable{position:relative;padding-right:2rem !important}.wfls-sortable .wfls-sorted-ascending,.wfls-sortable .wfls-sorted-descending{display:none;position:absolute;right:1rem;top:50%;transform:translateY(-50%)}.wfls-sortable.wfls-unsorted:hover .wfls-sorted-ascending{display:block}.wfls-sortable.wfls-unsorted,.wfls-sortable.wfls-sorted-ascending,.wfls-sortable.wfls-sorted-descending{cursor:pointer}.wfls-sortable.wfls-unsorted:hover,.wfls-sortable.wfls-sorted-ascending:hover,.wfls-sortable.wfls-sorted-descending:hover{background-color:#e0e0e0}.wfls-sortable.wfls-sorted-ascending,.wfls-sortable.wfls-sorted-descending{background-color:#e0e0e0}.wfls-sortable.wfls-sorted-ascending .wfls-sorted-ascending{display:block}.wfls-sortable.wfls-sorted-descending .wfls-sorted-descending{display:block}.wfls-nav{margin-bottom:0;padding-left:0;list-style:none}.wfls-nav:before,.wfls-nav:after{content:" ";display:table}.wfls-nav:after{clear:both}.wfls-nav>li{position:relative;display:block}.wfls-nav>li>a{position:relative;display:block;padding:8px 12px}.wfls-nav>li>a:hover,.wfls-nav>li>a:focus{text-decoration:none;background-color:#e2e2e2}.wfls-nav>li.wfls-disabled>a{color:#777}.wfls-nav>li.wfls-disabled>a:hover,.wfls-nav>li.wfls-disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.wfls-nav .wfls-open>a,.wfls-nav .wfls-open>a:hover,.wfls-nav .wfls-open>a:focus{background-color:#e2e2e2;border-color:#00709e}.wfls-nav>li>a>img{max-width:none}.wfls-nav-tabs{border-bottom:1px solid #d0d0d0}.wfls-nav-tabs>li{float:left;margin-bottom:-1px}.wfls-nav-tabs>li>a{margin-right:2px;line-height:1.42857;border:1px solid transparent;border-radius:4px 4px 0 0}.wfls-nav-tabs>li>a:hover{border-color:#e2e2e2 #e2e2e2 #d0d0d0}.wfls-nav-tabs>li.wfls-active>a,.wfls-nav-tabs>li.wfls-active>a:hover,.wfls-nav-tabs>li.wfls-active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.wfls-nav-pills>li{float:left}.wfls-nav-pills>li>a{border-radius:4px;text-decoration:none;position:relative;display:block;padding:8px 12px}.wfls-nav-pills>li>a:hover,.wfls-nav-pills>li>a:focus{text-decoration:none !important;background-color:#e2e2e2}.wfls-nav-pills>li+li{margin-left:2px}.wfls-nav-pills>li.wfls-active>a,.wfls-nav-pills>li.wfls-active>a:hover,.wfls-nav-pills>li.wfls-active>a:focus{color:#fff;background-color:#00709e}.wfls-nav-pills.wfls-nav-pills-bordered>li>a{border:1px solid #e2e2e2}.wfls-nav-pills.wfls-nav-pills-connected>li>a{border-radius:0;border-right-width:0px}.wfls-nav-pills.wfls-nav-pills-connected>li+li{margin-left:0}.wfls-nav-pills.wfls-nav-pills-connected>li.active+li>a{border-left-width:0px}.wfls-nav-pills.wfls-nav-pills-connected>li:first-of-type>a{-moz-border-radius:4px 0 0 4px;-webkit-border-radius:4px;border-radius:4px 0 0 4px}.wfls-nav-pills.wfls-nav-pills-connected>li:last-of-type>a{-moz-border-radius:0 4px 4px 0;-webkit-border-radius:0;border-radius:0 4px 4px 0;border-right-width:1px}.wfls-nav-stacked>li{float:none}.wfls-nav-stacked>li+li{margin-top:2px;margin-left:0}.wfls-nav-justified,.wfls-nav-tabs.wfls-nav-justified{width:100%}.wfls-nav-justified>li,.wfls-nav-tabs.wfls-nav-justified>li{float:none}.wfls-nav-justified>li>a,.wfls-nav-tabs.wfls-nav-justified>li>a{text-align:center;margin-bottom:5px}.wfls-nav-justified>.wfls-dropdown .wfls-dropdown-menu{top:auto;left:auto}@media (min-width: 768px){.wfls-nav-justified>li,.wfls-nav-tabs.wfls-nav-justified>li{display:table-cell;width:1%}.wfls-nav-justified>li>a,.wfls-nav-tabs.wfls-nav-justified>li>a{margin-bottom:0}}.wfls-nav-tabs-justified,.wfls-nav-tabs.wfls-nav-justified{border-bottom:0}.wfls-nav-tabs-justified>li>a,.wfls-nav-tabs.wfls-nav-justified>li>a{margin-right:0;border-radius:4px}.wfls-nav-tabs-justified>.wfls-active>a,.wfls-nav-tabs.wfls-nav-justified>.wfls-active>a,.wfls-nav-tabs-justified>.wfls-active>a:hover,.wfls-nav-tabs.wfls-nav-justified>.wfls-active>a:hover,.wfls-nav-tabs-justified>.wfls-active>a:focus,.wfls-nav-tabs.wfls-nav-justified>.wfls-active>a:focus{border:1px solid #ddd}@media (min-width: 768px){.wfls-nav-tabs-justified>li>a,.wfls-nav-tabs.wfls-nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.wfls-nav-tabs-justified>.wfls-active>a,.wfls-nav-tabs.wfls-nav-justified>.wfls-active>a,.wfls-nav-tabs-justified>.wfls-active>a:hover,.wfls-nav-tabs.wfls-nav-justified>.wfls-active>a:hover,.wfls-nav-tabs-justified>.wfls-active>a:focus,.wfls-nav-tabs.wfls-nav-justified>.wfls-active>a:focus{border-bottom-color:#fff}}.wfls-tab-content>.wfls-tab-pane{display:none}.wfls-tab-content>.wfls-active{display:block}.wfls-nav-tabs .wfls-dropdown-menu{margin-top:-1px;-moz-border-radius-topleft:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topright:0;-webkit-border-top-right-radius:0;border-top-right-radius:0}.wfls-navbar-brand{float:left;padding:12px 8px;font-size:18px;line-height:20px;margin:10px 0 0 0}.wfls-navbar-brand:hover,.wfls-navbar-brand:focus{text-decoration:none}.wfls-navbar-brand>img{display:block}@media (min-width: 768px){.navbar>.container .wfls-navbar-brand,.navbar>.container-fluid .wfls-navbar-brand{margin-left:-8px}}.wfls-caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.wfls-dropup,.wfls-dropdown{position:relative}.wfls-dropdown-toggle:focus{outline:0}.wfls-dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.wfls-dropdown-menu .wfls-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.wfls-dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857;color:#333;text-decoration:none;white-space:nowrap}.wfls-dropdown-menu>li>a:hover,.wfls-dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.wfls-dropdown-menu>.wfls-active>a,.wfls-dropdown-menu>.wfls-active>a:hover,.wfls-dropdown-menu>.wfls-active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#00709e}.wfls-dropdown-menu>.wfls-disabled>a,.wfls-dropdown-menu>.wfls-disabled>a:hover,.wfls-dropdown-menu>.wfls-disabled>a:focus{color:#777}.wfls-dropdown-menu>.wfls-disabled>a:hover,.wfls-dropdown-menu>.wfls-disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.wfls-open>.wfls-dropdown-menu{display:block}.wfls-open>a{outline:0}.wfls-dropdown-menu-right{left:auto;right:0}.wfls-dropdown-menu-left{left:0;right:auto}.wfls-dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857;color:#777;white-space:nowrap}.wfls-dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.wfls-pull-right>.wfls-dropdown-menu{right:0;left:auto}.wfls-dropup .wfls-caret,.wfls-navbar-fixed-bottom .wfls-dropdown .wfls-caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.wfls-dropup .wfls-dropdown-menu,.wfls-navbar-fixed-bottom .wfls-dropdown .wfls-dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width: 768px){.wfls-navbar-right .wfls-dropdown-menu{right:0;left:auto}.wfls-navbar-right .wfls-dropdown-menu-left{left:0;right:auto}}.wfls-mobile-dropdown{border:1px solid #ccc;margin-left:.5em;padding:5px 10px;font-size:14px;line-height:24px;margin:10px 10px 0 0;background:#f1f1f1;color:#000;font-weight:600;text-decoration:none}table.wfls-dataTable{width:auto;max-width:800px;clear:both;border-collapse:collapse;border-spacing:0}table.wfls-dataTable>thead th,table.wfls-dataTable>tfoot th{font-weight:bold}table.wfls-dataTable>thead th,table.wfls-dataTable>thead td{cursor:pointer;text-align:left;font-size:11px;border:1px solid #ccc;padding:8px 4px 5px 9px;text-transform:uppercase}table.wfls-dataTable>thead th:active,table.wfls-dataTable>thead td:active{outline:none}table.wfls-dataTable>tfoot th,table.wfls-dataTable>tfoot td{padding:10px 18px 6px 18px;border-top:1px solid #111}table.wfls-dataTable>thead .sorting,table.wfls-dataTable>thead .sorting_asc,table.wfls-dataTable>thead .sorting_desc{cursor:pointer;*cursor:hand}table.wfls-dataTable>thead .sorting,table.wfls-dataTable>thead .sorting_asc,table.wfls-dataTable>thead .sorting_desc,table.wfls-dataTable>thead .sorting_asc_disabled,table.wfls-dataTable>thead .sorting_desc_disabled{background-repeat:no-repeat;background-position:center right}table.wfls-dataTable>thead .sorting{background-image:url(../img/sort_both.png)}table.wfls-dataTable>thead .sorting_asc{background-image:url(../img/sort_asc.png)}table.wfls-dataTable>thead .sorting_desc{background-image:url(../img/sort_desc.png)}table.wfls-dataTable>thead .sorting_asc_disabled{background-image:url(../img/sort_asc_disabled.png)}table.wfls-dataTable>thead .sorting_desc_disabled{background-image:url(../img/sort_desc_disabled.png)}table.wfls-dataTable>tbody>tr{background-color:#ffffff}table.wfls-dataTable>tbody>tr.selected{background-color:#B0BED9}table.wfls-dataTable>tbody>tr>th,table.wfls-dataTable>tbody>tr>td{padding:5px 8px}table.wfls-dataTable.row-border>tbody>tr>th,table.wfls-dataTable.row-border>tbody>tr>td,table.wfls-dataTable.display>tbody>tr>th,table.wfls-dataTable.display>tbody>tr>td{border:1px solid #cccccc}table.wfls-dataTable.row-border>tbody>tr:first-child>th,table.wfls-dataTable.row-border>tbody>tr:first-child>td,table.wfls-dataTable.display>tbody>tr:first-child>th,table.wfls-dataTable.display>tbody>tr:first-child>td{border-top:none}table.wfls-dataTable.cell-border>tbody>tr>th,table.wfls-dataTable.cell-border>tbody>tr>td{border-top:1px solid #ddd;border-right:1px solid #ddd}table.wfls-dataTable.cell-border>tbody>tr>th:first-child,table.wfls-dataTable.cell-border>tbody>tr>td:first-child{border-left:1px solid #ddd}table.wfls-dataTable.cell-border>tbody>tr:first-child>th,table.wfls-dataTable.cell-border>tbody>tr:first-child>td{border-top:none}table.wfls-dataTable.stripe>tbody>tr.odd,table.wfls-dataTable.display>tbody>tr.odd{background-color:#f9f9f9}table.wfls-dataTable.stripe>tbody>tr.odd.selected,table.wfls-dataTable.display>tbody>tr.odd.selected{background-color:#acbad4}table.wfls-dataTable.hover>tbody>tr:hover,table.wfls-dataTable.display>tbody>tr:hover{background-color:#f6f6f6}table.wfls-dataTable.hover>tbody>tr:hover.selected,table.wfls-dataTable.display>tbody>tr:hover.selected{background-color:#aab7d1}table.wfls-dataTable.order-column>tbody>tr>.sorting_1,table.wfls-dataTable.order-column>tbody>tr>.sorting_2,table.wfls-dataTable.order-column>tbody>tr>.sorting_3,table.wfls-dataTable.display tbody>tr>.sorting_1,table.wfls-dataTable.display>tbody>tr>.sorting_2,table.wfls-dataTable.display>tbody>tr>.sorting_3{background-color:#fafafa}table.wfls-dataTable.order-column>tbody>tr.selected>.sorting_1,table.wfls-dataTable.order-column>tbody>tr.selected>.sorting_2,table.wfls-dataTable.order-column>tbody>tr.selected>.sorting_3,table.wfls-dataTable.display>tbody>tr.selected>.sorting_1,table.wfls-dataTable.display>tbody>tr.selected>.sorting_2,table.wfls-dataTable.display>tbody>tr.selected>.sorting_3{background-color:#acbad5}table.wfls-dataTable.display>tbody>tr.odd>.sorting_1,table.wfls-dataTable.order-column.stripe>tbody>tr.odd>.sorting_1{background-color:#f1f1f1}table.wfls-dataTable.display>tbody>tr.odd>.sorting_2,table.wfls-dataTable.order-column.stripe>tbody>tr.odd>.sorting_2{background-color:#f3f3f3}table.wfls-dataTable.display>tbody>tr.odd>.sorting_3,table.wfls-dataTable.order-column.stripe>tbody>tr.odd>.sorting_3{background-color:whitesmoke}table.wfls-dataTable.display>tbody>tr.odd.selected>.sorting_1,table.wfls-dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.wfls-dataTable.display>tbody>tr.odd.selected>.sorting_2,table.wfls-dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.wfls-dataTable.display>tbody>tr.odd.selected>.sorting_3,table.wfls-dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.wfls-dataTable.display>tbody>tr.even>.sorting_1,table.wfls-dataTable.order-column.stripe>tbody>tr.even>.sorting_1{background-color:#fafafa}table.wfls-dataTable.display>tbody>tr.even>.sorting_2,table.wfls-dataTable.order-column.stripe>tbody>tr.even>.sorting_2{background-color:#fcfcfc}table.wfls-dataTable.display>tbody>tr.even>.sorting_3,table.wfls-dataTable.order-column.stripe>tbody>tr.even>.sorting_3{background-color:#fefefe}table.wfls-dataTable.display>tbody>tr.even.selected>.sorting_1,table.wfls-dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_1{background-color:#acbad5}table.wfls-dataTable.display>tbody>tr.even.selected>.sorting_2,table.wfls-dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_2{background-color:#aebcd6}table.wfls-dataTable.display>tbody>tr.even.selected>.sorting_3,table.wfls-dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_3{background-color:#afbdd8}table.wfls-dataTable.display>tbody>tr:hover>.sorting_1,table.wfls-dataTable.order-column.hover>tbody>tr:hover>.sorting_1{background-color:#eaeaea}table.wfls-dataTable.display>tbody>tr:hover>.sorting_2,table.wfls-dataTable.order-column.hover>tbody>tr:hover>.sorting_2{background-color:#ececec}table.wfls-dataTable.display>tbody>tr:hover>.sorting_3,table.wfls-dataTable.order-column.hover>tbody>tr:hover>.sorting_3{background-color:#efefef}table.wfls-dataTable.display>tbody>tr:hover.selected>.sorting_1,table.wfls-dataTable.order-column.hover>tbody>tr:hover.selected>.sorting_1{background-color:#a2aec7}table.wfls-dataTable.display>tbody>tr:hover.selected>.sorting_2,table.wfls-dataTable.order-column.hover>tbody>tr:hover.selected>.sorting_2{background-color:#a3b0c9}table.wfls-dataTable.display>tbody>tr:hover.selected>.sorting_3,table.wfls-dataTable.order-column.hover>tbody>tr:hover.selected>.sorting_3{background-color:#a5b2cb}table.wfls-dataTable.no-footer{border-bottom:1px solid #111}table.wfls-dataTable.nowrap th,table.wfls-dataTable.nowrap td{white-space:nowrap}table.wfls-dataTable.compact thead th,table.wfls-dataTable.compact thead td{padding:4px 17px 4px 4px}table.wfls-dataTable.compact tfoot th,table.wfls-dataTable.compact tfoot td{padding:4px}table.wfls-dataTable.compact>tbody>tr>th,table.wfls-dataTable.compact>tbody>tr>td{padding:4px}table.wfls-dataTable th.dt-left,table.wfls-dataTable td.dt-left{text-align:left}table.wfls-dataTable th.dt-center,table.wfls-dataTable td.dt-center,table.wfls-dataTable td.dataTables_empty{text-align:center}table.wfls-dataTable th.dt-right,table.wfls-dataTable td.dt-right{text-align:right}table.wfls-dataTable th.dt-justify,table.wfls-dataTable td.dt-justify{text-align:justify}table.wfls-dataTable th.dt-nowrap,table.wfls-dataTable td.dt-nowrap{white-space:nowrap}table.wfls-dataTable thead th.dt-head-left,table.wfls-dataTable thead td.dt-head-left,table.wfls-dataTable tfoot th.dt-head-left,table.wfls-dataTable tfoot td.dt-head-left{text-align:left}table.wfls-dataTable thead th.dt-head-center,table.wfls-dataTable thead td.dt-head-center,table.wfls-dataTable tfoot th.dt-head-center,table.wfls-dataTable tfoot td.dt-head-center{text-align:center}table.wfls-dataTable thead th.dt-head-right,table.wfls-dataTable thead td.dt-head-right,table.wfls-dataTable tfoot th.dt-head-right,table.wfls-dataTable tfoot td.dt-head-right{text-align:right}table.wfls-dataTable thead th.dt-head-justify,table.wfls-dataTable thead td.dt-head-justify,table.wfls-dataTable tfoot th.dt-head-justify,table.wfls-dataTable tfoot td.dt-head-justify{text-align:justify}table.wfls-dataTable thead th.dt-head-nowrap,table.wfls-dataTable thead td.dt-head-nowrap,table.wfls-dataTable tfoot th.dt-head-nowrap,table.wfls-dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.wfls-dataTable>tbody>tr>th.dt-body-left,table.wfls-dataTable>tbody>tr>td.dt-body-left{text-align:left}table.wfls-dataTable>tbody>tr>th.dt-body-center,table.wfls-dataTable>tbody>tr>td.dt-body-center{text-align:center}table.wfls-dataTable>tbody>tr>th.dt-body-right,table.wfls-dataTable>tbody>tr>td.dt-body-right{text-align:right}table.wfls-dataTable>tbody>tr>th.dt-body-justify,table.wfls-dataTable>tbody>tr>td.dt-body-justify{text-align:justify}table.wfls-dataTable>tbody>tr>th.dt-body-nowrap,table.wfls-dataTable>tbody>tr>td.dt-body-nowrap{white-space:nowrap}table.wfls-dataTable table.dataTable,table.wfls-dataTable th,table.wfls-dataTable td{-webkit-box-sizing:content-box;box-sizing:content-box}.wfls-dataTables_wrapper{position:relative;clear:both;*zoom:1;zoom:1}.wfls-dataTables_wrapper .dataTables_length{float:left}.wfls-dataTables_wrapper .dataTables_filter{float:right;text-align:right}.wfls-dataTables_wrapper .dataTables_filter input{margin-left:0.5em}.wfls-dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:0.755em}.wfls-dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:0.25em}.wfls-dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:0.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;*cursor:hand;color:#333 !important;border:1px solid transparent;border-radius:2px}.wfls-dataTables_wrapper .dataTables_paginate .paginate_button.current,.wfls-dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:#333 !important;border:1px solid #979797;background-color:white;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #fff), color-stop(100%, #dcdcdc));background:-webkit-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-moz-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-ms-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:-o-linear-gradient(top, #fff 0%, #dcdcdc 100%);background:linear-gradient(to bottom, #ffffff 0%,#dcdcdc 100%)}.wfls-dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.wfls-dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.wfls-dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.wfls-dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%,#111111 100%)}.wfls-dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%,#0c0c0c 100%);box-shadow:inset 0 0 3px #111}.wfls-dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.wfls-dataTables_wrapper .dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:40px;margin-left:-50%;margin-top:-25px;padding-top:20px;text-align:center;font-size:1.2em;background-color:white;background:-webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0)));background:-webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:-o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%);background:linear-gradient(to right, rgba(255,255,255,0) 0%,rgba(255,255,255,0.9) 25%,rgba(255,255,255,0.9) 75%,rgba(255,255,255,0) 100%)}.wfls-dataTables_wrapper .dataTables_length,.wfls-dataTables_wrapper .dataTables_filter,.wfls-dataTables_wrapper .dataTables_info,.wfls-dataTables_wrapper .dataTables_processing,.wfls-dataTables_wrapper .dataTables_paginate{color:#333}.wfls-dataTables_wrapper .dataTables_scroll{clear:both}.wfls-dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}.wfls-dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th,.wfls-dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td{vertical-align:middle}.wfls-dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th>div.dataTables_sizing,.wfls-dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.wfls-dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid #111}.wfls-dataTables_wrapper.no-footer div.dataTables_scrollHead table,.wfls-dataTables_wrapper.no-footer div.dataTables_scrollBody table{border-bottom:none}.wfls-dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width: 767px){.wfls-dataTables_wrapper .dataTables_info,.wfls-dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.wfls-dataTables_wrapper .dataTables_paginate{margin-top:0.5em}}@media screen and (max-width: 640px){.wfls-dataTables_wrapper .dataTables_length,.wfls-dataTables_wrapper .dataTables_filter{float:none;text-align:center}.wfls-dataTables_wrapper .dataTables_filter{margin-top:0.5em}}.wfls-alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.wfls-alert h4{margin-top:0;color:inherit}.wfls-alert .wfls-alert-link{font-weight:bold}.wfls-alert>p,.wfls-alert>ul{margin-bottom:0}.wfls-alert>p+p{margin-top:5px}.wfls-alert-dismissable,.wfls-alert-dismissible{padding-right:35px}.wfls-alert-dismissable .close,.wfls-alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.wfls-alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.wfls-alert-success hr{border-top-color:#c9e2b3}.wfls-alert-success .alert-link{color:#2b542c}.wfls-alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.wfls-alert-info hr{border-top-color:#a6e1ec}.wfls-alert-info .alert-link{color:#245269}.wfls-alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.wfls-alert-warning hr{border-top-color:#f7e1b5}.wfls-alert-warning .alert-link{color:#66512c}.wfls-alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.wfls-alert-danger hr{border-top-color:#e4b9c0}.wfls-alert-danger .alert-link{color:#843534}#wfls-onboarding-standalone-modal{margin-bottom:1rem}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-header{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-start;justify-content:flex-start;-webkit-flex-direction:row;flex-direction:row;background-color:#00709e;color:#ffffff;padding:1rem 2rem}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-header #wfls-onboarding-standalone-modal-dismiss{font-size:1.35rem;color:#ffffff;text-decoration:none}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-header #wfls-onboarding-standalone-modal-dismiss:hover{color:#f1f1f1}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-header>*:last-child{-webkit-flex-grow:1;flex-grow:1;text-align:right}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-content{background-color:#ffffff;padding:1rem 2rem}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-content>p{margin-bottom:0}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-content>p:first-child{margin-top:0}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-footer{background-color:#525355;color:#ffffff;padding:0.5rem 2rem}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-footer>ul{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-flex-direction:row;flex-direction:row;margin:0;padding:0}#wfls-onboarding-standalone-modal #wfls-onboarding-standalone-modal-footer>ul>li{margin:0;padding:0 0 0 1rem}#toplevel_page_WFLS .wp-menu-image img{max-width:16px;max-height:16px}
css/colorbox.1559237323.css ADDED
@@ -0,0 +1 @@
 
1
+ #wflscolorbox,#wflscboxOverlay,#wflscboxWrapper{position:absolute;top:0;left:0;z-index:9999;overflow:hidden}#wflscboxOverlay{position:fixed;width:100%;height:100%}#wflscboxMiddleLeft,#wflscboxBottomLeft{clear:left}#wflscboxContent{position:relative}#wflscboxLoadedContent{overflow:auto}#wflscboxTitle{margin:0}#wflscboxLoadingOverlay,#wflscboxLoadingGraphic{position:absolute;top:0;left:0;width:100%}#wflscboxPrevious,#wflscboxNext,#wflscboxClose,#wflscboxSlideshow{cursor:pointer}.wflscboxPhoto{float:left;margin:auto;border:0;display:block}.wflscboxIframe{width:100%;height:100%;display:block;border:0}#wflscboxOverlay{background:#777;background:-webkit-radial-gradient(rgba(120,120,120,0.8), rgba(100,100,100,0.8) 50%, #464646);background:-moz-radial-gradient(rgba(120,120,120,0.6), rgba(100,100,100,0.8) 20%, #464646)}#wflscboxContent{background:#fff;overflow:hidden;padding:0 0 8px;margin:20px;-webkit-border-radius:3px 3px 2px 2px;-moz-border-radius:3px 3px 2px 2px;border-radius:3px 3px 2px 2px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,0.4);-moz-box-shadow:0 2px 4px rgba(0,0,0,0.4);box-shadow:0 2px 4px rgba(0,0,0,0.4);-webkit-background-clip:padding-box}#wflscboxError{padding:50px;border:1px solid #ccc}#wflscboxLoadedContent{margin:10px 20px 28px 20px;font-family:Arial;color:#333;-webkit-border-radius:2px 2px 0 0;-moz-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0}#wflscboxTitle{position:absolute;bottom:8px;left:5px;text-align:center;width:100%;color:#949494}#wflscboxCurrent{position:absolute;bottom:8px;left:63px;color:#949494;text-indent:-9999px}#wflscboxSlideshow{position:absolute;bottom:8px;right:35px;color:#0092ef}#wflscboxPrevious{position:absolute;bottom:5px;left:5px;background:url(../img/lightbox-controls.png) no-repeat -75px 0;width:25px;height:25px;text-indent:-9999px}#wflscboxPrevious.hover{background-position:-75px -25px}#wflscboxNext{position:absolute;bottom:5px;left:32px;background:url(../img/lightbox-controls.png) no-repeat -50px 0;width:25px;height:25px;text-indent:-9999px}#wflscboxNext.hover{background-position:-50px -25px}#wflscboxLoadingOverlay{background:url(../img/loading_background.png) no-repeat center center}#wflscboxLoadingGraphic{background:url(../img/loading.gif) no-repeat center center}#wflscboxClose{position:absolute;bottom:5px;right:5px;background:url(../img/lightbox-controls.png) no-repeat -25px 0;width:25px;height:25px;text-indent:-9999px}#wflscboxClose.hover{background-position:-25px -25px}#wflscolorbox.wfls-modal ul,#wflscolorbox.wfls-modal li{padding:0;margin:0}#wflscolorbox.wfls-modal #wflscboxContent{padding:0}#wflscolorbox.wfls-modal #wflscboxLoadedContent{margin:0}#wflscolorbox.wfls-modal .wfls-modal-success{overflow:auto;background-color:#00709e}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-model-success-wrapper{margin:0.25rem;background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA5MS42NSA3MC43OSI+PHBhdGggZD0iTTkwLjA4LDguNzMsODIuOTEsMS41N2E1LjE5LDUuMTksMCwwLDAtNy40MywwTDMzLjMxLDQzLjc0LDE2LjE2LDI2LjU5YTUuMiw1LjIsMCwwLDAtNy40MywwTDEuNTcsMzMuNzdhNS4xOSw1LjE5LDAsMCwwLDAsNy40M2wyOCwyOGE1LjIsNS4yLDAsMCwwLDcuNDMsMEw5MC4wOCwxNi4xN2E1LjE5LDUuMTksMCwwLDAsMC03LjQzWm0wLDAiIGZpbGw9IiMwMDdjYWMiLz48L3N2Zz4=");background-position:top center;background-repeat:no-repeat}#wflscolorbox.wfls-modal .wfls-modal-header{min-height:44px;padding:1rem;width:100%;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;position:relative;border-bottom:1px solid #d9d9d9}#wflscolorbox.wfls-modal .wfls-modal-header .wfls-modal-header-content{max-width:75%}#wflscolorbox.wfls-modal .wfls-modal-header .wfls-modal-header-content .wfls-modal-title{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:0.95rem;width:100%;transition:color 0.2s ease-in}#wflscolorbox.wfls-modal .wfls-modal-header .wfls-modal-header-content .wfls-modal-subtitle{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;margin-top:.125rem;margin-bottom:.125rem;font-size:.575rem;color:#4f748e}#wflscolorbox.wfls-modal .wfls-modal-header .wfls-modal-header-action{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:flex-end;justify-content:flex-end}#wflscolorbox.wfls-modal .wfls-modal-header .wfls-modal-header-action .wfls-modal-header-action-close a{color:#525355}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-modal-header{border-bottom:0px}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-modal-header .wfls-modal-header-content{max-width:100%;width:100%;padding-top:1rem}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-modal-header .wfls-modal-header-content .wfls-modal-title{font-size:1.3125rem;font-weight:300;line-height:1.5;text-align:center;color:#ffffff}#wflscolorbox.wfls-modal .wfls-modal-content{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;padding:1rem}#wflscolorbox.wfls-modal .wfls-modal-content>*:first-child{margin-top:0}#wflscolorbox.wfls-modal .wfls-modal-content select,#wflscolorbox.wfls-modal .wfls-modal-content select option,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default{font-size:0.7rem;font-weight:bold}@media (min-width: 768px){#wflscolorbox.wfls-modal .wfls-modal-content select,#wflscolorbox.wfls-modal .wfls-modal-content select option,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default{font-size:0.8rem}}@media (min-width: 992px){#wflscolorbox.wfls-modal .wfls-modal-content select,#wflscolorbox.wfls-modal .wfls-modal-content select option,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default{font-size:0.9rem}}#wflscolorbox.wfls-modal .wfls-modal-content .wfls-option-select-option,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection--single{text-align:left;height:40px;border-radius:0;border:0;background-color:#ffffff;box-shadow:1px 1px 1px 2px rgba(215,215,215,0.35)}#wflscolorbox.wfls-modal .wfls-modal-content .wfls-option-select-option .wflsselect2-selection__rendered,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection__rendered,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection--single .wflsselect2-selection__rendered{color:#333;line-height:40px}#wflscolorbox.wfls-modal .wfls-modal-content .wfls-option-select-option .wflsselect2-selection__arrow,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection__arrow,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection--single .wflsselect2-selection__arrow{height:38px}#wflscolorbox.wfls-modal .wfls-modal-content .wfls-option-select-option.wflsselect2-container--disabled .wflsselect2-selection__rendered,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default.wflsselect2-container--disabled .wflsselect2-selection__rendered,#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection--single.wflsselect2-container--disabled .wflsselect2-selection__rendered{color:#aaa}#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default .wflsselect2-selection--single .wflsselect2-selection__arrow b{border-color:#333 transparent transparent}#wflscolorbox.wfls-modal .wfls-modal-content .wflsselect2-container--default.wflsselect2-container--open .wflsselect2-selection--single .wflsselect2-selection__arrow b{border-color:transparent transparent #333}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-modal-content{text-align:center;color:#ffffff;padding:0 1.5rem 2rem 1.5rem}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-modal-content a{text-decoration:underline;color:#fff}#wflscolorbox.wfls-modal .wfls-modal-footer{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;min-height:44px;padding:1rem;width:100%;box-sizing:border-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:space-between;justify-content:space-between;position:relative;background-color:#f1f1f1;border-top:1px solid #d9d9d9}#wflscolorbox.wfls-modal .wfls-modal-success .wfls-modal-footer{background-color:#ccc;border-top:1px solid #bfbfbf}#wflscolorbox,#wflscolorbox:before,#wflscolorbox:after{box-sizing:content-box}#wflscolorbox h1,#wflscolorbox h2,#wflscolorbox h3,#wflscolorbox h4,#wflscolorbox h5,#wflscolorbox h6{display:block;font-weight:600}#wflscolorbox h1{font-size:2em;margin:.67em 0}#wflscolorbox h2,#wflscolorbox h3{font-size:1.3em;margin:1em 0}#wflscolorbox h1,#wflscolorbox h2,#wflscolorbox h3{color:#23282d}#wflscolorbox p{font-size:13px;line-height:1.5;margin:1em 0}
css/font-awesome.1559237323.css ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ /*!
2
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
3
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4
+ */@font-face{font-family:'FontAwesome';src:url("../font/fontawesome-webfont.woff?v=4.7.0") format("woff");font-weight:normal;font-style:normal}.wfls-fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.wfls-fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.wfls-fa-2x{font-size:2em}.wfls-fa-3x{font-size:3em}.wfls-fa-4x{font-size:4em}.wfls-fa-5x{font-size:5em}.wfls-fa-fw{width:1.28571em;text-align:center}.wfls-fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.wfls-fa-ul>li{position:relative}.wfls-fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.wfls-fa-li.wfls-fa-lg{left:-1.85714em}.wfls-fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.wfls-fa-pull-left{float:left}.wfls-fa-pull-right{float:right}.wfls-fa.wfls-fa-pull-left{margin-right:.3em}.wfls-fa.wfls-fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.wfls-fa.pull-left{margin-right:.3em}.wfls-fa.pull-right{margin-left:.3em}.wfls-fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.wfls-fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.wfls-fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.wfls-fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.wfls-fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.wfls-fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.wfls-fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .wfls-fa-rotate-90,:root .wfls-fa-rotate-180,:root .wfls-fa-rotate-270,:root .wfls-fa-flip-horizontal,:root .wfls-fa-flip-vertical{filter:none}.wfls-fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.wfls-fa-stack-1x,.wfls-fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.wfls-fa-stack-1x{line-height:inherit}.wfls-fa-stack-2x{font-size:2em}.wfls-fa-inverse{color:#fff}.wfls-fa-glass:before{content:""}.wfls-fa-music:before{content:""}.wfls-fa-search:before{content:""}.wfls-fa-envelope-o:before{content:""}.wfls-fa-heart:before{content:""}.wfls-fa-star:before{content:""}.wfls-fa-star-o:before{content:""}.wfls-fa-user:before{content:""}.wfls-fa-film:before{content:""}.wfls-fa-th-large:before{content:""}.wfls-fa-th:before{content:""}.wfls-fa-th-list:before{content:""}.wfls-fa-check:before{content:""}.wfls-fa-remove:before,.wfls-fa-close:before,.wfls-fa-times:before{content:""}.wfls-fa-search-plus:before{content:""}.wfls-fa-search-minus:before{content:""}.wfls-fa-power-off:before{content:""}.wfls-fa-signal:before{content:""}.wfls-fa-gear:before,.wfls-fa-cog:before{content:""}.wfls-fa-trash-o:before{content:""}.wfls-fa-home:before{content:""}.wfls-fa-file-o:before{content:""}.wfls-fa-clock-o:before{content:""}.wfls-fa-road:before{content:""}.wfls-fa-download:before{content:""}.wfls-fa-arrow-circle-o-down:before{content:""}.wfls-fa-arrow-circle-o-up:before{content:""}.wfls-fa-inbox:before{content:""}.wfls-fa-play-circle-o:before{content:""}.wfls-fa-rotate-right:before,.wfls-fa-repeat:before{content:""}.wfls-fa-refresh:before{content:""}.wfls-fa-list-alt:before{content:""}.wfls-fa-lock:before{content:""}.wfls-fa-flag:before{content:""}.wfls-fa-headphones:before{content:""}.wfls-fa-volume-off:before{content:""}.wfls-fa-volume-down:before{content:""}.wfls-fa-volume-up:before{content:""}.wfls-fa-qrcode:before{content:""}.wfls-fa-barcode:before{content:""}.wfls-fa-tag:before{content:""}.wfls-fa-tags:before{content:""}.wfls-fa-book:before{content:""}.wfls-fa-bookmark:before{content:""}.wfls-fa-print:before{content:""}.wfls-fa-camera:before{content:""}.wfls-fa-font:before{content:""}.wfls-fa-bold:before{content:""}.wfls-fa-italic:before{content:""}.wfls-fa-text-height:before{content:""}.wfls-fa-text-width:before{content:""}.wfls-fa-align-left:before{content:""}.wfls-fa-align-center:before{content:""}.wfls-fa-align-right:before{content:""}.wfls-fa-align-justify:before{content:""}.wfls-fa-list:before{content:""}.wfls-fa-dedent:before,.wfls-fa-outdent:before{content:""}.wfls-fa-indent:before{content:""}.wfls-fa-video-camera:before{content:""}.wfls-fa-photo:before,.wfls-fa-image:before,.wfls-fa-picture-o:before{content:""}.wfls-fa-pencil:before{content:""}.wfls-fa-map-marker:before{content:""}.wfls-fa-adjust:before{content:""}.wfls-fa-tint:before{content:""}.wfls-fa-edit:before,.wfls-fa-pencil-square-o:before{content:""}.wfls-fa-share-square-o:before{content:""}.wfls-fa-check-square-o:before{content:""}.wfls-fa-arrows:before{content:""}.wfls-fa-step-backward:before{content:""}.wfls-fa-fast-backward:before{content:""}.wfls-fa-backward:before{content:""}.wfls-fa-play:before{content:""}.wfls-fa-pause:before{content:""}.wfls-fa-stop:before{content:""}.wfls-fa-forward:before{content:""}.wfls-fa-fast-forward:before{content:""}.wfls-fa-step-forward:before{content:""}.wfls-fa-eject:before{content:""}.wfls-fa-chevron-left:before{content:""}.wfls-fa-chevron-right:before{content:""}.wfls-fa-plus-circle:before{content:""}.wfls-fa-minus-circle:before{content:""}.wfls-fa-times-circle:before{content:""}.wfls-fa-check-circle:before{content:""}.wfls-fa-question-circle:before{content:""}.wfls-fa-info-circle:before{content:""}.wfls-fa-crosshairs:before{content:""}.wfls-fa-times-circle-o:before{content:""}.wfls-fa-check-circle-o:before{content:""}.wfls-fa-ban:before{content:""}.wfls-fa-arrow-left:before{content:""}.wfls-fa-arrow-right:before{content:""}.wfls-fa-arrow-up:before{content:""}.wfls-fa-arrow-down:before{content:""}.wfls-fa-mail-forward:before,.wfls-fa-share:before{content:""}.wfls-fa-expand:before{content:""}.wfls-fa-compress:before{content:""}.wfls-fa-plus:before{content:""}.wfls-fa-minus:before{content:""}.wfls-fa-asterisk:before{content:""}.wfls-fa-exclamation-circle:before{content:""}.wfls-fa-gift:before{content:""}.wfls-fa-leaf:before{content:""}.wfls-fa-fire:before{content:""}.wfls-fa-eye:before{content:""}.wfls-fa-eye-slash:before{content:""}.wfls-fa-warning:before,.wfls-fa-exclamation-triangle:before{content:""}.wfls-fa-plane:before{content:""}.wfls-fa-calendar:before{content:""}.wfls-fa-random:before{content:""}.wfls-fa-comment:before{content:""}.wfls-fa-magnet:before{content:""}.wfls-fa-chevron-up:before{content:""}.wfls-fa-chevron-down:before{content:""}.wfls-fa-retweet:before{content:""}.wfls-fa-shopping-cart:before{content:""}.wfls-fa-folder:before{content:""}.wfls-fa-folder-open:before{content:""}.wfls-fa-arrows-v:before{content:""}.wfls-fa-arrows-h:before{content:""}.wfls-fa-bar-chart-o:before,.wfls-fa-bar-chart:before{content:""}.wfls-fa-twitter-square:before{content:""}.wfls-fa-facebook-square:before{content:""}.wfls-fa-camera-retro:before{content:""}.wfls-fa-key:before{content:""}.wfls-fa-gears:before,.wfls-fa-cogs:before{content:""}.wfls-fa-comments:before{content:""}.wfls-fa-thumbs-o-up:before{content:""}.wfls-fa-thumbs-o-down:before{content:""}.wfls-fa-star-half:before{content:""}.wfls-fa-heart-o:before{content:""}.wfls-fa-sign-out:before{content:""}.wfls-fa-linkedin-square:before{content:""}.wfls-fa-thumb-tack:before{content:""}.wfls-fa-external-link:before{content:""}.wfls-fa-sign-in:before{content:""}.wfls-fa-trophy:before{content:""}.wfls-fa-github-square:before{content:""}.wfls-fa-upload:before{content:""}.wfls-fa-lemon-o:before{content:""}.wfls-fa-phone:before{content:""}.wfls-fa-square-o:before{content:""}.wfls-fa-bookmark-o:before{content:""}.wfls-fa-phone-square:before{content:""}.wfls-fa-twitter:before{content:""}.wfls-fa-facebook-f:before,.wfls-fa-facebook:before{content:""}.wfls-fa-github:before{content:""}.wfls-fa-unlock:before{content:""}.wfls-fa-credit-card:before{content:""}.wfls-fa-feed:before,.wfls-fa-rss:before{content:""}.wfls-fa-hdd-o:before{content:""}.wfls-fa-bullhorn:before{content:""}.wfls-fa-bell:before{content:""}.wfls-fa-certificate:before{content:""}.wfls-fa-hand-o-right:before{content:""}.wfls-fa-hand-o-left:before{content:""}.wfls-fa-hand-o-up:before{content:""}.wfls-fa-hand-o-down:before{content:""}.wfls-fa-arrow-circle-left:before{content:""}.wfls-fa-arrow-circle-right:before{content:""}.wfls-fa-arrow-circle-up:before{content:""}.wfls-fa-arrow-circle-down:before{content:""}.wfls-fa-globe:before{content:""}.wfls-fa-wrench:before{content:""}.wfls-fa-tasks:before{content:""}.wfls-fa-filter:before{content:""}.wfls-fa-briefcase:before{content:""}.wfls-fa-arrows-alt:before{content:""}.wfls-fa-group:before,.wfls-fa-users:before{content:""}.wfls-fa-chain:before,.wfls-fa-link:before{content:""}.wfls-fa-cloud:before{content:""}.wfls-fa-flask:before{content:""}.wfls-fa-cut:before,.wfls-fa-scissors:before{content:""}.wfls-fa-copy:before,.wfls-fa-files-o:before{content:""}.wfls-fa-paperclip:before{content:""}.wfls-fa-save:before,.wfls-fa-floppy-o:before{content:""}.wfls-fa-square:before{content:""}.wfls-fa-navicon:before,.wfls-fa-reorder:before,.wfls-fa-bars:before{content:""}.wfls-fa-list-ul:before{content:""}.wfls-fa-list-ol:before{content:""}.wfls-fa-strikethrough:before{content:""}.wfls-fa-underline:before{content:""}.wfls-fa-table:before{content:""}.wfls-fa-magic:before{content:""}.wfls-fa-truck:before{content:""}.wfls-fa-pinterest:before{content:""}.wfls-fa-pinterest-square:before{content:""}.wfls-fa-google-plus-square:before{content:""}.wfls-fa-google-plus:before{content:""}.wfls-fa-money:before{content:""}.wfls-fa-caret-down:before{content:""}.wfls-fa-caret-up:before{content:""}.wfls-fa-caret-left:before{content:""}.wfls-fa-caret-right:before{content:""}.wfls-fa-columns:before{content:""}.wfls-fa-unsorted:before,.wfls-fa-sort:before{content:""}.wfls-fa-sort-down:before,.wfls-fa-sort-desc:before{content:""}.wfls-fa-sort-up:before,.wfls-fa-sort-asc:before{content:""}.wfls-fa-envelope:before{content:""}.wfls-fa-linkedin:before{content:""}.wfls-fa-rotate-left:before,.wfls-fa-undo:before{content:""}.wfls-fa-legal:before,.wfls-fa-gavel:before{content:""}.wfls-fa-dashboard:before,.wfls-fa-tachometer:before{content:""}.wfls-fa-comment-o:before{content:""}.wfls-fa-comments-o:before{content:""}.wfls-fa-flash:before,.wfls-fa-bolt:before{content:""}.wfls-fa-sitemap:before{content:""}.wfls-fa-umbrella:before{content:""}.wfls-fa-paste:before,.wfls-fa-clipboard:before{content:""}.wfls-fa-lightbulb-o:before{content:""}.wfls-fa-exchange:before{content:""}.wfls-fa-cloud-download:before{content:""}.wfls-fa-cloud-upload:before{content:""}.wfls-fa-user-md:before{content:""}.wfls-fa-stethoscope:before{content:""}.wfls-fa-suitcase:before{content:""}.wfls-fa-bell-o:before{content:""}.wfls-fa-coffee:before{content:""}.wfls-fa-cutlery:before{content:""}.wfls-fa-file-text-o:before{content:""}.wfls-fa-building-o:before{content:""}.wfls-fa-hospital-o:before{content:""}.wfls-fa-ambulance:before{content:""}.wfls-fa-medkit:before{content:""}.wfls-fa-fighter-jet:before{content:""}.wfls-fa-beer:before{content:""}.wfls-fa-h-square:before{content:""}.wfls-fa-plus-square:before{content:""}.wfls-fa-angle-double-left:before{content:""}.wfls-fa-angle-double-right:before{content:""}.wfls-fa-angle-double-up:before{content:""}.wfls-fa-angle-double-down:before{content:""}.wfls-fa-angle-left:before{content:""}.wfls-fa-angle-right:before{content:""}.wfls-fa-angle-up:before{content:""}.wfls-fa-angle-down:before{content:""}.wfls-fa-desktop:before{content:""}.wfls-fa-laptop:before{content:""}.wfls-fa-tablet:before{content:""}.wfls-fa-mobile-phone:before,.wfls-fa-mobile:before{content:""}.wfls-fa-circle-o:before{content:""}.wfls-fa-quote-left:before{content:""}.wfls-fa-quote-right:before{content:""}.wfls-fa-spinner:before{content:""}.wfls-fa-circle:before{content:""}.wfls-fa-mail-reply:before,.wfls-fa-reply:before{content:""}.wfls-fa-github-alt:before{content:""}.wfls-fa-folder-o:before{content:""}.wfls-fa-folder-open-o:before{content:""}.wfls-fa-smile-o:before{content:""}.wfls-fa-frown-o:before{content:""}.wfls-fa-meh-o:before{content:""}.wfls-fa-gamepad:before{content:""}.wfls-fa-keyboard-o:before{content:""}.wfls-fa-flag-o:before{content:""}.wfls-fa-flag-checkered:before{content:""}.wfls-fa-terminal:before{content:""}.wfls-fa-code:before{content:""}.wfls-fa-mail-reply-all:before,.wfls-fa-reply-all:before{content:""}.wfls-fa-star-half-empty:before,.wfls-fa-star-half-full:before,.wfls-fa-star-half-o:before{content:""}.wfls-fa-location-arrow:before{content:""}.wfls-fa-crop:before{content:""}.wfls-fa-code-fork:before{content:""}.wfls-fa-unlink:before,.wfls-fa-chain-broken:before{content:""}.wfls-fa-question:before{content:""}.wfls-fa-info:before{content:""}.wfls-fa-exclamation:before{content:""}.wfls-fa-superscript:before{content:""}.wfls-fa-subscript:before{content:""}.wfls-fa-eraser:before{content:""}.wfls-fa-puzzle-piece:before{content:""}.wfls-fa-microphone:before{content:""}.wfls-fa-microphone-slash:before{content:""}.wfls-fa-shield:before{content:""}.wfls-fa-calendar-o:before{content:""}.wfls-fa-fire-extinguisher:before{content:""}.wfls-fa-rocket:before{content:""}.wfls-fa-maxcdn:before{content:""}.wfls-fa-chevron-circle-left:before{content:""}.wfls-fa-chevron-circle-right:before{content:""}.wfls-fa-chevron-circle-up:before{content:""}.wfls-fa-chevron-circle-down:before{content:""}.wfls-fa-html5:before{content:""}.wfls-fa-css3:before{content:""}.wfls-fa-anchor:before{content:""}.wfls-fa-unlock-alt:before{content:""}.wfls-fa-bullseye:before{content:""}.wfls-fa-ellipsis-h:before{content:""}.wfls-fa-ellipsis-v:before{content:""}.wfls-fa-rss-square:before{content:""}.wfls-fa-play-circle:before{content:""}.wfls-fa-ticket:before{content:""}.wfls-fa-minus-square:before{content:""}.wfls-fa-minus-square-o:before{content:""}.wfls-fa-level-up:before{content:""}.wfls-fa-level-down:before{content:""}.wfls-fa-check-square:before{content:""}.wfls-fa-pencil-square:before{content:""}.wfls-fa-external-link-square:before{content:""}.wfls-fa-share-square:before{content:""}.wfls-fa-compass:before{content:""}.wfls-fa-toggle-down:before,.wfls-fa-caret-square-o-down:before{content:""}.wfls-fa-toggle-up:before,.wfls-fa-caret-square-o-up:before{content:""}.wfls-fa-toggle-right:before,.wfls-fa-caret-square-o-right:before{content:""}.wfls-fa-euro:before,.wfls-fa-eur:before{content:""}.wfls-fa-gbp:before{content:""}.wfls-fa-dollar:before,.wfls-fa-usd:before{content:""}.wfls-fa-rupee:before,.wfls-fa-inr:before{content:""}.wfls-fa-cny:before,.wfls-fa-rmb:before,.wfls-fa-yen:before,.wfls-fa-jpy:before{content:""}.wfls-fa-ruble:before,.wfls-fa-rouble:before,.wfls-fa-rub:before{content:""}.wfls-fa-won:before,.wfls-fa-krw:before{content:""}.wfls-fa-bitcoin:before,.wfls-fa-btc:before{content:""}.wfls-fa-file:before{content:""}.wfls-fa-file-text:before{content:""}.wfls-fa-sort-alpha-asc:before{content:""}.wfls-fa-sort-alpha-desc:before{content:""}.wfls-fa-sort-amount-asc:before{content:""}.wfls-fa-sort-amount-desc:before{content:""}.wfls-fa-sort-numeric-asc:before{content:""}.wfls-fa-sort-numeric-desc:before{content:""}.wfls-fa-thumbs-up:before{content:""}.wfls-fa-thumbs-down:before{content:""}.wfls-fa-youtube-square:before{content:""}.wfls-fa-youtube:before{content:""}.wfls-fa-xing:before{content:""}.wfls-fa-xing-square:before{content:""}.wfls-fa-youtube-play:before{content:""}.wfls-fa-dropbox:before{content:""}.wfls-fa-stack-overflow:before{content:""}.wfls-fa-instagram:before{content:""}.wfls-fa-flickr:before{content:""}.wfls-fa-adn:before{content:""}.wfls-fa-bitbucket:before{content:""}.wfls-fa-bitbucket-square:before{content:""}.wfls-fa-tumblr:before{content:""}.wfls-fa-tumblr-square:before{content:""}.wfls-fa-long-arrow-down:before{content:""}.wfls-fa-long-arrow-up:before{content:""}.wfls-fa-long-arrow-left:before{content:""}.wfls-fa-long-arrow-right:before{content:""}.wfls-fa-apple:before{content:""}.wfls-fa-windows:before{content:""}.wfls-fa-android:before{content:""}.wfls-fa-linux:before{content:""}.wfls-fa-dribbble:before{content:""}.wfls-fa-skype:before{content:""}.wfls-fa-foursquare:before{content:""}.wfls-fa-trello:before{content:""}.wfls-fa-female:before{content:""}.wfls-fa-male:before{content:""}.wfls-fa-gittip:before,.wfls-fa-gratipay:before{content:""}.wfls-fa-sun-o:before{content:""}.wfls-fa-moon-o:before{content:""}.wfls-fa-archive:before{content:""}.wfls-fa-bug:before{content:""}.wfls-fa-vk:before{content:""}.wfls-fa-weibo:before{content:""}.wfls-fa-renren:before{content:""}.wfls-fa-pagelines:before{content:""}.wfls-fa-stack-exchange:before{content:""}.wfls-fa-arrow-circle-o-right:before{content:""}.wfls-fa-arrow-circle-o-left:before{content:""}.wfls-fa-toggle-left:before,.wfls-fa-caret-square-o-left:before{content:""}.wfls-fa-dot-circle-o:before{content:""}.wfls-fa-wheelchair:before{content:""}.wfls-fa-vimeo-square:before{content:""}.wfls-fa-turkish-lira:before,.wfls-fa-try:before{content:""}.wfls-fa-plus-square-o:before{content:""}.wfls-fa-space-shuttle:before{content:""}.wfls-fa-slack:before{content:""}.wfls-fa-envelope-square:before{content:""}.wfls-fa-wordpress:before{content:""}.wfls-fa-openid:before{content:""}.wfls-fa-institution:before,.wfls-fa-bank:before,.wfls-fa-university:before{content:""}.wfls-fa-mortar-board:before,.wfls-fa-graduation-cap:before{content:""}.wfls-fa-yahoo:before{content:""}.wfls-fa-google:before{content:""}.wfls-fa-reddit:before{content:""}.wfls-fa-reddit-square:before{content:""}.wfls-fa-stumbleupon-circle:before{content:""}.wfls-fa-stumbleupon:before{content:""}.wfls-fa-delicious:before{content:""}.wfls-fa-digg:before{content:""}.wfls-fa-pied-piper-pp:before{content:""}.wfls-fa-pied-piper-alt:before{content:""}.wfls-fa-drupal:before{content:""}.wfls-fa-joomla:before{content:""}.wfls-fa-language:before{content:""}.wfls-fa-fax:before{content:""}.wfls-fa-building:before{content:""}.wfls-fa-child:before{content:""}.wfls-fa-paw:before{content:""}.wfls-fa-spoon:before{content:""}.wfls-fa-cube:before{content:""}.wfls-fa-cubes:before{content:""}.wfls-fa-behance:before{content:""}.wfls-fa-behance-square:before{content:""}.wfls-fa-steam:before{content:""}.wfls-fa-steam-square:before{content:""}.wfls-fa-recycle:before{content:""}.wfls-fa-automobile:before,.wfls-fa-car:before{content:""}.wfls-fa-cab:before,.wfls-fa-taxi:before{content:""}.wfls-fa-tree:before{content:""}.wfls-fa-spotify:before{content:""}.wfls-fa-deviantart:before{content:""}.wfls-fa-soundcloud:before{content:""}.wfls-fa-database:before{content:""}.wfls-fa-file-pdf-o:before{content:""}.wfls-fa-file-word-o:before{content:""}.wfls-fa-file-excel-o:before{content:""}.wfls-fa-file-powerpoint-o:before{content:""}.wfls-fa-file-photo-o:before,.wfls-fa-file-picture-o:before,.wfls-fa-file-image-o:before{content:""}.wfls-fa-file-zip-o:before,.wfls-fa-file-archive-o:before{content:""}.wfls-fa-file-sound-o:before,.wfls-fa-file-audio-o:before{content:""}.wfls-fa-file-movie-o:before,.wfls-fa-file-video-o:before{content:""}.wfls-fa-file-code-o:before{content:""}.wfls-fa-vine:before{content:""}.wfls-fa-codepen:before{content:""}.wfls-fa-jsfiddle:before{content:""}.wfls-fa-life-bouy:before,.wfls-fa-life-buoy:before,.wfls-fa-life-saver:before,.wfls-fa-support:before,.wfls-fa-life-ring:before{content:""}.wfls-fa-circle-o-notch:before{content:""}.wfls-fa-ra:before,.wfls-fa-resistance:before,.wfls-fa-rebel:before{content:""}.wfls-fa-ge:before,.wfls-fa-empire:before{content:""}.wfls-fa-git-square:before{content:""}.wfls-fa-git:before{content:""}.wfls-fa-y-combinator-square:before,.wfls-fa-yc-square:before,.wfls-fa-hacker-news:before{content:""}.wfls-fa-tencent-weibo:before{content:""}.wfls-fa-qq:before{content:""}.wfls-fa-wechat:before,.wfls-fa-weixin:before{content:""}.wfls-fa-send:before,.wfls-fa-paper-plane:before{content:""}.wfls-fa-send-o:before,.wfls-fa-paper-plane-o:before{content:""}.wfls-fa-history:before{content:""}.wfls-fa-circle-thin:before{content:""}.wfls-fa-header:before{content:""}.wfls-fa-paragraph:before{content:""}.wfls-fa-sliders:before{content:""}.wfls-fa-share-alt:before{content:""}.wfls-fa-share-alt-square:before{content:""}.wfls-fa-bomb:before{content:""}.wfls-fa-soccer-ball-o:before,.wfls-fa-futbol-o:before{content:""}.wfls-fa-tty:before{content:""}.wfls-fa-binoculars:before{content:""}.wfls-fa-plug:before{content:""}.wfls-fa-slideshare:before{content:""}.wfls-fa-twitch:before{content:""}.wfls-fa-yelp:before{content:""}.wfls-fa-newspaper-o:before{content:""}.wfls-fa-wifi:before{content:""}.wfls-fa-calculator:before{content:""}.wfls-fa-paypal:before{content:""}.wfls-fa-google-wallet:before{content:""}.wfls-fa-cc-visa:before{content:""}.wfls-fa-cc-mastercard:before{content:""}.wfls-fa-cc-discover:before{content:""}.wfls-fa-cc-amex:before{content:""}.wfls-fa-cc-paypal:before{content:""}.wfls-fa-cc-stripe:before{content:""}.wfls-fa-bell-slash:before{content:""}.wfls-fa-bell-slash-o:before{content:""}.wfls-fa-trash:before{content:""}.wfls-fa-copyright:before{content:""}.wfls-fa-at:before{content:""}.wfls-fa-eyedropper:before{content:""}.wfls-fa-paint-brush:before{content:""}.wfls-fa-birthday-cake:before{content:""}.wfls-fa-area-chart:before{content:""}.wfls-fa-pie-chart:before{content:""}.wfls-fa-line-chart:before{content:""}.wfls-fa-lastfm:before{content:""}.wfls-fa-lastfm-square:before{content:""}.wfls-fa-toggle-off:before{content:""}.wfls-fa-toggle-on:before{content:""}.wfls-fa-bicycle:before{content:""}.wfls-fa-bus:before{content:""}.wfls-fa-ioxhost:before{content:""}.wfls-fa-angellist:before{content:""}.wfls-fa-cc:before{content:""}.wfls-fa-shekel:before,.wfls-fa-sheqel:before,.wfls-fa-ils:before{content:""}.wfls-fa-meanpath:before{content:""}.wfls-fa-buysellads:before{content:""}.wfls-fa-connectdevelop:before{content:""}.wfls-fa-dashcube:before{content:""}.wfls-fa-forumbee:before{content:""}.wfls-fa-leanpub:before{content:""}.wfls-fa-sellsy:before{content:""}.wfls-fa-shirtsinbulk:before{content:""}.wfls-fa-simplybuilt:before{content:""}.wfls-fa-skyatlas:before{content:""}.wfls-fa-cart-plus:before{content:""}.wfls-fa-cart-arrow-down:before{content:""}.wfls-fa-diamond:before{content:""}.wfls-fa-ship:before{content:""}.wfls-fa-user-secret:before{content:""}.wfls-fa-motorcycle:before{content:""}.wfls-fa-street-view:before{content:""}.wfls-fa-heartbeat:before{content:""}.wfls-fa-venus:before{content:""}.wfls-fa-mars:before{content:""}.wfls-fa-mercury:before{content:""}.wfls-fa-intersex:before,.wfls-fa-transgender:before{content:""}.wfls-fa-transgender-alt:before{content:""}.wfls-fa-venus-double:before{content:""}.wfls-fa-mars-double:before{content:""}.wfls-fa-venus-mars:before{content:""}.wfls-fa-mars-stroke:before{content:""}.wfls-fa-mars-stroke-v:before{content:""}.wfls-fa-mars-stroke-h:before{content:""}.wfls-fa-neuter:before{content:""}.wfls-fa-genderless:before{content:""}.wfls-fa-facebook-official:before{content:""}.wfls-fa-pinterest-p:before{content:""}.wfls-fa-whatsapp:before{content:""}.wfls-fa-server:before{content:""}.wfls-fa-user-plus:before{content:""}.wfls-fa-user-times:before{content:""}.wfls-fa-hotel:before,.wfls-fa-bed:before{content:""}.wfls-fa-viacoin:before{content:""}.wfls-fa-train:before{content:""}.wfls-fa-subway:before{content:""}.wfls-fa-medium:before{content:""}.wfls-fa-yc:before,.wfls-fa-y-combinator:before{content:""}.wfls-fa-optin-monster:before{content:""}.wfls-fa-opencart:before{content:""}.wfls-fa-expeditedssl:before{content:""}.wfls-fa-battery-4:before,.wfls-fa-battery:before,.wfls-fa-battery-full:before{content:""}.wfls-fa-battery-3:before,.wfls-fa-battery-three-quarters:before{content:""}.wfls-fa-battery-2:before,.wfls-fa-battery-half:before{content:""}.wfls-fa-battery-1:before,.wfls-fa-battery-quarter:before{content:""}.wfls-fa-battery-0:before,.wfls-fa-battery-empty:before{content:""}.wfls-fa-mouse-pointer:before{content:""}.wfls-fa-i-cursor:before{content:""}.wfls-fa-object-group:before{content:""}.wfls-fa-object-ungroup:before{content:""}.wfls-fa-sticky-note:before{content:""}.wfls-fa-sticky-note-o:before{content:""}.wfls-fa-cc-jcb:before{content:""}.wfls-fa-cc-diners-club:before{content:""}.wfls-fa-clone:before{content:""}.wfls-fa-balance-scale:before{content:""}.wfls-fa-hourglass-o:before{content:""}.wfls-fa-hourglass-1:before,.wfls-fa-hourglass-start:before{content:""}.wfls-fa-hourglass-2:before,.wfls-fa-hourglass-half:before{content:""}.wfls-fa-hourglass-3:before,.wfls-fa-hourglass-end:before{content:""}.wfls-fa-hourglass:before{content:""}.wfls-fa-hand-grab-o:before,.wfls-fa-hand-rock-o:before{content:""}.wfls-fa-hand-stop-o:before,.wfls-fa-hand-paper-o:before{content:""}.wfls-fa-hand-scissors-o:before{content:""}.wfls-fa-hand-lizard-o:before{content:""}.wfls-fa-hand-spock-o:before{content:""}.wfls-fa-hand-pointer-o:before{content:""}.wfls-fa-hand-peace-o:before{content:""}.wfls-fa-trademark:before{content:""}.wfls-fa-registered:before{content:""}.wfls-fa-creative-commons:before{content:""}.wfls-fa-gg:before{content:""}.wfls-fa-gg-circle:before{content:""}.wfls-fa-tripadvisor:before{content:""}.wfls-fa-odnoklassniki:before{content:""}.wfls-fa-odnoklassniki-square:before{content:""}.wfls-fa-get-pocket:before{content:""}.wfls-fa-wikipedia-w:before{content:""}.wfls-fa-safari:before{content:""}.wfls-fa-chrome:before{content:""}.wfls-fa-firefox:before{content:""}.wfls-fa-opera:before{content:""}.wfls-fa-internet-explorer:before{content:""}.wfls-fa-tv:before,.wfls-fa-television:before{content:""}.wfls-fa-contao:before{content:""}.wfls-fa-500px:before{content:""}.wfls-fa-amazon:before{content:""}.wfls-fa-calendar-plus-o:before{content:""}.wfls-fa-calendar-minus-o:before{content:""}.wfls-fa-calendar-times-o:before{content:""}.wfls-fa-calendar-check-o:before{content:""}.wfls-fa-industry:before{content:""}.wfls-fa-map-pin:before{content:""}.wfls-fa-map-signs:before{content:""}.wfls-fa-map-o:before{content:""}.wfls-fa-map:before{content:""}.wfls-fa-commenting:before{content:""}.wfls-fa-commenting-o:before{content:""}.wfls-fa-houzz:before{content:""}.wfls-fa-vimeo:before{content:""}.wfls-fa-black-tie:before{content:""}.wfls-fa-fonticons:before{content:""}.wfls-fa-reddit-alien:before{content:""}.wfls-fa-edge:before{content:""}.wfls-fa-credit-card-alt:before{content:""}.wfls-fa-codiepie:before{content:""}.wfls-fa-modx:before{content:""}.wfls-fa-fort-awesome:before{content:""}.wfls-fa-usb:before{content:""}.wfls-fa-product-hunt:before{content:""}.wfls-fa-mixcloud:before{content:""}.wfls-fa-scribd:before{content:""}.wfls-fa-pause-circle:before{content:""}.wfls-fa-pause-circle-o:before{content:""}.wfls-fa-stop-circle:before{content:""}.wfls-fa-stop-circle-o:before{content:""}.wfls-fa-shopping-bag:before{content:""}.wfls-fa-shopping-basket:before{content:""}.wfls-fa-hashtag:before{content:""}.wfls-fa-bluetooth:before{content:""}.wfls-fa-bluetooth-b:before{content:""}.wfls-fa-percent:before{content:""}.wfls-fa-gitlab:before{content:""}.wfls-fa-wpbeginner:before{content:""}.wfls-fa-wpforms:before{content:""}.wfls-fa-envira:before{content:""}.wfls-fa-universal-access:before{content:""}.wfls-fa-wheelchair-alt:before{content:""}.wfls-fa-question-circle-o:before{content:""}.wfls-fa-blind:before{content:""}.wfls-fa-audio-description:before{content:""}.wfls-fa-volume-control-phone:before{content:""}.wfls-fa-braille:before{content:""}.wfls-fa-assistive-listening-systems:before{content:""}.wfls-fa-asl-interpreting:before,.wfls-fa-american-sign-language-interpreting:before{content:""}.wfls-fa-deafness:before,.wfls-fa-hard-of-hearing:before,.wfls-fa-deaf:before{content:""}.wfls-fa-glide:before{content:""}.wfls-fa-glide-g:before{content:""}.wfls-fa-signing:before,.wfls-fa-sign-language:before{content:""}.wfls-fa-low-vision:before{content:""}.wfls-fa-viadeo:before{content:""}.wfls-fa-viadeo-square:before{content:""}.wfls-fa-snapchat:before{content:""}.wfls-fa-snapchat-ghost:before{content:""}.wfls-fa-snapchat-square:before{content:""}.wfls-fa-pied-piper:before{content:""}.wfls-fa-first-order:before{content:""}.wfls-fa-yoast:before{content:""}.wfls-fa-themeisle:before{content:""}.wfls-fa-google-plus-circle:before,.wfls-fa-google-plus-official:before{content:""}.wfls-fa-fa:before,.wfls-fa-font-awesome:before{content:""}.wfls-fa-handshake-o:before{content:""}.wfls-fa-envelope-open:before{content:""}.wfls-fa-envelope-open-o:before{content:""}.wfls-fa-linode:before{content:""}.wfls-fa-address-book:before{content:""}.wfls-fa-address-book-o:before{content:""}.wfls-fa-vcard:before,.wfls-fa-address-card:before{content:""}.wfls-fa-vcard-o:before,.wfls-fa-address-card-o:before{content:""}.wfls-fa-user-circle:before{content:""}.wfls-fa-user-circle-o:before{content:""}.wfls-fa-user-o:before{content:""}.wfls-fa-id-badge:before{content:""}.wfls-fa-drivers-license:before,.wfls-fa-id-card:before{content:""}.wfls-fa-drivers-license-o:before,.wfls-fa-id-card-o:before{content:""}.wfls-fa-quora:before{content:""}.wfls-fa-free-code-camp:before{content:""}.wfls-fa-telegram:before{content:""}.wfls-fa-thermometer-4:before,.wfls-fa-thermometer:before,.wfls-fa-thermometer-full:before{content:""}.wfls-fa-thermometer-3:before,.wfls-fa-thermometer-three-quarters:before{content:""}.wfls-fa-thermometer-2:before,.wfls-fa-thermometer-half:before{content:""}.wfls-fa-thermometer-1:before,.wfls-fa-thermometer-quarter:before{content:""}.wfls-fa-thermometer-0:before,.wfls-fa-thermometer-empty:before{content:""}.wfls-fa-shower:before{content:""}.wfls-fa-bathtub:before,.wfls-fa-s15:before,.wfls-fa-bath:before{content:""}.wfls-fa-podcast:before{content:""}.wfls-fa-window-maximize:before{content:""}.wfls-fa-window-minimize:before{content:""}.wfls-fa-window-restore:before{content:""}.wfls-fa-times-rectangle:before,.wfls-fa-window-close:before{content:""}.wfls-fa-times-rectangle-o:before,.wfls-fa-window-close-o:before{content:""}.wfls-fa-bandcamp:before{content:""}.wfls-fa-grav:before{content:""}.wfls-fa-etsy:before{content:""}.wfls-fa-imdb:before{content:""}.wfls-fa-ravelry:before{content:""}.wfls-fa-eercast:before{content:""}.wfls-fa-microchip:before{content:""}.wfls-fa-snowflake-o:before{content:""}.wfls-fa-superpowers:before{content:""}.wfls-fa-wpexplorer:before{content:""}.wfls-fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
css/ionicons.1559237323.css ADDED
@@ -0,0 +1 @@
 
1
+ @font-face{font-family:"Ionicons";src:url("../font/ionicons.woff?v=2.0.0") format("woff");font-weight:normal;font-style:normal}.wf-ion,.wf-ionicons,.wfls-ion-alert:before,.wfls-ion-alert-circled:before,.wfls-ion-android-add:before,.wfls-ion-android-add-circle:before,.wfls-ion-android-alarm-clock:before,.wfls-ion-android-alert:before,.wfls-ion-android-apps:before,.wfls-ion-android-archive:before,.wfls-ion-android-arrow-back:before,.wfls-ion-android-arrow-down:before,.wfls-ion-android-arrow-dropdown:before,.wfls-ion-android-arrow-dropdown-circle:before,.wfls-ion-android-arrow-dropleft:before,.wfls-ion-android-arrow-dropleft-circle:before,.wfls-ion-android-arrow-dropright:before,.wfls-ion-android-arrow-dropright-circle:before,.wfls-ion-android-arrow-dropup:before,.wfls-ion-android-arrow-dropup-circle:before,.wfls-ion-android-arrow-forward:before,.wfls-ion-android-arrow-up:before,.wfls-ion-android-attach:before,.wfls-ion-android-bar:before,.wfls-ion-android-bicycle:before,.wfls-ion-android-boat:before,.wfls-ion-android-bookmark:before,.wfls-ion-android-bulb:before,.wfls-ion-android-bus:before,.wfls-ion-android-calendar:before,.wfls-ion-android-call:before,.wfls-ion-android-camera:before,.wfls-ion-android-cancel:before,.wfls-ion-android-car:before,.wfls-ion-android-cart:before,.wfls-ion-android-chat:before,.wfls-ion-android-checkbox:before,.wfls-ion-android-checkbox-blank:before,.wfls-ion-android-checkbox-outline:before,.wfls-ion-android-checkbox-outline-blank:before,.wfls-ion-android-checkmark-circle:before,.wfls-ion-android-clipboard:before,.wfls-ion-android-close:before,.wfls-ion-android-cloud:before,.wfls-ion-android-cloud-circle:before,.wfls-ion-android-cloud-done:before,.wfls-ion-android-cloud-outline:before,.wfls-ion-android-color-palette:before,.wfls-ion-android-compass:before,.wfls-ion-android-contact:before,.wfls-ion-android-contacts:before,.wfls-ion-android-contract:before,.wfls-ion-android-create:before,.wfls-ion-android-delete:before,.wfls-ion-android-desktop:before,.wfls-ion-android-document:before,.wfls-ion-android-done:before,.wfls-ion-android-done-all:before,.wfls-ion-android-download:before,.wfls-ion-android-drafts:before,.wfls-ion-android-exit:before,.wfls-ion-android-expand:before,.wfls-ion-android-favorite:before,.wfls-ion-android-favorite-outline:before,.wfls-ion-android-film:before,.wfls-ion-android-folder:before,.wfls-ion-android-folder-open:before,.wfls-ion-android-funnel:before,.wfls-ion-android-globe:before,.wfls-ion-android-hand:before,.wfls-ion-android-hangout:before,.wfls-ion-android-happy:before,.wfls-ion-android-home:before,.wfls-ion-android-image:before,.wfls-ion-android-laptop:before,.wfls-ion-android-list:before,.wfls-ion-android-locate:before,.wfls-ion-android-lock:before,.wfls-ion-android-mail:before,.wfls-ion-android-map:before,.wfls-ion-android-menu:before,.wfls-ion-android-microphone:before,.wfls-ion-android-microphone-off:before,.wfls-ion-android-more-horizontal:before,.wfls-ion-android-more-vertical:before,.wfls-ion-android-navigate:before,.wfls-ion-android-notifications:before,.wfls-ion-android-notifications-none:before,.wfls-ion-android-notifications-off:before,.wfls-ion-android-open:before,.wfls-ion-android-options:before,.wfls-ion-android-people:before,.wfls-ion-android-person:before,.wfls-ion-android-person-add:before,.wfls-ion-android-phone-landscape:before,.wfls-ion-android-phone-portrait:before,.wfls-ion-android-pin:before,.wfls-ion-android-plane:before,.wfls-ion-android-playstore:before,.wfls-ion-android-print:before,.wfls-ion-android-radio-button-off:before,.wfls-ion-android-radio-button-on:before,.wfls-ion-android-refresh:before,.wfls-ion-android-remove:before,.wfls-ion-android-remove-circle:before,.wfls-ion-android-restaurant:before,.wfls-ion-android-sad:before,.wfls-ion-android-search:before,.wfls-ion-android-send:before,.wfls-ion-android-settings:before,.wfls-ion-android-share:before,.wfls-ion-android-share-alt:before,.wfls-ion-android-star:before,.wfls-ion-android-star-half:before,.wfls-ion-android-star-outline:before,.wfls-ion-android-stopwatch:before,.wfls-ion-android-subway:before,.wfls-ion-android-sunny:before,.wfls-ion-android-sync:before,.wfls-ion-android-textsms:before,.wfls-ion-android-time:before,.wfls-ion-android-train:before,.wfls-ion-android-unlock:before,.wfls-ion-android-upload:before,.wfls-ion-android-volume-down:before,.wfls-ion-android-volume-mute:before,.wfls-ion-android-volume-off:before,.wfls-ion-android-volume-up:before,.wfls-ion-android-walk:before,.wfls-ion-android-warning:before,.wfls-ion-android-watch:before,.wfls-ion-android-wifi:before,.wfls-ion-aperture:before,.wfls-ion-archive:before,.wfls-ion-arrow-down-a:before,.wfls-ion-arrow-down-b:before,.wfls-ion-arrow-down-c:before,.wfls-ion-arrow-expand:before,.wfls-ion-arrow-graph-down-left:before,.wfls-ion-arrow-graph-down-right:before,.wfls-ion-arrow-graph-up-left:before,.wfls-ion-arrow-graph-up-right:before,.wfls-ion-arrow-left-a:before,.wfls-ion-arrow-left-b:before,.wfls-ion-arrow-left-c:before,.wfls-ion-arrow-move:before,.wfls-ion-arrow-resize:before,.wfls-ion-arrow-return-left:before,.wfls-ion-arrow-return-right:before,.wfls-ion-arrow-right-a:before,.wfls-ion-arrow-right-b:before,.wfls-ion-arrow-right-c:before,.wfls-ion-arrow-shrink:before,.wfls-ion-arrow-swap:before,.wfls-ion-arrow-up-a:before,.wfls-ion-arrow-up-b:before,.wfls-ion-arrow-up-c:before,.wfls-ion-asterisk:before,.wfls-ion-at:before,.wfls-ion-backspace:before,.wfls-ion-backspace-outline:before,.wfls-ion-bag:before,.wfls-ion-battery-charging:before,.wfls-ion-battery-empty:before,.wfls-ion-battery-full:before,.wfls-ion-battery-half:before,.wfls-ion-battery-low:before,.wfls-ion-beaker:before,.wfls-ion-beer:before,.wfls-ion-bluetooth:before,.wfls-ion-bonfire:before,.wfls-ion-bookmark:before,.wfls-ion-bowtie:before,.wfls-ion-briefcase:before,.wfls-ion-bug:before,.wfls-ion-calculator:before,.wfls-ion-calendar:before,.wfls-ion-camera:before,.wfls-ion-card:before,.wfls-ion-cash:before,.wfls-ion-chatbox:before,.wfls-ion-chatbox-working:before,.wfls-ion-chatboxes:before,.wfls-ion-chatbubble:before,.wfls-ion-chatbubble-working:before,.wfls-ion-chatbubbles:before,.wfls-ion-checkmark:before,.wfls-ion-checkmark-circled:before,.wfls-ion-checkmark-round:before,.wfls-ion-chevron-down:before,.wfls-ion-chevron-left:before,.wfls-ion-chevron-right:before,.wfls-ion-chevron-up:before,.wfls-ion-clipboard:before,.wfls-ion-clock:before,.wfls-ion-close:before,.wfls-ion-close-circled:before,.wfls-ion-close-round:before,.wfls-ion-closed-captioning:before,.wfls-ion-cloud:before,.wfls-ion-code:before,.wfls-ion-code-download:before,.wfls-ion-code-working:before,.wfls-ion-coffee:before,.wfls-ion-compass:before,.wfls-ion-compose:before,.wfls-ion-connection-bars:before,.wfls-ion-contrast:before,.wfls-ion-crop:before,.wfls-ion-cube:before,.wfls-ion-disc:before,.wfls-ion-document:before,.wfls-ion-document-text:before,.wfls-ion-drag:before,.wfls-ion-earth:before,.wfls-ion-easel:before,.wfls-ion-edit:before,.wfls-ion-egg:before,.wfls-ion-eject:before,.wfls-ion-email:before,.wfls-ion-email-unread:before,.wfls-ion-erlenmeyer-flask:before,.wfls-ion-erlenmeyer-flask-bubbles:before,.wfls-ion-eye:before,.wfls-ion-eye-disabled:before,.wfls-ion-female:before,.wfls-ion-filing:before,.wfls-ion-film-marker:before,.wfls-ion-fireball:before,.wfls-ion-flag:before,.wfls-ion-flame:before,.wfls-ion-flash:before,.wfls-ion-flash-off:before,.wfls-ion-folder:before,.wfls-ion-fork:before,.wfls-ion-fork-repo:before,.wfls-ion-forward:before,.wfls-ion-funnel:before,.wfls-ion-gear-a:before,.wfls-ion-gear-b:before,.wfls-ion-grid:before,.wfls-ion-hammer:before,.wfls-ion-happy:before,.wfls-ion-happy-outline:before,.wfls-ion-headphone:before,.wfls-ion-heart:before,.wfls-ion-heart-broken:before,.wfls-ion-help:before,.wfls-ion-help-buoy:before,.wfls-ion-help-circled:before,.wfls-ion-home:before,.wfls-ion-icecream:before,.wfls-ion-image:before,.wfls-ion-images:before,.wfls-ion-information:before,.wfls-ion-information-circled:before,.wfls-ion-ionic:before,.wfls-ion-ios-alarm:before,.wfls-ion-ios-alarm-outline:before,.wfls-ion-ios-albums:before,.wfls-ion-ios-albums-outline:before,.wfls-ion-ios-americanfootball:before,.wfls-ion-ios-americanfootball-outline:before,.wfls-ion-ios-analytics:before,.wfls-ion-ios-analytics-outline:before,.wfls-ion-ios-arrow-back:before,.wfls-ion-ios-arrow-down:before,.wfls-ion-ios-arrow-forward:before,.wfls-ion-ios-arrow-left:before,.wfls-ion-ios-arrow-right:before,.wfls-ion-ios-arrow-thin-down:before,.wfls-ion-ios-arrow-thin-left:before,.wfls-ion-ios-arrow-thin-right:before,.wfls-ion-ios-arrow-thin-up:before,.wfls-ion-ios-arrow-up:before,.wfls-ion-ios-at:before,.wfls-ion-ios-at-outline:before,.wfls-ion-ios-barcode:before,.wfls-ion-ios-barcode-outline:before,.wfls-ion-ios-baseball:before,.wfls-ion-ios-baseball-outline:before,.wfls-ion-ios-basketball:before,.wfls-ion-ios-basketball-outline:before,.wfls-ion-ios-bell:before,.wfls-ion-ios-bell-outline:before,.wfls-ion-ios-body:before,.wfls-ion-ios-body-outline:before,.wfls-ion-ios-bolt:before,.wfls-ion-ios-bolt-outline:before,.wfls-ion-ios-book:before,.wfls-ion-ios-book-outline:before,.wfls-ion-ios-bookmarks:before,.wfls-ion-ios-bookmarks-outline:before,.wfls-ion-ios-box:before,.wfls-ion-ios-box-outline:before,.wfls-ion-ios-briefcase:before,.wfls-ion-ios-briefcase-outline:before,.wfls-ion-ios-browsers:before,.wfls-ion-ios-browsers-outline:before,.wfls-ion-ios-calculator:before,.wfls-ion-ios-calculator-outline:before,.wfls-ion-ios-calendar:before,.wfls-ion-ios-calendar-outline:before,.wfls-ion-ios-camera:before,.wfls-ion-ios-camera-outline:before,.wfls-ion-ios-cart:before,.wfls-ion-ios-cart-outline:before,.wfls-ion-ios-chatboxes:before,.wfls-ion-ios-chatboxes-outline:before,.wfls-ion-ios-chatbubble:before,.wfls-ion-ios-chatbubble-outline:before,.wfls-ion-ios-checkmark:before,.wfls-ion-ios-checkmark-empty:before,.wfls-ion-ios-checkmark-outline:before,.wfls-ion-ios-circle-filled:before,.wfls-ion-ios-circle-outline:before,.wfls-ion-ios-clock:before,.wfls-ion-ios-clock-outline:before,.wfls-ion-ios-close:before,.wfls-ion-ios-close-empty:before,.wfls-ion-ios-close-outline:before,.wfls-ion-ios-cloud:before,.wfls-ion-ios-cloud-download:before,.wfls-ion-ios-cloud-download-outline:before,.wfls-ion-ios-cloud-outline:before,.wfls-ion-ios-cloud-upload:before,.wfls-ion-ios-cloud-upload-outline:before,.wfls-ion-ios-cloudy:before,.wfls-ion-ios-cloudy-night:before,.wfls-ion-ios-cloudy-night-outline:before,.wfls-ion-ios-cloudy-outline:before,.wfls-ion-ios-cog:before,.wfls-ion-ios-cog-outline:before,.wfls-ion-ios-color-filter:before,.wfls-ion-ios-color-filter-outline:before,.wfls-ion-ios-color-wand:before,.wfls-ion-ios-color-wand-outline:before,.wfls-ion-ios-compose:before,.wfls-ion-ios-compose-outline:before,.wfls-ion-ios-contact:before,.wfls-ion-ios-contact-outline:before,.wfls-ion-ios-copy:before,.wfls-ion-ios-copy-outline:before,.wfls-ion-ios-crop:before,.wfls-ion-ios-crop-strong:before,.wfls-ion-ios-download:before,.wfls-ion-ios-download-outline:before,.wfls-ion-ios-drag:before,.wfls-ion-ios-email:before,.wfls-ion-ios-email-outline:before,.wfls-ion-ios-eye:before,.wfls-ion-ios-eye-outline:before,.wfls-ion-ios-fastforward:before,.wfls-ion-ios-fastforward-outline:before,.wfls-ion-ios-filing:before,.wfls-ion-ios-filing-outline:before,.wfls-ion-ios-film:before,.wfls-ion-ios-film-outline:before,.wfls-ion-ios-flag:before,.wfls-ion-ios-flag-outline:before,.wfls-ion-ios-flame:before,.wfls-ion-ios-flame-outline:before,.wfls-ion-ios-flask:before,.wfls-ion-ios-flask-outline:before,.wfls-ion-ios-flower:before,.wfls-ion-ios-flower-outline:before,.wfls-ion-ios-folder:before,.wfls-ion-ios-folder-outline:before,.wfls-ion-ios-football:before,.wfls-ion-ios-football-outline:before,.wfls-ion-ios-game-controller-a:before,.wfls-ion-ios-game-controller-a-outline:before,.wfls-ion-ios-game-controller-b:before,.wfls-ion-ios-game-controller-b-outline:before,.wfls-ion-ios-gear:before,.wfls-ion-ios-gear-outline:before,.wfls-ion-ios-glasses:before,.wfls-ion-ios-glasses-outline:before,.wfls-ion-ios-grid-view:before,.wfls-ion-ios-grid-view-outline:before,.wfls-ion-ios-heart:before,.wfls-ion-ios-heart-outline:before,.wfls-ion-ios-help:before,.wfls-ion-ios-help-empty:before,.wfls-ion-ios-help-outline:before,.wfls-ion-ios-home:before,.wfls-ion-ios-home-outline:before,.wfls-ion-ios-infinite:before,.wfls-ion-ios-infinite-outline:before,.wfls-ion-ios-information:before,.wfls-ion-ios-information-empty:before,.wfls-ion-ios-information-outline:before,.wfls-ion-ios-ionic-outline:before,.wfls-ion-ios-keypad:before,.wfls-ion-ios-keypad-outline:before,.wfls-ion-ios-lightbulb:before,.wfls-ion-ios-lightbulb-outline:before,.wfls-ion-ios-list:before,.wfls-ion-ios-list-outline:before,.wfls-ion-ios-location:before,.wfls-ion-ios-location-outline:before,.wfls-ion-ios-locked:before,.wfls-ion-ios-locked-outline:before,.wfls-ion-ios-loop:before,.wfls-ion-ios-loop-strong:before,.wfls-ion-ios-medical:before,.wfls-ion-ios-medical-outline:before,.wfls-ion-ios-medkit:before,.wfls-ion-ios-medkit-outline:before,.wfls-ion-ios-mic:before,.wfls-ion-ios-mic-off:before,.wfls-ion-ios-mic-outline:before,.wfls-ion-ios-minus:before,.wfls-ion-ios-minus-empty:before,.wfls-ion-ios-minus-outline:before,.wfls-ion-ios-monitor:before,.wfls-ion-ios-monitor-outline:before,.wfls-ion-ios-moon:before,.wfls-ion-ios-moon-outline:before,.wfls-ion-ios-more:before,.wfls-ion-ios-more-outline:before,.wfls-ion-ios-musical-note:before,.wfls-ion-ios-musical-notes:before,.wfls-ion-ios-navigate:before,.wfls-ion-ios-navigate-outline:before,.wfls-ion-ios-nutrition:before,.wfls-ion-ios-nutrition-outline:before,.wfls-ion-ios-paper:before,.wfls-ion-ios-paper-outline:before,.wfls-ion-ios-paperplane:before,.wfls-ion-ios-paperplane-outline:before,.wfls-ion-ios-partlysunny:before,.wfls-ion-ios-partlysunny-outline:before,.wfls-ion-ios-pause:before,.wfls-ion-ios-pause-outline:before,.wfls-ion-ios-paw:before,.wfls-ion-ios-paw-outline:before,.wfls-ion-ios-people:before,.wfls-ion-ios-people-outline:before,.wfls-ion-ios-person:before,.wfls-ion-ios-person-outline:before,.wfls-ion-ios-personadd:before,.wfls-ion-ios-personadd-outline:before,.wfls-ion-ios-photos:before,.wfls-ion-ios-photos-outline:before,.wfls-ion-ios-pie:before,.wfls-ion-ios-pie-outline:before,.wfls-ion-ios-pint:before,.wfls-ion-ios-pint-outline:before,.wfls-ion-ios-play:before,.wfls-ion-ios-play-outline:before,.wfls-ion-ios-plus:before,.wfls-ion-ios-plus-empty:before,.wfls-ion-ios-plus-outline:before,.wfls-ion-ios-pricetag:before,.wfls-ion-ios-pricetag-outline:before,.wfls-ion-ios-pricetags:before,.wfls-ion-ios-pricetags-outline:before,.wfls-ion-ios-printer:before,.wfls-ion-ios-printer-outline:before,.wfls-ion-ios-pulse:before,.wfls-ion-ios-pulse-strong:before,.wfls-ion-ios-rainy:before,.wfls-ion-ios-rainy-outline:before,.wfls-ion-ios-recording:before,.wfls-ion-ios-recording-outline:before,.wfls-ion-ios-redo:before,.wfls-ion-ios-redo-outline:before,.wfls-ion-ios-refresh:before,.wfls-ion-ios-refresh-empty:before,.wfls-ion-ios-refresh-outline:before,.wfls-ion-ios-reload:before,.wfls-ion-ios-reverse-camera:before,.wfls-ion-ios-reverse-camera-outline:before,.wfls-ion-ios-rewind:before,.wfls-ion-ios-rewind-outline:before,.wfls-ion-ios-rose:before,.wfls-ion-ios-rose-outline:before,.wfls-ion-ios-search:before,.wfls-ion-ios-search-strong:before,.wfls-ion-ios-settings:before,.wfls-ion-ios-settings-strong:before,.wfls-ion-ios-shuffle:before,.wfls-ion-ios-shuffle-strong:before,.wfls-ion-ios-skipbackward:before,.wfls-ion-ios-skipbackward-outline:before,.wfls-ion-ios-skipforward:before,.wfls-ion-ios-skipforward-outline:before,.wfls-ion-ios-snowy:before,.wfls-ion-ios-speedometer:before,.wfls-ion-ios-speedometer-outline:before,.wfls-ion-ios-star:before,.wfls-ion-ios-star-half:before,.wfls-ion-ios-star-outline:before,.wfls-ion-ios-stopwatch:before,.wfls-ion-ios-stopwatch-outline:before,.wfls-ion-ios-sunny:before,.wfls-ion-ios-sunny-outline:before,.wfls-ion-ios-telephone:before,.wfls-ion-ios-telephone-outline:before,.wfls-ion-ios-tennisball:before,.wfls-ion-ios-tennisball-outline:before,.wfls-ion-ios-thunderstorm:before,.wfls-ion-ios-thunderstorm-outline:before,.wfls-ion-ios-time:before,.wfls-ion-ios-time-outline:before,.wfls-ion-ios-timer:before,.wfls-ion-ios-timer-outline:before,.wfls-ion-ios-toggle:before,.wfls-ion-ios-toggle-outline:before,.wfls-ion-ios-trash:before,.wfls-ion-ios-trash-outline:before,.wfls-ion-ios-undo:before,.wfls-ion-ios-undo-outline:before,.wfls-ion-ios-unlocked:before,.wfls-ion-ios-unlocked-outline:before,.wfls-ion-ios-upload:before,.wfls-ion-ios-upload-outline:before,.wfls-ion-ios-videocam:before,.wfls-ion-ios-videocam-outline:before,.wfls-ion-ios-volume-high:before,.wfls-ion-ios-volume-low:before,.wfls-ion-ios-wineglass:before,.wfls-ion-ios-wineglass-outline:before,.wfls-ion-ios-world:before,.wfls-ion-ios-world-outline:before,.wfls-ion-ipad:before,.wfls-ion-iphone:before,.wfls-ion-ipod:before,.wfls-ion-jet:before,.wfls-ion-key:before,.wfls-ion-knife:before,.wfls-ion-laptop:before,.wfls-ion-leaf:before,.wfls-ion-levels:before,.wfls-ion-lightbulb:before,.wfls-ion-link:before,.wfls-ion-load-a:before,.wfls-ion-load-b:before,.wfls-ion-load-c:before,.wfls-ion-load-d:before,.wfls-ion-location:before,.wfls-ion-lock-combination:before,.wfls-ion-locked:before,.wfls-ion-log-in:before,.wfls-ion-log-out:before,.wfls-ion-loop:before,.wfls-ion-magnet:before,.wfls-ion-male:before,.wfls-ion-man:before,.wfls-ion-map:before,.wfls-ion-medkit:before,.wfls-ion-merge:before,.wfls-ion-mic-a:before,.wfls-ion-mic-b:before,.wfls-ion-mic-c:before,.wfls-ion-minus:before,.wfls-ion-minus-circled:before,.wfls-ion-minus-round:before,.wfls-ion-model-s:before,.wfls-ion-monitor:before,.wfls-ion-more:before,.wfls-ion-mouse:before,.wfls-ion-music-note:before,.wfls-ion-navicon:before,.wfls-ion-navicon-round:before,.wfls-ion-navigate:before,.wfls-ion-network:before,.wfls-ion-no-smoking:before,.wfls-ion-nuclear:before,.wfls-ion-outlet:before,.wfls-ion-paintbrush:before,.wfls-ion-paintbucket:before,.wfls-ion-paper-airplane:before,.wfls-ion-paperclip:before,.wfls-ion-pause:before,.wfls-ion-person:before,.wfls-ion-person-add:before,.wfls-ion-person-stalker:before,.wfls-ion-pie-graph:before,.wfls-ion-pin:before,.wfls-ion-pinpoint:before,.wfls-ion-pizza:before,.wfls-ion-plane:before,.wfls-ion-planet:before,.wfls-ion-play:before,.wfls-ion-playstation:before,.wfls-ion-plus:before,.wfls-ion-plus-circled:before,.wfls-ion-plus-round:before,.wfls-ion-podium:before,.wfls-ion-pound:before,.wfls-ion-power:before,.wfls-ion-pricetag:before,.wfls-ion-pricetags:before,.wfls-ion-printer:before,.wfls-ion-pull-request:before,.wfls-ion-qr-scanner:before,.wfls-ion-quote:before,.wfls-ion-radio-waves:before,.wfls-ion-record:before,.wfls-ion-refresh:before,.wfls-ion-reply:before,.wfls-ion-reply-all:before,.wfls-ion-ribbon-a:before,.wfls-ion-ribbon-b:before,.wfls-ion-sad:before,.wfls-ion-sad-outline:before,.wfls-ion-scissors:before,.wfls-ion-search:before,.wfls-ion-settings:before,.wfls-ion-share:before,.wfls-ion-shuffle:before,.wfls-ion-skip-backward:before,.wfls-ion-skip-forward:before,.wfls-ion-social-android:before,.wfls-ion-social-android-outline:before,.wfls-ion-social-angular:before,.wfls-ion-social-angular-outline:before,.wfls-ion-social-apple:before,.wfls-ion-social-apple-outline:before,.wfls-ion-social-bitcoin:before,.wfls-ion-social-bitcoin-outline:before,.wfls-ion-social-buffer:before,.wfls-ion-social-buffer-outline:before,.wfls-ion-social-chrome:before,.wfls-ion-social-chrome-outline:before,.wfls-ion-social-codepen:before,.wfls-ion-social-codepen-outline:before,.wfls-ion-social-css3:before,.wfls-ion-social-css3-outline:before,.wfls-ion-social-designernews:before,.wfls-ion-social-designernews-outline:before,.wfls-ion-social-dribbble:before,.wfls-ion-social-dribbble-outline:before,.wfls-ion-social-dropbox:before,.wfls-ion-social-dropbox-outline:before,.wfls-ion-social-euro:before,.wfls-ion-social-euro-outline:before,.wfls-ion-social-facebook:before,.wfls-ion-social-facebook-outline:before,.wfls-ion-social-foursquare:before,.wfls-ion-social-foursquare-outline:before,.wfls-ion-social-freebsd-devil:before,.wfls-ion-social-github:before,.wfls-ion-social-github-outline:before,.wfls-ion-social-google:before,.wfls-ion-social-google-outline:before,.wfls-ion-social-googleplus:before,.wfls-ion-social-googleplus-outline:before,.wfls-ion-social-hackernews:before,.wfls-ion-social-hackernews-outline:before,.wfls-ion-social-html5:before,.wfls-ion-social-html5-outline:before,.wfls-ion-social-instagram:before,.wfls-ion-social-instagram-outline:before,.wfls-ion-social-javascript:before,.wfls-ion-social-javascript-outline:before,.wfls-ion-social-linkedin:before,.wfls-ion-social-linkedin-outline:before,.wfls-ion-social-markdown:before,.wfls-ion-social-nodejs:before,.wfls-ion-social-octocat:before,.wfls-ion-social-pinterest:before,.wfls-ion-social-pinterest-outline:before,.wfls-ion-social-python:before,.wfls-ion-social-reddit:before,.wfls-ion-social-reddit-outline:before,.wfls-ion-social-rss:before,.wfls-ion-social-rss-outline:before,.wfls-ion-social-sass:before,.wfls-ion-social-skype:before,.wfls-ion-social-skype-outline:before,.wfls-ion-social-snapchat:before,.wfls-ion-social-snapchat-outline:before,.wfls-ion-social-tumblr:before,.wfls-ion-social-tumblr-outline:before,.wfls-ion-social-tux:before,.wfls-ion-social-twitch:before,.wfls-ion-social-twitch-outline:before,.wfls-ion-social-twitter:before,.wfls-ion-social-twitter-outline:before,.wfls-ion-social-usd:before,.wfls-ion-social-usd-outline:before,.wfls-ion-social-vimeo:before,.wfls-ion-social-vimeo-outline:before,.wfls-ion-social-whatsapp:before,.wfls-ion-social-whatsapp-outline:before,.wfls-ion-social-windows:before,.wfls-ion-social-windows-outline:before,.wfls-ion-social-wordpress:before,.wfls-ion-social-wordpress-outline:before,.wfls-ion-social-yahoo:before,.wfls-ion-social-yahoo-outline:before,.wfls-ion-social-yen:before,.wfls-ion-social-yen-outline:before,.wfls-ion-social-youtube:before,.wfls-ion-social-youtube-outline:before,.wfls-ion-soup-can:before,.wfls-ion-soup-can-outline:before,.wfls-ion-speakerphone:before,.wfls-ion-speedometer:before,.wfls-ion-spoon:before,.wfls-ion-star:before,.wfls-ion-stats-bars:before,.wfls-ion-steam:before,.wfls-ion-stop:before,.wfls-ion-thermometer:before,.wfls-ion-thumbsdown:before,.wfls-ion-thumbsup:before,.wfls-ion-toggle:before,.wfls-ion-toggle-filled:before,.wfls-ion-transgender:before,.wfls-ion-trash-a:before,.wfls-ion-trash-b:before,.wfls-ion-trophy:before,.wfls-ion-tshirt:before,.wfls-ion-tshirt-outline:before,.wfls-ion-umbrella:before,.wfls-ion-university:before,.wfls-ion-unlocked:before,.wfls-ion-upload:before,.wfls-ion-usb:before,.wfls-ion-videocamera:before,.wfls-ion-volume-high:before,.wfls-ion-volume-low:before,.wfls-ion-volume-medium:before,.wfls-ion-volume-mute:before,.wfls-ion-wand:before,.wfls-ion-waterdrop:before,.wfls-ion-wifi:before,.wfls-ion-wineglass:before,.wfls-ion-woman:before,.wfls-ion-wrench:before,.wfls-ion-xbox:before{display:inline-block;font-family:"Ionicons" !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.wfls-ion-alert:before{content:""}.wfls-ion-alert-circled:before{content:""}.wfls-ion-android-add:before{content:""}.wfls-ion-android-add-circle:before{content:""}.wfls-ion-android-alarm-clock:before{content:""}.wfls-ion-android-alert:before{content:""}.wfls-ion-android-apps:before{content:""}.wfls-ion-android-archive:before{content:""}.wfls-ion-android-arrow-back:before{content:""}.wfls-ion-android-arrow-down:before{content:""}.wfls-ion-android-arrow-dropdown:before{content:""}.wfls-ion-android-arrow-dropdown-circle:before{content:""}.wfls-ion-android-arrow-dropleft:before{content:""}.wfls-ion-android-arrow-dropleft-circle:before{content:""}.wfls-ion-android-arrow-dropright:before{content:""}.wfls-ion-android-arrow-dropright-circle:before{content:""}.wfls-ion-android-arrow-dropup:before{content:""}.wfls-ion-android-arrow-dropup-circle:before{content:""}.wfls-ion-android-arrow-forward:before{content:""}.wfls-ion-android-arrow-up:before{content:""}.wfls-ion-android-attach:before{content:""}.wfls-ion-android-bar:before{content:""}.wfls-ion-android-bicycle:before{content:""}.wfls-ion-android-boat:before{content:""}.wfls-ion-android-bookmark:before{content:""}.wfls-ion-android-bulb:before{content:""}.wfls-ion-android-bus:before{content:""}.wfls-ion-android-calendar:before{content:""}.wfls-ion-android-call:before{content:""}.wfls-ion-android-camera:before{content:""}.wfls-ion-android-cancel:before{content:""}.wfls-ion-android-car:before{content:""}.wfls-ion-android-cart:before{content:""}.wfls-ion-android-chat:before{content:""}.wfls-ion-android-checkbox:before{content:""}.wfls-ion-android-checkbox-blank:before{content:""}.wfls-ion-android-checkbox-outline:before{content:""}.wfls-ion-android-checkbox-outline-blank:before{content:""}.wfls-ion-android-checkmark-circle:before{content:""}.wfls-ion-android-clipboard:before{content:""}.wfls-ion-android-close:before{content:""}.wfls-ion-android-cloud:before{content:""}.wfls-ion-android-cloud-circle:before{content:""}.wfls-ion-android-cloud-done:before{content:""}.wfls-ion-android-cloud-outline:before{content:""}.wfls-ion-android-color-palette:before{content:""}.wfls-ion-android-compass:before{content:""}.wfls-ion-android-contact:before{content:""}.wfls-ion-android-contacts:before{content:""}.wfls-ion-android-contract:before{content:""}.wfls-ion-android-create:before{content:""}.wfls-ion-android-delete:before{content:""}.wfls-ion-android-desktop:before{content:""}.wfls-ion-android-document:before{content:""}.wfls-ion-android-done:before{content:""}.wfls-ion-android-done-all:before{content:""}.wfls-ion-android-download:before{content:""}.wfls-ion-android-drafts:before{content:""}.wfls-ion-android-exit:before{content:""}.wfls-ion-android-expand:before{content:""}.wfls-ion-android-favorite:before{content:""}.wfls-ion-android-favorite-outline:before{content:""}.wfls-ion-android-film:before{content:""}.wfls-ion-android-folder:before{content:""}.wfls-ion-android-folder-open:before{content:""}.wfls-ion-android-funnel:before{content:""}.wfls-ion-android-globe:before{content:""}.wfls-ion-android-hand:before{content:""}.wfls-ion-android-hangout:before{content:""}.wfls-ion-android-happy:before{content:""}.wfls-ion-android-home:before{content:""}.wfls-ion-android-image:before{content:""}.wfls-ion-android-laptop:before{content:""}.wfls-ion-android-list:before{content:""}.wfls-ion-android-locate:before{content:""}.wfls-ion-android-lock:before{content:""}.wfls-ion-android-mail:before{content:""}.wfls-ion-android-map:before{content:""}.wfls-ion-android-menu:before{content:""}.wfls-ion-android-microphone:before{content:""}.wfls-ion-android-microphone-off:before{content:""}.wfls-ion-android-more-horizontal:before{content:""}.wfls-ion-android-more-vertical:before{content:""}.wfls-ion-android-navigate:before{content:""}.wfls-ion-android-notifications:before{content:""}.wfls-ion-android-notifications-none:before{content:""}.wfls-ion-android-notifications-off:before{content:""}.wfls-ion-android-open:before{content:""}.wfls-ion-android-options:before{content:""}.wfls-ion-android-people:before{content:""}.wfls-ion-android-person:before{content:""}.wfls-ion-android-person-add:before{content:""}.wfls-ion-android-phone-landscape:before{content:""}.wfls-ion-android-phone-portrait:before{content:""}.wfls-ion-android-pin:before{content:""}.wfls-ion-android-plane:before{content:""}.wfls-ion-android-playstore:before{content:""}.wfls-ion-android-print:before{content:""}.wfls-ion-android-radio-button-off:before{content:""}.wfls-ion-android-radio-button-on:before{content:""}.wfls-ion-android-refresh:before{content:""}.wfls-ion-android-remove:before{content:""}.wfls-ion-android-remove-circle:before{content:""}.wfls-ion-android-restaurant:before{content:""}.wfls-ion-android-sad:before{content:""}.wfls-ion-android-search:before{content:""}.wfls-ion-android-send:before{content:""}.wfls-ion-android-settings:before{content:""}.wfls-ion-android-share:before{content:""}.wfls-ion-android-share-alt:before{content:""}.wfls-ion-android-star:before{content:""}.wfls-ion-android-star-half:before{content:""}.wfls-ion-android-star-outline:before{content:""}.wfls-ion-android-stopwatch:before{content:""}.wfls-ion-android-subway:before{content:""}.wfls-ion-android-sunny:before{content:""}.wfls-ion-android-sync:before{content:""}.wfls-ion-android-textsms:before{content:""}.wfls-ion-android-time:before{content:""}.wfls-ion-android-train:before{content:""}.wfls-ion-android-unlock:before{content:""}.wfls-ion-android-upload:before{content:""}.wfls-ion-android-volume-down:before{content:""}.wfls-ion-android-volume-mute:before{content:""}.wfls-ion-android-volume-off:before{content:""}.wfls-ion-android-volume-up:before{content:""}.wfls-ion-android-walk:before{content:""}.wfls-ion-android-warning:before{content:""}.wfls-ion-android-watch:before{content:""}.wfls-ion-android-wifi:before{content:""}.wfls-ion-aperture:before{content:""}.wfls-ion-archive:before{content:""}.wfls-ion-arrow-down-a:before{content:""}.wfls-ion-arrow-down-b:before{content:""}.wfls-ion-arrow-down-c:before{content:""}.wfls-ion-arrow-expand:before{content:""}.wfls-ion-arrow-graph-down-left:before{content:""}.wfls-ion-arrow-graph-down-right:before{content:""}.wfls-ion-arrow-graph-up-left:before{content:""}.wfls-ion-arrow-graph-up-right:before{content:""}.wfls-ion-arrow-left-a:before{content:""}.wfls-ion-arrow-left-b:before{content:""}.wfls-ion-arrow-left-c:before{content:""}.wfls-ion-arrow-move:before{content:""}.wfls-ion-arrow-resize:before{content:""}.wfls-ion-arrow-return-left:before{content:""}.wfls-ion-arrow-return-right:before{content:""}.wfls-ion-arrow-right-a:before{content:""}.wfls-ion-arrow-right-b:before{content:""}.wfls-ion-arrow-right-c:before{content:""}.wfls-ion-arrow-shrink:before{content:""}.wfls-ion-arrow-swap:before{content:""}.wfls-ion-arrow-up-a:before{content:""}.wfls-ion-arrow-up-b:before{content:""}.wfls-ion-arrow-up-c:before{content:""}.wfls-ion-asterisk:before{content:""}.wfls-ion-at:before{content:""}.wfls-ion-backspace:before{content:""}.wfls-ion-backspace-outline:before{content:""}.wfls-ion-bag:before{content:""}.wfls-ion-battery-charging:before{content:""}.wfls-ion-battery-empty:before{content:""}.wfls-ion-battery-full:before{content:""}.wfls-ion-battery-half:before{content:""}.wfls-ion-battery-low:before{content:""}.wfls-ion-beaker:before{content:""}.wfls-ion-beer:before{content:""}.wfls-ion-bluetooth:before{content:""}.wfls-ion-bonfire:before{content:""}.wfls-ion-bookmark:before{content:""}.wfls-ion-bowtie:before{content:""}.wfls-ion-briefcase:before{content:""}.wfls-ion-bug:before{content:""}.wfls-ion-calculator:before{content:""}.wfls-ion-calendar:before{content:""}.wfls-ion-camera:before{content:""}.wfls-ion-card:before{content:""}.wfls-ion-cash:before{content:""}.wfls-ion-chatbox:before{content:""}.wfls-ion-chatbox-working:before{content:""}.wfls-ion-chatboxes:before{content:""}.wfls-ion-chatbubble:before{content:""}.wfls-ion-chatbubble-working:before{content:""}.wfls-ion-chatbubbles:before{content:""}.wfls-ion-checkmark:before{content:""}.wfls-ion-checkmark-circled:before{content:""}.wfls-ion-checkmark-round:before{content:""}.wfls-ion-chevron-down:before{content:""}.wfls-ion-chevron-left:before{content:""}.wfls-ion-chevron-right:before{content:""}.wfls-ion-chevron-up:before{content:""}.wfls-ion-clipboard:before{content:""}.wfls-ion-clock:before{content:""}.wfls-ion-close:before{content:""}.wfls-ion-close-circled:before{content:""}.wfls-ion-close-round:before{content:""}.wfls-ion-closed-captioning:before{content:""}.wfls-ion-cloud:before{content:""}.wfls-ion-code:before{content:""}.wfls-ion-code-download:before{content:""}.wfls-ion-code-working:before{content:""}.wfls-ion-coffee:before{content:""}.wfls-ion-compass:before{content:""}.wfls-ion-compose:before{content:""}.wfls-ion-connection-bars:before{content:""}.wfls-ion-contrast:before{content:""}.wfls-ion-crop:before{content:""}.wfls-ion-cube:before{content:""}.wfls-ion-disc:before{content:""}.wfls-ion-document:before{content:""}.wfls-ion-document-text:before{content:""}.wfls-ion-drag:before{content:""}.wfls-ion-earth:before{content:""}.wfls-ion-easel:before{content:""}.wfls-ion-edit:before{content:""}.wfls-ion-egg:before{content:""}.wfls-ion-eject:before{content:""}.wfls-ion-email:before{content:""}.wfls-ion-email-unread:before{content:""}.wfls-ion-erlenmeyer-flask:before{content:""}.wfls-ion-erlenmeyer-flask-bubbles:before{content:""}.wfls-ion-eye:before{content:""}.wfls-ion-eye-disabled:before{content:""}.wfls-ion-female:before{content:""}.wfls-ion-filing:before{content:""}.wfls-ion-film-marker:before{content:""}.wfls-ion-fireball:before{content:""}.wfls-ion-flag:before{content:""}.wfls-ion-flame:before{content:""}.wfls-ion-flash:before{content:""}.wfls-ion-flash-off:before{content:""}.wfls-ion-folder:before{content:""}.wfls-ion-fork:before{content:""}.wfls-ion-fork-repo:before{content:""}.wfls-ion-forward:before{content:""}.wfls-ion-funnel:before{content:""}.wfls-ion-gear-a:before{content:""}.wfls-ion-gear-b:before{content:""}.wfls-ion-grid:before{content:""}.wfls-ion-hammer:before{content:""}.wfls-ion-happy:before{content:""}.wfls-ion-happy-outline:before{content:""}.wfls-ion-headphone:before{content:""}.wfls-ion-heart:before{content:""}.wfls-ion-heart-broken:before{content:""}.wfls-ion-help:before{content:""}.wfls-ion-help-buoy:before{content:""}.wfls-ion-help-circled:before{content:""}.wfls-ion-home:before{content:""}.wfls-ion-icecream:before{content:""}.wfls-ion-image:before{content:""}.wfls-ion-images:before{content:""}.wfls-ion-information:before{content:""}.wfls-ion-information-circled:before{content:""}.wfls-ion-ionic:before{content:""}.wfls-ion-ios-alarm:before{content:""}.wfls-ion-ios-alarm-outline:before{content:""}.wfls-ion-ios-albums:before{content:""}.wfls-ion-ios-albums-outline:before{content:""}.wfls-ion-ios-americanfootball:before{content:""}.wfls-ion-ios-americanfootball-outline:before{content:""}.wfls-ion-ios-analytics:before{content:""}.wfls-ion-ios-analytics-outline:before{content:""}.wfls-ion-ios-arrow-back:before{content:""}.wfls-ion-ios-arrow-down:before{content:""}.wfls-ion-ios-arrow-forward:before{content:""}.wfls-ion-ios-arrow-left:before{content:""}.wfls-ion-ios-arrow-right:before{content:""}.wfls-ion-ios-arrow-thin-down:before{content:""}.wfls-ion-ios-arrow-thin-left:before{content:""}.wfls-ion-ios-arrow-thin-right:before{content:""}.wfls-ion-ios-arrow-thin-up:before{content:""}.wfls-ion-ios-arrow-up:before{content:""}.wfls-ion-ios-at:before{content:""}.wfls-ion-ios-at-outline:before{content:""}.wfls-ion-ios-barcode:before{content:""}.wfls-ion-ios-barcode-outline:before{content:""}.wfls-ion-ios-baseball:before{content:""}.wfls-ion-ios-baseball-outline:before{content:""}.wfls-ion-ios-basketball:before{content:""}.wfls-ion-ios-basketball-outline:before{content:""}.wfls-ion-ios-bell:before{content:""}.wfls-ion-ios-bell-outline:before{content:""}.wfls-ion-ios-body:before{content:""}.wfls-ion-ios-body-outline:before{content:""}.wfls-ion-ios-bolt:before{content:""}.wfls-ion-ios-bolt-outline:before{content:""}.wfls-ion-ios-book:before{content:""}.wfls-ion-ios-book-outline:before{content:""}.wfls-ion-ios-bookmarks:before{content:""}.wfls-ion-ios-bookmarks-outline:before{content:""}.wfls-ion-ios-box:before{content:""}.wfls-ion-ios-box-outline:before{content:""}.wfls-ion-ios-briefcase:before{content:""}.wfls-ion-ios-briefcase-outline:before{content:""}.wfls-ion-ios-browsers:before{content:""}.wfls-ion-ios-browsers-outline:before{content:""}.wfls-ion-ios-calculator:before{content:""}.wfls-ion-ios-calculator-outline:before{content:""}.wfls-ion-ios-calendar:before{content:""}.wfls-ion-ios-calendar-outline:before{content:""}.wfls-ion-ios-camera:before{content:""}.wfls-ion-ios-camera-outline:before{content:""}.wfls-ion-ios-cart:before{content:""}.wfls-ion-ios-cart-outline:before{content:""}.wfls-ion-ios-chatboxes:before{content:""}.wfls-ion-ios-chatboxes-outline:before{content:""}.wfls-ion-ios-chatbubble:before{content:""}.wfls-ion-ios-chatbubble-outline:before{content:""}.wfls-ion-ios-checkmark:before{content:""}.wfls-ion-ios-checkmark-empty:before{content:""}.wfls-ion-ios-checkmark-outline:before{content:""}.wfls-ion-ios-circle-filled:before{content:""}.wfls-ion-ios-circle-outline:before{content:""}.wfls-ion-ios-clock:before{content:""}.wfls-ion-ios-clock-outline:before{content:""}.wfls-ion-ios-close:before{content:""}.wfls-ion-ios-close-empty:before{content:""}.wfls-ion-ios-close-outline:before{content:""}.wfls-ion-ios-cloud:before{content:""}.wfls-ion-ios-cloud-download:before{content:""}.wfls-ion-ios-cloud-download-outline:before{content:""}.wfls-ion-ios-cloud-outline:before{content:""}.wfls-ion-ios-cloud-upload:before{content:""}.wfls-ion-ios-cloud-upload-outline:before{content:""}.wfls-ion-ios-cloudy:before{content:""}.wfls-ion-ios-cloudy-night:before{content:""}.wfls-ion-ios-cloudy-night-outline:before{content:""}.wfls-ion-ios-cloudy-outline:before{content:""}.wfls-ion-ios-cog:before{content:""}.wfls-ion-ios-cog-outline:before{content:""}.wfls-ion-ios-color-filter:before{content:""}.wfls-ion-ios-color-filter-outline:before{content:""}.wfls-ion-ios-color-wand:before{content:""}.wfls-ion-ios-color-wand-outline:before{content:""}.wfls-ion-ios-compose:before{content:""}.wfls-ion-ios-compose-outline:before{content:""}.wfls-ion-ios-contact:before{content:""}.wfls-ion-ios-contact-outline:before{content:""}.wfls-ion-ios-copy:before{content:""}.wfls-ion-ios-copy-outline:before{content:""}.wfls-ion-ios-crop:before{content:""}.wfls-ion-ios-crop-strong:before{content:""}.wfls-ion-ios-download:before{content:""}.wfls-ion-ios-download-outline:before{content:""}.wfls-ion-ios-drag:before{content:""}.wfls-ion-ios-email:before{content:""}.wfls-ion-ios-email-outline:before{content:""}.wfls-ion-ios-eye:before{content:""}.wfls-ion-ios-eye-outline:before{content:""}.wfls-ion-ios-fastforward:before{content:""}.wfls-ion-ios-fastforward-outline:before{content:""}.wfls-ion-ios-filing:before{content:""}.wfls-ion-ios-filing-outline:before{content:""}.wfls-ion-ios-film:before{content:""}.wfls-ion-ios-film-outline:before{content:""}.wfls-ion-ios-flag:before{content:""}.wfls-ion-ios-flag-outline:before{content:""}.wfls-ion-ios-flame:before{content:""}.wfls-ion-ios-flame-outline:before{content:""}.wfls-ion-ios-flask:before{content:""}.wfls-ion-ios-flask-outline:before{content:""}.wfls-ion-ios-flower:before{content:""}.wfls-ion-ios-flower-outline:before{content:""}.wfls-ion-ios-folder:before{content:""}.wfls-ion-ios-folder-outline:before{content:""}.wfls-ion-ios-football:before{content:""}.wfls-ion-ios-football-outline:before{content:""}.wfls-ion-ios-game-controller-a:before{content:""}.wfls-ion-ios-game-controller-a-outline:before{content:""}.wfls-ion-ios-game-controller-b:before{content:""}.wfls-ion-ios-game-controller-b-outline:before{content:""}.wfls-ion-ios-gear:before{content:""}.wfls-ion-ios-gear-outline:before{content:""}.wfls-ion-ios-glasses:before{content:""}.wfls-ion-ios-glasses-outline:before{content:""}.wfls-ion-ios-grid-view:before{content:""}.wfls-ion-ios-grid-view-outline:before{content:""}.wfls-ion-ios-heart:before{content:""}.wfls-ion-ios-heart-outline:before{content:""}.wfls-ion-ios-help:before{content:""}.wfls-ion-ios-help-empty:before{content:""}.wfls-ion-ios-help-outline:before{content:""}.wfls-ion-ios-home:before{content:""}.wfls-ion-ios-home-outline:before{content:""}.wfls-ion-ios-infinite:before{content:""}.wfls-ion-ios-infinite-outline:before{content:""}.wfls-ion-ios-information:before{content:""}.wfls-ion-ios-information-empty:before{content:""}.wfls-ion-ios-information-outline:before{content:""}.wfls-ion-ios-ionic-outline:before{content:""}.wfls-ion-ios-keypad:before{content:""}.wfls-ion-ios-keypad-outline:before{content:""}.wfls-ion-ios-lightbulb:before{content:""}.wfls-ion-ios-lightbulb-outline:before{content:""}.wfls-ion-ios-list:before{content:""}.wfls-ion-ios-list-outline:before{content:""}.wfls-ion-ios-location:before{content:""}.wfls-ion-ios-location-outline:before{content:""}.wfls-ion-ios-locked:before{content:""}.wfls-ion-ios-locked-outline:before{content:""}.wfls-ion-ios-loop:before{content:""}.wfls-ion-ios-loop-strong:before{content:""}.wfls-ion-ios-medical:before{content:""}.wfls-ion-ios-medical-outline:before{content:""}.wfls-ion-ios-medkit:before{content:""}.wfls-ion-ios-medkit-outline:before{content:""}.wfls-ion-ios-mic:before{content:""}.wfls-ion-ios-mic-off:before{content:""}.wfls-ion-ios-mic-outline:before{content:""}.wfls-ion-ios-minus:before{content:""}.wfls-ion-ios-minus-empty:before{content:""}.wfls-ion-ios-minus-outline:before{content:""}.wfls-ion-ios-monitor:before{content:""}.wfls-ion-ios-monitor-outline:before{content:""}.wfls-ion-ios-moon:before{content:""}.wfls-ion-ios-moon-outline:before{content:""}.wfls-ion-ios-more:before{content:""}.wfls-ion-ios-more-outline:before{content:""}.wfls-ion-ios-musical-note:before{content:""}.wfls-ion-ios-musical-notes:before{content:""}.wfls-ion-ios-navigate:before{content:""}.wfls-ion-ios-navigate-outline:before{content:""}.wfls-ion-ios-nutrition:before{content:""}.wfls-ion-ios-nutrition-outline:before{content:""}.wfls-ion-ios-paper:before{content:""}.wfls-ion-ios-paper-outline:before{content:""}.wfls-ion-ios-paperplane:before{content:""}.wfls-ion-ios-paperplane-outline:before{content:""}.wfls-ion-ios-partlysunny:before{content:""}.wfls-ion-ios-partlysunny-outline:before{content:""}.wfls-ion-ios-pause:before{content:""}.wfls-ion-ios-pause-outline:before{content:""}.wfls-ion-ios-paw:before{content:""}.wfls-ion-ios-paw-outline:before{content:""}.wfls-ion-ios-people:before{content:""}.wfls-ion-ios-people-outline:before{content:""}.wfls-ion-ios-person:before{content:""}.wfls-ion-ios-person-outline:before{content:""}.wfls-ion-ios-personadd:before{content:""}.wfls-ion-ios-personadd-outline:before{content:""}.wfls-ion-ios-photos:before{content:""}.wfls-ion-ios-photos-outline:before{content:""}.wfls-ion-ios-pie:before{content:""}.wfls-ion-ios-pie-outline:before{content:""}.wfls-ion-ios-pint:before{content:""}.wfls-ion-ios-pint-outline:before{content:""}.wfls-ion-ios-play:before{content:""}.wfls-ion-ios-play-outline:before{content:""}.wfls-ion-ios-plus:before{content:""}.wfls-ion-ios-plus-empty:before{content:""}.wfls-ion-ios-plus-outline:before{content:""}.wfls-ion-ios-pricetag:before{content:""}.wfls-ion-ios-pricetag-outline:before{content:""}.wfls-ion-ios-pricetags:before{content:""}.wfls-ion-ios-pricetags-outline:before{content:""}.wfls-ion-ios-printer:before{content:""}.wfls-ion-ios-printer-outline:before{content:""}.wfls-ion-ios-pulse:before{content:""}.wfls-ion-ios-pulse-strong:before{content:""}.wfls-ion-ios-rainy:before{content:""}.wfls-ion-ios-rainy-outline:before{content:""}.wfls-ion-ios-recording:before{content:""}.wfls-ion-ios-recording-outline:before{content:""}.wfls-ion-ios-redo:before{content:""}.wfls-ion-ios-redo-outline:before{content:""}.wfls-ion-ios-refresh:before{content:""}.wfls-ion-ios-refresh-empty:before{content:""}.wfls-ion-ios-refresh-outline:before{content:""}.wfls-ion-ios-reload:before{content:""}.wfls-ion-ios-reverse-camera:before{content:""}.wfls-ion-ios-reverse-camera-outline:before{content:""}.wfls-ion-ios-rewind:before{content:""}.wfls-ion-ios-rewind-outline:before{content:""}.wfls-ion-ios-rose:before{content:""}.wfls-ion-ios-rose-outline:before{content:""}.wfls-ion-ios-search:before{content:""}.wfls-ion-ios-search-strong:before{content:""}.wfls-ion-ios-settings:before{content:""}.wfls-ion-ios-settings-strong:before{content:""}.wfls-ion-ios-shuffle:before{content:""}.wfls-ion-ios-shuffle-strong:before{content:""}.wfls-ion-ios-skipbackward:before{content:""}.wfls-ion-ios-skipbackward-outline:before{content:""}.wfls-ion-ios-skipforward:before{content:""}.wfls-ion-ios-skipforward-outline:before{content:""}.wfls-ion-ios-snowy:before{content:""}.wfls-ion-ios-speedometer:before{content:""}.wfls-ion-ios-speedometer-outline:before{content:""}.wfls-ion-ios-star:before{content:""}.wfls-ion-ios-star-half:before{content:""}.wfls-ion-ios-star-outline:before{content:""}.wfls-ion-ios-stopwatch:before{content:""}.wfls-ion-ios-stopwatch-outline:before{content:""}.wfls-ion-ios-sunny:before{content:""}.wfls-ion-ios-sunny-outline:before{content:""}.wfls-ion-ios-telephone:before{content:""}.wfls-ion-ios-telephone-outline:before{content:""}.wfls-ion-ios-tennisball:before{content:""}.wfls-ion-ios-tennisball-outline:before{content:""}.wfls-ion-ios-thunderstorm:before{content:""}.wfls-ion-ios-thunderstorm-outline:before{content:""}.wfls-ion-ios-time:before{content:""}.wfls-ion-ios-time-outline:before{content:""}.wfls-ion-ios-timer:before{content:""}.wfls-ion-ios-timer-outline:before{content:""}.wfls-ion-ios-toggle:before{content:""}.wfls-ion-ios-toggle-outline:before{content:""}.wfls-ion-ios-trash:before{content:""}.wfls-ion-ios-trash-outline:before{content:""}.wfls-ion-ios-undo:before{content:""}.wfls-ion-ios-undo-outline:before{content:""}.wfls-ion-ios-unlocked:before{content:""}.wfls-ion-ios-unlocked-outline:before{content:""}.wfls-ion-ios-upload:before{content:""}.wfls-ion-ios-upload-outline:before{content:""}.wfls-ion-ios-videocam:before{content:""}.wfls-ion-ios-videocam-outline:before{content:""}.wfls-ion-ios-volume-high:before{content:""}.wfls-ion-ios-volume-low:before{content:""}.wfls-ion-ios-wineglass:before{content:""}.wfls-ion-ios-wineglass-outline:before{content:""}.wfls-ion-ios-world:before{content:""}.wfls-ion-ios-world-outline:before{content:""}.wfls-ion-ipad:before{content:""}.wfls-ion-iphone:before{content:""}.wfls-ion-ipod:before{content:""}.wfls-ion-jet:before{content:""}.wfls-ion-key:before{content:""}.wfls-ion-knife:before{content:""}.wfls-ion-laptop:before{content:""}.wfls-ion-leaf:before{content:""}.wfls-ion-levels:before{content:""}.wfls-ion-lightbulb:before{content:""}.wfls-ion-link:before{content:""}.wfls-ion-load-a:before{content:""}.wfls-ion-load-b:before{content:""}.wfls-ion-load-c:before{content:""}.wfls-ion-load-d:before{content:""}.wfls-ion-location:before{content:""}.wfls-ion-lock-combination:before{content:""}.wfls-ion-locked:before{content:""}.wfls-ion-log-in:before{content:""}.wfls-ion-log-out:before{content:""}.wfls-ion-loop:before{content:""}.wfls-ion-magnet:before{content:""}.wfls-ion-male:before{content:""}.wfls-ion-man:before{content:""}.wfls-ion-map:before{content:""}.wfls-ion-medkit:before{content:""}.wfls-ion-merge:before{content:""}.wfls-ion-mic-a:before{content:""}.wfls-ion-mic-b:before{content:""}.wfls-ion-mic-c:before{content:""}.wfls-ion-minus:before{content:""}.wfls-ion-minus-circled:before{content:""}.wfls-ion-minus-round:before{content:""}.wfls-ion-model-s:before{content:""}.wfls-ion-monitor:before{content:""}.wfls-ion-more:before{content:""}.wfls-ion-mouse:before{content:""}.wfls-ion-music-note:before{content:""}.wfls-ion-navicon:before{content:""}.wfls-ion-navicon-round:before{content:""}.wfls-ion-navigate:before{content:""}.wfls-ion-network:before{content:""}.wfls-ion-no-smoking:before{content:""}.wfls-ion-nuclear:before{content:""}.wfls-ion-outlet:before{content:""}.wfls-ion-paintbrush:before{content:""}.wfls-ion-paintbucket:before{content:""}.wfls-ion-paper-airplane:before{content:""}.wfls-ion-paperclip:before{content:""}.wfls-ion-pause:before{content:""}.wfls-ion-person:before{content:""}.wfls-ion-person-add:before{content:""}.wfls-ion-person-stalker:before{content:""}.wfls-ion-pie-graph:before{content:""}.wfls-ion-pin:before{content:""}.wfls-ion-pinpoint:before{content:""}.wfls-ion-pizza:before{content:""}.wfls-ion-plane:before{content:""}.wfls-ion-planet:before{content:""}.wfls-ion-play:before{content:""}.wfls-ion-playstation:before{content:""}.wfls-ion-plus:before{content:""}.wfls-ion-plus-circled:before{content:""}.wfls-ion-plus-round:before{content:""}.wfls-ion-podium:before{content:""}.wfls-ion-pound:before{content:""}.wfls-ion-power:before{content:""}.wfls-ion-pricetag:before{content:""}.wfls-ion-pricetags:before{content:""}.wfls-ion-printer:before{content:""}.wfls-ion-pull-request:before{content:""}.wfls-ion-qr-scanner:before{content:""}.wfls-ion-quote:before{content:""}.wfls-ion-radio-waves:before{content:""}.wfls-ion-record:before{content:""}.wfls-ion-refresh:before{content:""}.wfls-ion-reply:before{content:""}.wfls-ion-reply-all:before{content:""}.wfls-ion-ribbon-a:before{content:""}.wfls-ion-ribbon-b:before{content:""}.wfls-ion-sad:before{content:""}.wfls-ion-sad-outline:before{content:""}.wfls-ion-scissors:before{content:""}.wfls-ion-search:before{content:""}.wfls-ion-settings:before{content:""}.wfls-ion-share:before{content:""}.wfls-ion-shuffle:before{content:""}.wfls-ion-skip-backward:before{content:""}.wfls-ion-skip-forward:before{content:""}.wfls-ion-social-android:before{content:""}.wfls-ion-social-android-outline:before{content:""}.wfls-ion-social-angular:before{content:""}.wfls-ion-social-angular-outline:before{content:""}.wfls-ion-social-apple:before{content:""}.wfls-ion-social-apple-outline:before{content:""}.wfls-ion-social-bitcoin:before{content:""}.wfls-ion-social-bitcoin-outline:before{content:""}.wfls-ion-social-buffer:before{content:""}.wfls-ion-social-buffer-outline:before{content:""}.wfls-ion-social-chrome:before{content:""}.wfls-ion-social-chrome-outline:before{content:""}.wfls-ion-social-codepen:before{content:""}.wfls-ion-social-codepen-outline:before{content:""}.wfls-ion-social-css3:before{content:""}.wfls-ion-social-css3-outline:before{content:""}.wfls-ion-social-designernews:before{content:""}.wfls-ion-social-designernews-outline:before{content:""}.wfls-ion-social-dribbble:before{content:""}.wfls-ion-social-dribbble-outline:before{content:""}.wfls-ion-social-dropbox:before{content:""}.wfls-ion-social-dropbox-outline:before{content:""}.wfls-ion-social-euro:before{content:""}.wfls-ion-social-euro-outline:before{content:""}.wfls-ion-social-facebook:before{content:""}.wfls-ion-social-facebook-outline:before{content:""}.wfls-ion-social-foursquare:before{content:""}.wfls-ion-social-foursquare-outline:before{content:""}.wfls-ion-social-freebsd-devil:before{content:""}.wfls-ion-social-github:before{content:""}.wfls-ion-social-github-outline:before{content:""}.wfls-ion-social-google:before{content:""}.wfls-ion-social-google-outline:before{content:""}.wfls-ion-social-googleplus:before{content:""}.wfls-ion-social-googleplus-outline:before{content:""}.wfls-ion-social-hackernews:before{content:""}.wfls-ion-social-hackernews-outline:before{content:""}.wfls-ion-social-html5:before{content:""}.wfls-ion-social-html5-outline:before{content:""}.wfls-ion-social-instagram:before{content:""}.wfls-ion-social-instagram-outline:before{content:""}.wfls-ion-social-javascript:before{content:""}.wfls-ion-social-javascript-outline:before{content:""}.wfls-ion-social-linkedin:before{content:""}.wfls-ion-social-linkedin-outline:before{content:""}.wfls-ion-social-markdown:before{content:""}.wfls-ion-social-nodejs:before{content:""}.wfls-ion-social-octocat:before{content:""}.wfls-ion-social-pinterest:before{content:""}.wfls-ion-social-pinterest-outline:before{content:""}.wfls-ion-social-python:before{content:""}.wfls-ion-social-reddit:before{content:""}.wfls-ion-social-reddit-outline:before{content:""}.wfls-ion-social-rss:before{content:""}.wfls-ion-social-rss-outline:before{content:""}.wfls-ion-social-sass:before{content:""}.wfls-ion-social-skype:before{content:""}.wfls-ion-social-skype-outline:before{content:""}.wfls-ion-social-snapchat:before{content:""}.wfls-ion-social-snapchat-outline:before{content:""}.wfls-ion-social-tumblr:before{content:""}.wfls-ion-social-tumblr-outline:before{content:""}.wfls-ion-social-tux:before{content:""}.wfls-ion-social-twitch:before{content:""}.wfls-ion-social-twitch-outline:before{content:""}.wfls-ion-social-twitter:before{content:""}.wfls-ion-social-twitter-outline:before{content:""}.wfls-ion-social-usd:before{content:""}.wfls-ion-social-usd-outline:before{content:""}.wfls-ion-social-vimeo:before{content:""}.wfls-ion-social-vimeo-outline:before{content:""}.wfls-ion-social-whatsapp:before{content:""}.wfls-ion-social-whatsapp-outline:before{content:""}.wfls-ion-social-windows:before{content:""}.wfls-ion-social-windows-outline:before{content:""}.wfls-ion-social-wordpress:before{content:""}.wfls-ion-social-wordpress-outline:before{content:""}.wfls-ion-social-yahoo:before{content:""}.wfls-ion-social-yahoo-outline:before{content:""}.wfls-ion-social-yen:before{content:""}.wfls-ion-social-yen-outline:before{content:""}.wfls-ion-social-youtube:before{content:""}.wfls-ion-social-youtube-outline:before{content:""}.wfls-ion-soup-can:before{content:""}.wfls-ion-soup-can-outline:before{content:""}.wfls-ion-speakerphone:before{content:""}.wfls-ion-speedometer:before{content:""}.wfls-ion-spoon:before{content:""}.wfls-ion-star:before{content:""}.wfls-ion-stats-bars:before{content:""}.wfls-ion-steam:before{content:""}.wfls-ion-stop:before{content:""}.wfls-ion-thermometer:before{content:""}.wfls-ion-thumbsdown:before{content:""}.wfls-ion-thumbsup:before{content:""}.wfls-ion-toggle:before{content:""}.wfls-ion-toggle-filled:before{content:""}.wfls-ion-transgender:before{content:""}.wfls-ion-trash-a:before{content:""}.wfls-ion-trash-b:before{content:""}.wfls-ion-trophy:before{content:""}.wfls-ion-tshirt:before{content:""}.wfls-ion-tshirt-outline:before{content:""}.wfls-ion-umbrella:before{content:""}.wfls-ion-university:before{content:""}.wfls-ion-unlocked:before{content:""}.wfls-ion-upload:before{content:""}.wfls-ion-usb:before{content:""}.wfls-ion-videocamera:before{content:""}.wfls-ion-volume-high:before{content:""}.wfls-ion-volume-low:before{content:""}.wfls-ion-volume-medium:before{content:""}.wfls-ion-volume-mute:before{content:""}.wfls-ion-wand:before{content:""}.wfls-ion-waterdrop:before{content:""}.wfls-ion-wifi:before{content:""}.wfls-ion-wineglass:before{content:""}.wfls-ion-woman:before{content:""}.wfls-ion-wrench:before{content:""}.wfls-ion-xbox:before{content:""}
css/jquery-ui-timepicker-addon.1559237323.css ADDED
@@ -0,0 +1 @@
 
1
+ .ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-tpicker-grid-label{background:none;border:none;margin:0;padding:0}.ui-timepicker-div .ui_tpicker_unit_hide{display:none}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px}.ui-timepicker-div.ui-timepicker-oneLine{padding-right:2px}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,.ui-timepicker-div.ui-timepicker-oneLine dt{display:none}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label{display:block;padding-top:2px}.ui-timepicker-div.ui-timepicker-oneLine dl{text-align:right}.ui-timepicker-div.ui-timepicker-oneLine dl dd,.ui-timepicker-div.ui-timepicker-oneLine dl dd>div{display:inline-block;margin:0}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before{content:':';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before{content:'.';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{display:none}
css/jquery-ui.min.1559237323.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery UI - v1.11.4 - 2018-06-29
2
+ * http://jqueryui.com
3
+ * Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px
5
+ * Copyright jQuery Foundation and other contributors; Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default !important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#2b2b2b;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:0 0 0 0;padding:5px;background:#666;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
css/jquery-ui.structure.min.1559237323.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! jQuery UI - v1.11.4 - 2018-06-29
2
+ * http://jqueryui.com
3
+ * Copyright jQuery Foundation and other contributors; Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default !important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}
css/jquery-ui.theme.min.1559237323.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! jQuery UI - v1.11.4 - 2018-06-29
2
+ * http://jqueryui.com
3
+ * Copyright jQuery Foundation and other contributors; Licensed MIT */.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#2b2b2b;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("../img/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("../img/ui-icons_444444_256x240.png")}.ui-state-default .ui-icon{background-image:url("../img/ui-icons_777777_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("../img/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon{background-image:url("../img/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("../img/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("../img/ui-icons_cc0000_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:0 0 0 0;padding:5px;background:#666;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
css/login.1559237323.css ADDED
@@ -0,0 +1 @@
 
1
+ #wfls-prompt-overlay{position:absolute;top:0px;right:0px;bottom:0px;left:0px;background-color:#fff;padding:26px 24px 46px;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:stretch;justify-content:stretch}#wfls-prompt-wrapper{-webkit-flex-grow:1;flex-grow:1;width:100%}.login form .wfls-textarea{font-size:1rem;width:100%;padding:3px;margin:2px 6px 16px 0;background:#fbfbfb;height:150px}.login form .wfls-remember-device-wrapper{font-weight:400;float:left;margin-bottom:0}.login form .wfls-remember-device-wrapper label{font-size:12px;line-height:19px}.wfls-2fa-code-help{text-decoration:none}.Zebra_Tooltip{background:0 0;position:absolute;z-index:8000}.Zebra_Tooltip .Zebra_Tooltip_Message{background:#000;border-radius:5px;box-shadow:0 0 6px rgba(0,0,0,0.6);color:#fff;font-size:12px;font-family:Tahoma,Arial,Helvetica,sans-serif;line-height:1.4;*margin-right:0;max-width:250px;padding:10px;position:relative;_width:expression(document.body.clientWidth > 250px ? '250px': 'auto');border:0 solid #000}.Zebra_Tooltip .Zebra_Tooltip_Message.Zebra_Tooltip_Has_Close{padding-right:23px}.Zebra_Tooltip .Zebra_Tooltip_Arrow{position:absolute;width:20px;height:10px;overflow:hidden}.Zebra_Tooltip .Zebra_Tooltip_Arrow.Zebra_Tooltip_Arrow_Bottom{bottom:0}.Zebra_Tooltip .Zebra_Tooltip_Arrow.Zebra_Tooltip_Arrow_Bottom div{top:0;border-color:#000 transparent transparent;_border-bottom-color:pink}.Zebra_Tooltip .Zebra_Tooltip_Arrow.Zebra_Tooltip_Arrow_Bottom div.Zebra_Tooltip_Arrow_Border{border-color:#000 transparent transparent}.Zebra_Tooltip .Zebra_Tooltip_Arrow.Zebra_Tooltip_Arrow_Top{top:0}.Zebra_Tooltip .Zebra_Tooltip_Arrow.Zebra_Tooltip_Arrow_Top div{bottom:0;border-color:transparent transparent #000;_border-top-color:pink}.Zebra_Tooltip .Zebra_Tooltip_Arrow.Zebra_Tooltip_Arrow_Top div.Zebra_Tooltip_Arrow_Border{border-color:transparent transparent #000}.Zebra_Tooltip .Zebra_Tooltip_Arrow div{position:absolute;border-style:solid;border-width:10px;width:0;height:0;left:0;_border-left-color:pink;_border-right-color:pink;_filter:chroma(color=pink)}.Zebra_Tooltip .Zebra_Tooltip_Arrow div.Zebra_Tooltip_Arrow_Border{border-width:10px;box-shadow:0 0 6px rgba(0,0,0,0.6);left:0}.Zebra_Tooltip .Zebra_Tooltip_Close{color:#fff;font-family:Arial,sans-serif;font-size:18px;line-height:1;padding:0 4px;position:absolute;right:2px;text-decoration:none;top:2px}.Zebra_Tooltip .Zebra_Tooltip_Close:hover{color:#000;background:#c2d076;border-radius:5px}
font/fontawesome-webfont.woff ADDED
Binary file
font/ionicons.woff ADDED
Binary file
img/header.svg ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
4
+ <g>
5
+ <path d="M16,8.59L17.59,12.08L17.6,12.11L17.06,12.11L17.06,12.12C17.07,12.17 17.08,12.22 17.08,12.28C17.08,12.45 17.04,12.61 16.96,12.75C16.93,12.82 16.88,12.88 16.84,12.93C16.84,12.93 16.77,13.69 16.78,15.11C16.78,15.96 16.83,17.21 16.93,18.58C18.59,18.67 20.13,18.86 21.55,19.11L21.55,13.19L21.14,13.19L22.2,10.87L23.22,13.2L22.81,13.2L22.81,19.35C24.32,19.66 25.66,20.04 26.82,20.42L26.82,15.27L26.41,15.27L27.47,12.95L28.49,15.28L28.08,15.28L28.08,20.86C29.45,21.37 30.48,21.85 31.11,22.17C31.9,14.72 30.28,8.26 30.28,8.26C22.71,8.01 16,4 16,4L16,8.59Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
6
+ <path d="M28.04,22.18L28.04,28L29.81,28C30.06,27.19 30.27,26.36 30.45,25.55C30.68,24.74 30.81,24.07 30.9,23.59C30.9,23.59 30.9,23.57 30.9,23.56C30.91,23.53 30.91,23.5 30.91,23.47C30.47,23.23 29.49,22.73 28.04,22.18Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
7
+ <path d="M22.79,20.61L22.79,28L26.8,28L26.8,21.72C25.66,21.33 24.31,20.94 22.79,20.61Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
8
+ <path d="M21.54,28L21.54,20.36C20.16,20.11 18.64,19.91 17.02,19.81C17.02,19.82 17.02,19.82 17.02,19.83C17.02,19.86 17.13,20.68 17.14,20.81C17.39,22.7 17.9,25.67 18.43,27.99L18.4,27.99L21.54,27.99L21.54,28Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
9
+ <path d="M13.57,28C14.09,25.68 14.6,22.71 14.86,20.82L14.85,20.82L14.86,20.82C14.88,20.68 14.98,19.87 14.98,19.84C14.98,19.83 14.98,19.83 14.98,19.82C13.35,19.92 11.83,20.12 10.46,20.37L10.46,28L13.59,28L13.57,28Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
10
+ <path d="M3.96,20.86L3.96,15.28L3.55,15.28L4.57,12.95L5.63,15.27L5.22,15.27L5.22,20.42C6.38,20.04 7.72,19.67 9.23,19.35L9.23,13.2L8.82,13.2L9.84,10.87L10.9,13.19L10.49,13.19L10.49,19.11C11.91,18.86 13.45,18.67 15.11,18.58C15.21,17.21 15.26,15.96 15.26,15.11C15.27,13.7 15.2,12.93 15.2,12.93C15.15,12.87 15.11,12.81 15.08,12.75C15,12.61 14.96,12.45 14.96,12.28C14.96,12.23 14.97,12.17 14.98,12.12L14.98,12.11L14.44,12.11L14.45,12.08L16,8.59L16,4C16,4 9.29,8.01 1.75,8.26C1.75,8.26 0.13,14.72 0.92,22.17C1.56,21.85 2.58,21.36 3.96,20.86Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
11
+ <path d="M5.2,21.72L5.2,28L9.21,28L9.21,20.61C7.64,20.95 6.28,21.35 5.2,21.72Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
12
+ <path d="M1.09,23.47C1.08,23.47 1.08,23.47 1.09,23.47C1.09,23.5 1.1,23.53 1.1,23.56C1.1,23.57 1.1,23.58 1.1,23.59C1.18,24.07 1.32,24.74 1.55,25.55C1.73,26.36 1.95,27.19 2.19,28L3.95,28L3.95,22.17C2.51,22.73 1.53,23.23 1.09,23.47Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
13
+ </g>
14
+ </svg>
img/lightbox-controls.png ADDED
Binary file
img/loading.gif ADDED
Binary file
img/loading_background.png ADDED
Binary file
img/menu.svg ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
4
+ <g>
5
+ <path d="M16,8.59L17.59,12.08L17.6,12.11L17.06,12.11L17.06,12.12C17.07,12.17 17.08,12.22 17.08,12.28C17.08,12.45 17.04,12.61 16.96,12.75C16.93,12.82 16.88,12.88 16.84,12.93C16.84,12.93 16.77,13.69 16.78,15.11C16.78,15.96 16.83,17.21 16.93,18.58C18.59,18.67 20.13,18.86 21.55,19.11L21.55,13.19L21.14,13.19L22.2,10.87L23.22,13.2L22.81,13.2L22.81,19.35C24.32,19.66 25.66,20.04 26.82,20.42L26.82,15.27L26.41,15.27L27.47,12.95L28.49,15.28L28.08,15.28L28.08,20.86C29.45,21.37 30.48,21.85 31.11,22.17C31.9,14.72 30.28,8.26 30.28,8.26C22.71,8.01 16,4 16,4L16,8.59Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
6
+ <path d="M28.04,22.18L28.04,28L29.81,28C30.06,27.19 30.27,26.36 30.45,25.55C30.68,24.74 30.81,24.07 30.9,23.59C30.9,23.59 30.9,23.57 30.9,23.56C30.91,23.53 30.91,23.5 30.91,23.47C30.47,23.23 29.49,22.73 28.04,22.18Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
7
+ <path d="M22.79,20.61L22.79,28L26.8,28L26.8,21.72C25.66,21.33 24.31,20.94 22.79,20.61Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
8
+ <path d="M21.54,28L21.54,20.36C20.16,20.11 18.64,19.91 17.02,19.81C17.02,19.82 17.02,19.82 17.02,19.83C17.02,19.86 17.13,20.68 17.14,20.81C17.39,22.7 17.9,25.67 18.43,27.99L18.4,27.99L21.54,27.99L21.54,28Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
9
+ <path d="M13.57,28C14.09,25.68 14.6,22.71 14.86,20.82L14.85,20.82L14.86,20.82C14.88,20.68 14.98,19.87 14.98,19.84C14.98,19.83 14.98,19.83 14.98,19.82C13.35,19.92 11.83,20.12 10.46,20.37L10.46,28L13.59,28L13.57,28Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
10
+ <path d="M3.96,20.86L3.96,15.28L3.55,15.28L4.57,12.95L5.63,15.27L5.22,15.27L5.22,20.42C6.38,20.04 7.72,19.67 9.23,19.35L9.23,13.2L8.82,13.2L9.84,10.87L10.9,13.19L10.49,13.19L10.49,19.11C11.91,18.86 13.45,18.67 15.11,18.58C15.21,17.21 15.26,15.96 15.26,15.11C15.27,13.7 15.2,12.93 15.2,12.93C15.15,12.87 15.11,12.81 15.08,12.75C15,12.61 14.96,12.45 14.96,12.28C14.96,12.23 14.97,12.17 14.98,12.12L14.98,12.11L14.44,12.11L14.45,12.08L16,8.59L16,4C16,4 9.29,8.01 1.75,8.26C1.75,8.26 0.13,14.72 0.92,22.17C1.56,21.85 2.58,21.36 3.96,20.86Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
11
+ <path d="M5.2,21.72L5.2,28L9.21,28L9.21,20.61C7.64,20.95 6.28,21.35 5.2,21.72Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
12
+ <path d="M1.09,23.47C1.08,23.47 1.08,23.47 1.09,23.47C1.09,23.5 1.1,23.53 1.1,23.56C1.1,23.57 1.1,23.58 1.1,23.59C1.18,24.07 1.32,24.74 1.55,25.55C1.73,26.36 1.95,27.19 2.19,28L3.95,28L3.95,22.17C2.51,22.73 1.53,23.23 1.09,23.47Z" style="fill:rgb(33,141,193);fill-rule:nonzero;"/>
13
+ </g>
14
+ </svg>
img/ui-icons_444444_256x240.png ADDED
Binary file
img/ui-icons_555555_256x240.png ADDED
Binary file
img/ui-icons_777620_256x240.png ADDED
Binary file
img/ui-icons_777777_256x240.png ADDED
Binary file
img/ui-icons_cc0000_256x240.png ADDED
Binary file
img/ui-icons_ffffff_256x240.png ADDED
Binary file
js/admin-global.1559237323.js ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ window['GWFLS'] = {
3
+ init: function() {
4
+
5
+ },
6
+
7
+ /**
8
+ * Sends a WP AJAX call, automatically adding our nonce.
9
+ *
10
+ * @param string action
11
+ * @param string|array|object payload
12
+ * @param function successCallback
13
+ * @param function failureCallback
14
+ */
15
+ ajax: function(action, payload, successCallback, failureCallback) {
16
+ if (typeof(payload) == 'string') {
17
+ if (payload.length > 0) {
18
+ payload += '&';
19
+ }
20
+ payload += 'action=' + action + '&nonce=' + GWFLSVars.nonce;
21
+ }
22
+ else if (typeof(payload) == 'object' && payload instanceof Array) {
23
+ // jQuery serialized form data
24
+ payload.push({
25
+ name: 'action',
26
+ value: action
27
+ });
28
+ payload.push({
29
+ name: 'nonce',
30
+ value: GWFLSVars.nonce
31
+ });
32
+ }
33
+ else if (typeof(payload) == 'object') {
34
+ payload['action'] = action;
35
+ payload['nonce'] = GWFLSVars.nonce;
36
+ }
37
+
38
+
39
+ $.ajax({
40
+ type: 'POST',
41
+ url: GWFLSVars.ajaxurl,
42
+ dataType: "json",
43
+ data: payload,
44
+ success: function(json) {
45
+ typeof successCallback == 'function' && successCallback(json);
46
+ },
47
+ error: function() {
48
+ typeof failureCallback == 'function' && failureCallback();
49
+ }
50
+ });
51
+ },
52
+
53
+ dismiss_notice: function(nid) {
54
+ this.ajax('wordfence_ls_dismiss_notice', {
55
+ id: nid
56
+ },
57
+ function(res) { $('.wfls-notice[data-notice-id="' + nid + '"]').fadeOut(); },
58
+ function() { $('.wfls-notice[data-notice-id="' + nid + '"]').fadeOut(); }
59
+ );
60
+ },
61
+ };
62
+
63
+ $(function() {
64
+ GWFLS.init();
65
+ });
66
+ })(jQuery);
67
+
js/admin.1559237323.js ADDED
@@ -0,0 +1,842 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ window['WFLS'] = {
3
+ panelIsOpen: false,
4
+ basePageName: '',
5
+ panelQueue: [],
6
+ pendingChanges: {},
7
+
8
+ //Screen sizes
9
+ SCREEN_XS: 'xs',
10
+ SCREEN_SM: 'sm',
11
+ SCREEN_MD: 'md',
12
+ SCREEN_LG: 'lg',
13
+
14
+ init: function() {
15
+ this.basePageName = document.title;
16
+
17
+ var tabs = $('.wfls-page-tabs').find('.wfls-tab a');
18
+ if (tabs.length > 0) {
19
+ tabs.click(function() {
20
+ $('.wfls-page-tabs').find('.wfls-tab').removeClass('wfls-active');
21
+ $('.wfls-tab-content').removeClass('wfls-active');
22
+
23
+ var tab = $(this).closest('.wfls-tab');
24
+ tab.addClass('wfls-active');
25
+ var content = $('#' + tab.data('target'));
26
+ content.addClass('wfls-active');
27
+ document.title = tab.data('pageTitle') + " \u2039 " + WFLS.basePageName;
28
+ $(window).trigger('wfls-tab-change', [tab.data('target')]);
29
+ });
30
+ if (window.location.hash) {
31
+ var hashes = WFLS.parseHashes();
32
+ var hash = hashes[hashes.length - 1];
33
+ for (var i = 0; i < tabs.length; i++) {
34
+ if (hash == $(tabs[i]).closest('.wfls-tab').data('target')) {
35
+ $(tabs[i]).trigger('click');
36
+ }
37
+ }
38
+ }
39
+ else {
40
+ $(tabs[0]).trigger('click');
41
+ }
42
+ $(window).on('hashchange', function () {
43
+ var hashes = WFLS.parseHashes();
44
+ var hash = hashes[hashes.length - 1];
45
+ for (var i = 0; i < tabs.length; i++) {
46
+ if (hash == $(tabs[i]).closest('.wfls-tab').data('target')) {
47
+ $(tabs[i]).trigger('click');
48
+ }
49
+ }
50
+ });
51
+ }
52
+
53
+ //On/Off Option
54
+ $('.wfls-option.wfls-option-toggled .wfls-option-checkbox').each(function() {
55
+ $(this).on('keydown', function(e) {
56
+ if (e.keyCode == 32) {
57
+ e.preventDefault();
58
+ e.stopPropagation();
59
+
60
+ $(this).trigger('click');
61
+ }
62
+ });
63
+
64
+ $(this).on('click', function(e) {
65
+ e.preventDefault();
66
+ e.stopPropagation();
67
+
68
+ var optionElement = $(this).closest('.wfls-option');
69
+ if (optionElement.hasClass('wfls-option-premium') || optionElement.hasClass('wfls-disabled')) {
70
+ return;
71
+ }
72
+
73
+ var option = optionElement.data('option');
74
+ var value = false;
75
+ var isActive = $(this).hasClass('wfls-checked');
76
+ if (isActive) {
77
+ $(this).removeClass('wfls-checked').attr('aria-checked', 'false');
78
+ value = optionElement.data('disabledValue');
79
+ }
80
+ else {
81
+ $(this).addClass('wfls-checked').attr('aria-checked', 'true');
82
+ value = optionElement.data('enabledValue');
83
+ }
84
+
85
+ var originalValue = optionElement.data('originalValue');
86
+ if (originalValue == value) {
87
+ delete WFLS.pendingChanges[option];
88
+ }
89
+ else {
90
+ WFLS.pendingChanges[option] = value;
91
+ }
92
+
93
+ $(optionElement).trigger('change', [false]);
94
+ WFLS.updatePendingChanges();
95
+ });
96
+
97
+ $(this).parent().find('.wfls-option-title').on('click', function(e) {
98
+ var links = $(this).find('a');
99
+ var buffer = 10;
100
+ for (var i = 0; i < links.length; i++) {
101
+ var t = $(links[i]).offset().top;
102
+ var l = $(links[i]).offset().left;
103
+ var b = t + $(links[i]).height();
104
+ var r = l + $(links[i]).width();
105
+
106
+ if (e.pageX > l - buffer && e.pageX < r + buffer && e.pageY > t - buffer && e.pageY < b + buffer) {
107
+ return;
108
+ }
109
+ }
110
+ $(this).parent().find('.wfls-option-checkbox').trigger('click');
111
+ }).css('cursor', 'pointer');
112
+ });
113
+
114
+ //On/Off Boolean Switch Option
115
+ $('.wfls-option.wfls-option-toggled-boolean-switch .wfls-boolean-switch').each(function() {
116
+ $(this).on('keydown', function(e) {
117
+ if (e.keyCode == 32) {
118
+ e.preventDefault();
119
+ e.stopPropagation();
120
+
121
+ $(this).trigger('click');
122
+ }
123
+ });
124
+
125
+ $(this).on('click', function(e) {
126
+ e.preventDefault();
127
+ e.stopPropagation();
128
+
129
+ $(this).find('.wfls-boolean-switch-handle').trigger('click');
130
+ });
131
+
132
+ $(this).find('.wfls-boolean-switch-handle').on('click', function(e) {
133
+ e.preventDefault();
134
+ e.stopPropagation();
135
+
136
+ var optionElement = $(this).closest('.wfls-option');
137
+ if (optionElement.hasClass('wfls-option-premium') || optionElement.hasClass('wfls-disabled')) {
138
+ return;
139
+ }
140
+
141
+ var switchElement = $(this).closest('.wfls-boolean-switch');
142
+ var option = optionElement.data('option');
143
+ var value = false;
144
+ var isActive = switchElement.hasClass('wfls-active');
145
+ if (isActive) {
146
+ switchElement.removeClass('wfls-active').attr('aria-checked', 'false');
147
+ value = optionElement.data('disabledValue');
148
+ }
149
+ else {
150
+ switchElement.addClass('wfls-active').attr('aria-checked', 'true');
151
+ value = optionElement.data('enabledValue');
152
+ }
153
+
154
+ var originalValue = optionElement.data('originalValue');
155
+ if (originalValue == value) {
156
+ delete WFLS.pendingChanges[option];
157
+ }
158
+ else {
159
+ WFLS.pendingChanges[option] = value;
160
+ }
161
+
162
+ $(optionElement).trigger('change', [false]);
163
+ WFLS.updatePendingChanges();
164
+ });
165
+
166
+ $(this).parent().find('.wfls-option-title').on('click', function(e) {
167
+ var links = $(this).find('a');
168
+ var buffer = 10;
169
+ for (var i = 0; i < links.length; i++) {
170
+ var t = $(links[i]).offset().top;
171
+ var l = $(links[i]).offset().left;
172
+ var b = t + $(links[i]).height();
173
+ var r = l + $(links[i]).width();
174
+
175
+ if (e.pageX > l - buffer && e.pageX < r + buffer && e.pageY > t - buffer && e.pageY < b + buffer) {
176
+ return;
177
+ }
178
+ }
179
+ $(this).parent().find('.wfls-boolean-switch-handle').trigger('click');
180
+ }).css('cursor', 'pointer');
181
+ });
182
+
183
+ //On/Off Segmented Option
184
+ $('.wfls-option.wfls-option-toggled-segmented [type=radio]').each(function() {
185
+ $(this).on('click', function(e) {
186
+ var optionElement = $(this).closest('.wfls-option');
187
+ if (optionElement.hasClass('wfls-option-premium') || optionElement.hasClass('wfls-disabled')) {
188
+ return;
189
+ }
190
+
191
+ var option = optionElement.data('option');
192
+ var value = this.value;
193
+
194
+ var originalValue = optionElement.data('originalValue');
195
+ if (originalValue == value) {
196
+ delete WFLS.pendingChanges[option];
197
+ }
198
+ else {
199
+ WFLS.pendingChanges[option] = value;
200
+ }
201
+
202
+ $(optionElement).trigger('change', [false]);
203
+ WFLS.updatePendingChanges();
204
+ });
205
+ });
206
+
207
+ //On/Off Multiple Option
208
+ $('.wfls-option.wfls-option-toggled-multiple .wfls-option-checkbox').each(function() {
209
+ $(this).on('keydown', function(e) {
210
+ if (e.keyCode == 32) {
211
+ e.preventDefault();
212
+ e.stopPropagation();
213
+
214
+ $(this).trigger('click');
215
+ }
216
+ });
217
+
218
+ $(this).on('click', function(e) {
219
+ e.preventDefault();
220
+ e.stopPropagation();
221
+
222
+ var optionElement = $(this).closest('.wfls-option');
223
+ if (optionElement.hasClass('wfls-option-premium') || optionElement.hasClass('wfls-disabled') || $(this).hasClass('wfls-disabled')) {
224
+ return;
225
+ }
226
+
227
+ var checkboxElement = $(this).closest('ul');
228
+ var option = checkboxElement.data('option');
229
+ var value = false;
230
+ var isActive = $(this).hasClass('wfls-checked');
231
+ if (isActive) {
232
+ $(this).removeClass('wfls-checked').attr('aria-checked', 'false');
233
+ value = checkboxElement.data('disabledValue');
234
+ }
235
+ else {
236
+ $(this).addClass('wfls-checked').attr('aria-checked', 'true');
237
+ value = checkboxElement.data('enabledValue');
238
+ }
239
+
240
+ var originalValue = checkboxElement.data('originalValue');
241
+ if (originalValue == value) {
242
+ delete WFLS.pendingChanges[option];
243
+ }
244
+ else {
245
+ WFLS.pendingChanges[option] = value;
246
+ }
247
+
248
+ $(optionElement).trigger('change', [false]);
249
+ WFLS.updatePendingChanges();
250
+ });
251
+
252
+ $(this).parent().find('.wfls-option-title').on('click', function(e) {
253
+ var links = $(this).find('a');
254
+ var buffer = 10;
255
+ for (var i = 0; i < links.length; i++) {
256
+ var t = $(links[i]).offset().top;
257
+ var l = $(links[i]).offset().left;
258
+ var b = t + $(links[i]).height();
259
+ var r = l + $(links[i]).width();
260
+
261
+ if (e.pageX > l - buffer && e.pageX < r + buffer && e.pageY > t - buffer && e.pageY < b + buffer) {
262
+ return;
263
+ }
264
+ }
265
+ $(this).parent().find('.wfls-option-checkbox').trigger('click');
266
+ }).css('cursor', 'pointer');
267
+ });
268
+
269
+ //Text field option
270
+ $('.wfls-option.wfls-option-text > .wfls-option-content > ul > li.wfls-option-text input').on('change paste keyup', function() {
271
+ var e = this;
272
+
273
+ setTimeout(function() {
274
+ var optionElement = $(e).closest('.wfls-option');
275
+ var option = optionElement.data('textOption');
276
+
277
+ if (typeof option !== 'undefined') {
278
+ var value = $(e).val();
279
+
280
+ var originalValue = optionElement.data('originalTextValue');
281
+ if (originalValue == value) {
282
+ delete WFLS.pendingChanges[option];
283
+ }
284
+ else {
285
+ WFLS.pendingChanges[option] = value;
286
+ }
287
+
288
+ $(optionElement).trigger('change', [false]);
289
+ WFLS.updatePendingChanges();
290
+ }
291
+ }, 4);
292
+ });
293
+
294
+ //Text area option
295
+ $('.wfls-option.wfls-option-textarea > .wfls-option-content > ul > li.wfls-option-textarea textarea').on('change paste keyup', function() {
296
+ var e = this;
297
+
298
+ setTimeout(function() {
299
+ var optionElement = $(e).closest('.wfls-option');
300
+ var option = optionElement.data('textOption');
301
+ var value = $(e).val();
302
+
303
+ var originalValue = optionElement.data('originalTextValue');
304
+ if (originalValue == value) {
305
+ delete WFLS.pendingChanges[option];
306
+ }
307
+ else {
308
+ WFLS.pendingChanges[option] = value;
309
+ }
310
+
311
+ $(optionElement).trigger('change', [false]);
312
+ WFLS.updatePendingChanges();
313
+ }, 4);
314
+ });
315
+
316
+ //Switch Option
317
+ $('.wfls-option.wfls-option-switch .wfls-switch > li').each(function(index, element) {
318
+ $(this).on('keydown', function(e) {
319
+ if (e.keyCode == 32) {
320
+ e.preventDefault();
321
+ e.stopPropagation();
322
+
323
+ $(this).trigger('click');
324
+ }
325
+ });
326
+
327
+ $(element).on('click', function(e) {
328
+ e.preventDefault();
329
+ e.stopPropagation();
330
+
331
+ var optionElement = $(this).closest('ul.wfls-option-switch, div.wfls-option-switch');
332
+ var optionName = optionElement.data('optionName');
333
+ var originalValue = optionElement.data('originalValue');
334
+ var value = $(this).data('optionValue');
335
+
336
+ var control = $(this).closest('.wfls-switch');
337
+ control.find('li').each(function() {
338
+ $(this).toggleClass('wfls-active', value == $(this).data('optionValue')).attr('aria-checked', value == $(this).data('optionValue') ? 'true' : 'false');
339
+ });
340
+
341
+ if (originalValue == value) {
342
+ delete WFLS.pendingChanges[optionName];
343
+ }
344
+ else {
345
+ WFLS.pendingChanges[optionName] = value;
346
+ }
347
+
348
+ $(optionElement).trigger('change', [false]);
349
+ WFLS.updatePendingChanges();
350
+ });
351
+ });
352
+
353
+ $('#wfls-save-changes').on('click', function(e) {
354
+ e.preventDefault();
355
+ e.stopPropagation();
356
+
357
+ WFLS.saveOptions(function(res) {
358
+ WFLS.pendingChanges = {};
359
+ WFLS.updatePendingChanges();
360
+
361
+ if (res.redirect) {
362
+ window.location.href = res.redirect;
363
+ }
364
+ else {
365
+ window.location.reload(true);
366
+ }
367
+ });
368
+ });
369
+
370
+ $('#wfls-cancel-changes').on('click', function(e) {
371
+ e.preventDefault();
372
+ e.stopPropagation();
373
+
374
+ //On/Off options
375
+ $('.wfls-option.wfls-option-toggled').each(function() {
376
+ var enabledValue = $(this).data('enabledValue');
377
+ var disabledValue = $(this).data('disabledValue');
378
+ var originalValue = $(this).data('originalValue');
379
+ if (enabledValue == originalValue) {
380
+ $(this).find('.wfls-option-checkbox').addClass('wfls-checked').attr('aria-checked', 'true');
381
+ }
382
+ else {
383
+ $(this).find('.wfls-option-checkbox').removeClass('wfls-checked').attr('aria-checked', 'false');
384
+ }
385
+ $(this).trigger('change', [true]);
386
+ });
387
+
388
+ $('.wfls-option-toggled-boolean-switch').each(function() {
389
+ var enabledValue = $(this).data('enabledValue');
390
+ var disabledValue = $(this).data('disabledValue');
391
+ var originalValue = $(this).data('originalValue');
392
+ if (enabledValue == originalValue) {
393
+ $(this).find('.wfls-boolean-switch').addClass('wfls-active').attr('aria-checked', 'true');
394
+ }
395
+ else {
396
+ $(this).find('.wfls-boolean-switch').removeClass('wfls-active').attr('aria-checked', 'false');
397
+ }
398
+ $(this).trigger('change', [true]);
399
+ });
400
+
401
+ $('.wfls-option.wfls-option-toggled-segmented').each(function() {
402
+ var originalValue = $(this).data('originalValue');
403
+ $(this).find('[type=radio]').each(function() {
404
+ if (this.value == originalValue) {
405
+ this.checked = true;
406
+ return false;
407
+ }
408
+ });
409
+ $(this).trigger('change', [true]);
410
+ });
411
+
412
+ //On/Off multiple options
413
+ $('.wfls-option.wfls-option-toggled-multiple').each(function() {
414
+ $(this).find('.wfls-option-checkboxes > ul').each(function() {
415
+ var enabledValue = $(this).data('enabledValue');
416
+ var disabledValue = $(this).data('disabledValue');
417
+ var originalValue = $(this).data('originalValue');
418
+ if (enabledValue == originalValue) {
419
+ $(this).find('.wfls-option-checkbox').addClass('wfls-checked').attr('aria-checked', 'true');
420
+ }
421
+ else {
422
+ $(this).find('.wfls-option-checkbox').removeClass('wfls-checked').attr('aria-checked', 'false');
423
+ }
424
+ });
425
+ $(this).trigger('change', [true]);
426
+ });
427
+
428
+ //On/Off options with menu
429
+ $('.wfls-option.wfls-option-toggled-select').each(function() {
430
+ var selectElement = $(this).find('.wfls-option-select select');
431
+ var enabledToggleValue = $(this).data('enabledToggleValue');
432
+ var disabledToggleValue = $(this).data('disabledToggleValue');
433
+ var originalToggleValue = $(this).data('originalToggleValue');
434
+ if (enabledToggleValue == originalToggleValue) {
435
+ $(this).find('.wfls-option-checkbox').addClass('wfls-checked').attr('aria-checked', 'true');
436
+ selectElement.attr('disabled', false);
437
+ }
438
+ else {
439
+ $(this).find('.wfls-option-checkbox').removeClass('wfls-checked').attr('aria-checked', 'false');
440
+ selectElement.attr('disabled', true);
441
+ }
442
+
443
+ var originalSelectValue = $(this).data('originalSelectValue');
444
+ $(this).find('.wfls-option-select select').val(originalSelectValue).trigger('change');
445
+ $(this).trigger('change', [true]);
446
+ });
447
+
448
+ //Menu options
449
+ $('.wfls-option.wfls-option-select').each(function() {
450
+ var originalSelectValue = $(this).data('originalSelectValue');
451
+ $(this).find('.wfls-option-select select').val(originalSelectValue).trigger('change');
452
+ $(this).trigger('change', [true]);
453
+ });
454
+
455
+ //Text options
456
+ $('.wfls-option.wfls-option-text').each(function() {
457
+ var originalTextValue = $(this).data('originalTextValue');
458
+ if (typeof originalTextValue !== 'undefined') {
459
+ $(this).find('.wfls-option-text input').val(originalTextValue);
460
+ }
461
+ $(this).trigger('change', [true]);
462
+ });
463
+
464
+ //Text area options
465
+ $('.wfls-option.wfls-option-textarea').each(function() {
466
+ var originalTextValue = $(this).data('originalTextValue');
467
+ $(this).find('.wfls-option-textarea textarea').val(originalTextValue);
468
+ $(this).trigger('change', [true]);
469
+ });
470
+
471
+ //Token options
472
+ $('.wfls-option.wfls-option-token').each(function() {
473
+ var originalTokenValue = $(this).data('originalTokenValue');
474
+ $(this).find('select').val(originalTokenValue).trigger('change');
475
+ $(this).trigger('change', [true]);
476
+ });
477
+
478
+ //Switch options
479
+ $('.wfls-option.wfls-option-switch').each(function() {
480
+ var originalValue = $(this).data('originalValue');
481
+ $(this).find('.wfls-switch > li').each(function() {
482
+ $(this).toggleClass('wfls-active', originalValue == $(this).data('optionValue')).attr('aria-checked', originalValue == $(this).data('optionValue') ? 'true' : 'false');
483
+ });
484
+ $(this).trigger('change', [true]);
485
+ });
486
+
487
+ //Other options
488
+ $(window).trigger('wflsOptionsReset');
489
+
490
+ WFLS.pendingChanges = {};
491
+ WFLS.updatePendingChanges();
492
+ });
493
+ },
494
+
495
+ updatePendingChanges: function() {
496
+ $(window).off('beforeunload', WFLS._unsavedOptionsHandler);
497
+ if (Object.keys(WFLS.pendingChanges).length) {
498
+ $('#wfls-cancel-changes').removeClass('wfls-disabled');
499
+ $('#wfls-save-changes').removeClass('wfls-disabled');
500
+ $(window).on('beforeunload', WFLS._unsavedOptionsHandler);
501
+ }
502
+ else {
503
+ $('#wfls-cancel-changes').addClass('wfls-disabled');
504
+ $('#wfls-save-changes').addClass('wfls-disabled');
505
+ }
506
+ },
507
+
508
+ _unsavedOptionsHandler: function(e) {
509
+ var message = "You have unsaved changes to your options. If you leave this page, those changes will be lost."; //Only shows on older browsers, newer browsers don't allow message customization
510
+ e = e || window.event;
511
+ if (e) {
512
+ e.returnValue = message; //IE and Firefox
513
+ }
514
+ return message; //Others
515
+ },
516
+
517
+ setOptions: function(options, successCallback, failureCallback) {
518
+ if (!Object.keys(options).length) {
519
+ return;
520
+ }
521
+
522
+ this.ajax('wordfence_ls_save_options', {changes: JSON.stringify(options)}, function(res) {
523
+ if (res.success) {
524
+ typeof successCallback == 'function' && successCallback(res);
525
+ }
526
+ else {
527
+ if (res.hasOwnProperty('html') && res.html) {
528
+ WFLS.panelModalHTML((WFLS.screenSize(500) ? '300px' : '400px'), 'Error Saving Options', res.error);
529
+ }
530
+ else {
531
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), 'Error Saving Options', res.error);
532
+ }
533
+
534
+ typeof failureCallback == 'function' && failureCallback
535
+ }
536
+ });
537
+ },
538
+
539
+ saveOptions: function(successCallback, failureCallback) {
540
+ this.setOptions(WFLS.pendingChanges, successCallback, failureCallback);
541
+ },
542
+
543
+ updateIPPreview: function(value, successCallback) {
544
+ this.ajax('wordfence_ls_update_ip_preview', value, function(response) {
545
+ if (successCallback) {
546
+ successCallback(response);
547
+ }
548
+ });
549
+ },
550
+
551
+ /**
552
+ * Sends a WP AJAX call, automatically adding our nonce.
553
+ *
554
+ * @param string action
555
+ * @param string|array|object payload
556
+ * @param function successCallback
557
+ * @param function failureCallback
558
+ */
559
+ ajax: function(action, payload, successCallback, failureCallback) {
560
+ if (typeof(payload) == 'string') {
561
+ if (payload.length > 0) {
562
+ payload += '&';
563
+ }
564
+ payload += 'action=' + action + '&nonce=' + WFLSVars.nonce;
565
+ }
566
+ else if (typeof(payload) == 'object' && payload instanceof Array) {
567
+ // jQuery serialized form data
568
+ payload.push({
569
+ name: 'action',
570
+ value: action
571
+ });
572
+ payload.push({
573
+ name: 'nonce',
574
+ value: WFLSVars.nonce
575
+ });
576
+ }
577
+ else if (typeof(payload) == 'object') {
578
+ payload['action'] = action;
579
+ payload['nonce'] = WFLSVars.nonce;
580
+ }
581
+
582
+
583
+ $.ajax({
584
+ type: 'POST',
585
+ url: WFLSVars.ajaxurl,
586
+ dataType: "json",
587
+ data: payload,
588
+ success: function(json) {
589
+ typeof successCallback == 'function' && successCallback(json);
590
+ },
591
+ error: function() {
592
+ typeof failureCallback == 'function' && failureCallback();
593
+ }
594
+ });
595
+ },
596
+
597
+ /**
598
+ * Displays a generic panel.
599
+ *
600
+ * @param @param string width A width string in the format '100px'
601
+ * @param string heading
602
+ * @param string body
603
+ * @param object settings
604
+ */
605
+ panel: function(width, heading, body, settings) {
606
+ if (typeof settings === 'undefined') {
607
+ settings = {};
608
+ }
609
+ WFLS.panelQueue.push([width, "<h3>" + heading + "</h3><p>" + body + "</p>", settings]);
610
+ WFLS._panelServiceQueue();
611
+ },
612
+
613
+ /**
614
+ * Displays a modal panel with fixed HTML content.
615
+ *
616
+ * @param @param string width A width string in the format '100px'
617
+ * @param string heading
618
+ * @param string body
619
+ * @param object settings
620
+ */
621
+ panelModalHTML: function(width, heading, body, settings) {
622
+ if (typeof settings === 'undefined') {
623
+ settings = {};
624
+ }
625
+
626
+ var prompt = $.tmpl(WFLSVars.modalHTMLTemplate, {title: heading, message: body});
627
+ var promptHTML = $("<div />").append(prompt).html();
628
+ var callback = settings.onComplete;
629
+ settings.overlayClose = false;
630
+ settings.closeButton = false;
631
+ settings.className = 'wfls-modal';
632
+ settings.onComplete = function() {
633
+ $('#wfls-generic-modal-close').on('click', function(e) {
634
+ e.preventDefault();
635
+ e.stopPropagation();
636
+
637
+ WFLS.panelClose();
638
+ });
639
+
640
+ typeof callback === 'function' && callback();
641
+ };
642
+ WFLS.panelHTML(width, promptHTML, settings)
643
+ },
644
+
645
+ /**
646
+ * Displays a modal panel, automatically escaping the content.
647
+ *
648
+ * @param @param string width A width string in the format '100px'
649
+ * @param string heading
650
+ * @param string body
651
+ * @param object settings
652
+ */
653
+ panelModal: function(width, heading, body, settings) {
654
+ if (typeof settings === 'undefined') {
655
+ settings = {};
656
+ }
657
+
658
+ var prompt = $.tmpl(WFLSVars.modalTemplate, {title: heading, message: body});
659
+ var promptHTML = $("<div />").append(prompt).html();
660
+ var callback = settings.onComplete;
661
+ settings.overlayClose = false;
662
+ settings.closeButton = false;
663
+ settings.className = 'wfls-modal';
664
+ settings.onComplete = function() {
665
+ $('#wfls-generic-modal-close').on('click', function(e) {
666
+ e.preventDefault();
667
+ e.stopPropagation();
668
+
669
+ WFLS.panelClose();
670
+ });
671
+
672
+ typeof callback === 'function' && callback();
673
+ };
674
+ WFLS.panelHTML(width, promptHTML, settings)
675
+ },
676
+
677
+ /**
678
+ * Displays a modal panel with the error formatting.
679
+ *
680
+ * @param string errorMsg
681
+ * @param bool isTokenError Whether or not this error is an expired nonce error.
682
+ */
683
+ panelError: function(errorMsg, isTokenError) {
684
+ var callback = false;
685
+ if (isTokenError) {
686
+ if (WFLS.tokenErrorShowing) {
687
+ return;
688
+ }
689
+
690
+ callback = function() {
691
+ setTimeout(function() {
692
+ WFLS.tokenErrorShowing = false;
693
+ }, 30000);
694
+ };
695
+
696
+ WFLS.tokenErrorShowing = true;
697
+ }
698
+
699
+ var prompt = $.tmpl(WFLSVars.tokenInvalidTemplate, {title: 'An error occurred', message: errorMsg});
700
+ var promptHTML = $("<div />").append(prompt).html();
701
+ var settings = {};
702
+ settings.overlayClose = false;
703
+ settings.closeButton = false;
704
+ settings.className = 'wfls-modal';
705
+ settings.onComplete = function() {
706
+ $('#wfls-token-invalid-modal-reload').on('click', function(e) {
707
+ e.preventDefault();
708
+ e.stopPropagation();
709
+
710
+ window.location.reload(true);
711
+ });
712
+
713
+ typeof callback === 'function' && callback();
714
+ };
715
+ WFLS.panelHTML((WFLS.screenSize(500) ? '300px' : '400px'), promptHTML, settings);
716
+ },
717
+
718
+ /**
719
+ * Displays a panel with fixed HTML content.
720
+ *
721
+ * @param string width A width string in the format '100px'
722
+ * @param string html
723
+ * @param object settings
724
+ */
725
+ panelHTML: function(width, html, settings) {
726
+ if (typeof settings === 'undefined') {
727
+ settings = {};
728
+ }
729
+ WFLS.panelQueue.push([width, html, settings]);
730
+ WFLS._panelServiceQueue();
731
+ },
732
+
733
+ /**
734
+ * Displays the next panel in the queue.
735
+ */
736
+ _panelServiceQueue: function() {
737
+ if (WFLS.panelIsOpen) {
738
+ return;
739
+ }
740
+ if (WFLS.panelQueue.length < 1) {
741
+ return;
742
+ }
743
+ var elem = WFLS.panelQueue.shift();
744
+ WFLS._panelOpen(elem[0], elem[1], elem[2]);
745
+ },
746
+
747
+ /**
748
+ * Does the actual function call to display the panel.
749
+ *
750
+ * @param string width A width string in the format '100px'
751
+ * @param string html
752
+ * @param object settings
753
+ */
754
+ _panelOpen: function(width, html, settings) {
755
+ this.panelIsOpen = true;
756
+ $.extend(settings, {
757
+ width: width,
758
+ html: html,
759
+ onClosed: function() {
760
+ WFLS.panelClose();
761
+ }
762
+ });
763
+ $.wflscolorbox(settings);
764
+ },
765
+
766
+ /**
767
+ * Closes the current panel.
768
+ */
769
+ panelClose: function() {
770
+ WFLS.panelIsOpen = false;
771
+ if (WFLS.panelQueue.length < 1) {
772
+ $.wflscolorbox.close();
773
+ }
774
+ else {
775
+ WFLS._panelServiceQueue();
776
+ }
777
+ },
778
+
779
+ /**
780
+ * Parses and returns the hash portion of a URL, working around user agents that URL-encode the # character.
781
+ *
782
+ * @returns {Array}
783
+ */
784
+ parseHashes: function() {
785
+ var hashes = window.location.hash.replace('%23', '#');
786
+ var splitHashes = hashes.split('#');
787
+ var result = [];
788
+ for (var i = 0; i < splitHashes.length; i++) {
789
+ if (splitHashes[i].length > 0) {
790
+ result.push(splitHashes[i]);
791
+ }
792
+ }
793
+ return result;
794
+ },
795
+
796
+ /**
797
+ * Returns whether or not the screen size is within the size given. This may be a numerical value
798
+ * or one of the WFLS_SCREEN_ constants.
799
+ *
800
+ * @param size
801
+ * @returns {boolean}
802
+ */
803
+ screenSize: function(size) {
804
+ switch (size) {
805
+ case WFLS.SCREEN_XS:
806
+ return window.matchMedia("only screen and (max-width: 767px)").matches;
807
+ case WFLS.SCREEN_SM:
808
+ return window.matchMedia("only screen and (max-width: 991px)").matches;
809
+ case WFLS.SCREEN_MD:
810
+ return window.matchMedia("only screen and (max-width: 1199px)").matches;
811
+ case WFLS.SCREEN_LG:
812
+ return window.matchMedia("only screen and (max-width: 32767px)").matches;
813
+ }
814
+
815
+ var parsed = parseInt(size);
816
+ if (isNaN(parsed)) {
817
+ return false;
818
+ }
819
+ return window.matchMedia("only screen and (max-width: " + parsed + "px)").matches;
820
+ },
821
+ };
822
+
823
+ $(function() {
824
+ WFLS.init();
825
+ });
826
+
827
+ $.fn.crossfade = function(incoming, duration, complete) {
828
+ duration = duration || 400;
829
+ complete = complete || function() { };
830
+
831
+ return this.each(function() {
832
+ $(this).fadeOut(duration, function() {
833
+ $(incoming).fadeIn(duration, complete);
834
+ });
835
+ });
836
+ };
837
+ })(jQuery);
838
+
839
+ /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
840
+ var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,i=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},a=/constructor/i.test(e.HTMLElement),f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},d="application/octet-stream",s=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,s)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(i){u(i)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,s){if(!s){t=p(t)}var v=this,w=t.type,m=w===d,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&a)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;i(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!==null){define([],function(){return saveAs})}
841
+
842
+ !function(t){"use strict";if(t.URL=t.URL||t.webkitURL,t.Blob&&t.URL)try{return void new Blob}catch(e){}var n=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||function(t){var e=function(t){return Object.prototype.toString.call(t).match(/^\[object\s(.*)\]$/)[1]},n=function(){this.data=[]},o=function(t,e,n){this.data=t,this.size=t.length,this.type=e,this.encoding=n},i=n.prototype,a=o.prototype,r=t.FileReaderSync,c=function(t){this.code=this[this.name=t]},l="NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR".split(" "),s=l.length,u=t.URL||t.webkitURL||t,d=u.createObjectURL,f=u.revokeObjectURL,R=u,p=t.btoa,h=t.atob,b=t.ArrayBuffer,g=t.Uint8Array,w=/^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/;for(o.fake=a.fake=!0;s--;)c.prototype[l[s]]=s+1;return u.createObjectURL||(R=t.URL=function(t){var e,n=document.createElementNS("http://www.w3.org/1999/xhtml","a");return n.href=t,"origin"in n||("data:"===n.protocol.toLowerCase()?n.origin=null:(e=t.match(w),n.origin=e&&e[1])),n}),R.createObjectURL=function(t){var e,n=t.type;return null===n&&(n="application/octet-stream"),t instanceof o?(e="data:"+n,"base64"===t.encoding?e+";base64,"+t.data:"URI"===t.encoding?e+","+decodeURIComponent(t.data):p?e+";base64,"+p(t.data):e+","+encodeURIComponent(t.data)):d?d.call(u,t):void 0},R.revokeObjectURL=function(t){"data:"!==t.substring(0,5)&&f&&f.call(u,t)},i.append=function(t){var n=this.data;if(g&&(t instanceof b||t instanceof g)){for(var i="",a=new g(t),l=0,s=a.length;s>l;l++)i+=String.fromCharCode(a[l]);n.push(i)}else if("Blob"===e(t)||"File"===e(t)){if(!r)throw new c("NOT_READABLE_ERR");var u=new r;n.push(u.readAsBinaryString(t))}else t instanceof o?"base64"===t.encoding&&h?n.push(h(t.data)):"URI"===t.encoding?n.push(decodeURIComponent(t.data)):"raw"===t.encoding&&n.push(t.data):("string"!=typeof t&&(t+=""),n.push(unescape(encodeURIComponent(t))))},i.getBlob=function(t){return arguments.length||(t=null),new o(this.data.join(""),t,"raw")},i.toString=function(){return"[object BlobBuilder]"},a.slice=function(t,e,n){var i=arguments.length;return 3>i&&(n=null),new o(this.data.slice(t,i>1?e:this.data.length),n,this.encoding)},a.toString=function(){return"[object Blob]"},a.close=function(){this.size=0,delete this.data},n}(t);t.Blob=function(t,e){var o=e?e.type||"":"",i=new n;if(t)for(var a=0,r=t.length;r>a;a++)Uint8Array&&t[a]instanceof Uint8Array?i.append(t[a].buffer):i.append(t[a]);var c=i.getBlob(o);return!c.slice&&c.webkitSlice&&(c.slice=c.webkitSlice),c};var o=Object.getPrototypeOf||function(t){return t.__proto__};t.Blob.prototype=o(new t.Blob)}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this);
js/jquery-ui-timepicker-addon.1559237323.js ADDED
@@ -0,0 +1,2291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20
2
+ * http://trentrichardson.com/examples/timepicker
3
+ * Copyright (c) 2016 Trent Richardson; Licensed MIT */
4
+ (function (factory) {
5
+ if (typeof define === 'function' && define.amd) {
6
+ define(['jquery', 'jquery-ui'], factory);
7
+ } else {
8
+ factory(jQuery);
9
+ }
10
+ }(function ($) {
11
+
12
+ /*
13
+ * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded"
14
+ */
15
+ $.ui.timepicker = $.ui.timepicker || {};
16
+ if ($.ui.timepicker.version) {
17
+ return;
18
+ }
19
+
20
+ /*
21
+ * Extend jQueryUI, get it started with our version number
22
+ */
23
+ $.extend($.ui, {
24
+ timepicker: {
25
+ version: "1.6.3"
26
+ }
27
+ });
28
+
29
+ /*
30
+ * Timepicker manager.
31
+ * Use the singleton instance of this class, $.timepicker, to interact with the time picker.
32
+ * Settings for (groups of) time pickers are maintained in an instance object,
33
+ * allowing multiple different settings on the same page.
34
+ */
35
+ var Timepicker = function () {
36
+ this.regional = []; // Available regional settings, indexed by language code
37
+ this.regional[''] = { // Default regional settings
38
+ currentText: 'Now',
39
+ closeText: 'Done',
40
+ amNames: ['AM', 'A'],
41
+ pmNames: ['PM', 'P'],
42
+ timeFormat: 'HH:mm',
43
+ timeSuffix: '',
44
+ timeOnlyTitle: 'Choose Time',
45
+ timeText: 'Time',
46
+ hourText: 'Hour',
47
+ minuteText: 'Minute',
48
+ secondText: 'Second',
49
+ millisecText: 'Millisecond',
50
+ microsecText: 'Microsecond',
51
+ timezoneText: 'Time Zone',
52
+ isRTL: false
53
+ };
54
+ this._defaults = { // Global defaults for all the datetime picker instances
55
+ showButtonPanel: true,
56
+ timeOnly: false,
57
+ timeOnlyShowDate: false,
58
+ showHour: null,
59
+ showMinute: null,
60
+ showSecond: null,
61
+ showMillisec: null,
62
+ showMicrosec: null,
63
+ showTimezone: null,
64
+ showTime: true,
65
+ stepHour: 1,
66
+ stepMinute: 1,
67
+ stepSecond: 1,
68
+ stepMillisec: 1,
69
+ stepMicrosec: 1,
70
+ hour: 0,
71
+ minute: 0,
72
+ second: 0,
73
+ millisec: 0,
74
+ microsec: 0,
75
+ timezone: null,
76
+ hourMin: 0,
77
+ minuteMin: 0,
78
+ secondMin: 0,
79
+ millisecMin: 0,
80
+ microsecMin: 0,
81
+ hourMax: 23,
82
+ minuteMax: 59,
83
+ secondMax: 59,
84
+ millisecMax: 999,
85
+ microsecMax: 999,
86
+ minDateTime: null,
87
+ maxDateTime: null,
88
+ maxTime: null,
89
+ minTime: null,
90
+ onSelect: null,
91
+ hourGrid: 0,
92
+ minuteGrid: 0,
93
+ secondGrid: 0,
94
+ millisecGrid: 0,
95
+ microsecGrid: 0,
96
+ alwaysSetTime: true,
97
+ separator: ' ',
98
+ altFieldTimeOnly: true,
99
+ altTimeFormat: null,
100
+ altSeparator: null,
101
+ altTimeSuffix: null,
102
+ altRedirectFocus: true,
103
+ pickerTimeFormat: null,
104
+ pickerTimeSuffix: null,
105
+ showTimepicker: true,
106
+ timezoneList: null,
107
+ addSliderAccess: false,
108
+ sliderAccessArgs: null,
109
+ controlType: 'slider',
110
+ oneLine: false,
111
+ defaultValue: null,
112
+ parse: 'strict',
113
+ afterInject: null
114
+ };
115
+ $.extend(this._defaults, this.regional['']);
116
+ };
117
+
118
+ $.extend(Timepicker.prototype, {
119
+ $input: null,
120
+ $altInput: null,
121
+ $timeObj: null,
122
+ inst: null,
123
+ hour_slider: null,
124
+ minute_slider: null,
125
+ second_slider: null,
126
+ millisec_slider: null,
127
+ microsec_slider: null,
128
+ timezone_select: null,
129
+ maxTime: null,
130
+ minTime: null,
131
+ hour: 0,
132
+ minute: 0,
133
+ second: 0,
134
+ millisec: 0,
135
+ microsec: 0,
136
+ timezone: null,
137
+ hourMinOriginal: null,
138
+ minuteMinOriginal: null,
139
+ secondMinOriginal: null,
140
+ millisecMinOriginal: null,
141
+ microsecMinOriginal: null,
142
+ hourMaxOriginal: null,
143
+ minuteMaxOriginal: null,
144
+ secondMaxOriginal: null,
145
+ millisecMaxOriginal: null,
146
+ microsecMaxOriginal: null,
147
+ ampm: '',
148
+ formattedDate: '',
149
+ formattedTime: '',
150
+ formattedDateTime: '',
151
+ timezoneList: null,
152
+ units: ['hour', 'minute', 'second', 'millisec', 'microsec'],
153
+ support: {},
154
+ control: null,
155
+
156
+ /*
157
+ * Override the default settings for all instances of the time picker.
158
+ * @param {Object} settings object - the new settings to use as defaults (anonymous object)
159
+ * @return {Object} the manager object
160
+ */
161
+ setDefaults: function (settings) {
162
+ extendRemove(this._defaults, settings || {});
163
+ return this;
164
+ },
165
+
166
+ /*
167
+ * Create a new Timepicker instance
168
+ */
169
+ _newInst: function ($input, opts) {
170
+ var tp_inst = new Timepicker(),
171
+ inlineSettings = {},
172
+ fns = {},
173
+ overrides, i;
174
+
175
+ for (var attrName in this._defaults) {
176
+ if (this._defaults.hasOwnProperty(attrName)) {
177
+ var attrValue = $input.attr('time:' + attrName);
178
+ if (attrValue) {
179
+ try {
180
+ inlineSettings[attrName] = eval(attrValue);
181
+ } catch (err) {
182
+ inlineSettings[attrName] = attrValue;
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ overrides = {
189
+ beforeShow: function (input, dp_inst) {
190
+ if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) {
191
+ return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst);
192
+ }
193
+ },
194
+ onChangeMonthYear: function (year, month, dp_inst) {
195
+ // Update the time as well : this prevents the time from disappearing from the $input field.
196
+ // tp_inst._updateDateTime(dp_inst);
197
+ if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) {
198
+ tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
199
+ }
200
+ },
201
+ onClose: function (dateText, dp_inst) {
202
+ if (tp_inst.timeDefined === true && $input.val() !== '') {
203
+ tp_inst._updateDateTime(dp_inst);
204
+ }
205
+ if ($.isFunction(tp_inst._defaults.evnts.onClose)) {
206
+ tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst);
207
+ }
208
+ }
209
+ };
210
+ for (i in overrides) {
211
+ if (overrides.hasOwnProperty(i)) {
212
+ fns[i] = opts[i] || this._defaults[i] || null;
213
+ }
214
+ }
215
+
216
+ tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, {
217
+ evnts: fns,
218
+ timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
219
+ });
220
+ tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) {
221
+ return val.toUpperCase();
222
+ });
223
+ tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) {
224
+ return val.toUpperCase();
225
+ });
226
+
227
+ // detect which units are supported
228
+ tp_inst.support = detectSupport(
229
+ tp_inst._defaults.timeFormat +
230
+ (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') +
231
+ (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : ''));
232
+
233
+ // controlType is string - key to our this._controls
234
+ if (typeof(tp_inst._defaults.controlType) === 'string') {
235
+ if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') {
236
+ tp_inst._defaults.controlType = 'select';
237
+ }
238
+ tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType];
239
+ }
240
+ // controlType is an object and must implement create, options, value methods
241
+ else {
242
+ tp_inst.control = tp_inst._defaults.controlType;
243
+ }
244
+
245
+ // prep the timezone options
246
+ var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60,
247
+ 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840];
248
+ if (tp_inst._defaults.timezoneList !== null) {
249
+ timezoneList = tp_inst._defaults.timezoneList;
250
+ }
251
+ var tzl = timezoneList.length, tzi = 0, tzv = null;
252
+ if (tzl > 0 && typeof timezoneList[0] !== 'object') {
253
+ for (; tzi < tzl; tzi++) {
254
+ tzv = timezoneList[tzi];
255
+ timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) };
256
+ }
257
+ }
258
+ tp_inst._defaults.timezoneList = timezoneList;
259
+
260
+ // set the default units
261
+ tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) :
262
+ ((new Date()).getTimezoneOffset() * -1);
263
+ tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin :
264
+ tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour;
265
+ tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin :
266
+ tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute;
267
+ tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin :
268
+ tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second;
269
+ tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin :
270
+ tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec;
271
+ tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin :
272
+ tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec;
273
+ tp_inst.ampm = '';
274
+ tp_inst.$input = $input;
275
+
276
+ if (tp_inst._defaults.altField) {
277
+ tp_inst.$altInput = $(tp_inst._defaults.altField);
278
+ if (tp_inst._defaults.altRedirectFocus === true) {
279
+ tp_inst.$altInput.css({
280
+ cursor: 'pointer'
281
+ }).focus(function () {
282
+ $input.trigger("focus");
283
+ });
284
+ }
285
+ }
286
+
287
+ if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) {
288
+ tp_inst._defaults.minDate = new Date();
289
+ }
290
+ if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) {
291
+ tp_inst._defaults.maxDate = new Date();
292
+ }
293
+
294
+ // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
295
+ if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {
296
+ tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
297
+ }
298
+ if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {
299
+ tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
300
+ }
301
+ if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {
302
+ tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
303
+ }
304
+ if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {
305
+ tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
306
+ }
307
+ tp_inst.$input.bind('focus', function () {
308
+ tp_inst._onFocus();
309
+ });
310
+
311
+ return tp_inst;
312
+ },
313
+
314
+ /*
315
+ * add our sliders to the calendar
316
+ */
317
+ _addTimePicker: function (dp_inst) {
318
+ var currDT = $.trim((this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val());
319
+
320
+ this.timeDefined = this._parseTime(currDT);
321
+ this._limitMinMaxDateTime(dp_inst, false);
322
+ this._injectTimePicker();
323
+ this._afterInject();
324
+ },
325
+
326
+ /*
327
+ * parse the time string from input value or _setTime
328
+ */
329
+ _parseTime: function (timeString, withDate) {
330
+ if (!this.inst) {
331
+ this.inst = $.datepicker._getInst(this.$input[0]);
332
+ }
333
+
334
+ if (withDate || !this._defaults.timeOnly) {
335
+ var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
336
+ try {
337
+ var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);
338
+ if (!parseRes.timeObj) {
339
+ return false;
340
+ }
341
+ $.extend(this, parseRes.timeObj);
342
+ } catch (err) {
343
+ $.timepicker.log("Error parsing the date/time string: " + err +
344
+ "\ndate/time string = " + timeString +
345
+ "\ntimeFormat = " + this._defaults.timeFormat +
346
+ "\ndateFormat = " + dp_dateFormat);
347
+ return false;
348
+ }
349
+ return true;
350
+ } else {
351
+ var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);
352
+ if (!timeObj) {
353
+ return false;
354
+ }
355
+ $.extend(this, timeObj);
356
+ return true;
357
+ }
358
+ },
359
+
360
+ /*
361
+ * Handle callback option after injecting timepicker
362
+ */
363
+ _afterInject: function() {
364
+ var o = this.inst.settings;
365
+ if ($.isFunction(o.afterInject)) {
366
+ o.afterInject.call(this);
367
+ }
368
+ },
369
+
370
+ /*
371
+ * generate and inject html for timepicker into ui datepicker
372
+ */
373
+ _injectTimePicker: function () {
374
+ var $dp = this.inst.dpDiv,
375
+ o = this.inst.settings,
376
+ tp_inst = this,
377
+ litem = '',
378
+ uitem = '',
379
+ show = null,
380
+ max = {},
381
+ gridSize = {},
382
+ size = null,
383
+ i = 0,
384
+ l = 0;
385
+
386
+ // Prevent displaying twice
387
+ if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) {
388
+ var noDisplay = ' ui_tpicker_unit_hide',
389
+ html = '<div class="ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + (o.oneLine && o.controlType === 'select' ? ' ui-timepicker-oneLine' : '') + '"><dl>' + '<dt class="ui_tpicker_time_label' + ((o.showTime) ? '' : noDisplay) + '">' + o.timeText + '</dt>' +
390
+ '<dd class="ui_tpicker_time '+ ((o.showTime) ? '' : noDisplay) + '"><input class="ui_tpicker_time_input" ' + (o.timeInput ? '' : 'disabled') + '/></dd>';
391
+
392
+ // Create the markup
393
+ for (i = 0, l = this.units.length; i < l; i++) {
394
+ litem = this.units[i];
395
+ uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);
396
+ show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];
397
+
398
+ // Added by Peter Medeiros:
399
+ // - Figure out what the hour/minute/second max should be based on the step values.
400
+ // - Example: if stepMinute is 15, then minMax is 45.
401
+ max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10);
402
+ gridSize[litem] = 0;
403
+
404
+ html += '<dt class="ui_tpicker_' + litem + '_label' + (show ? '' : noDisplay) + '">' + o[litem + 'Text'] + '</dt>' +
405
+ '<dd class="ui_tpicker_' + litem + (show ? '' : noDisplay) + '"><div class="ui_tpicker_' + litem + '_slider' + (show ? '' : noDisplay) + '"></div>';
406
+
407
+ if (show && o[litem + 'Grid'] > 0) {
408
+ html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
409
+
410
+ if (litem === 'hour') {
411
+ for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) {
412
+ gridSize[litem]++;
413
+ var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o);
414
+ html += '<td data-for="' + litem + '">' + tmph + '</td>';
415
+ }
416
+ }
417
+ else {
418
+ for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) {
419
+ gridSize[litem]++;
420
+ html += '<td data-for="' + litem + '">' + ((m < 10) ? '0' : '') + m + '</td>';
421
+ }
422
+ }
423
+
424
+ html += '</tr></table></div>';
425
+ }
426
+ html += '</dd>';
427
+ }
428
+
429
+ // Timezone
430
+ var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone;
431
+ html += '<dt class="ui_tpicker_timezone_label' + (showTz ? '' : noDisplay) + '">' + o.timezoneText + '</dt>';
432
+ html += '<dd class="ui_tpicker_timezone' + (showTz ? '' : noDisplay) + '"></dd>';
433
+
434
+ // Create the elements from string
435
+ html += '</dl></div>';
436
+ var $tp = $(html);
437
+
438
+ // if we only want time picker...
439
+ if (o.timeOnly === true) {
440
+ $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>');
441
+ $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
442
+ }
443
+
444
+ // add sliders, adjust grids, add events
445
+ for (i = 0, l = tp_inst.units.length; i < l; i++) {
446
+ litem = tp_inst.units[i];
447
+ uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1);
448
+ show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem];
449
+
450
+ // add the slider
451
+ tp_inst[litem + '_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_' + litem + '_slider'), litem, tp_inst[litem], o[litem + 'Min'], max[litem], o['step' + uitem]);
452
+
453
+ // adjust the grid and add click event
454
+ if (show && o[litem + 'Grid'] > 0) {
455
+ size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']);
456
+ $tp.find('.ui_tpicker_' + litem + ' table').css({
457
+ width: size + "%",
458
+ marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"),
459
+ marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0',
460
+ borderCollapse: 'collapse'
461
+ }).find("td").click(function (e) {
462
+ var $t = $(this),
463
+ h = $t.html(),
464
+ n = parseInt(h.replace(/[^0-9]/g), 10),
465
+ ap = h.replace(/[^apm]/ig),
466
+ f = $t.data('for'); // loses scope, so we use data-for
467
+
468
+ if (f === 'hour') {
469
+ if (ap.indexOf('p') !== -1 && n < 12) {
470
+ n += 12;
471
+ }
472
+ else {
473
+ if (ap.indexOf('a') !== -1 && n === 12) {
474
+ n = 0;
475
+ }
476
+ }
477
+ }
478
+
479
+ tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n);
480
+
481
+ tp_inst._onTimeChange();
482
+ tp_inst._onSelectHandler();
483
+ }).css({
484
+ cursor: 'pointer',
485
+ width: (100 / gridSize[litem]) + '%',
486
+ textAlign: 'center',
487
+ overflow: 'hidden'
488
+ });
489
+ } // end if grid > 0
490
+ } // end for loop
491
+
492
+ // Add timezone options
493
+ this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select");
494
+ $.fn.append.apply(this.timezone_select,
495
+ $.map(o.timezoneList, function (val, idx) {
496
+ return $("<option />").val(typeof val === "object" ? val.value : val).text(typeof val === "object" ? val.label : val);
497
+ }));
498
+ if (typeof(this.timezone) !== "undefined" && this.timezone !== null && this.timezone !== "") {
499
+ var local_timezone = (new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12)).getTimezoneOffset() * -1;
500
+ if (local_timezone === this.timezone) {
501
+ selectLocalTimezone(tp_inst);
502
+ } else {
503
+ this.timezone_select.val(this.timezone);
504
+ }
505
+ } else {
506
+ if (typeof(this.hour) !== "undefined" && this.hour !== null && this.hour !== "") {
507
+ this.timezone_select.val(o.timezone);
508
+ } else {
509
+ selectLocalTimezone(tp_inst);
510
+ }
511
+ }
512
+ this.timezone_select.change(function () {
513
+ tp_inst._onTimeChange();
514
+ tp_inst._onSelectHandler();
515
+ tp_inst._afterInject();
516
+ });
517
+ // End timezone options
518
+
519
+ // inject timepicker into datepicker
520
+ var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
521
+ if ($buttonPanel.length) {
522
+ $buttonPanel.before($tp);
523
+ } else {
524
+ $dp.append($tp);
525
+ }
526
+
527
+ this.$timeObj = $tp.find('.ui_tpicker_time_input');
528
+ this.$timeObj.change(function () {
529
+ var timeFormat = tp_inst.inst.settings.timeFormat;
530
+ var parsedTime = $.datepicker.parseTime(timeFormat, this.value);
531
+ var update = new Date();
532
+ if (parsedTime) {
533
+ update.setHours(parsedTime.hour);
534
+ update.setMinutes(parsedTime.minute);
535
+ update.setSeconds(parsedTime.second);
536
+ $.datepicker._setTime(tp_inst.inst, update);
537
+ } else {
538
+ this.value = tp_inst.formattedTime;
539
+ this.blur();
540
+ }
541
+ });
542
+
543
+ if (this.inst !== null) {
544
+ var timeDefined = this.timeDefined;
545
+ this._onTimeChange();
546
+ this.timeDefined = timeDefined;
547
+ }
548
+
549
+ // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
550
+ if (this._defaults.addSliderAccess) {
551
+ var sliderAccessArgs = this._defaults.sliderAccessArgs,
552
+ rtl = this._defaults.isRTL;
553
+ sliderAccessArgs.isRTL = rtl;
554
+
555
+ setTimeout(function () { // fix for inline mode
556
+ if ($tp.find('.ui-slider-access').length === 0) {
557
+ $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
558
+
559
+ // fix any grids since sliders are shorter
560
+ var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
561
+ if (sliderAccessWidth) {
562
+ $tp.find('table:visible').each(function () {
563
+ var $g = $(this),
564
+ oldWidth = $g.outerWidth(),
565
+ oldMarginLeft = $g.css(rtl ? 'marginRight' : 'marginLeft').toString().replace('%', ''),
566
+ newWidth = oldWidth - sliderAccessWidth,
567
+ newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%',
568
+ css = { width: newWidth, marginRight: 0, marginLeft: 0 };
569
+ css[rtl ? 'marginRight' : 'marginLeft'] = newMarginLeft;
570
+ $g.css(css);
571
+ });
572
+ }
573
+ }
574
+ }, 10);
575
+ }
576
+ // end slideAccess integration
577
+
578
+ tp_inst._limitMinMaxDateTime(this.inst, true);
579
+ }
580
+ },
581
+
582
+ /*
583
+ * This function tries to limit the ability to go outside the
584
+ * min/max date range
585
+ */
586
+ _limitMinMaxDateTime: function (dp_inst, adjustSliders) {
587
+ var o = this._defaults,
588
+ dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
589
+
590
+ if (!this._defaults.showTimepicker) {
591
+ return;
592
+ } // No time so nothing to check here
593
+
594
+ if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) {
595
+ var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
596
+ minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
597
+
598
+ if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null || this.microsecMinOriginal === null) {
599
+ this.hourMinOriginal = o.hourMin;
600
+ this.minuteMinOriginal = o.minuteMin;
601
+ this.secondMinOriginal = o.secondMin;
602
+ this.millisecMinOriginal = o.millisecMin;
603
+ this.microsecMinOriginal = o.microsecMin;
604
+ }
605
+
606
+ if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() === dp_date.getTime()) {
607
+ this._defaults.hourMin = minDateTime.getHours();
608
+ if (this.hour <= this._defaults.hourMin) {
609
+ this.hour = this._defaults.hourMin;
610
+ this._defaults.minuteMin = minDateTime.getMinutes();
611
+ if (this.minute <= this._defaults.minuteMin) {
612
+ this.minute = this._defaults.minuteMin;
613
+ this._defaults.secondMin = minDateTime.getSeconds();
614
+ if (this.second <= this._defaults.secondMin) {
615
+ this.second = this._defaults.secondMin;
616
+ this._defaults.millisecMin = minDateTime.getMilliseconds();
617
+ if (this.millisec <= this._defaults.millisecMin) {
618
+ this.millisec = this._defaults.millisecMin;
619
+ this._defaults.microsecMin = minDateTime.getMicroseconds();
620
+ } else {
621
+ if (this.microsec < this._defaults.microsecMin) {
622
+ this.microsec = this._defaults.microsecMin;
623
+ }
624
+ this._defaults.microsecMin = this.microsecMinOriginal;
625
+ }
626
+ } else {
627
+ this._defaults.millisecMin = this.millisecMinOriginal;
628
+ this._defaults.microsecMin = this.microsecMinOriginal;
629
+ }
630
+ } else {
631
+ this._defaults.secondMin = this.secondMinOriginal;
632
+ this._defaults.millisecMin = this.millisecMinOriginal;
633
+ this._defaults.microsecMin = this.microsecMinOriginal;
634
+ }
635
+ } else {
636
+ this._defaults.minuteMin = this.minuteMinOriginal;
637
+ this._defaults.secondMin = this.secondMinOriginal;
638
+ this._defaults.millisecMin = this.millisecMinOriginal;
639
+ this._defaults.microsecMin = this.microsecMinOriginal;
640
+ }
641
+ } else {
642
+ this._defaults.hourMin = this.hourMinOriginal;
643
+ this._defaults.minuteMin = this.minuteMinOriginal;
644
+ this._defaults.secondMin = this.secondMinOriginal;
645
+ this._defaults.millisecMin = this.millisecMinOriginal;
646
+ this._defaults.microsecMin = this.microsecMinOriginal;
647
+ }
648
+ }
649
+
650
+ if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) {
651
+ var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
652
+ maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
653
+
654
+ if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null || this.millisecMaxOriginal === null) {
655
+ this.hourMaxOriginal = o.hourMax;
656
+ this.minuteMaxOriginal = o.minuteMax;
657
+ this.secondMaxOriginal = o.secondMax;
658
+ this.millisecMaxOriginal = o.millisecMax;
659
+ this.microsecMaxOriginal = o.microsecMax;
660
+ }
661
+
662
+ if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() === dp_date.getTime()) {
663
+ this._defaults.hourMax = maxDateTime.getHours();
664
+ if (this.hour >= this._defaults.hourMax) {
665
+ this.hour = this._defaults.hourMax;
666
+ this._defaults.minuteMax = maxDateTime.getMinutes();
667
+ if (this.minute >= this._defaults.minuteMax) {
668
+ this.minute = this._defaults.minuteMax;
669
+ this._defaults.secondMax = maxDateTime.getSeconds();
670
+ if (this.second >= this._defaults.secondMax) {
671
+ this.second = this._defaults.secondMax;
672
+ this._defaults.millisecMax = maxDateTime.getMilliseconds();
673
+ if (this.millisec >= this._defaults.millisecMax) {
674
+ this.millisec = this._defaults.millisecMax;
675
+ this._defaults.microsecMax = maxDateTime.getMicroseconds();
676
+ } else {
677
+ if (this.microsec > this._defaults.microsecMax) {
678
+ this.microsec = this._defaults.microsecMax;
679
+ }
680
+ this._defaults.microsecMax = this.microsecMaxOriginal;
681
+ }
682
+ } else {
683
+ this._defaults.millisecMax = this.millisecMaxOriginal;
684
+ this._defaults.microsecMax = this.microsecMaxOriginal;
685
+ }
686
+ } else {
687
+ this._defaults.secondMax = this.secondMaxOriginal;
688
+ this._defaults.millisecMax = this.millisecMaxOriginal;
689
+ this._defaults.microsecMax = this.microsecMaxOriginal;
690
+ }
691
+ } else {
692
+ this._defaults.minuteMax = this.minuteMaxOriginal;
693
+ this._defaults.secondMax = this.secondMaxOriginal;
694
+ this._defaults.millisecMax = this.millisecMaxOriginal;
695
+ this._defaults.microsecMax = this.microsecMaxOriginal;
696
+ }
697
+ } else {
698
+ this._defaults.hourMax = this.hourMaxOriginal;
699
+ this._defaults.minuteMax = this.minuteMaxOriginal;
700
+ this._defaults.secondMax = this.secondMaxOriginal;
701
+ this._defaults.millisecMax = this.millisecMaxOriginal;
702
+ this._defaults.microsecMax = this.microsecMaxOriginal;
703
+ }
704
+ }
705
+
706
+ if (dp_inst.settings.minTime!==null) {
707
+ var tempMinTime=new Date("01/01/1970 " + dp_inst.settings.minTime);
708
+ if (this.hour<tempMinTime.getHours()) {
709
+ this.hour=this._defaults.hourMin=tempMinTime.getHours();
710
+ this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();
711
+ } else if (this.hour===tempMinTime.getHours() && this.minute<tempMinTime.getMinutes()) {
712
+ this.minute=this._defaults.minuteMin=tempMinTime.getMinutes();
713
+ } else {
714
+ if (this._defaults.hourMin<tempMinTime.getHours()) {
715
+ this._defaults.hourMin=tempMinTime.getHours();
716
+ this._defaults.minuteMin=tempMinTime.getMinutes();
717
+ } else if (this._defaults.hourMin===tempMinTime.getHours()===this.hour && this._defaults.minuteMin<tempMinTime.getMinutes()) {
718
+ this._defaults.minuteMin=tempMinTime.getMinutes();
719
+ } else {
720
+ this._defaults.minuteMin=0;
721
+ }
722
+ }
723
+ }
724
+
725
+ if (dp_inst.settings.maxTime!==null) {
726
+ var tempMaxTime=new Date("01/01/1970 " + dp_inst.settings.maxTime);
727
+ if (this.hour>tempMaxTime.getHours()) {
728
+ this.hour=this._defaults.hourMax=tempMaxTime.getHours();
729
+ this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();
730
+ } else if (this.hour===tempMaxTime.getHours() && this.minute>tempMaxTime.getMinutes()) {
731
+ this.minute=this._defaults.minuteMax=tempMaxTime.getMinutes();
732
+ } else {
733
+ if (this._defaults.hourMax>tempMaxTime.getHours()) {
734
+ this._defaults.hourMax=tempMaxTime.getHours();
735
+ this._defaults.minuteMax=tempMaxTime.getMinutes();
736
+ } else if (this._defaults.hourMax===tempMaxTime.getHours()===this.hour && this._defaults.minuteMax>tempMaxTime.getMinutes()) {
737
+ this._defaults.minuteMax=tempMaxTime.getMinutes();
738
+ } else {
739
+ this._defaults.minuteMax=59;
740
+ }
741
+ }
742
+ }
743
+
744
+ if (adjustSliders !== undefined && adjustSliders === true) {
745
+ var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10),
746
+ minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10),
747
+ secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10),
748
+ millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10),
749
+ microsecMax = parseInt((this._defaults.microsecMax - ((this._defaults.microsecMax - this._defaults.microsecMin) % this._defaults.stepMicrosec)), 10);
750
+
751
+ if (this.hour_slider) {
752
+ this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax, step: this._defaults.stepHour });
753
+ this.control.value(this, this.hour_slider, 'hour', this.hour - (this.hour % this._defaults.stepHour));
754
+ }
755
+ if (this.minute_slider) {
756
+ this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax, step: this._defaults.stepMinute });
757
+ this.control.value(this, this.minute_slider, 'minute', this.minute - (this.minute % this._defaults.stepMinute));
758
+ }
759
+ if (this.second_slider) {
760
+ this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax, step: this._defaults.stepSecond });
761
+ this.control.value(this, this.second_slider, 'second', this.second - (this.second % this._defaults.stepSecond));
762
+ }
763
+ if (this.millisec_slider) {
764
+ this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax, step: this._defaults.stepMillisec });
765
+ this.control.value(this, this.millisec_slider, 'millisec', this.millisec - (this.millisec % this._defaults.stepMillisec));
766
+ }
767
+ if (this.microsec_slider) {
768
+ this.control.options(this, this.microsec_slider, 'microsec', { min: this._defaults.microsecMin, max: microsecMax, step: this._defaults.stepMicrosec });
769
+ this.control.value(this, this.microsec_slider, 'microsec', this.microsec - (this.microsec % this._defaults.stepMicrosec));
770
+ }
771
+ }
772
+
773
+ },
774
+
775
+ /*
776
+ * when a slider moves, set the internal time...
777
+ * on time change is also called when the time is updated in the text field
778
+ */
779
+ _onTimeChange: function () {
780
+ if (!this._defaults.showTimepicker) {
781
+ return;
782
+ }
783
+ var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false,
784
+ minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false,
785
+ second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false,
786
+ millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false,
787
+ microsec = (this.microsec_slider) ? this.control.value(this, this.microsec_slider, 'microsec') : false,
788
+ timezone = (this.timezone_select) ? this.timezone_select.val() : false,
789
+ o = this._defaults,
790
+ pickerTimeFormat = o.pickerTimeFormat || o.timeFormat,
791
+ pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix;
792
+
793
+ if (typeof(hour) === 'object') {
794
+ hour = false;
795
+ }
796
+ if (typeof(minute) === 'object') {
797
+ minute = false;
798
+ }
799
+ if (typeof(second) === 'object') {
800
+ second = false;
801
+ }
802
+ if (typeof(millisec) === 'object') {
803
+ millisec = false;
804
+ }
805
+ if (typeof(microsec) === 'object') {
806
+ microsec = false;
807
+ }
808
+ if (typeof(timezone) === 'object') {
809
+ timezone = false;
810
+ }
811
+
812
+ if (hour !== false) {
813
+ hour = parseInt(hour, 10);
814
+ }
815
+ if (minute !== false) {
816
+ minute = parseInt(minute, 10);
817
+ }
818
+ if (second !== false) {
819
+ second = parseInt(second, 10);
820
+ }
821
+ if (millisec !== false) {
822
+ millisec = parseInt(millisec, 10);
823
+ }
824
+ if (microsec !== false) {
825
+ microsec = parseInt(microsec, 10);
826
+ }
827
+ if (timezone !== false) {
828
+ timezone = timezone.toString();
829
+ }
830
+
831
+ var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
832
+
833
+ // If the update was done in the input field, the input field should not be updated.
834
+ // If the update was done using the sliders, update the input field.
835
+ var hasChanged = (
836
+ hour !== parseInt(this.hour,10) || // sliders should all be numeric
837
+ minute !== parseInt(this.minute,10) ||
838
+ second !== parseInt(this.second,10) ||
839
+ millisec !== parseInt(this.millisec,10) ||
840
+ microsec !== parseInt(this.microsec,10) ||
841
+ (this.ampm.length > 0 && (hour < 12) !== ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) ||
842
+ (this.timezone !== null && timezone !== this.timezone.toString()) // could be numeric or "EST" format, so use toString()
843
+ );
844
+
845
+ if (hasChanged) {
846
+
847
+ if (hour !== false) {
848
+ this.hour = hour;
849
+ }
850
+ if (minute !== false) {
851
+ this.minute = minute;
852
+ }
853
+ if (second !== false) {
854
+ this.second = second;
855
+ }
856
+ if (millisec !== false) {
857
+ this.millisec = millisec;
858
+ }
859
+ if (microsec !== false) {
860
+ this.microsec = microsec;
861
+ }
862
+ if (timezone !== false) {
863
+ this.timezone = timezone;
864
+ }
865
+
866
+ if (!this.inst) {
867
+ this.inst = $.datepicker._getInst(this.$input[0]);
868
+ }
869
+
870
+ this._limitMinMaxDateTime(this.inst, true);
871
+ }
872
+ if (this.support.ampm) {
873
+ this.ampm = ampm;
874
+ }
875
+
876
+ // Updates the time within the timepicker
877
+ this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o);
878
+ if (this.$timeObj) {
879
+ if (pickerTimeFormat === o.timeFormat) {
880
+ this.$timeObj.val(this.formattedTime + pickerTimeSuffix);
881
+ }
882
+ else {
883
+ this.$timeObj.val($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix);
884
+ }
885
+ if (this.$timeObj[0].setSelectionRange) {
886
+ var sPos = this.$timeObj[0].selectionStart;
887
+ var ePos = this.$timeObj[0].selectionEnd;
888
+ this.$timeObj[0].setSelectionRange(sPos, ePos);
889
+ }
890
+ }
891
+
892
+ this.timeDefined = true;
893
+ if (hasChanged) {
894
+ this._updateDateTime();
895
+ //this.$input.focus(); // may automatically open the picker on setDate
896
+ }
897
+ },
898
+
899
+ /*
900
+ * call custom onSelect.
901
+ * bind to sliders slidestop, and grid click.
902
+ */
903
+ _onSelectHandler: function () {
904
+ var onSelect = this._defaults.onSelect || this.inst.settings.onSelect;
905
+ var inputEl = this.$input ? this.$input[0] : null;
906
+ if (onSelect && inputEl) {
907
+ onSelect.apply(inputEl, [this.formattedDateTime, this]);
908
+ }
909
+ },
910
+
911
+ /*
912
+ * update our input with the new date time..
913
+ */
914
+ _updateDateTime: function (dp_inst) {
915
+ dp_inst = this.inst || dp_inst;
916
+ var dtTmp = (dp_inst.currentYear > 0?
917
+ new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay) :
918
+ new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
919
+ dt = $.datepicker._daylightSavingAdjust(dtTmp),
920
+ //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
921
+ //dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.currentYear, dp_inst.currentMonth, dp_inst.currentDay)),
922
+ dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
923
+ formatCfg = $.datepicker._getFormatConfig(dp_inst),
924
+ timeAvailable = dt !== null && this.timeDefined;
925
+ this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
926
+ var formattedDateTime = this.formattedDate;
927
+
928
+ // if a slider was changed but datepicker doesn't have a value yet, set it
929
+ if (dp_inst.lastVal === "") {
930
+ dp_inst.currentYear = dp_inst.selectedYear;
931
+ dp_inst.currentMonth = dp_inst.selectedMonth;
932
+ dp_inst.currentDay = dp_inst.selectedDay;
933
+ }
934
+
935
+ /*
936
+ * remove following lines to force every changes in date picker to change the input value
937
+ * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker.
938
+ * If the user manually empty the value in the input field, the date picker will never change selected value.
939
+ */
940
+ //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {
941
+ // return;
942
+ //}
943
+
944
+ if (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === false) {
945
+ formattedDateTime = this.formattedTime;
946
+ } else if ((this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) || (this._defaults.timeOnly === true && this._defaults.timeOnlyShowDate === true)) {
947
+ formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
948
+ }
949
+
950
+ this.formattedDateTime = formattedDateTime;
951
+
952
+ if (!this._defaults.showTimepicker) {
953
+ this.$input.val(this.formattedDate);
954
+ } else if (this.$altInput && this._defaults.timeOnly === false && this._defaults.altFieldTimeOnly === true) {
955
+ this.$altInput.val(this.formattedTime);
956
+ this.$input.val(this.formattedDate);
957
+ } else if (this.$altInput) {
958
+ this.$input.val(formattedDateTime);
959
+ var altFormattedDateTime = '',
960
+ altSeparator = this._defaults.altSeparator !== null ? this._defaults.altSeparator : this._defaults.separator,
961
+ altTimeSuffix = this._defaults.altTimeSuffix !== null ? this._defaults.altTimeSuffix : this._defaults.timeSuffix;
962
+
963
+ if (!this._defaults.timeOnly) {
964
+ if (this._defaults.altFormat) {
965
+ altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg);
966
+ }
967
+ else {
968
+ altFormattedDateTime = this.formattedDate;
969
+ }
970
+
971
+ if (altFormattedDateTime) {
972
+ altFormattedDateTime += altSeparator;
973
+ }
974
+ }
975
+
976
+ if (this._defaults.altTimeFormat !== null) {
977
+ altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix;
978
+ }
979
+ else {
980
+ altFormattedDateTime += this.formattedTime + altTimeSuffix;
981
+ }
982
+ this.$altInput.val(altFormattedDateTime);
983
+ } else {
984
+ this.$input.val(formattedDateTime);
985
+ }
986
+
987
+ this.$input.trigger("change");
988
+ },
989
+
990
+ _onFocus: function () {
991
+ if (!this.$input.val() && this._defaults.defaultValue) {
992
+ this.$input.val(this._defaults.defaultValue);
993
+ var inst = $.datepicker._getInst(this.$input.get(0)),
994
+ tp_inst = $.datepicker._get(inst, 'timepicker');
995
+ if (tp_inst) {
996
+ if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {
997
+ try {
998
+ $.datepicker._updateDatepicker(inst);
999
+ } catch (err) {
1000
+ $.timepicker.log(err);
1001
+ }
1002
+ }
1003
+ }
1004
+ }
1005
+ },
1006
+
1007
+ /*
1008
+ * Small abstraction to control types
1009
+ * We can add more, just be sure to follow the pattern: create, options, value
1010
+ */
1011
+ _controls: {
1012
+ // slider methods
1013
+ slider: {
1014
+ create: function (tp_inst, obj, unit, val, min, max, step) {
1015
+ var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60
1016
+ return obj.prop('slide', null).slider({
1017
+ orientation: "horizontal",
1018
+ value: rtl ? val * -1 : val,
1019
+ min: rtl ? max * -1 : min,
1020
+ max: rtl ? min * -1 : max,
1021
+ step: step,
1022
+ slide: function (event, ui) {
1023
+ tp_inst.control.value(tp_inst, $(this), unit, rtl ? ui.value * -1 : ui.value);
1024
+ tp_inst._onTimeChange();
1025
+ },
1026
+ stop: function (event, ui) {
1027
+ tp_inst._onSelectHandler();
1028
+ }
1029
+ });
1030
+ },
1031
+ options: function (tp_inst, obj, unit, opts, val) {
1032
+ if (tp_inst._defaults.isRTL) {
1033
+ if (typeof(opts) === 'string') {
1034
+ if (opts === 'min' || opts === 'max') {
1035
+ if (val !== undefined) {
1036
+ return obj.slider(opts, val * -1);
1037
+ }
1038
+ return Math.abs(obj.slider(opts));
1039
+ }
1040
+ return obj.slider(opts);
1041
+ }
1042
+ var min = opts.min,
1043
+ max = opts.max;
1044
+ opts.min = opts.max = null;
1045
+ if (min !== undefined) {
1046
+ opts.max = min * -1;
1047
+ }
1048
+ if (max !== undefined) {
1049
+ opts.min = max * -1;
1050
+ }
1051
+ return obj.slider(opts);
1052
+ }
1053
+ if (typeof(opts) === 'string' && val !== undefined) {
1054
+ return obj.slider(opts, val);
1055
+ }
1056
+ return obj.slider(opts);
1057
+ },
1058
+ value: function (tp_inst, obj, unit, val) {
1059
+ if (tp_inst._defaults.isRTL) {
1060
+ if (val !== undefined) {
1061
+ return obj.slider('value', val * -1);
1062
+ }
1063
+ return Math.abs(obj.slider('value'));
1064
+ }
1065
+ if (val !== undefined) {
1066
+ return obj.slider('value', val);
1067
+ }
1068
+ return obj.slider('value');
1069
+ }
1070
+ },
1071
+ // select methods
1072
+ select: {
1073
+ create: function (tp_inst, obj, unit, val, min, max, step) {
1074
+ var sel = '<select class="ui-timepicker-select ui-state-default ui-corner-all" data-unit="' + unit + '" data-min="' + min + '" data-max="' + max + '" data-step="' + step + '">',
1075
+ format = tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat;
1076
+
1077
+ for (var i = min; i <= max; i += step) {
1078
+ sel += '<option value="' + i + '"' + (i === val ? ' selected' : '') + '>';
1079
+ if (unit === 'hour') {
1080
+ sel += $.datepicker.formatTime($.trim(format.replace(/[^ht ]/ig, '')), {hour: i}, tp_inst._defaults);
1081
+ }
1082
+ else if (unit === 'millisec' || unit === 'microsec' || i >= 10) { sel += i; }
1083
+ else {sel += '0' + i.toString(); }
1084
+ sel += '</option>';
1085
+ }
1086
+ sel += '</select>';
1087
+
1088
+ obj.children('select').remove();
1089
+
1090
+ $(sel).appendTo(obj).change(function (e) {
1091
+ tp_inst._onTimeChange();
1092
+ tp_inst._onSelectHandler();
1093
+ tp_inst._afterInject();
1094
+ });
1095
+
1096
+ return obj;
1097
+ },
1098
+ options: function (tp_inst, obj, unit, opts, val) {
1099
+ var o = {},
1100
+ $t = obj.children('select');
1101
+ if (typeof(opts) === 'string') {
1102
+ if (val === undefined) {
1103
+ return $t.data(opts);
1104
+ }
1105
+ o[opts] = val;
1106
+ }
1107
+ else { o = opts; }
1108
+ return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min>=0 ? o.min : $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step'));
1109
+ },
1110
+ value: function (tp_inst, obj, unit, val) {
1111
+ var $t = obj.children('select');
1112
+ if (val !== undefined) {
1113
+ return $t.val(val);
1114
+ }
1115
+ return $t.val();
1116
+ }
1117
+ }
1118
+ } // end _controls
1119
+
1120
+ });
1121
+
1122
+ $.fn.extend({
1123
+ /*
1124
+ * shorthand just to use timepicker.
1125
+ */
1126
+ timepicker: function (o) {
1127
+ o = o || {};
1128
+ var tmp_args = Array.prototype.slice.call(arguments);
1129
+
1130
+ if (typeof o === 'object') {
1131
+ tmp_args[0] = $.extend(o, {
1132
+ timeOnly: true
1133
+ });
1134
+ }
1135
+
1136
+ return $(this).each(function () {
1137
+ $.fn.datetimepicker.apply($(this), tmp_args);
1138
+ });
1139
+ },
1140
+
1141
+ /*
1142
+ * extend timepicker to datepicker
1143
+ */
1144
+ datetimepicker: function (o) {
1145
+ o = o || {};
1146
+ var tmp_args = arguments;
1147
+
1148
+ if (typeof(o) === 'string') {
1149
+ if (o === 'getDate' || (o === 'option' && tmp_args.length === 2 && typeof (tmp_args[1]) === 'string')) {
1150
+ return $.fn.datepicker.apply($(this[0]), tmp_args);
1151
+ } else {
1152
+ return this.each(function () {
1153
+ var $t = $(this);
1154
+ $t.datepicker.apply($t, tmp_args);
1155
+ });
1156
+ }
1157
+ } else {
1158
+ return this.each(function () {
1159
+ var $t = $(this);
1160
+ $t.datepicker($.timepicker._newInst($t, o)._defaults);
1161
+ });
1162
+ }
1163
+ }
1164
+ });
1165
+
1166
+ /*
1167
+ * Public Utility to parse date and time
1168
+ */
1169
+ $.datepicker.parseDateTime = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
1170
+ var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);
1171
+ if (parseRes.timeObj) {
1172
+ var t = parseRes.timeObj;
1173
+ parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);
1174
+ parseRes.date.setMicroseconds(t.microsec);
1175
+ }
1176
+
1177
+ return parseRes.date;
1178
+ };
1179
+
1180
+ /*
1181
+ * Public utility to parse time
1182
+ */
1183
+ $.datepicker.parseTime = function (timeFormat, timeString, options) {
1184
+ var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}),
1185
+ iso8601 = (timeFormat.replace(/\'.*?\'/g, '').indexOf('Z') !== -1);
1186
+
1187
+ // Strict parse requires the timeString to match the timeFormat exactly
1188
+ var strictParse = function (f, s, o) {
1189
+
1190
+ // pattern for standard and localized AM/PM markers
1191
+ var getPatternAmpm = function (amNames, pmNames) {
1192
+ var markers = [];
1193
+ if (amNames) {
1194
+ $.merge(markers, amNames);
1195
+ }
1196
+ if (pmNames) {
1197
+ $.merge(markers, pmNames);
1198
+ }
1199
+ markers = $.map(markers, function (val) {
1200
+ return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&');
1201
+ });
1202
+ return '(' + markers.join('|') + ')?';
1203
+ };
1204
+
1205
+ // figure out position of time elements.. cause js cant do named captures
1206
+ var getFormatPositions = function (timeFormat) {
1207
+ var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|c{1}|t{1,2}|z|'.*?')/g),
1208
+ orders = {
1209
+ h: -1,
1210
+ m: -1,
1211
+ s: -1,
1212
+ l: -1,
1213
+ c: -1,
1214
+ t: -1,
1215
+ z: -1
1216
+ };
1217
+
1218
+ if (finds) {
1219
+ for (var i = 0; i < finds.length; i++) {
1220
+ if (orders[finds[i].toString().charAt(0)] === -1) {
1221
+ orders[finds[i].toString().charAt(0)] = i + 1;
1222
+ }
1223
+ }
1224
+ }
1225
+ return orders;
1226
+ };
1227
+
1228
+ var regstr = '^' + f.toString()
1229
+ .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {
1230
+ var ml = match.length;
1231
+ switch (match.charAt(0).toLowerCase()) {
1232
+ case 'h':
1233
+ return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
1234
+ case 'm':
1235
+ return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
1236
+ case 's':
1237
+ return ml === 1 ? '(\\d?\\d)' : '(\\d{' + ml + '})';
1238
+ case 'l':
1239
+ return '(\\d?\\d?\\d)';
1240
+ case 'c':
1241
+ return '(\\d?\\d?\\d)';
1242
+ case 'z':
1243
+ return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?';
1244
+ case 't':
1245
+ return getPatternAmpm(o.amNames, o.pmNames);
1246
+ default: // literal escaped in quotes
1247
+ return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?';
1248
+ }
1249
+ })
1250
+ .replace(/\s/g, '\\s?') +
1251
+ o.timeSuffix + '$',
1252
+ order = getFormatPositions(f),
1253
+ ampm = '',
1254
+ treg;
1255
+
1256
+ treg = s.match(new RegExp(regstr, 'i'));
1257
+
1258
+ var resTime = {
1259
+ hour: 0,
1260
+ minute: 0,
1261
+ second: 0,
1262
+ millisec: 0,
1263
+ microsec: 0
1264
+ };
1265
+
1266
+ if (treg) {
1267
+ if (order.t !== -1) {
1268
+ if (treg[order.t] === undefined || treg[order.t].length === 0) {
1269
+ ampm = '';
1270
+ resTime.ampm = '';
1271
+ } else {
1272
+ ampm = $.inArray(treg[order.t].toUpperCase(), $.map(o.amNames, function (x,i) { return x.toUpperCase(); })) !== -1 ? 'AM' : 'PM';
1273
+ resTime.ampm = o[ampm === 'AM' ? 'amNames' : 'pmNames'][0];
1274
+ }
1275
+ }
1276
+
1277
+ if (order.h !== -1) {
1278
+ if (ampm === 'AM' && treg[order.h] === '12') {
1279
+ resTime.hour = 0; // 12am = 0 hour
1280
+ } else {
1281
+ if (ampm === 'PM' && treg[order.h] !== '12') {
1282
+ resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12
1283
+ } else {
1284
+ resTime.hour = Number(treg[order.h]);
1285
+ }
1286
+ }
1287
+ }
1288
+
1289
+ if (order.m !== -1) {
1290
+ resTime.minute = Number(treg[order.m]);
1291
+ }
1292
+ if (order.s !== -1) {
1293
+ resTime.second = Number(treg[order.s]);
1294
+ }
1295
+ if (order.l !== -1) {
1296
+ resTime.millisec = Number(treg[order.l]);
1297
+ }
1298
+ if (order.c !== -1) {
1299
+ resTime.microsec = Number(treg[order.c]);
1300
+ }
1301
+ if (order.z !== -1 && treg[order.z] !== undefined) {
1302
+ resTime.timezone = $.timepicker.timezoneOffsetNumber(treg[order.z]);
1303
+ }
1304
+
1305
+
1306
+ return resTime;
1307
+ }
1308
+ return false;
1309
+ };// end strictParse
1310
+
1311
+ // First try JS Date, if that fails, use strictParse
1312
+ var looseParse = function (f, s, o) {
1313
+ try {
1314
+ var d = new Date('2012-01-01 ' + s);
1315
+ if (isNaN(d.getTime())) {
1316
+ d = new Date('2012-01-01T' + s);
1317
+ if (isNaN(d.getTime())) {
1318
+ d = new Date('01/01/2012 ' + s);
1319
+ if (isNaN(d.getTime())) {
1320
+ throw "Unable to parse time with native Date: " + s;
1321
+ }
1322
+ }
1323
+ }
1324
+
1325
+ return {
1326
+ hour: d.getHours(),
1327
+ minute: d.getMinutes(),
1328
+ second: d.getSeconds(),
1329
+ millisec: d.getMilliseconds(),
1330
+ microsec: d.getMicroseconds(),
1331
+ timezone: d.getTimezoneOffset() * -1
1332
+ };
1333
+ }
1334
+ catch (err) {
1335
+ try {
1336
+ return strictParse(f, s, o);
1337
+ }
1338
+ catch (err2) {
1339
+ $.timepicker.log("Unable to parse \ntimeString: " + s + "\ntimeFormat: " + f);
1340
+ }
1341
+ }
1342
+ return false;
1343
+ }; // end looseParse
1344
+
1345
+ if (typeof o.parse === "function") {
1346
+ return o.parse(timeFormat, timeString, o);
1347
+ }
1348
+ if (o.parse === 'loose') {
1349
+ return looseParse(timeFormat, timeString, o);
1350
+ }
1351
+ return strictParse(timeFormat, timeString, o);
1352
+ };
1353
+
1354
+ /**
1355
+ * Public utility to format the time
1356
+ * @param {string} format format of the time
1357
+ * @param {Object} time Object not a Date for timezones
1358
+ * @param {Object} [options] essentially the regional[].. amNames, pmNames, ampm
1359
+ * @returns {string} the formatted time
1360
+ */
1361
+ $.datepicker.formatTime = function (format, time, options) {
1362
+ options = options || {};
1363
+ options = $.extend({}, $.timepicker._defaults, options);
1364
+ time = $.extend({
1365
+ hour: 0,
1366
+ minute: 0,
1367
+ second: 0,
1368
+ millisec: 0,
1369
+ microsec: 0,
1370
+ timezone: null
1371
+ }, time);
1372
+
1373
+ var tmptime = format,
1374
+ ampmName = options.amNames[0],
1375
+ hour = parseInt(time.hour, 10);
1376
+
1377
+ if (hour > 11) {
1378
+ ampmName = options.pmNames[0];
1379
+ }
1380
+
1381
+ tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[zZ]|[lc]|'.*?')/g, function (match) {
1382
+ switch (match) {
1383
+ case 'HH':
1384
+ return ('0' + hour).slice(-2);
1385
+ case 'H':
1386
+ return hour;
1387
+ case 'hh':
1388
+ return ('0' + convert24to12(hour)).slice(-2);
1389
+ case 'h':
1390
+ return convert24to12(hour);
1391
+ case 'mm':
1392
+ return ('0' + time.minute).slice(-2);
1393
+ case 'm':
1394
+ return time.minute;
1395
+ case 'ss':
1396
+ return ('0' + time.second).slice(-2);
1397
+ case 's':
1398
+ return time.second;
1399
+ case 'l':
1400
+ return ('00' + time.millisec).slice(-3);
1401
+ case 'c':
1402
+ return ('00' + time.microsec).slice(-3);
1403
+ case 'z':
1404
+ return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, false);
1405
+ case 'Z':
1406
+ return $.timepicker.timezoneOffsetString(time.timezone === null ? options.timezone : time.timezone, true);
1407
+ case 'T':
1408
+ return ampmName.charAt(0).toUpperCase();
1409
+ case 'TT':
1410
+ return ampmName.toUpperCase();
1411
+ case 't':
1412
+ return ampmName.charAt(0).toLowerCase();
1413
+ case 'tt':
1414
+ return ampmName.toLowerCase();
1415
+ default:
1416
+ return match.replace(/'/g, "");
1417
+ }
1418
+ });
1419
+
1420
+ return tmptime;
1421
+ };
1422
+
1423
+ /*
1424
+ * the bad hack :/ override datepicker so it doesn't close on select
1425
+ // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
1426
+ */
1427
+ $.datepicker._base_selectDate = $.datepicker._selectDate;
1428
+ $.datepicker._selectDate = function (id, dateStr) {
1429
+ var inst = this._getInst($(id)[0]),
1430
+ tp_inst = this._get(inst, 'timepicker'),
1431
+ was_inline;
1432
+
1433
+ if (tp_inst && inst.settings.showTimepicker) {
1434
+ tp_inst._limitMinMaxDateTime(inst, true);
1435
+ was_inline = inst.inline;
1436
+ inst.inline = inst.stay_open = true;
1437
+ //This way the onSelect handler called from calendarpicker get the full dateTime
1438
+ this._base_selectDate(id, dateStr);
1439
+ inst.inline = was_inline;
1440
+ inst.stay_open = false;
1441
+ this._notifyChange(inst);
1442
+ this._updateDatepicker(inst);
1443
+ } else {
1444
+ this._base_selectDate(id, dateStr);
1445
+ }
1446
+ };
1447
+
1448
+ /*
1449
+ * second bad hack :/ override datepicker so it triggers an event when changing the input field
1450
+ * and does not redraw the datepicker on every selectDate event
1451
+ */
1452
+ $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
1453
+ $.datepicker._updateDatepicker = function (inst) {
1454
+
1455
+ // don't popup the datepicker if there is another instance already opened
1456
+ var input = inst.input[0];
1457
+ if ($.datepicker._curInst && $.datepicker._curInst !== inst && $.datepicker._datepickerShowing && $.datepicker._lastInput !== input) {
1458
+ return;
1459
+ }
1460
+
1461
+ if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
1462
+
1463
+ this._base_updateDatepicker(inst);
1464
+
1465
+ // Reload the time control when changing something in the input text field.
1466
+ var tp_inst = this._get(inst, 'timepicker');
1467
+ if (tp_inst) {
1468
+ tp_inst._addTimePicker(inst);
1469
+ }
1470
+ }
1471
+ };
1472
+
1473
+ /*
1474
+ * third bad hack :/ override datepicker so it allows spaces and colon in the input field
1475
+ */
1476
+ $.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
1477
+ $.datepicker._doKeyPress = function (event) {
1478
+ var inst = $.datepicker._getInst(event.target),
1479
+ tp_inst = $.datepicker._get(inst, 'timepicker');
1480
+
1481
+ if (tp_inst) {
1482
+ if ($.datepicker._get(inst, 'constrainInput')) {
1483
+ var ampm = tp_inst.support.ampm,
1484
+ tz = tp_inst._defaults.showTimezone !== null ? tp_inst._defaults.showTimezone : tp_inst.support.timezone,
1485
+ dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
1486
+ datetimeChars = tp_inst._defaults.timeFormat.toString()
1487
+ .replace(/[hms]/g, '')
1488
+ .replace(/TT/g, ampm ? 'APM' : '')
1489
+ .replace(/Tt/g, ampm ? 'AaPpMm' : '')
1490
+ .replace(/tT/g, ampm ? 'AaPpMm' : '')
1491
+ .replace(/T/g, ampm ? 'AP' : '')
1492
+ .replace(/tt/g, ampm ? 'apm' : '')
1493
+ .replace(/t/g, ampm ? 'ap' : '') +
1494
+ " " + tp_inst._defaults.separator +
1495
+ tp_inst._defaults.timeSuffix +
1496
+ (tz ? tp_inst._defaults.timezoneList.join('') : '') +
1497
+ (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) +
1498
+ dateChars,
1499
+ chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
1500
+ return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
1501
+ }
1502
+ }
1503
+
1504
+ return $.datepicker._base_doKeyPress(event);
1505
+ };
1506
+
1507
+ /*
1508
+ * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField
1509
+ * Update any alternate field to synchronise with the main field.
1510
+ */
1511
+ $.datepicker._base_updateAlternate = $.datepicker._updateAlternate;
1512
+ $.datepicker._updateAlternate = function (inst) {
1513
+ var tp_inst = this._get(inst, 'timepicker');
1514
+ if (tp_inst) {
1515
+ var altField = tp_inst._defaults.altField;
1516
+ if (altField) { // update alternate field too
1517
+ var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat,
1518
+ date = this._getDate(inst),
1519
+ formatCfg = $.datepicker._getFormatConfig(inst),
1520
+ altFormattedDateTime = '',
1521
+ altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator,
1522
+ altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix,
1523
+ altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat;
1524
+
1525
+ altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix;
1526
+ if (!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly && date !== null) {
1527
+ if (tp_inst._defaults.altFormat) {
1528
+ altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, date, formatCfg) + altSeparator + altFormattedDateTime;
1529
+ }
1530
+ else {
1531
+ altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime;
1532
+ }
1533
+ }
1534
+ $(altField).val( inst.input.val() ? altFormattedDateTime : "");
1535
+ }
1536
+ }
1537
+ else {
1538
+ $.datepicker._base_updateAlternate(inst);
1539
+ }
1540
+ };
1541
+
1542
+ /*
1543
+ * Override key up event to sync manual input changes.
1544
+ */
1545
+ $.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
1546
+ $.datepicker._doKeyUp = function (event) {
1547
+ var inst = $.datepicker._getInst(event.target),
1548
+ tp_inst = $.datepicker._get(inst, 'timepicker');
1549
+
1550
+ if (tp_inst) {
1551
+ if (tp_inst._defaults.timeOnly && (inst.input.val() !== inst.lastVal)) {
1552
+ try {
1553
+ $.datepicker._updateDatepicker(inst);
1554
+ } catch (err) {
1555
+ $.timepicker.log(err);
1556
+ }
1557
+ }
1558
+ }
1559
+
1560
+ return $.datepicker._base_doKeyUp(event);
1561
+ };
1562
+
1563
+ /*
1564
+ * override "Today" button to also grab the time and set it to input field.
1565
+ */
1566
+ $.datepicker._base_gotoToday = $.datepicker._gotoToday;
1567
+ $.datepicker._gotoToday = function (id) {
1568
+ var inst = this._getInst($(id)[0]);
1569
+ this._base_gotoToday(id);
1570
+ var tp_inst = this._get(inst, 'timepicker');
1571
+ if (!tp_inst) {
1572
+ return;
1573
+ }
1574
+
1575
+ var tzoffset = $.timepicker.timezoneOffsetNumber(tp_inst.timezone);
1576
+ var now = new Date();
1577
+ now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + parseInt(tzoffset, 10));
1578
+ this._setTime(inst, now);
1579
+ this._setDate(inst, now);
1580
+ tp_inst._onSelectHandler();
1581
+ };
1582
+
1583
+ /*
1584
+ * Disable & enable the Time in the datetimepicker
1585
+ */
1586
+ $.datepicker._disableTimepickerDatepicker = function (target) {
1587
+ var inst = this._getInst(target);
1588
+ if (!inst) {
1589
+ return;
1590
+ }
1591
+
1592
+ var tp_inst = this._get(inst, 'timepicker');
1593
+ $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1594
+ if (tp_inst) {
1595
+ inst.settings.showTimepicker = false;
1596
+ tp_inst._defaults.showTimepicker = false;
1597
+ tp_inst._updateDateTime(inst);
1598
+ }
1599
+ };
1600
+
1601
+ $.datepicker._enableTimepickerDatepicker = function (target) {
1602
+ var inst = this._getInst(target);
1603
+ if (!inst) {
1604
+ return;
1605
+ }
1606
+
1607
+ var tp_inst = this._get(inst, 'timepicker');
1608
+ $(target).datepicker('getDate'); // Init selected[Year|Month|Day]
1609
+ if (tp_inst) {
1610
+ inst.settings.showTimepicker = true;
1611
+ tp_inst._defaults.showTimepicker = true;
1612
+ tp_inst._addTimePicker(inst); // Could be disabled on page load
1613
+ tp_inst._updateDateTime(inst);
1614
+ }
1615
+ };
1616
+
1617
+ /*
1618
+ * Create our own set time function
1619
+ */
1620
+ $.datepicker._setTime = function (inst, date) {
1621
+ var tp_inst = this._get(inst, 'timepicker');
1622
+ if (tp_inst) {
1623
+ var defaults = tp_inst._defaults;
1624
+
1625
+ // calling _setTime with no date sets time to defaults
1626
+ tp_inst.hour = date ? date.getHours() : defaults.hour;
1627
+ tp_inst.minute = date ? date.getMinutes() : defaults.minute;
1628
+ tp_inst.second = date ? date.getSeconds() : defaults.second;
1629
+ tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec;
1630
+ tp_inst.microsec = date ? date.getMicroseconds() : defaults.microsec;
1631
+
1632
+ //check if within min/max times..
1633
+ tp_inst._limitMinMaxDateTime(inst, true);
1634
+
1635
+ tp_inst._onTimeChange();
1636
+ tp_inst._updateDateTime(inst);
1637
+ }
1638
+ };
1639
+
1640
+ /*
1641
+ * Create new public method to set only time, callable as $().datepicker('setTime', date)
1642
+ */
1643
+ $.datepicker._setTimeDatepicker = function (target, date, withDate) {
1644
+ var inst = this._getInst(target);
1645
+ if (!inst) {
1646
+ return;
1647
+ }
1648
+
1649
+ var tp_inst = this._get(inst, 'timepicker');
1650
+
1651
+ if (tp_inst) {
1652
+ this._setDateFromField(inst);
1653
+ var tp_date;
1654
+ if (date) {
1655
+ if (typeof date === "string") {
1656
+ tp_inst._parseTime(date, withDate);
1657
+ tp_date = new Date();
1658
+ tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1659
+ tp_date.setMicroseconds(tp_inst.microsec);
1660
+ } else {
1661
+ tp_date = new Date(date.getTime());
1662
+ tp_date.setMicroseconds(date.getMicroseconds());
1663
+ }
1664
+ if (tp_date.toString() === 'Invalid Date') {
1665
+ tp_date = undefined;
1666
+ }
1667
+ this._setTime(inst, tp_date);
1668
+ }
1669
+ }
1670
+
1671
+ };
1672
+
1673
+ /*
1674
+ * override setDate() to allow setting time too within Date object
1675
+ */
1676
+ $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
1677
+ $.datepicker._setDateDatepicker = function (target, _date) {
1678
+ var inst = this._getInst(target);
1679
+ var date = _date;
1680
+ if (!inst) {
1681
+ return;
1682
+ }
1683
+
1684
+ if (typeof(_date) === 'string') {
1685
+ date = new Date(_date);
1686
+ if (!date.getTime()) {
1687
+ this._base_setDateDatepicker.apply(this, arguments);
1688
+ date = $(target).datepicker('getDate');
1689
+ }
1690
+ }
1691
+
1692
+ var tp_inst = this._get(inst, 'timepicker');
1693
+ var tp_date;
1694
+ if (date instanceof Date) {
1695
+ tp_date = new Date(date.getTime());
1696
+ tp_date.setMicroseconds(date.getMicroseconds());
1697
+ } else {
1698
+ tp_date = date;
1699
+ }
1700
+
1701
+ // This is important if you are using the timezone option, javascript's Date
1702
+ // object will only return the timezone offset for the current locale, so we
1703
+ // adjust it accordingly. If not using timezone option this won't matter..
1704
+ // If a timezone is different in tp, keep the timezone as is
1705
+ if (tp_inst && tp_date) {
1706
+ // look out for DST if tz wasn't specified
1707
+ if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {
1708
+ tp_inst.timezone = tp_date.getTimezoneOffset() * -1;
1709
+ }
1710
+ date = $.timepicker.timezoneAdjust(date, $.timepicker.timezoneOffsetString(-date.getTimezoneOffset()), tp_inst.timezone);
1711
+ tp_date = $.timepicker.timezoneAdjust(tp_date, $.timepicker.timezoneOffsetString(-tp_date.getTimezoneOffset()), tp_inst.timezone);
1712
+ }
1713
+
1714
+ this._updateDatepicker(inst);
1715
+ this._base_setDateDatepicker.apply(this, arguments);
1716
+ this._setTimeDatepicker(target, tp_date, true);
1717
+ };
1718
+
1719
+ /*
1720
+ * override getDate() to allow getting time too within Date object
1721
+ */
1722
+ $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
1723
+ $.datepicker._getDateDatepicker = function (target, noDefault) {
1724
+ var inst = this._getInst(target);
1725
+ if (!inst) {
1726
+ return;
1727
+ }
1728
+
1729
+ var tp_inst = this._get(inst, 'timepicker');
1730
+
1731
+ if (tp_inst) {
1732
+ // if it hasn't yet been defined, grab from field
1733
+ if (inst.lastVal === undefined) {
1734
+ this._setDateFromField(inst, noDefault);
1735
+ }
1736
+
1737
+ var date = this._getDate(inst);
1738
+
1739
+ var currDT = null;
1740
+
1741
+ if (tp_inst.$altInput && tp_inst._defaults.altFieldTimeOnly) {
1742
+ currDT = tp_inst.$input.val() + ' ' + tp_inst.$altInput.val();
1743
+ }
1744
+ else if (tp_inst.$input.get(0).tagName !== 'INPUT' && tp_inst.$altInput) {
1745
+ /**
1746
+ * in case the datetimepicker has been applied to a non-input tag for inline UI,
1747
+ * and the user has not configured the plugin to display only time in altInput,
1748
+ * pick current date time from the altInput (and hope for the best, for now, until "ER1" is applied)
1749
+ *
1750
+ * @todo ER1. Since altInput can have a totally difference format, convert it to standard format by reading input format from "altFormat" and "altTimeFormat" option values
1751
+ */
1752
+ currDT = tp_inst.$altInput.val();
1753
+ }
1754
+ else {
1755
+ currDT = tp_inst.$input.val();
1756
+ }
1757
+
1758
+ if (date && tp_inst._parseTime(currDT, !inst.settings.timeOnly)) {
1759
+ date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
1760
+ date.setMicroseconds(tp_inst.microsec);
1761
+
1762
+ // This is important if you are using the timezone option, javascript's Date
1763
+ // object will only return the timezone offset for the current locale, so we
1764
+ // adjust it accordingly. If not using timezone option this won't matter..
1765
+ if (tp_inst.timezone != null) {
1766
+ // look out for DST if tz wasn't specified
1767
+ if (!tp_inst.support.timezone && tp_inst._defaults.timezone === null) {
1768
+ tp_inst.timezone = date.getTimezoneOffset() * -1;
1769
+ }
1770
+ date = $.timepicker.timezoneAdjust(date, tp_inst.timezone, $.timepicker.timezoneOffsetString(-date.getTimezoneOffset()));
1771
+ }
1772
+ }
1773
+ return date;
1774
+ }
1775
+ return this._base_getDateDatepicker(target, noDefault);
1776
+ };
1777
+
1778
+ /*
1779
+ * override parseDate() because UI 1.8.14 throws an error about "Extra characters"
1780
+ * An option in datapicker to ignore extra format characters would be nicer.
1781
+ */
1782
+ $.datepicker._base_parseDate = $.datepicker.parseDate;
1783
+ $.datepicker.parseDate = function (format, value, settings) {
1784
+ var date;
1785
+ try {
1786
+ date = this._base_parseDate(format, value, settings);
1787
+ } catch (err) {
1788
+ // Hack! The error message ends with a colon, a space, and
1789
+ // the "extra" characters. We rely on that instead of
1790
+ // attempting to perfectly reproduce the parsing algorithm.
1791
+ if (err.indexOf(":") >= 0) {
1792
+ date = this._base_parseDate(format, value.substring(0, value.length - (err.length - err.indexOf(':') - 2)), settings);
1793
+ $.timepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format);
1794
+ } else {
1795
+ throw err;
1796
+ }
1797
+ }
1798
+ return date;
1799
+ };
1800
+
1801
+ /*
1802
+ * override formatDate to set date with time to the input
1803
+ */
1804
+ $.datepicker._base_formatDate = $.datepicker._formatDate;
1805
+ $.datepicker._formatDate = function (inst, day, month, year) {
1806
+ var tp_inst = this._get(inst, 'timepicker');
1807
+ if (tp_inst) {
1808
+ tp_inst._updateDateTime(inst);
1809
+ return tp_inst.$input.val();
1810
+ }
1811
+ return this._base_formatDate(inst);
1812
+ };
1813
+
1814
+ /*
1815
+ * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
1816
+ */
1817
+ $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
1818
+ $.datepicker._optionDatepicker = function (target, name, value) {
1819
+ var inst = this._getInst(target),
1820
+ name_clone;
1821
+ if (!inst) {
1822
+ return null;
1823
+ }
1824
+
1825
+ var tp_inst = this._get(inst, 'timepicker');
1826
+ if (tp_inst) {
1827
+ var min = null,
1828
+ max = null,
1829
+ onselect = null,
1830
+ overrides = tp_inst._defaults.evnts,
1831
+ fns = {},
1832
+ prop,
1833
+ ret,
1834
+ oldVal,
1835
+ $target;
1836
+ if (typeof name === 'string') { // if min/max was set with the string
1837
+ if (name === 'minDate' || name === 'minDateTime') {
1838
+ min = value;
1839
+ } else if (name === 'maxDate' || name === 'maxDateTime') {
1840
+ max = value;
1841
+ } else if (name === 'onSelect') {
1842
+ onselect = value;
1843
+ } else if (overrides.hasOwnProperty(name)) {
1844
+ if (typeof (value) === 'undefined') {
1845
+ return overrides[name];
1846
+ }
1847
+ fns[name] = value;
1848
+ name_clone = {}; //empty results in exiting function after overrides updated
1849
+ }
1850
+ } else if (typeof name === 'object') { //if min/max was set with the JSON
1851
+ if (name.minDate) {
1852
+ min = name.minDate;
1853
+ } else if (name.minDateTime) {
1854
+ min = name.minDateTime;
1855
+ } else if (name.maxDate) {
1856
+ max = name.maxDate;
1857
+ } else if (name.maxDateTime) {
1858
+ max = name.maxDateTime;
1859
+ }
1860
+ for (prop in overrides) {
1861
+ if (overrides.hasOwnProperty(prop) && name[prop]) {
1862
+ fns[prop] = name[prop];
1863
+ }
1864
+ }
1865
+ }
1866
+ for (prop in fns) {
1867
+ if (fns.hasOwnProperty(prop)) {
1868
+ overrides[prop] = fns[prop];
1869
+ if (!name_clone) { name_clone = $.extend({}, name); }
1870
+ delete name_clone[prop];
1871
+ }
1872
+ }
1873
+ if (name_clone && isEmptyObject(name_clone)) { return; }
1874
+ if (min) { //if min was set
1875
+ if (min === 0) {
1876
+ min = new Date();
1877
+ } else {
1878
+ min = new Date(min);
1879
+ }
1880
+ tp_inst._defaults.minDate = min;
1881
+ tp_inst._defaults.minDateTime = min;
1882
+ } else if (max) { //if max was set
1883
+ if (max === 0) {
1884
+ max = new Date();
1885
+ } else {
1886
+ max = new Date(max);
1887
+ }
1888
+ tp_inst._defaults.maxDate = max;
1889
+ tp_inst._defaults.maxDateTime = max;
1890
+ } else if (onselect) {
1891
+ tp_inst._defaults.onSelect = onselect;
1892
+ }
1893
+
1894
+ // Datepicker will override our date when we call _base_optionDatepicker when
1895
+ // calling minDate/maxDate, so we will first grab the value, call
1896
+ // _base_optionDatepicker, then set our value back.
1897
+ if(min || max){
1898
+ $target = $(target);
1899
+ oldVal = $target.datetimepicker('getDate');
1900
+ ret = this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);
1901
+ $target.datetimepicker('setDate', oldVal);
1902
+ return ret;
1903
+ }
1904
+ }
1905
+ if (value === undefined) {
1906
+ return this._base_optionDatepicker.call($.datepicker, target, name);
1907
+ }
1908
+ return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value);
1909
+ };
1910
+
1911
+ /*
1912
+ * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype,
1913
+ * it will return false for all objects
1914
+ */
1915
+ var isEmptyObject = function (obj) {
1916
+ var prop;
1917
+ for (prop in obj) {
1918
+ if (obj.hasOwnProperty(prop)) {
1919
+ return false;
1920
+ }
1921
+ }
1922
+ return true;
1923
+ };
1924
+
1925
+ /*
1926
+ * jQuery extend now ignores nulls!
1927
+ */
1928
+ var extendRemove = function (target, props) {
1929
+ $.extend(target, props);
1930
+ for (var name in props) {
1931
+ if (props[name] === null || props[name] === undefined) {
1932
+ target[name] = props[name];
1933
+ }
1934
+ }
1935
+ return target;
1936
+ };
1937
+
1938
+ /*
1939
+ * Determine by the time format which units are supported
1940
+ * Returns an object of booleans for each unit
1941
+ */
1942
+ var detectSupport = function (timeFormat) {
1943
+ var tf = timeFormat.replace(/'.*?'/g, '').toLowerCase(), // removes literals
1944
+ isIn = function (f, t) { // does the format contain the token?
1945
+ return f.indexOf(t) !== -1 ? true : false;
1946
+ };
1947
+ return {
1948
+ hour: isIn(tf, 'h'),
1949
+ minute: isIn(tf, 'm'),
1950
+ second: isIn(tf, 's'),
1951
+ millisec: isIn(tf, 'l'),
1952
+ microsec: isIn(tf, 'c'),
1953
+ timezone: isIn(tf, 'z'),
1954
+ ampm: isIn(tf, 't') && isIn(timeFormat, 'h'),
1955
+ iso8601: isIn(timeFormat, 'Z')
1956
+ };
1957
+ };
1958
+
1959
+ /*
1960
+ * Converts 24 hour format into 12 hour
1961
+ * Returns 12 hour without leading 0
1962
+ */
1963
+ var convert24to12 = function (hour) {
1964
+ hour %= 12;
1965
+
1966
+ if (hour === 0) {
1967
+ hour = 12;
1968
+ }
1969
+
1970
+ return String(hour);
1971
+ };
1972
+
1973
+ var computeEffectiveSetting = function (settings, property) {
1974
+ return settings && settings[property] ? settings[property] : $.timepicker._defaults[property];
1975
+ };
1976
+
1977
+ /*
1978
+ * Splits datetime string into date and time substrings.
1979
+ * Throws exception when date can't be parsed
1980
+ * Returns {dateString: dateString, timeString: timeString}
1981
+ */
1982
+ var splitDateTime = function (dateTimeString, timeSettings) {
1983
+ // The idea is to get the number separator occurrences in datetime and the time format requested (since time has
1984
+ // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split.
1985
+ var separator = computeEffectiveSetting(timeSettings, 'separator'),
1986
+ format = computeEffectiveSetting(timeSettings, 'timeFormat'),
1987
+ timeParts = format.split(separator), // how many occurrences of separator may be in our format?
1988
+ timePartsLen = timeParts.length,
1989
+ allParts = dateTimeString.split(separator),
1990
+ allPartsLen = allParts.length;
1991
+
1992
+ if (allPartsLen > 1) {
1993
+ return {
1994
+ dateString: allParts.splice(0, allPartsLen - timePartsLen).join(separator),
1995
+ timeString: allParts.splice(0, timePartsLen).join(separator)
1996
+ };
1997
+ }
1998
+
1999
+ return {
2000
+ dateString: dateTimeString,
2001
+ timeString: ''
2002
+ };
2003
+ };
2004
+
2005
+ /*
2006
+ * Internal function to parse datetime interval
2007
+ * Returns: {date: Date, timeObj: Object}, where
2008
+ * date - parsed date without time (type Date)
2009
+ * timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional
2010
+ */
2011
+ var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
2012
+ var date,
2013
+ parts,
2014
+ parsedTime;
2015
+
2016
+ parts = splitDateTime(dateTimeString, timeSettings);
2017
+ date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);
2018
+
2019
+ if (parts.timeString === '') {
2020
+ return {
2021
+ date: date
2022
+ };
2023
+ }
2024
+
2025
+ parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);
2026
+
2027
+ if (!parsedTime) {
2028
+ throw 'Wrong time format';
2029
+ }
2030
+
2031
+ return {
2032
+ date: date,
2033
+ timeObj: parsedTime
2034
+ };
2035
+ };
2036
+
2037
+ /*
2038
+ * Internal function to set timezone_select to the local timezone
2039
+ */
2040
+ var selectLocalTimezone = function (tp_inst, date) {
2041
+ if (tp_inst && tp_inst.timezone_select) {
2042
+ var now = date || new Date();
2043
+ tp_inst.timezone_select.val(-now.getTimezoneOffset());
2044
+ }
2045
+ };
2046
+
2047
+ /*
2048
+ * Create a Singleton Instance
2049
+ */
2050
+ $.timepicker = new Timepicker();
2051
+
2052
+ /**
2053
+ * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)
2054
+ * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned
2055
+ * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45"
2056
+ * @return {string}
2057
+ */
2058
+ $.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {
2059
+ if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {
2060
+ return tzMinutes;
2061
+ }
2062
+
2063
+ var off = tzMinutes,
2064
+ minutes = off % 60,
2065
+ hours = (off - minutes) / 60,
2066
+ iso = iso8601 ? ':' : '',
2067
+ tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);
2068
+
2069
+ if (tz === '+00:00') {
2070
+ return 'Z';
2071
+ }
2072
+ return tz;
2073
+ };
2074
+
2075
+ /**
2076
+ * Get the number in minutes that represents a timezone string
2077
+ * @param {string} tzString formatted like "+0500", "-1245", "Z"
2078
+ * @return {number} the offset minutes or the original string if it doesn't match expectations
2079
+ */
2080
+ $.timepicker.timezoneOffsetNumber = function (tzString) {
2081
+ var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with "+1245"
2082
+
2083
+ if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset
2084
+ return 0;
2085
+ }
2086
+
2087
+ if (!/^(\-|\+)\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back
2088
+ return parseInt(tzString, 10);
2089
+ }
2090
+
2091
+ return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus
2092
+ ((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)
2093
+ parseInt(normalized.substr(3, 2), 10))); // minutes
2094
+ };
2095
+
2096
+ /**
2097
+ * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)
2098
+ * @param {Date} date
2099
+ * @param {string} fromTimezone formatted like "+0500", "-1245"
2100
+ * @param {string} toTimezone formatted like "+0500", "-1245"
2101
+ * @return {Date}
2102
+ */
2103
+ $.timepicker.timezoneAdjust = function (date, fromTimezone, toTimezone) {
2104
+ var fromTz = $.timepicker.timezoneOffsetNumber(fromTimezone);
2105
+ var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);
2106
+ if (!isNaN(toTz)) {
2107
+ date.setMinutes(date.getMinutes() + (-fromTz) - (-toTz));
2108
+ }
2109
+ return date;
2110
+ };
2111
+
2112
+ /**
2113
+ * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to
2114
+ * enforce date range limits.
2115
+ * n.b. The input value must be correctly formatted (reformatting is not supported)
2116
+ * @param {Element} startTime
2117
+ * @param {Element} endTime
2118
+ * @param {Object} options Options for the timepicker() call
2119
+ * @return {jQuery}
2120
+ */
2121
+ $.timepicker.timeRange = function (startTime, endTime, options) {
2122
+ return $.timepicker.handleRange('timepicker', startTime, endTime, options);
2123
+ };
2124
+
2125
+ /**
2126
+ * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to
2127
+ * enforce date range limits.
2128
+ * @param {Element} startTime
2129
+ * @param {Element} endTime
2130
+ * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
2131
+ * a boolean value that can be used to reformat the input values to the `dateFormat`.
2132
+ * @param {string} method Can be used to specify the type of picker to be added
2133
+ * @return {jQuery}
2134
+ */
2135
+ $.timepicker.datetimeRange = function (startTime, endTime, options) {
2136
+ $.timepicker.handleRange('datetimepicker', startTime, endTime, options);
2137
+ };
2138
+
2139
+ /**
2140
+ * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to
2141
+ * enforce date range limits.
2142
+ * @param {Element} startTime
2143
+ * @param {Element} endTime
2144
+ * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
2145
+ * a boolean value that can be used to reformat the input values to the `dateFormat`.
2146
+ * @return {jQuery}
2147
+ */
2148
+ $.timepicker.dateRange = function (startTime, endTime, options) {
2149
+ $.timepicker.handleRange('datepicker', startTime, endTime, options);
2150
+ };
2151
+
2152
+ /**
2153
+ * Calls `method` on the `startTime` and `endTime` elements, and configures them to
2154
+ * enforce date range limits.
2155
+ * @param {string} method Can be used to specify the type of picker to be added
2156
+ * @param {Element} startTime
2157
+ * @param {Element} endTime
2158
+ * @param {Object} options Options for the `timepicker()` call. Also supports `reformat`,
2159
+ * a boolean value that can be used to reformat the input values to the `dateFormat`.
2160
+ * @return {jQuery}
2161
+ */
2162
+ $.timepicker.handleRange = function (method, startTime, endTime, options) {
2163
+ options = $.extend({}, {
2164
+ minInterval: 0, // min allowed interval in milliseconds
2165
+ maxInterval: 0, // max allowed interval in milliseconds
2166
+ start: {}, // options for start picker
2167
+ end: {} // options for end picker
2168
+ }, options);
2169
+
2170
+ // for the mean time this fixes an issue with calling getDate with timepicker()
2171
+ var timeOnly = false;
2172
+ if(method === 'timepicker'){
2173
+ timeOnly = true;
2174
+ method = 'datetimepicker';
2175
+ }
2176
+
2177
+ function checkDates(changed, other) {
2178
+ var startdt = startTime[method]('getDate'),
2179
+ enddt = endTime[method]('getDate'),
2180
+ changeddt = changed[method]('getDate');
2181
+
2182
+ if (startdt !== null) {
2183
+ var minDate = new Date(startdt.getTime()),
2184
+ maxDate = new Date(startdt.getTime());
2185
+
2186
+ minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);
2187
+ maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);
2188
+
2189
+ if (options.minInterval > 0 && minDate > enddt) { // minInterval check
2190
+ endTime[method]('setDate', minDate);
2191
+ }
2192
+ else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check
2193
+ endTime[method]('setDate', maxDate);
2194
+ }
2195
+ else if (startdt > enddt) {
2196
+ other[method]('setDate', changeddt);
2197
+ }
2198
+ }
2199
+ }
2200
+
2201
+ function selected(changed, other, option) {
2202
+ if (!changed.val()) {
2203
+ return;
2204
+ }
2205
+ var date = changed[method].call(changed, 'getDate');
2206
+ if (date !== null && options.minInterval > 0) {
2207
+ if (option === 'minDate') {
2208
+ date.setMilliseconds(date.getMilliseconds() + options.minInterval);
2209
+ }
2210
+ if (option === 'maxDate') {
2211
+ date.setMilliseconds(date.getMilliseconds() - options.minInterval);
2212
+ }
2213
+ }
2214
+
2215
+ if (date.getTime) {
2216
+ other[method].call(other, 'option', option, date);
2217
+ }
2218
+ }
2219
+
2220
+ $.fn[method].call(startTime, $.extend({
2221
+ timeOnly: timeOnly,
2222
+ onClose: function (dateText, inst) {
2223
+ checkDates($(this), endTime);
2224
+ },
2225
+ onSelect: function (selectedDateTime) {
2226
+ selected($(this), endTime, 'minDate');
2227
+ }
2228
+ }, options, options.start));
2229
+ $.fn[method].call(endTime, $.extend({
2230
+ timeOnly: timeOnly,
2231
+ onClose: function (dateText, inst) {
2232
+ checkDates($(this), startTime);
2233
+ },
2234
+ onSelect: function (selectedDateTime) {
2235
+ selected($(this), startTime, 'maxDate');
2236
+ }
2237
+ }, options, options.end));
2238
+
2239
+ checkDates(startTime, endTime);
2240
+
2241
+ selected(startTime, endTime, 'minDate');
2242
+ selected(endTime, startTime, 'maxDate');
2243
+
2244
+ return $([startTime.get(0), endTime.get(0)]);
2245
+ };
2246
+
2247
+ /**
2248
+ * Log error or data to the console during error or debugging
2249
+ * @param {Object} err pass any type object to log to the console during error or debugging
2250
+ * @return {void}
2251
+ */
2252
+ $.timepicker.log = function () {
2253
+ // Older IE (9, maybe 10) throw error on accessing `window.console.log.apply`, so check first.
2254
+ if (window.console && window.console.log && window.console.log.apply) {
2255
+ window.console.log.apply(window.console, Array.prototype.slice.call(arguments));
2256
+ }
2257
+ };
2258
+
2259
+ /*
2260
+ * Add util object to allow access to private methods for testability.
2261
+ */
2262
+ $.timepicker._util = {
2263
+ _extendRemove: extendRemove,
2264
+ _isEmptyObject: isEmptyObject,
2265
+ _convert24to12: convert24to12,
2266
+ _detectSupport: detectSupport,
2267
+ _selectLocalTimezone: selectLocalTimezone,
2268
+ _computeEffectiveSetting: computeEffectiveSetting,
2269
+ _splitDateTime: splitDateTime,
2270
+ _parseDateTimeInternal: parseDateTimeInternal
2271
+ };
2272
+
2273
+ /*
2274
+ * Microsecond support
2275
+ */
2276
+ if (!Date.prototype.getMicroseconds) {
2277
+ Date.prototype.microseconds = 0;
2278
+ Date.prototype.getMicroseconds = function () { return this.microseconds; };
2279
+ Date.prototype.setMicroseconds = function (m) {
2280
+ this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));
2281
+ this.microseconds = m % 1000;
2282
+ return this;
2283
+ };
2284
+ }
2285
+
2286
+ /*
2287
+ * Keep up with the version
2288
+ */
2289
+ $.timepicker.version = "1.6.3";
2290
+
2291
+ }));
js/jquery.colorbox.1559237323.js ADDED
@@ -0,0 +1,1105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Colorbox 1.6.4
3
+ license: MIT
4
+ http://www.jacklmoore.com/colorbox
5
+ */
6
+ (function ($, document, window) {
7
+ var
8
+ // Default settings object.
9
+ // See http://jacklmoore.com/colorbox for details.
10
+ defaults = {
11
+ // data sources
12
+ html: false,
13
+ photo: false,
14
+ iframe: false,
15
+ inline: false,
16
+
17
+ // behavior and appearance
18
+ transition: "elastic",
19
+ speed: 300,
20
+ fadeOut: 300,
21
+ width: false,
22
+ initialWidth: "600",
23
+ innerWidth: false,
24
+ maxWidth: false,
25
+ height: false,
26
+ initialHeight: "450",
27
+ innerHeight: false,
28
+ maxHeight: false,
29
+ scalePhotos: true,
30
+ scrolling: true,
31
+ opacity: 0.9,
32
+ preloading: true,
33
+ className: false,
34
+ overlayClose: true,
35
+ escKey: true,
36
+ arrowKey: true,
37
+ top: false,
38
+ bottom: false,
39
+ left: false,
40
+ right: false,
41
+ fixed: false,
42
+ data: undefined,
43
+ closeButton: true,
44
+ fastIframe: true,
45
+ open: false,
46
+ reposition: true,
47
+ loop: true,
48
+ slideshow: false,
49
+ slideshowAuto: true,
50
+ slideshowSpeed: 2500,
51
+ slideshowStart: "start slideshow",
52
+ slideshowStop: "stop slideshow",
53
+ photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,
54
+
55
+ // alternate image paths for high-res displays
56
+ retinaImage: false,
57
+ retinaUrl: false,
58
+ retinaSuffix: '@2x.$1',
59
+
60
+ // internationalization
61
+ current: "image {current} of {total}",
62
+ previous: "previous",
63
+ next: "next",
64
+ close: "close",
65
+ xhrError: "This content failed to load.",
66
+ imgError: "This image failed to load.",
67
+
68
+ // accessbility
69
+ returnFocus: true,
70
+ trapFocus: true,
71
+
72
+ // callbacks
73
+ onOpen: false,
74
+ onLoad: false,
75
+ onComplete: false,
76
+ onCleanup: false,
77
+ onClosed: false,
78
+
79
+ rel: function() {
80
+ return this.rel;
81
+ },
82
+ href: function() {
83
+ // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container')
84
+ return $(this).attr('href');
85
+ },
86
+ title: function() {
87
+ return this.title;
88
+ },
89
+ createImg: function() {
90
+ var img = new Image();
91
+ var attrs = $(this).data('cbox-img-attrs');
92
+
93
+ if (typeof attrs === 'object') {
94
+ $.each(attrs, function(key, val){
95
+ img[key] = val;
96
+ });
97
+ }
98
+
99
+ return img;
100
+ },
101
+ createIframe: function() {
102
+ var iframe = document.createElement('iframe');
103
+ var attrs = $(this).data('cbox-iframe-attrs');
104
+
105
+ if (typeof attrs === 'object') {
106
+ $.each(attrs, function(key, val){
107
+ iframe[key] = val;
108
+ });
109
+ }
110
+
111
+ if ('frameBorder' in iframe) {
112
+ iframe.frameBorder = 0;
113
+ }
114
+ if ('allowTransparency' in iframe) {
115
+ iframe.allowTransparency = "true";
116
+ }
117
+ iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching
118
+ iframe.allowFullscreen = true;
119
+
120
+ return iframe;
121
+ }
122
+ },
123
+
124
+ // Abstracting the HTML and event identifiers for easy rebranding
125
+ colorbox = 'wflscolorbox',
126
+ prefix = 'wflscbox',
127
+ boxElement = prefix + 'Element',
128
+
129
+ // Events
130
+ event_open = prefix + '_open',
131
+ event_load = prefix + '_load',
132
+ event_complete = prefix + '_complete',
133
+ event_cleanup = prefix + '_cleanup',
134
+ event_closed = prefix + '_closed',
135
+ event_purge = prefix + '_purge',
136
+
137
+ // Cached jQuery Object Variables
138
+ $overlay,
139
+ $box,
140
+ $wrap,
141
+ $content,
142
+ $topBorder,
143
+ $leftBorder,
144
+ $rightBorder,
145
+ $bottomBorder,
146
+ $related,
147
+ $window,
148
+ $loaded,
149
+ $loadingBay,
150
+ $loadingOverlay,
151
+ $title,
152
+ $current,
153
+ $slideshow,
154
+ $next,
155
+ $prev,
156
+ $close,
157
+ $groupControls,
158
+ $events = $('<a/>'), // $({}) would be preferred, but there is an issue with jQuery 1.4.2
159
+
160
+ // Variables for cached values or use across multiple functions
161
+ settings,
162
+ interfaceHeight,
163
+ interfaceWidth,
164
+ loadedHeight,
165
+ loadedWidth,
166
+ index,
167
+ photo,
168
+ open,
169
+ active,
170
+ closing,
171
+ loadingTimer,
172
+ publicMethod,
173
+ div = "div",
174
+ requests = 0,
175
+ previousCSS = {},
176
+ init;
177
+
178
+ // ****************
179
+ // HELPER FUNCTIONS
180
+ // ****************
181
+
182
+ // Convenience function for creating new jQuery objects
183
+ function $tag(tag, id, css) {
184
+ var element = document.createElement(tag);
185
+
186
+ if (id) {
187
+ element.id = prefix + id;
188
+ }
189
+
190
+ if (css) {
191
+ element.style.cssText = css;
192
+ }
193
+
194
+ return $(element);
195
+ }
196
+
197
+ // Get the window height using innerHeight when available to avoid an issue with iOS
198
+ // http://bugs.jquery.com/ticket/6724
199
+ function winheight() {
200
+ return window.innerHeight ? window.innerHeight : $(window).height();
201
+ }
202
+
203
+ function Settings(element, options) {
204
+ if (options !== Object(options)) {
205
+ options = {};
206
+ }
207
+
208
+ this.cache = {};
209
+ this.el = element;
210
+
211
+ this.value = function(key) {
212
+ var dataAttr;
213
+
214
+ if (this.cache[key] === undefined) {
215
+ dataAttr = $(this.el).attr('data-cbox-'+key);
216
+
217
+ if (dataAttr !== undefined) {
218
+ this.cache[key] = dataAttr;
219
+ } else if (options[key] !== undefined) {
220
+ this.cache[key] = options[key];
221
+ } else if (defaults[key] !== undefined) {
222
+ this.cache[key] = defaults[key];
223
+ }
224
+ }
225
+
226
+ return this.cache[key];
227
+ };
228
+
229
+ this.get = function(key) {
230
+ var value = this.value(key);
231
+ return $.isFunction(value) ? value.call(this.el, this) : value;
232
+ };
233
+ }
234
+
235
+ // Determine the next and previous members in a group.
236
+ function getIndex(increment) {
237
+ var
238
+ max = $related.length,
239
+ newIndex = (index + increment) % max;
240
+
241
+ return (newIndex < 0) ? max + newIndex : newIndex;
242
+ }
243
+
244
+ // Convert '%' and 'px' values to integers
245
+ function setSize(size, dimension) {
246
+ return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10));
247
+ }
248
+
249
+ // Checks an href to see if it is a photo.
250
+ // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex.
251
+ function isImage(settings, url) {
252
+ return settings.get('photo') || settings.get('photoRegex').test(url);
253
+ }
254
+
255
+ function retinaUrl(settings, url) {
256
+ return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url;
257
+ }
258
+
259
+ function trapFocus(e) {
260
+ if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) {
261
+ e.stopPropagation();
262
+ $box.focus();
263
+ }
264
+ }
265
+
266
+ function setClass(str) {
267
+ if (setClass.str !== str) {
268
+ $box.add($overlay).removeClass(setClass.str).addClass(str);
269
+ setClass.str = str;
270
+ }
271
+ }
272
+
273
+ function getRelated(rel) {
274
+ index = 0;
275
+
276
+ if (rel && rel !== false && rel !== 'nofollow') {
277
+ $related = $('.' + boxElement).filter(function () {
278
+ var options = $.data(this, colorbox);
279
+ var settings = new Settings(this, options);
280
+ return (settings.get('rel') === rel);
281
+ });
282
+ index = $related.index(settings.el);
283
+
284
+ // Check direct calls to Colorbox.
285
+ if (index === -1) {
286
+ $related = $related.add(settings.el);
287
+ index = $related.length - 1;
288
+ }
289
+ } else {
290
+ $related = $(settings.el);
291
+ }
292
+ }
293
+
294
+ function trigger(event) {
295
+ // for external use
296
+ $(document).trigger(event);
297
+ // for internal use
298
+ $events.triggerHandler(event);
299
+ }
300
+
301
+ var slideshow = (function(){
302
+ var active,
303
+ className = prefix + "Slideshow_",
304
+ click = "click." + prefix,
305
+ timeOut;
306
+
307
+ function clear () {
308
+ clearTimeout(timeOut);
309
+ }
310
+
311
+ function set() {
312
+ if (settings.get('loop') || $related[index + 1]) {
313
+ clear();
314
+ timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed'));
315
+ }
316
+ }
317
+
318
+ function start() {
319
+ $slideshow
320
+ .html(settings.get('slideshowStop'))
321
+ .unbind(click)
322
+ .one(click, stop);
323
+
324
+ $events
325
+ .bind(event_complete, set)
326
+ .bind(event_load, clear);
327
+
328
+ $box.removeClass(className + "off").addClass(className + "on");
329
+ }
330
+
331
+ function stop() {
332
+ clear();
333
+
334
+ $events
335
+ .unbind(event_complete, set)
336
+ .unbind(event_load, clear);
337
+
338
+ $slideshow
339
+ .html(settings.get('slideshowStart'))
340
+ .unbind(click)
341
+ .one(click, function () {
342
+ publicMethod.next();
343
+ start();
344
+ });
345
+
346
+ $box.removeClass(className + "on").addClass(className + "off");
347
+ }
348
+
349
+ function reset() {
350
+ active = false;
351
+ $slideshow.hide();
352
+ clear();
353
+ $events
354
+ .unbind(event_complete, set)
355
+ .unbind(event_load, clear);
356
+ $box.removeClass(className + "off " + className + "on");
357
+ }
358
+
359
+ return function(){
360
+ if (active) {
361
+ if (!settings.get('slideshow')) {
362
+ $events.unbind(event_cleanup, reset);
363
+ reset();
364
+ }
365
+ } else {
366
+ if (settings.get('slideshow') && $related[1]) {
367
+ active = true;
368
+ $events.one(event_cleanup, reset);
369
+ if (settings.get('slideshowAuto')) {
370
+ start();
371
+ } else {
372
+ stop();
373
+ }
374
+ $slideshow.show();
375
+ }
376
+ }
377
+ };
378
+
379
+ }());
380
+
381
+
382
+ function launch(element) {
383
+ var options;
384
+
385
+ if (!closing) {
386
+
387
+ options = $(element).data(colorbox);
388
+
389
+ settings = new Settings(element, options);
390
+
391
+ getRelated(settings.get('rel'));
392
+
393
+ if (!open) {
394
+ open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
395
+
396
+ setClass(settings.get('className'));
397
+
398
+ // Show colorbox so the sizes can be calculated in older versions of jQuery
399
+ $box.css({visibility:'hidden', display:'block', opacity:''});
400
+
401
+ $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden');
402
+ $content.css({width:'', height:''}).append($loaded);
403
+
404
+ // Cache values needed for size calculations
405
+ interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();
406
+ interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
407
+ loadedHeight = $loaded.outerHeight(true);
408
+ loadedWidth = $loaded.outerWidth(true);
409
+
410
+ // Opens inital empty Colorbox prior to content being loaded.
411
+ var initialWidth = setSize(settings.get('initialWidth'), 'x');
412
+ var initialHeight = setSize(settings.get('initialHeight'), 'y');
413
+ var maxWidth = settings.get('maxWidth');
414
+ var maxHeight = settings.get('maxHeight');
415
+
416
+ settings.w = Math.max((maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth, 0);
417
+ settings.h = Math.max((maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight, 0);
418
+
419
+ $loaded.css({width:'', height:settings.h});
420
+ publicMethod.position();
421
+
422
+ trigger(event_open);
423
+ settings.get('onOpen');
424
+
425
+ $groupControls.add($title).hide();
426
+
427
+ $box.focus();
428
+
429
+ if (settings.get('trapFocus')) {
430
+ // Confine focus to the modal
431
+ // Uses event capturing that is not supported in IE8-
432
+ if (document.addEventListener) {
433
+
434
+ document.addEventListener('focus', trapFocus, true);
435
+
436
+ $events.one(event_closed, function () {
437
+ document.removeEventListener('focus', trapFocus, true);
438
+ });
439
+ }
440
+ }
441
+
442
+ // Return focus on closing
443
+ if (settings.get('returnFocus')) {
444
+ $events.one(event_closed, function () {
445
+ $(settings.el).focus();
446
+ });
447
+ }
448
+ }
449
+
450
+ var opacity = parseFloat(settings.get('opacity'));
451
+ $overlay.css({
452
+ opacity: opacity === opacity ? opacity : '',
453
+ cursor: settings.get('overlayClose') ? 'pointer' : '',
454
+ visibility: 'visible'
455
+ }).show();
456
+
457
+ if (settings.get('closeButton')) {
458
+ $close.html(settings.get('close')).appendTo($content);
459
+ } else {
460
+ $close.appendTo('<div/>'); // replace with .detach() when dropping jQuery < 1.4
461
+ }
462
+
463
+ load();
464
+ }
465
+ }
466
+
467
+ // Colorbox's markup needs to be added to the DOM prior to being called
468
+ // so that the browser will go ahead and load the CSS background images.
469
+ function appendHTML() {
470
+ if (!$box) {
471
+ init = false;
472
+ $window = $(window);
473
+ $box = $tag(div).attr({
474
+ id: colorbox,
475
+ 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS.
476
+ role: 'dialog',
477
+ tabindex: '-1'
478
+ }).hide();
479
+ $overlay = $tag(div, "Overlay").hide();
480
+ $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]);
481
+ $wrap = $tag(div, "Wrapper");
482
+ $content = $tag(div, "Content").append(
483
+ $title = $tag(div, "Title"),
484
+ $current = $tag(div, "Current"),
485
+ $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}),
486
+ $next = $('<button type="button"/>').attr({id:prefix+'Next'}),
487
+ $slideshow = $('<button type="button"/>').attr({id:prefix+'Slideshow'}),
488
+ $loadingOverlay
489
+ );
490
+
491
+ $close = $('<button type="button"/>').attr({id:prefix+'Close'});
492
+
493
+ $wrap.append( // The 3x3 Grid that makes up Colorbox
494
+ $tag(div).append(
495
+ $tag(div, "TopLeft"),
496
+ $topBorder = $tag(div, "TopCenter"),
497
+ $tag(div, "TopRight")
498
+ ),
499
+ $tag(div, false, 'clear:left').append(
500
+ $leftBorder = $tag(div, "MiddleLeft"),
501
+ $content,
502
+ $rightBorder = $tag(div, "MiddleRight")
503
+ ),
504
+ $tag(div, false, 'clear:left').append(
505
+ $tag(div, "BottomLeft"),
506
+ $bottomBorder = $tag(div, "BottomCenter"),
507
+ $tag(div, "BottomRight")
508
+ )
509
+ ).find('div div').css({'float': 'left'});
510
+
511
+ $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;');
512
+
513
+ $groupControls = $next.add($prev).add($current).add($slideshow);
514
+ }
515
+ if (document.body && !$box.parent().length) {
516
+ $(document.body).append($overlay, $box.append($wrap, $loadingBay));
517
+ }
518
+ }
519
+
520
+ // Add Colorbox's event bindings
521
+ function addBindings() {
522
+ function clickHandler(e) {
523
+ // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt.
524
+ // See: http://jacklmoore.com/notes/click-events/
525
+ if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) {
526
+ e.preventDefault();
527
+ launch(this);
528
+ }
529
+ }
530
+
531
+ if ($box) {
532
+ if (!init) {
533
+ init = true;
534
+
535
+ // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly.
536
+ $next.click(function () {
537
+ publicMethod.next();
538
+ });
539
+ $prev.click(function () {
540
+ publicMethod.prev();
541
+ });
542
+ $close.click(function () {
543
+ publicMethod.close();
544
+ });
545
+ $overlay.click(function () {
546
+ if (settings.get('overlayClose')) {
547
+ publicMethod.close();
548
+ }
549
+ });
550
+
551
+ // Key Bindings
552
+ $(document).bind('keydown.' + prefix, function (e) {
553
+ var key = e.keyCode;
554
+ if (open && settings.get('escKey') && key === 27) {
555
+ e.preventDefault();
556
+ publicMethod.close();
557
+ }
558
+ if (open && settings.get('arrowKey') && $related[1] && !e.altKey) {
559
+ if (key === 37) {
560
+ e.preventDefault();
561
+ $prev.click();
562
+ } else if (key === 39) {
563
+ e.preventDefault();
564
+ $next.click();
565
+ }
566
+ }
567
+ });
568
+
569
+ if ($.isFunction($.fn.on)) {
570
+ // For jQuery 1.7+
571
+ $(document).on('click.'+prefix, '.'+boxElement, clickHandler);
572
+ } else {
573
+ // For jQuery 1.3.x -> 1.6.x
574
+ // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed.
575
+ // This is not here for jQuery 1.9, it's here for legacy users.
576
+ $('.'+boxElement).live('click.'+prefix, clickHandler);
577
+ }
578
+ }
579
+ return true;
580
+ }
581
+ return false;
582
+ }
583
+
584
+ // Don't do anything if Colorbox already exists.
585
+ if ($[colorbox]) {
586
+ return;
587
+ }
588
+
589
+ // Append the HTML when the DOM loads
590
+ $(appendHTML);
591
+
592
+
593
+ // ****************
594
+ // PUBLIC FUNCTIONS
595
+ // Usage format: $.colorbox.close();
596
+ // Usage from within an iframe: parent.jQuery.colorbox.close();
597
+ // ****************
598
+
599
+ publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
600
+ var settings;
601
+ var $obj = this;
602
+
603
+ options = options || {};
604
+
605
+ if ($.isFunction($obj)) { // assume a call to $.colorbox
606
+ $obj = $('<a/>');
607
+ options.open = true;
608
+ }
609
+
610
+ if (!$obj[0]) { // colorbox being applied to empty collection
611
+ return $obj;
612
+ }
613
+
614
+ appendHTML();
615
+
616
+ if (addBindings()) {
617
+
618
+ if (callback) {
619
+ options.onComplete = callback;
620
+ }
621
+
622
+ $obj.each(function () {
623
+ var old = $.data(this, colorbox) || {};
624
+ $.data(this, colorbox, $.extend(old, options));
625
+ }).addClass(boxElement);
626
+
627
+ settings = new Settings($obj[0], options);
628
+
629
+ if (settings.get('open')) {
630
+ launch($obj[0]);
631
+ }
632
+ }
633
+
634
+ return $obj;
635
+ };
636
+
637
+ publicMethod.position = function (speed, loadedCallback) {
638
+ var
639
+ css,
640
+ top = 0,
641
+ left = 0,
642
+ offset = $box.offset(),
643
+ scrollTop,
644
+ scrollLeft;
645
+
646
+ $window.unbind('resize.' + prefix);
647
+
648
+ // remove the modal so that it doesn't influence the document width/height
649
+ $box.css({top: -9e4, left: -9e4});
650
+
651
+ scrollTop = $window.scrollTop();
652
+ scrollLeft = $window.scrollLeft();
653
+
654
+ if (settings.get('fixed')) {
655
+ offset.top -= scrollTop;
656
+ offset.left -= scrollLeft;
657
+ $box.css({position: 'fixed'});
658
+ } else {
659
+ top = scrollTop;
660
+ left = scrollLeft;
661
+ $box.css({position: 'absolute'});
662
+ }
663
+
664
+ // keeps the top and left positions within the browser's viewport.
665
+ if (settings.get('right') !== false) {
666
+ left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.get('right'), 'x'), 0);
667
+ } else if (settings.get('left') !== false) {
668
+ left += setSize(settings.get('left'), 'x');
669
+ } else {
670
+ left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2);
671
+ }
672
+
673
+ if (settings.get('bottom') !== false) {
674
+ top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.get('bottom'), 'y'), 0);
675
+ } else if (settings.get('top') !== false) {
676
+ top += setSize(settings.get('top'), 'y');
677
+ } else {
678
+ top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2);
679
+ }
680
+
681
+ $box.css({top: offset.top, left: offset.left, visibility:'visible'});
682
+
683
+ // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
684
+ // but it has to be shrank down around the size of div#colorbox when it's done. If not,
685
+ // it can invoke an obscure IE bug when using iframes.
686
+ $wrap[0].style.width = $wrap[0].style.height = "9999px";
687
+
688
+ function modalDimensions() {
689
+ $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px';
690
+ $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px';
691
+ }
692
+
693
+ css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left};
694
+
695
+ // setting the speed to 0 if the content hasn't changed size or position
696
+ if (speed) {
697
+ var tempSpeed = 0;
698
+ $.each(css, function(i){
699
+ if (css[i] !== previousCSS[i]) {
700
+ tempSpeed = speed;
701
+ return;
702
+ }
703
+ });
704
+ speed = tempSpeed;
705
+ }
706
+
707
+ previousCSS = css;
708
+
709
+ if (!speed) {
710
+ $box.css(css);
711
+ }
712
+
713
+ $box.dequeue().animate(css, {
714
+ duration: speed || 0,
715
+ complete: function () {
716
+ modalDimensions();
717
+
718
+ active = false;
719
+
720
+ // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
721
+ $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
722
+ $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
723
+
724
+ if (settings.get('reposition')) {
725
+ setTimeout(function () { // small delay before binding onresize due to an IE8 bug.
726
+ $window.bind('resize.' + prefix, publicMethod.position);
727
+ }, 1);
728
+ }
729
+
730
+ if ($.isFunction(loadedCallback)) {
731
+ loadedCallback();
732
+ }
733
+ },
734
+ step: modalDimensions
735
+ });
736
+ };
737
+
738
+ publicMethod.resize = function (options) {
739
+ var scrolltop;
740
+
741
+ if (open) {
742
+ options = options || {};
743
+
744
+ if (options.width) {
745
+ settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
746
+ }
747
+
748
+ if (options.innerWidth) {
749
+ settings.w = setSize(options.innerWidth, 'x');
750
+ }
751
+
752
+ $loaded.css({width: settings.w});
753
+
754
+ if (options.height) {
755
+ settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
756
+ }
757
+
758
+ if (options.innerHeight) {
759
+ settings.h = setSize(options.innerHeight, 'y');
760
+ }
761
+
762
+ if (!options.innerHeight && !options.height) {
763
+ scrolltop = $loaded.scrollTop();
764
+ $loaded.css({height: "auto"});
765
+ settings.h = $loaded.height();
766
+ }
767
+
768
+ $loaded.css({height: settings.h});
769
+
770
+ if(scrolltop) {
771
+ $loaded.scrollTop(scrolltop);
772
+ }
773
+
774
+ publicMethod.position(settings.get('transition') === "none" ? 0 : settings.get('speed'));
775
+ }
776
+ };
777
+
778
+ publicMethod.prep = function (object) {
779
+ if (!open) {
780
+ return;
781
+ }
782
+
783
+ var callback, speed = settings.get('transition') === "none" ? 0 : settings.get('speed');
784
+
785
+ $loaded.remove();
786
+
787
+ $loaded = $tag(div, 'LoadedContent').append(object);
788
+
789
+ function getWidth() {
790
+ settings.w = settings.w || $loaded.width();
791
+ settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
792
+ return settings.w;
793
+ }
794
+ function getHeight() {
795
+ settings.h = settings.h || $loaded.height();
796
+ settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
797
+ return settings.h;
798
+ }
799
+
800
+ $loaded.hide()
801
+ .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
802
+ .css({width: getWidth(), overflow: settings.get('scrolling') ? 'auto' : 'hidden'})
803
+ .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
804
+ .prependTo($content);
805
+
806
+ $loadingBay.hide();
807
+
808
+ // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
809
+
810
+ $(photo).css({'float': 'none'});
811
+
812
+ setClass(settings.get('className'));
813
+
814
+ callback = function () {
815
+ var total = $related.length,
816
+ iframe,
817
+ complete;
818
+
819
+ if (!open) {
820
+ return;
821
+ }
822
+
823
+ function removeFilter() { // Needed for IE8 in versions of jQuery prior to 1.7.2
824
+ if ($.support.opacity === false) {
825
+ $box[0].style.removeAttribute('filter');
826
+ }
827
+ }
828
+
829
+ complete = function () {
830
+ clearTimeout(loadingTimer);
831
+ $loadingOverlay.hide();
832
+ trigger(event_complete);
833
+ settings.get('onComplete');
834
+ };
835
+
836
+
837
+ $title.html(settings.get('title')).show();
838
+ $loaded.show();
839
+
840
+ if (total > 1) { // handle grouping
841
+ if (typeof settings.get('current') === "string") {
842
+ $current.html(settings.get('current').replace('{current}', index + 1).replace('{total}', total)).show();
843
+ }
844
+
845
+ $next[(settings.get('loop') || index < total - 1) ? "show" : "hide"]().html(settings.get('next'));
846
+ $prev[(settings.get('loop') || index) ? "show" : "hide"]().html(settings.get('previous'));
847
+
848
+ slideshow();
849
+
850
+ // Preloads images within a rel group
851
+ if (settings.get('preloading')) {
852
+ $.each([getIndex(-1), getIndex(1)], function(){
853
+ var img,
854
+ i = $related[this],
855
+ settings = new Settings(i, $.data(i, colorbox)),
856
+ src = settings.get('href');
857
+
858
+ if (src && isImage(settings, src)) {
859
+ src = retinaUrl(settings, src);
860
+ img = document.createElement('img');
861
+ img.src = src;
862
+ }
863
+ });
864
+ }
865
+ } else {
866
+ $groupControls.hide();
867
+ }
868
+
869
+ if (settings.get('iframe')) {
870
+
871
+ iframe = settings.get('createIframe');
872
+
873
+ if (!settings.get('scrolling')) {
874
+ iframe.scrolling = "no";
875
+ }
876
+
877
+ $(iframe)
878
+ .attr({
879
+ src: settings.get('href'),
880
+ 'class': prefix + 'Iframe'
881
+ })
882
+ .one('load', complete)
883
+ .appendTo($loaded);
884
+
885
+ $events.one(event_purge, function () {
886
+ iframe.src = "//about:blank";
887
+ });
888
+
889
+ if (settings.get('fastIframe')) {
890
+ $(iframe).trigger('load');
891
+ }
892
+ } else {
893
+ complete();
894
+ }
895
+
896
+ if (settings.get('transition') === 'fade') {
897
+ $box.fadeTo(speed, 1, removeFilter);
898
+ } else {
899
+ removeFilter();
900
+ }
901
+ };
902
+
903
+ if (settings.get('transition') === 'fade') {
904
+ $box.fadeTo(speed, 0, function () {
905
+ publicMethod.position(0, callback);
906
+ });
907
+ } else {
908
+ publicMethod.position(speed, callback);
909
+ }
910
+ };
911
+
912
+ function load () {
913
+ var href, setResize, prep = publicMethod.prep, $inline, request = ++requests;
914
+
915
+ active = true;
916
+
917
+ photo = false;
918
+
919
+ trigger(event_purge);
920
+ trigger(event_load);
921
+ settings.get('onLoad');
922
+
923
+ settings.h = settings.get('height') ?
924
+ setSize(settings.get('height'), 'y') - loadedHeight - interfaceHeight :
925
+ settings.get('innerHeight') && setSize(settings.get('innerHeight'), 'y');
926
+
927
+ settings.w = settings.get('width') ?
928
+ setSize(settings.get('width'), 'x') - loadedWidth - interfaceWidth :
929
+ settings.get('innerWidth') && setSize(settings.get('innerWidth'), 'x');
930
+
931
+ // Sets the minimum dimensions for use in image scaling
932
+ settings.mw = settings.w;
933
+ settings.mh = settings.h;
934
+
935
+ // Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
936
+ // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
937
+ if (settings.get('maxWidth')) {
938
+ settings.mw = setSize(settings.get('maxWidth'), 'x') - loadedWidth - interfaceWidth;
939
+ settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
940
+ }
941
+ if (settings.get('maxHeight')) {
942
+ settings.mh = setSize(settings.get('maxHeight'), 'y') - loadedHeight - interfaceHeight;
943
+ settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
944
+ }
945
+
946
+ href = settings.get('href');
947
+
948
+ loadingTimer = setTimeout(function () {
949
+ $loadingOverlay.show();
950
+ }, 100);
951
+
952
+ if (settings.get('inline')) {
953
+ var $target = $(href).eq(0);
954
+ // Inserts an empty placeholder where inline content is being pulled from.
955
+ // An event is bound to put inline content back when Colorbox closes or loads new content.
956
+ $inline = $('<div>').hide().insertBefore($target);
957
+
958
+ $events.one(event_purge, function () {
959
+ $inline.replaceWith($target);
960
+ });
961
+
962
+ prep($target);
963
+ } else if (settings.get('iframe')) {
964
+ // IFrame element won't be added to the DOM until it is ready to be displayed,
965
+ // to avoid problems with DOM-ready JS that might be trying to run in that iframe.
966
+ prep(" ");
967
+ } else if (settings.get('html')) {
968
+ prep(settings.get('html'));
969
+ } else if (isImage(settings, href)) {
970
+
971
+ href = retinaUrl(settings, href);
972
+
973
+ photo = settings.get('createImg');
974
+
975
+ $(photo)
976
+ .addClass(prefix + 'Photo')
977
+ .bind('error.'+prefix,function () {
978
+ prep($tag(div, 'Error').html(settings.get('imgError')));
979
+ })
980
+ .one('load', function () {
981
+ if (request !== requests) {
982
+ return;
983
+ }
984
+
985
+ // A small pause because some browsers will occasionally report a
986
+ // img.width and img.height of zero immediately after the img.onload fires
987
+ setTimeout(function(){
988
+ var percent;
989
+
990
+ if (settings.get('retinaImage') && window.devicePixelRatio > 1) {
991
+ photo.height = photo.height / window.devicePixelRatio;
992
+ photo.width = photo.width / window.devicePixelRatio;
993
+ }
994
+
995
+ if (settings.get('scalePhotos')) {
996
+ setResize = function () {
997
+ photo.height -= photo.height * percent;
998
+ photo.width -= photo.width * percent;
999
+ };
1000
+ if (settings.mw && photo.width > settings.mw) {
1001
+ percent = (photo.width - settings.mw) / photo.width;
1002
+ setResize();
1003
+ }
1004
+ if (settings.mh && photo.height > settings.mh) {
1005
+ percent = (photo.height - settings.mh) / photo.height;
1006
+ setResize();
1007
+ }
1008
+ }
1009
+
1010
+ if (settings.h) {
1011
+ photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px';
1012
+ }
1013
+
1014
+ if ($related[1] && (settings.get('loop') || $related[index + 1])) {
1015
+ photo.style.cursor = 'pointer';
1016
+
1017
+ $(photo).bind('click.'+prefix, function () {
1018
+ publicMethod.next();
1019
+ });
1020
+ }
1021
+
1022
+ photo.style.width = photo.width + 'px';
1023
+ photo.style.height = photo.height + 'px';
1024
+ prep(photo);
1025
+ }, 1);
1026
+ });
1027
+
1028
+ photo.src = href;
1029
+
1030
+ } else if (href) {
1031
+ $loadingBay.load(href, settings.get('data'), function (data, status) {
1032
+ if (request === requests) {
1033
+ prep(status === 'error' ? $tag(div, 'Error').html(settings.get('xhrError')) : $(this).contents());
1034
+ }
1035
+ });
1036
+ }
1037
+ }
1038
+
1039
+ // Navigates to the next page/image in a set.
1040
+ publicMethod.next = function () {
1041
+ if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) {
1042
+ index = getIndex(1);
1043
+ launch($related[index]);
1044
+ }
1045
+ };
1046
+
1047
+ publicMethod.prev = function () {
1048
+ if (!active && $related[1] && (settings.get('loop') || index)) {
1049
+ index = getIndex(-1);
1050
+ launch($related[index]);
1051
+ }
1052
+ };
1053
+
1054
+ // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close();
1055
+ publicMethod.close = function () {
1056
+ if (open && !closing) {
1057
+
1058
+ closing = true;
1059
+ open = false;
1060
+ trigger(event_cleanup);
1061
+ settings.get('onCleanup');
1062
+ $window.unbind('.' + prefix);
1063
+ $overlay.fadeTo(settings.get('fadeOut') || 0, 0);
1064
+
1065
+ $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () {
1066
+ $box.hide();
1067
+ $overlay.hide();
1068
+ trigger(event_purge);
1069
+ $loaded.remove();
1070
+
1071
+ setTimeout(function () {
1072
+ closing = false;
1073
+ trigger(event_closed);
1074
+ settings.get('onClosed');
1075
+ }, 1);
1076
+ });
1077
+ }
1078
+ };
1079
+
1080
+ // Removes changes Colorbox made to the document, but does not remove the plugin.
1081
+ publicMethod.remove = function () {
1082
+ if (!$box) { return; }
1083
+
1084
+ $box.stop();
1085
+ $[colorbox].close();
1086
+ $box.stop(false, true).remove();
1087
+ $overlay.remove();
1088
+ closing = false;
1089
+ $box = null;
1090
+ $('.' + boxElement)
1091
+ .removeData(colorbox)
1092
+ .removeClass(boxElement);
1093
+
1094
+ $(document).unbind('click.'+prefix).unbind('keydown.'+prefix);
1095
+ };
1096
+
1097
+ // A method for fetching the current element Colorbox is referencing.
1098
+ // returns a jQuery object.
1099
+ publicMethod.element = function () {
1100
+ return $(settings.el);
1101
+ };
1102
+
1103
+ publicMethod.settings = defaults;
1104
+
1105
+ }(jQuery, document, window));
js/jquery.colorbox.min.1559237323.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(d,s,l){var c,g,u,f,p,m,w,v,x,y,b,T,C,H,h,k,r,a,W,E,I,M,L,F,R,S,K,P,B,O,_,j,n,o={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1,rel:function(){return this.rel},href:function(){return d(this).attr("href")},title:function(){return this.title},createImg:function(){var i=new Image,t=d(this).data("cbox-img-attrs");return"object"==typeof t&&d.each(t,function(t,e){i[t]=e}),i},createIframe:function(){var i=s.createElement("iframe"),t=d(this).data("cbox-iframe-attrs");return"object"==typeof t&&d.each(t,function(t,e){i[t]=e}),"frameBorder"in i&&(i.frameBorder=0),"allowTransparency"in i&&(i.allowTransparency="true"),i.name=(new Date).getTime(),i.allowFullscreen=!0,i}},D="wflscolorbox",N="wflscbox",z=N+"Element",A=N+"_open",q=N+"_load",U=N+"_complete",$=N+"_cleanup",G=N+"_closed",Q=N+"_purge",J=d("<a/>"),V="div",X=0,Y={};function Z(t,e,i){var n=s.createElement(t);return e&&(n.id=N+e),i&&(n.style.cssText=i),d(n)}function tt(){return l.innerHeight?l.innerHeight:d(l).height()}function et(t,i){i!==Object(i)&&(i={}),this.cache={},this.el=t,this.value=function(t){var e;return void 0===this.cache[t]&&(void 0!==(e=d(this.el).attr("data-cbox-"+t))?this.cache[t]=e:void 0!==i[t]?this.cache[t]=i[t]:void 0!==o[t]&&(this.cache[t]=o[t])),this.cache[t]},this.get=function(t){var e=this.value(t);return d.isFunction(e)?e.call(this.el,this):e}}function it(t){var e=x.length,i=(S+t)%e;return i<0?e+i:i}function nt(t,e){return Math.round((/%/.test(t)?("x"===e?y.width():tt())/100:1)*parseInt(t,10))}function ot(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function ht(t,e){return t.get("retinaUrl")&&1<l.devicePixelRatio?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function rt(t){"contains"in g[0]&&!g[0].contains(t.target)&&t.target!==c[0]&&(t.stopPropagation(),g.focus())}function at(t){at.str!==t&&(g.add(c).removeClass(at.str).addClass(t),at.str=t)}function st(t){d(s).trigger(t),J.triggerHandler(t)}var lt=function(){var t,e,i=N+"Slideshow_",n="click."+N;function o(){clearTimeout(e)}function h(){(I.get("loop")||x[S+1])&&(o(),e=setTimeout(j.next,I.get("slideshowSpeed")))}function r(){k.html(I.get("slideshowStop")).unbind(n).one(n,a),J.bind(U,h).bind(q,o),g.removeClass(i+"off").addClass(i+"on")}function a(){o(),J.unbind(U,h).unbind(q,o),k.html(I.get("slideshowStart")).unbind(n).one(n,function(){j.next(),r()}),g.removeClass(i+"on").addClass(i+"off")}function s(){t=!1,k.hide(),o(),J.unbind(U,h).unbind(q,o),g.removeClass(i+"off "+i+"on")}return function(){t?I.get("slideshow")||(J.unbind($,s),s()):I.get("slideshow")&&x[1]&&(t=!0,J.one($,s),I.get("slideshowAuto")?r():a(),k.show())}}();function dt(t){var e,i;if(!O){if(e=d(t).data(D),I=new et(t,e),i=I.get("rel"),S=0,i&&!1!==i&&"nofollow"!==i?(x=d("."+z).filter(function(){return new et(this,d.data(this,D)).get("rel")===i}),-1===(S=x.index(I.el))&&(x=x.add(I.el),S=x.length-1)):x=d(I.el),!P){P=B=!0,at(I.get("className")),g.css({visibility:"hidden",display:"block",opacity:""}),b=Z(V,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),f.css({width:"",height:""}).append(b),M=p.height()+v.height()+f.outerHeight(!0)-f.height(),L=m.width()+w.width()+f.outerWidth(!0)-f.width(),F=b.outerHeight(!0),R=b.outerWidth(!0);var n=nt(I.get("initialWidth"),"x"),o=nt(I.get("initialHeight"),"y"),h=I.get("maxWidth"),r=I.get("maxHeight");I.w=Math.max((!1!==h?Math.min(n,nt(h,"x")):n)-R-L,0),I.h=Math.max((!1!==r?Math.min(o,nt(r,"y")):o)-F-M,0),b.css({width:"",height:I.h}),j.position(),st(A),I.get("onOpen"),E.add(H).hide(),g.focus(),I.get("trapFocus")&&s.addEventListener&&(s.addEventListener("focus",rt,!0),J.one(G,function(){s.removeEventListener("focus",rt,!0)})),I.get("returnFocus")&&J.one(G,function(){d(I.el).focus()})}var a=parseFloat(I.get("opacity"));c.css({opacity:a==a?a:"",cursor:I.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),I.get("closeButton")?W.html(I.get("close")).appendTo(f):W.appendTo("<div/>"),function(){var t,e,i,n=j.prep,o=++X;K=!(B=!0),st(Q),st(q),I.get("onLoad"),I.h=I.get("height")?nt(I.get("height"),"y")-F-M:I.get("innerHeight")&&nt(I.get("innerHeight"),"y"),I.w=I.get("width")?nt(I.get("width"),"x")-R-L:I.get("innerWidth")&&nt(I.get("innerWidth"),"x"),I.mw=I.w,I.mh=I.h,I.get("maxWidth")&&(I.mw=nt(I.get("maxWidth"),"x")-R-L,I.mw=I.w&&I.w<I.mw?I.w:I.mw);I.get("maxHeight")&&(I.mh=nt(I.get("maxHeight"),"y")-F-M,I.mh=I.h&&I.h<I.mh?I.h:I.mh);if(t=I.get("href"),_=setTimeout(function(){C.show()},100),I.get("inline")){var h=d(t).eq(0);i=d("<div>").hide().insertBefore(h),J.one(Q,function(){i.replaceWith(h)}),n(h)}else I.get("iframe")?n(" "):I.get("html")?n(I.get("html")):ot(I,t)?(t=ht(I,t),K=I.get("createImg"),d(K).addClass(N+"Photo").bind("error."+N,function(){n(Z(V,"Error").html(I.get("imgError")))}).one("load",function(){o===X&&setTimeout(function(){var t;I.get("retinaImage")&&1<l.devicePixelRatio&&(K.height=K.height/l.devicePixelRatio,K.width=K.width/l.devicePixelRatio),I.get("scalePhotos")&&(e=function(){K.height-=K.height*t,K.width-=K.width*t},I.mw&&K.width>I.mw&&(t=(K.width-I.mw)/K.width,e()),I.mh&&K.height>I.mh&&(t=(K.height-I.mh)/K.height,e())),I.h&&(K.style.marginTop=Math.max(I.mh-K.height,0)/2+"px"),x[1]&&(I.get("loop")||x[S+1])&&(K.style.cursor="pointer",d(K).bind("click."+N,function(){j.next()})),K.style.width=K.width+"px",K.style.height=K.height+"px",n(K)},1)}),K.src=t):t&&T.load(t,I.get("data"),function(t,e){o===X&&n("error"===e?Z(V,"Error").html(I.get("xhrError")):d(this).contents())})}()}}function ct(){g||(n=!1,y=d(l),g=Z(V).attr({id:D,class:!1===d.support.opacity?N+"IE":"",role:"dialog",tabindex:"-1"}).hide(),c=Z(V,"Overlay").hide(),C=d([Z(V,"LoadingOverlay")[0],Z(V,"LoadingGraphic")[0]]),u=Z(V,"Wrapper"),f=Z(V,"Content").append(H=Z(V,"Title"),h=Z(V,"Current"),a=d('<button type="button"/>').attr({id:N+"Previous"}),r=d('<button type="button"/>').attr({id:N+"Next"}),k=d('<button type="button"/>').attr({id:N+"Slideshow"}),C),W=d('<button type="button"/>').attr({id:N+"Close"}),u.append(Z(V).append(Z(V,"TopLeft"),p=Z(V,"TopCenter"),Z(V,"TopRight")),Z(V,!1,"clear:left").append(m=Z(V,"MiddleLeft"),f,w=Z(V,"MiddleRight")),Z(V,!1,"clear:left").append(Z(V,"BottomLeft"),v=Z(V,"BottomCenter"),Z(V,"BottomRight"))).find("div div").css({float:"left"}),T=Z(V,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),E=r.add(a).add(h).add(k)),s.body&&!g.parent().length&&d(s.body).append(c,g.append(u,T))}d[D]||(d(ct),(j=d.fn[D]=d[D]=function(e,t){var i=this;return e=e||{},d.isFunction(i)&&(i=d("<a/>"),e.open=!0),i[0]&&(ct(),function(){function t(t){1<t.which||t.shiftKey||t.altKey||t.metaKey||t.ctrlKey||(t.preventDefault(),dt(this))}return!!g&&(n||(n=!0,r.click(function(){j.next()}),a.click(function(){j.prev()}),W.click(function(){j.close()}),c.click(function(){I.get("overlayClose")&&j.close()}),d(s).bind("keydown."+N,function(t){var e=t.keyCode;P&&I.get("escKey")&&27===e&&(t.preventDefault(),j.close()),P&&I.get("arrowKey")&&x[1]&&!t.altKey&&(37===e?(t.preventDefault(),a.click()):39===e&&(t.preventDefault(),r.click()))}),d.isFunction(d.fn.on)?d(s).on("click."+N,"."+z,t):d("."+z).live("click."+N,t)),!0)}()&&(t&&(e.onComplete=t),i.each(function(){var t=d.data(this,D)||{};d.data(this,D,d.extend(t,e))}).addClass(z),new et(i[0],e).get("open")&&dt(i[0]))),i}).position=function(e,t){var i,n,o,h=0,r=0,a=g.offset();function s(){p[0].style.width=v[0].style.width=f[0].style.width=parseInt(g[0].style.width,10)-L+"px",f[0].style.height=m[0].style.height=w[0].style.height=parseInt(g[0].style.height,10)-M+"px"}if(y.unbind("resize."+N),g.css({top:-9e4,left:-9e4}),n=y.scrollTop(),o=y.scrollLeft(),I.get("fixed")?(a.top-=n,a.left-=o,g.css({position:"fixed"})):(h=n,r=o,g.css({position:"absolute"})),!1!==I.get("right")?r+=Math.max(y.width()-I.w-R-L-nt(I.get("right"),"x"),0):!1!==I.get("left")?r+=nt(I.get("left"),"x"):r+=Math.round(Math.max(y.width()-I.w-R-L,0)/2),!1!==I.get("bottom")?h+=Math.max(tt()-I.h-F-M-nt(I.get("bottom"),"y"),0):!1!==I.get("top")?h+=nt(I.get("top"),"y"):h+=Math.round(Math.max(tt()-I.h-F-M,0)/2),g.css({top:a.top,left:a.left,visibility:"visible"}),u[0].style.width=u[0].style.height="9999px",i={width:I.w+R+L,height:I.h+F+M,top:h,left:r},e){var l=0;d.each(i,function(t){i[t]===Y[t]||(l=e)}),e=l}Y=i,e||g.css(i),g.dequeue().animate(i,{duration:e||0,complete:function(){s(),B=!1,u[0].style.width=I.w+R+L+"px",u[0].style.height=I.h+F+M+"px",I.get("reposition")&&setTimeout(function(){y.bind("resize."+N,j.position)},1),d.isFunction(t)&&t()},step:s})},j.resize=function(t){var e;P&&((t=t||{}).width&&(I.w=nt(t.width,"x")-R-L),t.innerWidth&&(I.w=nt(t.innerWidth,"x")),b.css({width:I.w}),t.height&&(I.h=nt(t.height,"y")-F-M),t.innerHeight&&(I.h=nt(t.innerHeight,"y")),t.innerHeight||t.height||(e=b.scrollTop(),b.css({height:"auto"}),I.h=b.height()),b.css({height:I.h}),e&&b.scrollTop(e),j.position("none"===I.get("transition")?0:I.get("speed")))},j.prep=function(t){if(P){var e,o="none"===I.get("transition")?0:I.get("speed");b.remove(),(b=Z(V,"LoadedContent").append(t)).hide().appendTo(T.show()).css({width:(I.w=I.w||b.width(),I.w=I.mw&&I.mw<I.w?I.mw:I.w,I.w),overflow:I.get("scrolling")?"auto":"hidden"}).css({height:(I.h=I.h||b.height(),I.h=I.mh&&I.mh<I.h?I.mh:I.h,I.h)}).prependTo(f),T.hide(),d(K).css({float:"none"}),at(I.get("className")),e=function(){var t,e,i=x.length;function n(){!1===d.support.opacity&&g[0].style.removeAttribute("filter")}P&&(e=function(){clearTimeout(_),C.hide(),st(U),I.get("onComplete")},H.html(I.get("title")).show(),b.show(),1<i?("string"==typeof I.get("current")&&h.html(I.get("current").replace("{current}",S+1).replace("{total}",i)).show(),r[I.get("loop")||S<i-1?"show":"hide"]().html(I.get("next")),a[I.get("loop")||S?"show":"hide"]().html(I.get("previous")),lt(),I.get("preloading")&&d.each([it(-1),it(1)],function(){var t=x[this],e=new et(t,d.data(t,D)),i=e.get("href");i&&ot(e,i)&&(i=ht(e,i),s.createElement("img").src=i)})):E.hide(),I.get("iframe")?(t=I.get("createIframe"),I.get("scrolling")||(t.scrolling="no"),d(t).attr({src:I.get("href"),class:N+"Iframe"}).one("load",e).appendTo(b),J.one(Q,function(){t.src="//about:blank"}),I.get("fastIframe")&&d(t).trigger("load")):e(),"fade"===I.get("transition")?g.fadeTo(o,1,n):n())},"fade"===I.get("transition")?g.fadeTo(o,0,function(){j.position(0,e)}):j.position(o,e)}},j.next=function(){!B&&x[1]&&(I.get("loop")||x[S+1])&&(S=it(1),dt(x[S]))},j.prev=function(){!B&&x[1]&&(I.get("loop")||S)&&(S=it(-1),dt(x[S]))},j.close=function(){P&&!O&&(P=!(O=!0),st($),I.get("onCleanup"),y.unbind("."+N),c.fadeTo(I.get("fadeOut")||0,0),g.stop().fadeTo(I.get("fadeOut")||0,0,function(){g.hide(),c.hide(),st(Q),b.remove(),setTimeout(function(){O=!1,st(G),I.get("onClosed")},1)}))},j.remove=function(){g&&(g.stop(),d[D].close(),g.stop(!1,!0).remove(),c.remove(),O=!1,g=null,d("."+z).removeData(D).removeClass(z),d(s).unbind("click."+N).unbind("keydown."+N))},j.element=function(){return d(I.el)},j.settings=o)}(jQuery,document,window);
js/jquery.qrcode.min.1559237323.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(r){r.fn.qrcode=function(h){var s;function u(a){this.mode=s;this.data=a}function o(a,c){this.typeNumber=a;this.errorCorrectLevel=c;this.modules=null;this.moduleCount=0;this.dataCache=null;this.dataList=[]}function q(a,c){if(void 0==a.length)throw Error(a.length+"/"+c);for(var d=0;d<a.length&&0==a[d];)d++;this.num=Array(a.length-d+c);for(var b=0;b<a.length-d;b++)this.num[b]=a[b+d]}function p(a,c){this.totalCount=a;this.dataCount=c}function t(){this.buffer=[];this.length=0}u.prototype={getLength:function(){return this.data.length},
2
+ write:function(a){for(var c=0;c<this.data.length;c++)a.put(this.data.charCodeAt(c),8)}};o.prototype={addData:function(a){this.dataList.push(new u(a));this.dataCache=null},isDark:function(a,c){if(0>a||this.moduleCount<=a||0>c||this.moduleCount<=c)throw Error(a+","+c);return this.modules[a][c]},getModuleCount:function(){return this.moduleCount},make:function(){if(1>this.typeNumber){for(var a=1,a=1;40>a;a++){for(var c=p.getRSBlocks(a,this.errorCorrectLevel),d=new t,b=0,e=0;e<c.length;e++)b+=c[e].dataCount;
3
+ for(e=0;e<this.dataList.length;e++)c=this.dataList[e],d.put(c.mode,4),d.put(c.getLength(),j.getLengthInBits(c.mode,a)),c.write(d);if(d.getLengthInBits()<=8*b)break}this.typeNumber=a}this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17;this.modules=Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=Array(this.moduleCount);for(var b=0;b<this.moduleCount;b++)this.modules[d][b]=null}this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-
4
+ 7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(a,c);7<=this.typeNumber&&this.setupTypeNumber(a);null==this.dataCache&&(this.dataCache=o.createData(this.typeNumber,this.errorCorrectLevel,this.dataList));this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,c){for(var d=-1;7>=d;d++)if(!(-1>=a+d||this.moduleCount<=a+d))for(var b=-1;7>=b;b++)-1>=c+b||this.moduleCount<=c+b||(this.modules[a+d][c+b]=
5
+ 0<=d&&6>=d&&(0==b||6==b)||0<=b&&6>=b&&(0==d||6==d)||2<=d&&4>=d&&2<=b&&4>=b?!0:!1)},getBestMaskPattern:function(){for(var a=0,c=0,d=0;8>d;d++){this.makeImpl(!0,d);var b=j.getLostPoint(this);if(0==d||a>b)a=b,c=d}return c},createMovieClip:function(a,c,d){a=a.createEmptyMovieClip(c,d);this.make();for(c=0;c<this.modules.length;c++)for(var d=1*c,b=0;b<this.modules[c].length;b++){var e=1*b;this.modules[c][b]&&(a.beginFill(0,100),a.moveTo(e,d),a.lineTo(e+1,d),a.lineTo(e+1,d+1),a.lineTo(e,d+1),a.endFill())}return a},
6
+ setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(a=8;a<this.moduleCount-8;a++)null==this.modules[6][a]&&(this.modules[6][a]=0==a%2)},setupPositionAdjustPattern:function(){for(var a=j.getPatternPosition(this.typeNumber),c=0;c<a.length;c++)for(var d=0;d<a.length;d++){var b=a[c],e=a[d];if(null==this.modules[b][e])for(var f=-2;2>=f;f++)for(var i=-2;2>=i;i++)this.modules[b+f][e+i]=-2==f||2==f||-2==i||2==i||0==f&&0==i?!0:!1}},setupTypeNumber:function(a){for(var c=
7
+ j.getBCHTypeNumber(this.typeNumber),d=0;18>d;d++){var b=!a&&1==(c>>d&1);this.modules[Math.floor(d/3)][d%3+this.moduleCount-8-3]=b}for(d=0;18>d;d++)b=!a&&1==(c>>d&1),this.modules[d%3+this.moduleCount-8-3][Math.floor(d/3)]=b},setupTypeInfo:function(a,c){for(var d=j.getBCHTypeInfo(this.errorCorrectLevel<<3|c),b=0;15>b;b++){var e=!a&&1==(d>>b&1);6>b?this.modules[b][8]=e:8>b?this.modules[b+1][8]=e:this.modules[this.moduleCount-15+b][8]=e}for(b=0;15>b;b++)e=!a&&1==(d>>b&1),8>b?this.modules[8][this.moduleCount-
8
+ b-1]=e:9>b?this.modules[8][15-b-1+1]=e:this.modules[8][15-b-1]=e;this.modules[this.moduleCount-8][8]=!a},mapData:function(a,c){for(var d=-1,b=this.moduleCount-1,e=7,f=0,i=this.moduleCount-1;0<i;i-=2)for(6==i&&i--;;){for(var g=0;2>g;g++)if(null==this.modules[b][i-g]){var n=!1;f<a.length&&(n=1==(a[f]>>>e&1));j.getMask(c,b,i-g)&&(n=!n);this.modules[b][i-g]=n;e--; -1==e&&(f++,e=7)}b+=d;if(0>b||this.moduleCount<=b){b-=d;d=-d;break}}}};o.PAD0=236;o.PAD1=17;o.createData=function(a,c,d){for(var c=p.getRSBlocks(a,
9
+ c),b=new t,e=0;e<d.length;e++){var f=d[e];b.put(f.mode,4);b.put(f.getLength(),j.getLengthInBits(f.mode,a));f.write(b)}for(e=a=0;e<c.length;e++)a+=c[e].dataCount;if(b.getLengthInBits()>8*a)throw Error("code length overflow. ("+b.getLengthInBits()+">"+8*a+")");for(b.getLengthInBits()+4<=8*a&&b.put(0,4);0!=b.getLengthInBits()%8;)b.putBit(!1);for(;!(b.getLengthInBits()>=8*a);){b.put(o.PAD0,8);if(b.getLengthInBits()>=8*a)break;b.put(o.PAD1,8)}return o.createBytes(b,c)};o.createBytes=function(a,c){for(var d=
10
+ 0,b=0,e=0,f=Array(c.length),i=Array(c.length),g=0;g<c.length;g++){var n=c[g].dataCount,h=c[g].totalCount-n,b=Math.max(b,n),e=Math.max(e,h);f[g]=Array(n);for(var k=0;k<f[g].length;k++)f[g][k]=255&a.buffer[k+d];d+=n;k=j.getErrorCorrectPolynomial(h);n=(new q(f[g],k.getLength()-1)).mod(k);i[g]=Array(k.getLength()-1);for(k=0;k<i[g].length;k++)h=k+n.getLength()-i[g].length,i[g][k]=0<=h?n.get(h):0}for(k=g=0;k<c.length;k++)g+=c[k].totalCount;d=Array(g);for(k=n=0;k<b;k++)for(g=0;g<c.length;g++)k<f[g].length&&
11
+ (d[n++]=f[g][k]);for(k=0;k<e;k++)for(g=0;g<c.length;g++)k<i[g].length&&(d[n++]=i[g][k]);return d};s=4;for(var j={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,
12
+ 78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var c=a<<10;0<=j.getBCHDigit(c)-j.getBCHDigit(j.G15);)c^=j.G15<<j.getBCHDigit(c)-j.getBCHDigit(j.G15);return(a<<10|c)^j.G15_MASK},getBCHTypeNumber:function(a){for(var c=a<<12;0<=j.getBCHDigit(c)-
13
+ j.getBCHDigit(j.G18);)c^=j.G18<<j.getBCHDigit(c)-j.getBCHDigit(j.G18);return a<<12|c},getBCHDigit:function(a){for(var c=0;0!=a;)c++,a>>>=1;return c},getPatternPosition:function(a){return j.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,c,d){switch(a){case 0:return 0==(c+d)%2;case 1:return 0==c%2;case 2:return 0==d%3;case 3:return 0==(c+d)%3;case 4:return 0==(Math.floor(c/2)+Math.floor(d/3))%2;case 5:return 0==c*d%2+c*d%3;case 6:return 0==(c*d%2+c*d%3)%2;case 7:return 0==(c*d%3+(c+d)%2)%2;default:throw Error("bad maskPattern:"+
14
+ a);}},getErrorCorrectPolynomial:function(a){for(var c=new q([1],0),d=0;d<a;d++)c=c.multiply(new q([1,l.gexp(d)],0));return c},getLengthInBits:function(a,c){if(1<=c&&10>c)switch(a){case 1:return 10;case 2:return 9;case s:return 8;case 8:return 8;default:throw Error("mode:"+a);}else if(27>c)switch(a){case 1:return 12;case 2:return 11;case s:return 16;case 8:return 10;default:throw Error("mode:"+a);}else if(41>c)switch(a){case 1:return 14;case 2:return 13;case s:return 16;case 8:return 12;default:throw Error("mode:"+
15
+ a);}else throw Error("type:"+c);},getLostPoint:function(a){for(var c=a.getModuleCount(),d=0,b=0;b<c;b++)for(var e=0;e<c;e++){for(var f=0,i=a.isDark(b,e),g=-1;1>=g;g++)if(!(0>b+g||c<=b+g))for(var h=-1;1>=h;h++)0>e+h||c<=e+h||0==g&&0==h||i==a.isDark(b+g,e+h)&&f++;5<f&&(d+=3+f-5)}for(b=0;b<c-1;b++)for(e=0;e<c-1;e++)if(f=0,a.isDark(b,e)&&f++,a.isDark(b+1,e)&&f++,a.isDark(b,e+1)&&f++,a.isDark(b+1,e+1)&&f++,0==f||4==f)d+=3;for(b=0;b<c;b++)for(e=0;e<c-6;e++)a.isDark(b,e)&&!a.isDark(b,e+1)&&a.isDark(b,e+
16
+ 2)&&a.isDark(b,e+3)&&a.isDark(b,e+4)&&!a.isDark(b,e+5)&&a.isDark(b,e+6)&&(d+=40);for(e=0;e<c;e++)for(b=0;b<c-6;b++)a.isDark(b,e)&&!a.isDark(b+1,e)&&a.isDark(b+2,e)&&a.isDark(b+3,e)&&a.isDark(b+4,e)&&!a.isDark(b+5,e)&&a.isDark(b+6,e)&&(d+=40);for(e=f=0;e<c;e++)for(b=0;b<c;b++)a.isDark(b,e)&&f++;a=Math.abs(100*f/c/c-50)/5;return d+10*a}},l={glog:function(a){if(1>a)throw Error("glog("+a+")");return l.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;256<=a;)a-=255;return l.EXP_TABLE[a]},EXP_TABLE:Array(256),
17
+ LOG_TABLE:Array(256)},m=0;8>m;m++)l.EXP_TABLE[m]=1<<m;for(m=8;256>m;m++)l.EXP_TABLE[m]=l.EXP_TABLE[m-4]^l.EXP_TABLE[m-5]^l.EXP_TABLE[m-6]^l.EXP_TABLE[m-8];for(m=0;255>m;m++)l.LOG_TABLE[l.EXP_TABLE[m]]=m;q.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var c=Array(this.getLength()+a.getLength()-1),d=0;d<this.getLength();d++)for(var b=0;b<a.getLength();b++)c[d+b]^=l.gexp(l.glog(this.get(d))+l.glog(a.get(b)));return new q(c,0)},mod:function(a){if(0>
18
+ this.getLength()-a.getLength())return this;for(var c=l.glog(this.get(0))-l.glog(a.get(0)),d=Array(this.getLength()),b=0;b<this.getLength();b++)d[b]=this.get(b);for(b=0;b<a.getLength();b++)d[b]^=l.gexp(l.glog(a.get(b))+c);return(new q(d,0)).mod(a)}};p.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],
19
+ [4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,
20
+ 116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,
21
+ 43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,
22
+ 3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,
23
+ 55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,
24
+ 45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];p.getRSBlocks=function(a,c){var d=p.getRsBlockTable(a,c);if(void 0==d)throw Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+c);for(var b=d.length/3,e=[],f=0;f<b;f++)for(var h=d[3*f+0],g=d[3*f+1],j=d[3*f+2],l=0;l<h;l++)e.push(new p(g,j));return e};p.getRsBlockTable=function(a,c){switch(c){case 1:return p.RS_BLOCK_TABLE[4*(a-1)+0];case 0:return p.RS_BLOCK_TABLE[4*(a-1)+1];case 3:return p.RS_BLOCK_TABLE[4*
25
+ (a-1)+2];case 2:return p.RS_BLOCK_TABLE[4*(a-1)+3]}};t.prototype={get:function(a){return 1==(this.buffer[Math.floor(a/8)]>>>7-a%8&1)},put:function(a,c){for(var d=0;d<c;d++)this.putBit(1==(a>>>c-d-1&1))},getLengthInBits:function(){return this.length},putBit:function(a){var c=Math.floor(this.length/8);this.buffer.length<=c&&this.buffer.push(0);a&&(this.buffer[c]|=128>>>this.length%8);this.length++}};"string"===typeof h&&(h={text:h});h=r.extend({},{render:"canvas",width:256,height:256,typeNumber:-1,
26
+ correctLevel:2,background:"#ffffff",foreground:"#000000"},h);return this.each(function(){var a;if("canvas"==h.render){a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();var c=document.createElement("canvas");c.width=h.width;c.height=h.height;for(var d=c.getContext("2d"),b=h.width/a.getModuleCount(),e=h.height/a.getModuleCount(),f=0;f<a.getModuleCount();f++)for(var i=0;i<a.getModuleCount();i++){d.fillStyle=a.isDark(f,i)?h.foreground:h.background;var g=Math.ceil((i+1)*b)-Math.floor(i*b),
27
+ j=Math.ceil((f+1)*b)-Math.floor(f*b);d.fillRect(Math.round(i*b),Math.round(f*e),g,j)}}else{a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();c=r("<table></table>").css("width",h.width+"px").css("height",h.height+"px").css("border","0px").css("border-collapse","collapse").css("background-color",h.background);d=h.width/a.getModuleCount();b=h.height/a.getModuleCount();for(e=0;e<a.getModuleCount();e++){f=r("<tr></tr>").css("height",b+"px").appendTo(c);for(i=0;i<a.getModuleCount();i++)r("<td></td>").css("width",
28
+ d+"px").css("background-color",a.isDark(e,i)?h.foreground:h.background).appendTo(f)}}a=c;jQuery(a).appendTo(this)})}})(jQuery);
js/jquery.tmpl.min.1559237323.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery Templates Plugin 1.0.0pre
3
+ * http://github.com/jquery/jquery-tmpl
4
+ * Requires jQuery 1.4.2
5
+ *
6
+ * Copyright Software Freedom Conservancy, Inc.
7
+ * Dual licensed under the MIT or GPL Version 2 licenses.
8
+ * http://jquery.org/license
9
+ */
10
+ (function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},i=0,c=0,l=[];function g(g,d,h,e){var c={data:e||(e===0||e===false)?e:d?d.data:{},_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};g&&a.extend(c,g,{nodes:[],parent:d});if(h){c.tmpl=h;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++i;(l.length?f:b)[i]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h<m;h++){c=h;k=(h>0?this.clone(true):this).get();a(i[h])[d](k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,m,k){if(d[0]&&a.isArray(d[0])){var g=a.makeArray(arguments),h=d[0],j=h.length,i=0,f;while(i<j&&!(f=a.data(h[i++],"tmplItem")));if(f&&c)g[2]=function(b){a.tmpl.afterManip(this,b,k)};r.apply(this,g)}else r.apply(this,arguments);c=0;!e&&a.tmpl.complete(b);return this}});a.extend({tmpl:function(d,h,e,c){var i,k=!c;if(k){c=p;d=a.template[d]||a.template(null,d);f={}}else if(!d){d=c.tmpl;b[c.key]=c;c.nodes=[];c.wrapped&&n(c,c.wrapped);return a(j(c,null,c.tmpl(a,c)))}if(!d)return[];if(typeof h==="function")h=h.call(c||{});e&&e.wrapped&&n(e,e.wrapped);i=a.isArray(h)?a.map(h,function(a){return a?g(e,c,d,a):null}):[g(e,c,d,h)];return k?a(j(c,null,i)):i},tmplItem:function(b){var c;if(b instanceof a)b=b[0];while(b&&b.nodeType===1&&!(c=a.data(b,"tmplItem"))&&(b=b.parentNode));return c||p},template:function(c,b){if(b){if(typeof b==="string")b=o(b);else if(b instanceof a)b=b[0]||{};if(b.nodeType)b=a.data(b,"tmpl")||a.data(b,"tmpl",o(b.innerHTML));return typeof c==="string"?(a.template[c]=b):b}return c?typeof c!=="string"?a.template(null,c):a.template[c]||a.template(null,q.test(c)?c:a(c)):null},encode:function(a){return(""+a).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){__=__.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(__,$1,$2);__=[];",close:"call=$item.calls();__=call._.concat($item.wrap(call,__));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){__.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){__.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function j(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:j(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=k(c).concat(b);if(d)b=b.concat(k(d))});return b?b:k(c)}function k(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,__=[],$data=$item.data;with($data){__.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,k,g,b,c,d){var j=a.tmpl.tag[k],i,e,f;if(!j)throw"Unknown template tag: "+k;i=j._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=h(b);d=d?","+h(d)+")":c?")":"";e=c?b.indexOf(".")>-1?b+h(c):"("+b+").call($item"+d:b;f=c?e:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else f=e=i.$1||"null";g=h(g);return"');"+j[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(f).split("$1").join(e).split("$2").join(g||i.$2||"")+"__.push('"})+"');}return __;")}function n(c,b){c._wrap=j(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function h(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,h;for(e=0,p=o.length;e<p;e++){if((k=o[e]).nodeType!==1)continue;j=k.getElementsByTagName("*");for(h=j.length-1;h>=0;h--)m(j[h]);m(k)}function m(j){var p,h=j,k,e,m;if(m=j.getAttribute(d)){while(h.parentNode&&(h=h.parentNode).nodeType===1&&!(p=h.getAttribute(d)));if(p!==m){h=h.parentNode?h.nodeType===11?0:h.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[h]||f[h]);e.key=++i;b[i]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;h=a.data(j.parentNode,"tmplItem");h=h?h.key:0}if(e){k=e;while(k&&k.key!=h){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery);
js/login.1559237323.js ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ !function(Z){"use strict";Z.Zebra_Tooltips=function(t,l){var u,T,b,v,n={animation_speed:250,animation_offset:20,close_on_click:!0,content:!(this.version="2.1.0"),hide_delay:100,keep_visible:!0,max_width:250,opacity:".95",position:"center",prerender:!1,show_delay:100,vertical_alignment:"above",vertical_offset:0,onBeforeHide:null,onHide:null,onBeforeShow:null,onShow:null},r=this,_=function(e){var t,o,i,a,l,n,r,_,s,p,d,h,c,f,w=e.data("Zebra_Tooltip"),m=Z(window);return w.tooltip||(t=Z("<div>",{"class":"Zebra_Tooltip",css:{opacity:0,display:"block"}}),o=Z("<div>",{"class":"Zebra_Tooltip_Message",css:{maxWidth:w.max_width}}).html(w.content).appendTo(t),i=Z("<div>",{"class":"Zebra_Tooltip_Arrow"}).appendTo(t),a=Z("<div>").addClass("Zebra_Tooltip_Arrow_Border").appendTo(i),Z("<div>").appendTo(i),w.keep_visible&&(t.on("mouseleave"+(w.close_on_click?" click":""),function(){y(e)}),t.on("mouseenter",function(){g(e)})),t.appendTo("body"),w.sticky&&o.addClass("Zebra_Tooltip_Has_Close"),l=t.outerWidth(),n=t.outerHeight(),r=a.outerWidth(),_=a.outerHeight(),s=o.outerWidth(),p=o.outerHeight(),w={tooltip:t,tooltip_width:l,tooltip_height:n+_/2,message:o,arrow_container:i,arrow_width:r,arrow_height:_,arrow:a},t.css({width:w.tooltip_width,height:w.tooltip_height}),w.tooltip_width=w.tooltip_width+(o.outerWidth()-s),w.tooltip_height=w.tooltip_height+(o.outerHeight()-p),t.css({width:w.tooltip_width,height:w.tooltip_height,display:"none"}),w=Z.extend(e.data("Zebra_Tooltip"),w),e.data("Zebra_Tooltip",w)),w.sticky&&!w.close&&(Z("<a>",{"class":"Zebra_Tooltip_Close",href:"javascript:void(0)"}).html("&times;").on("click",function(t){t.preventDefault();var o=e.data("Zebra_Tooltip");o.sticky=!1,e.data("Zebra_Tooltip",o),y(e)}).appendTo(w.message),w.close=!0,w=Z.extend(e.data("Zebra_Tooltip"),w),e.data("Zebra_Tooltip",w)),u=m.width(),T=m.height(),d=e.offset(),Z.extend(w,{element_left:d.left,element_top:d.top,element_width:e.outerWidth(),element_height:e.outerHeight()}),v=m.scrollTop(),b=m.scrollLeft(),h="left"===w.position?w.element_left-w.tooltip_width+w.arrow_width:"right"===w.position?w.element_left+w.element_width-w.arrow_width:w.element_left+(w.element_width-w.tooltip_width)/2,c=w.element_top-w.tooltip_height,f="left"===w.position?w.tooltip_width-w.arrow_width-w.arrow_width/2:"right"===w.position?w.arrow_width/2:(w.tooltip_width-w.arrow_width)/2,h+w.tooltip_width>u+b&&(f-=u+b-(h+w.tooltip_width)-6,h=u+b-w.tooltip_width-6,f+w.arrow_width>w.tooltip_width-6&&(f=w.tooltip_width-6-w.arrow_width),h+f+w.arrow_width/2<w.element_left&&(f=-1e4)),h<b&&(f-=b-h,h=b+2,f<0&&(f=w.arrow_width/2),h+f+w.arrow_width/2>w.element_left+w.element_width&&(f=-1e4)),w.message.css("margin-top",""),w.arrow_container.removeClass("Zebra_Tooltip_Arrow_Top").addClass("Zebra_Tooltip_Arrow_Bottom"),c<v||"below"===w.vertical_alignment&&w.element_top+w.element_height+w.vertical_offset+w.tooltip_height+w.animation_offset<T+v?(c=w.element_top+w.element_height-w.vertical_offset,w.animation_offset=Math.abs(w.animation_offset),w.message.css("margin-top",w.arrow_height/2),w.arrow_container.removeClass("Zebra_Tooltip_Arrow_Bottom").addClass("Zebra_Tooltip_Arrow_Top")):(w.animation_offset=-Math.abs(w.animation_offset),c+=w.vertical_offset),w.arrow_container.css("left",f),w.tooltip.css({left:h,top:c}),Z.extend(w,{tooltip_left:h,tooltip_top:c,arrow_left:f}),w=Z.extend(e.data("Zebra_Tooltip"),w),e.data("Zebra_Tooltip",w),w},g=function(t){var o=t.data("Zebra_Tooltip");clearTimeout(o.show_timeout),o.muted||(clearTimeout(o.hide_timeout),o.show_timeout=setTimeout(function(){(o=_(t)).onBeforeShow&&"function"==typeof o.onBeforeShow&&!1===o.onBeforeShow(t,o.tooltip)||("block"!==o.tooltip.css("display")&&o.tooltip.css({top:o.tooltip_top+o.animation_offset}),o.tooltip.css("display","block"),o.tooltip.stop(),o.tooltip.animate({top:o.tooltip_top,opacity:o.opacity},o.animation_speed,function(){o.onShow&&"function"==typeof o.onShow&&o.onShow(t,o.tooltip)}))},o.show_delay))},y=function(t){var o=t.data("Zebra_Tooltip");clearTimeout(o.hide_timeout),o.sticky||(clearTimeout(o.show_timeout),o.hide_timeout=setTimeout(function(){if(o.tooltip){if(o.onBeforeHide&&"function"==typeof o.onBeforeHide&&!1===o.onBeforeHide(t,o.tooltip))return;o.close=!1,o.destroy&&(o.muted=!0),t.data("Zebra_Tooltip",o),Z("a.Zebra_Tooltip_Close",o.tooltip).remove(),o.tooltip.stop(),o.tooltip.animate({opacity:0,top:o.tooltip_top+o.animation_offset},o.animation_speed,function(){Z(this).css("display","none"),o.onHide&&"function"==typeof o.onHide&&o.onHide(t,o.tooltip)})}},o.hide_delay))};r.hide=function(t,e){t.each(function(){var t=Z(this),o=t.data("Zebra_Tooltip");o&&(o.sticky=!1,e&&(o.destroy=!0),t.data("Zebra_Tooltip",o),y(t))})},r.show=function(t,e){t.each(function(){var t=Z(this),o=t.data("Zebra_Tooltip");o&&(o.sticky=!0,o.muted=!1,e&&(o.destroy=!0),t.data("Zebra_Tooltip",o),g(t))})},t.each(function(){var t,o=Z(this),e=o.attr("title"),i=o.data(),a={};for(t in i)0===t.indexOf("ztt_")&&(t=t.replace(/^ztt\_/,""),void 0!==n[t]&&(a[t]=i["ztt_"+t]));a=Z.extend(n,r.settings,l,a),e&&(a.content=o.attr("title")),void 0!==a.content&&""!==a.content.trim()&&(o.on({mouseenter:function(){e&&Z(this).attr("title",""),g(o)},mouseleave:function(){y(o),e&&Z(this).attr("title",e)}}),o.data("Zebra_Tooltip",Z.extend({tooltip:null,show_timeout:null,hide_timeout:null,sticky:!1,destroy:!1,muted:!1},a)),a.prerender&&_(o))})}}($);
3
+
4
+ var wfls_init_captcha = function() {
5
+ grecaptcha.ready(function() {
6
+ grecaptcha.execute(WFLSVars.recaptchasitekey, {action: 'login'}).then(function(token) {
7
+ var tokenField = $('#wfls-captcha-token');
8
+ if (tokenField.length) {
9
+ tokenField.val(token);
10
+ }
11
+ else {
12
+ var log = $('input[name="log"], input[name="user_login"]');
13
+ if (log.length) {
14
+ tokenField = $('<input type="hidden" name="wfls-captcha-token" id="wfls-captcha-token" />');
15
+ tokenField.val(token);
16
+ log.parent().append(tokenField);
17
+ }
18
+ }
19
+ });
20
+ });
21
+ };
22
+
23
+ var wfls_init_captcha_contact = function() {
24
+ $('.wfls-registration-captcha-contact').on('click', function(e) {
25
+ e.preventDefault();
26
+ e.stopPropagation();
27
+
28
+ var log = $('input[name="user_login"]');
29
+ if (log.length) {
30
+ $('#wfls-prompt-overlay').remove();
31
+ var overlay = $('<div id="wfls-prompt-overlay"></div>');
32
+ var wrapper = $('<div id="wfls-prompt-wrapper"></div>');
33
+ var field = $('<p><label for="wfls-message">Message to Support</label><br/><textarea name="wfls-message" id="wfls-message" class="wfls-textarea"></textarea></p>');
34
+ var nonce = $('<input type="hidden" name="wfls-message-nonce" id="wfls-message-nonce"/>');
35
+ var button = $('<p class="submit"><input type="submit" name="wfls-support-submit" id="wfls-support-submit" class="button button-primary button-large" value="Send"/></p>');
36
+ wrapper.append(field).append(nonce).append(button);
37
+ overlay.append(wrapper);
38
+ log.closest('form').css('position', 'relative').append(overlay);
39
+
40
+ $('#wfls-message-nonce').val($(this).data('token'));
41
+
42
+ $('#wfls-support-submit').on('click', function(e) {
43
+ e.preventDefault();
44
+ e.stopPropagation();
45
+
46
+ $('#login_error, p.message').remove();
47
+
48
+ var data = log.closest('form').serialize();
49
+ data += '&action=wordfence_ls_register_support';
50
+
51
+ $.ajax({
52
+ type: 'POST',
53
+ url: WFLSVars.ajaxurl,
54
+ dataType: 'json',
55
+ data: data,
56
+ success: function(json) {
57
+ if (json.hasOwnProperty('error')) {
58
+ var dom = $('<div id="login_error">' + json.error + '</div>');
59
+ $('#login > h1').after(dom);
60
+ }
61
+ else if (json.hasOwnProperty('message')) { //Success
62
+ var dom = $('<p class="message">' + json.message + '</p>');
63
+ $('#login > h1').after(dom);
64
+ $('#wfls-support-submit, #wfls-message').attr('disabled', true);
65
+ }
66
+ },
67
+ error: function(err) {
68
+ var dom = $('<div id="login_error"><strong>ERROR</strong>: An error was encountered while trying to send the message. Please try again.</div>');
69
+ $('#login > h1').after(dom);
70
+ }
71
+ });
72
+ });
73
+ }
74
+ });
75
+ };
76
+
77
+ var wfls_query_ajax = function() {
78
+ $('#login_error, p.message').remove();
79
+
80
+ var log = $('input[name="log"]');
81
+ var pwd = $('input[name="pwd"]');
82
+ var form = null;
83
+ if (log.length && pwd.length) {
84
+ form = log.closest('form');
85
+ }
86
+
87
+ if (form === null) {
88
+ console.log('Expected fields not found, try reloading page.');
89
+ return;
90
+ }
91
+
92
+ var data = $(form).serialize();
93
+ data += '&action=wordfence_ls_authenticate';
94
+
95
+ $.ajax({
96
+ type: 'POST',
97
+ url: WFLSVars.ajaxurl,
98
+ dataType: 'json',
99
+ data: data,
100
+ success: function(json) {
101
+ form.data('wflsLoggingIn', 0);
102
+ if (json.hasOwnProperty('reset') && json.reset) {
103
+ $('#wfls-prompt-overlay, #wfls-token-jwt').remove();
104
+ }
105
+
106
+ if (json.hasOwnProperty('error')) {
107
+ var dom = $('<div id="login_error">' + json.error + '</div>');
108
+ $('#login > h1').after(dom);
109
+ $('#wfls-token').val('');
110
+
111
+ if (parseInt(WFLSVars.useCAPTCHA)) {
112
+ wfls_init_captcha();
113
+ }
114
+ }
115
+ else if (json.hasOwnProperty('message')) {
116
+ var dom = $('<p class="message">' + json.message + '</p>');
117
+ $('#login > h1').after(dom);
118
+ $('#wfls-token').val('');
119
+
120
+ if (parseInt(WFLSVars.useCAPTCHA)) {
121
+ wfls_init_captcha();
122
+ }
123
+ }
124
+ else if (json.hasOwnProperty('login')) {
125
+ if (json.hasOwnProperty('captcha')) {
126
+ var captchaField = $('#wfls-captcha-jwt');
127
+ if (!captchaField.length) {
128
+ captchaField = $('<input type="hidden" name="wfls-captcha-jwt" id="wfls-captcha-jwt" value=""/>');
129
+ form.append(captchaField);
130
+ }
131
+
132
+ $('#wfls-captcha-jwt').val(json.captcha);
133
+ }
134
+
135
+ if (parseInt(WFLSVars.useCAPTCHA)) {
136
+ wfls_init_captcha();
137
+ wfls_init_captcha_contact();
138
+ }
139
+
140
+ if (json.hasOwnProperty('jwt')) {
141
+ var jwtField = $('#wfls-token-jwt');
142
+ if (!jwtField.length) {
143
+ jwtField = $('<input type="hidden" name="wfls-token-jwt" id="wfls-token-jwt" value=""/>');
144
+ form.append(jwtField);
145
+ }
146
+ $('#wfls-token-jwt').val(json.jwt);
147
+
148
+ if (parseInt(WFLSVars.useCAPTCHA)) {
149
+ wfls_init_captcha();
150
+ wfls_init_captcha_contact();
151
+ }
152
+
153
+ if (json.hasOwnProperty('combined')) {
154
+ form.data('wflsLoggingIn', 1);
155
+ $('#wp-submit').trigger('click');
156
+ return;
157
+ }
158
+
159
+ if (!$('#wfls-token').length) {
160
+ var overlay = $('<div id="wfls-prompt-overlay"></div>');
161
+ var wrapper = $('<div id="wfls-prompt-wrapper"></div>');
162
+ var field = $('<p><label for="wfls-token">2FA Code <a href="javascript:void(0)" class="wfls-2fa-code-help wfls-tooltip-trigger" title="The 2FA Code can be found within the authenticator app you used when first activating two-factor authentication. You may also use one of your recovery codes."><i class="dashicons dashicons-editor-help"></i></a><br/><input type="text" name="wfls-token" id="wfls-token" aria-describedby="wfls-token-error" class="input" value="" size="6" autocomplete="off"/></label></p>');
163
+ var remember = $('<p class="wfls-remember-device-wrapper"><label for="wfls-remember-device"><input name="wfls-remember-device" type="checkbox" id="wfls-remember-device" value="1" /> Remember for 30 days</label></p>');
164
+ var button = $('<p class="submit"><input type="submit" name="wfls-token-submit" id="wfls-token-submit" class="button button-primary button-large" value="Log In"/></p>');
165
+ wrapper.append(field);
166
+ if (parseInt(WFLSVars.allowremember)) {
167
+ wrapper.append(remember);
168
+ }
169
+ wrapper.append(button);
170
+ overlay.append(wrapper);
171
+ form.css('position', 'relative').append(overlay);
172
+
173
+ new $.Zebra_Tooltips($('.wfls-tooltip-trigger'));
174
+
175
+ $('#wfls-token-submit').on('click', function(e) {
176
+ e.preventDefault();
177
+ e.stopPropagation();
178
+
179
+ wfls_query_ajax();
180
+ });
181
+ }
182
+
183
+ $('#wfls-token').focus();
184
+ }
185
+ else { //Unexpected response, skip AJAX and process via the regular login flow
186
+ form.data('wflsLoggingIn', 1);
187
+ $('#wp-submit').trigger('click');
188
+ }
189
+ }
190
+ },
191
+ error: function(err) {
192
+ if (err.status == 503 || err.status == 403) {
193
+ window.location.reload(true);
194
+ return;
195
+ }
196
+ var dom = $('<div id="login_error"><strong>ERROR</strong>: An error was encountered while trying to authenticate. Please try again.</div>');
197
+ $('#login > h1').after(dom);
198
+ }
199
+ });
200
+ };
201
+
202
+ $(function() {
203
+ var log = $('input[name="log"]');
204
+ var pwd = $('input[name="pwd"]');
205
+ if (log.length && pwd.length) {
206
+ log.closest('form').on('submit', function(e) {
207
+ var loggingIn = !!parseInt($(this).data('wflsLoggingIn'));
208
+ $(this).data('wflsLoggingIn', 0);
209
+ if (loggingIn) { return; }
210
+
211
+ e.preventDefault();
212
+ e.stopPropagation();
213
+
214
+ wfls_query_ajax();
215
+ });
216
+ }
217
+
218
+ var verificationField = $('#wfls-email-verification');
219
+ if (verificationField.length) {
220
+ verificationField.val(WFLSVars.verification);
221
+ }
222
+ else {
223
+ var log = $('input[name="log"], input[name="user_login"]');
224
+ if (log.length) {
225
+ verificationField = $('<input type="hidden" name="wfls-email-verification" id="wfls-email-verification" />');
226
+ verificationField.val(WFLSVars.verification);
227
+ log.parent().append(verificationField);
228
+ }
229
+ }
230
+
231
+ if (parseInt(WFLSVars.useCAPTCHA)) {
232
+ wfls_init_captcha_contact();
233
+ }
234
+ });
235
+
236
+ if (parseInt(WFLSVars.useCAPTCHA)) {
237
+ wfls_init_captcha();
238
+ }
239
+ })(jQuery);
readme.txt ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Wordfence Login Security ===
2
+ Contributors: wfryan
3
+ Tags: security, login security, 2fa, two factor authentication, captcha, xml-rpc, mfa, 2 factor
4
+ Requires at least: 4.5
5
+ Requires PHP: 5.3
6
+ Tested up to: 5.2
7
+ Stable tag: 1.0.2
8
+
9
+ Secure your website with Wordfence Login Security, providing two-factor authentication, login and registration CAPTCHA, and XML-RPC protection.
10
+
11
+ == Description ==
12
+
13
+ ### WORDFENCE LOGIN SECURITY
14
+
15
+ Wordfence Login Security contains a subset of the functionality found in the full Wordfence plugin: Two-factor Authentication, XML-RPC Protection and Login Page CAPTCHA.
16
+
17
+ Are you looking for comprehensive WordPress Security? [Check out the full Wordfence plugin](https://wordpress.org/plugins/wordfence/).
18
+
19
+ #### TWO-FACTOR AUTHENTICATION
20
+
21
+ * Two-factor authentication (2FA), one of the most secure forms of remote system authentication available.
22
+ * Use any TOTP-based authenticator app or service like Google Authenticator, Authy, 1Password or FreeOTP.
23
+ * Enable 2FA for any WordPress user role.
24
+ * Completely free to use, no limits or restrictions of any kind.
25
+
26
+ #### LOGIN PAGE CAPTCHA
27
+
28
+ * Easily enable Google ReCAPTCHA v3 on your login and registration pages.
29
+ * Stops bots from logging in without inconveniencing your site visitors.
30
+ * Robust protection against password guessing and credential stuffing attacks distributed across large IP pools
31
+
32
+ #### XML-RPC PROTECTION
33
+
34
+ * XML-RPC is the biggest target for WordPress attacks, but is often overlooked.
35
+ * Protect XML-RPC with 2FA or disable it altogether if it’s not needed.
36
+
37
+ == Installation ==
38
+
39
+ Secure your website using the following steps to install Wordfence:
40
+
41
+ 1. Install Wordfence Login Security automatically or by uploading the ZIP file.
42
+ 2. Activate the Wordfence Login Security through the 'Plugins' menu in WordPress. Wordfence Login Security is now activated.
43
+ 3. Go to the 'Login Security' menu and activate two-factor authentication and configure other settings.
44
+
45
+ To install Wordfence Login Security on WordPress Multisite installations:
46
+
47
+ 1. Install Wordfence Login Security via the plugin directory or by uploading the ZIP file.
48
+ 2. Network Activate Wordfence Login Security. This step is important because until you network activate it, your sites will see the plugin option on their 'Plugins' menu. Once activated, that option disappears.
49
+ 3. Now that Wordfence Login Security is network activated, it will appear on your Network Admin menu for super administrators and individual sites for users who have permission to activate 2FA.
50
+
51
+ == Screenshots ==
52
+
53
+ Secure your website with Wordfence Login Security.
54
+
55
+ 1. Take login security to the next level with two-factor authentication.
56
+ 2. Logging in is easy with Wordfence 2FA.
57
+ 3. Configuration options include XML-RPC protection and login page CAPTCHA.
58
+
59
+ == Changelog ==
60
+
61
+ = 1.0.2 - May 30, 2019 =
62
+ * Initial release
views/.htaccess ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <IfModule mod_rewrite.c>
2
+ RewriteEngine On
3
+ RewriteCond %{REQUEST_URI} \.php$
4
+ RewriteRule .* - [F,L,NC]
5
+ </IfModule>
6
+ <IfModule !mod_rewrite.c>
7
+ <FilesMatch "\.php$">
8
+ <IfModule mod_authz_core.c>
9
+ Require all denied
10
+ </IfModule>
11
+ <IfModule !mod_authz_core.c>
12
+ Order deny,allow
13
+ Deny from all
14
+ </IfModule>
15
+ </FilesMatch>
16
+ </IfModule>
views/common/modal-prompt.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a modal prompt.
5
+ *
6
+ * @var string|\WordfenceLS\Text\Model_HTML $title The title for the prompt. Required.
7
+ * @var string|\WordfenceLS\Text\Model_HTML $message The message for the prompt. Required.
8
+ * @var array $primaryButton The parameters for the primary button. The array is in the format array('id' => <element id>, 'label' => <button text>, 'link' => <href value>). Required.
9
+ * @var array $secondaryButtons The parameters for any secondary buttons. It is an array of arrays in the format array('id' => <element id>, 'label' => <button text>, 'link' => <href value>). The ordering of entries is the right-to-left order the buttons will be displayed. Optional.
10
+ */
11
+
12
+ $titleHTML = \WordfenceLS\Text\Model_HTML::esc_html($title);
13
+ $messageHTML = \WordfenceLS\Text\Model_HTML::esc_html($message);
14
+
15
+ if (!isset($secondaryButtons)) {
16
+ $secondaryButtons = array();
17
+ }
18
+ $secondaryButtons = array_reverse($secondaryButtons);
19
+ ?>
20
+ <div class="wfls-modal">
21
+ <div class="wfls-modal-header">
22
+ <div class="wfls-modal-header-content">
23
+ <div class="wfls-modal-title">
24
+ <strong><?php echo $titleHTML; ?></strong>
25
+ </div>
26
+ </div>
27
+ <div class="wfls-modal-header-action">
28
+ <div class="wfls-padding-add-left-small wfls-modal-header-action-close"><a href="#" onclick="WFLS.panelClose(); return false"><i class="<?php echo (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-times-circle' : 'wfls-fa wfls-fa-times-circle'); ?>" aria-hidden="true"></i></a></div>
29
+ </div>
30
+ </div>
31
+ <div class="wfls-modal-content">
32
+ <?php echo $messageHTML; ?>
33
+ </div>
34
+ <div class="wfls-modal-footer">
35
+ <ul class="wfls-flex-horizontal wfls-flex-align-right wfls-full-width">
36
+ <?php foreach ($secondaryButtons as $button): ?>
37
+ <li class="wfls-padding-add-left-small"><a href="<?php echo esc_url($button['link']); ?>" class="wfls-btn <?php echo isset($button['type']) ? $button['type'] : 'wfls-btn-default'; ?> wfls-btn-callout-subtle" id="<?php echo esc_attr($button['id']); ?>"><?php echo isset($button['labelHTML']) ? $button['labelHTML'] : esc_html($button['label']); ?></a></li>
38
+ <?php endforeach; ?>
39
+ <li class="wfls-padding-add-left-small"><a href="<?php echo esc_url($primaryButton['link']); ?>" class="wfls-btn <?php echo isset($primaryButton['type']) ? $primaryButton['type'] : 'wfls-btn-primary'; ?> wfls-btn-callout-subtle" id="<?php echo esc_attr($primaryButton['id']); ?>"><?php echo isset($primaryButton['labelHTML']) ? $primaryButton['labelHTML'] : esc_html($primaryButton['label']); ?></a></li>
40
+ </ul>
41
+ </div>
42
+ </div>
views/email/login-verification.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var string $ip The requesting IP. Required.
5
+ * @var string $siteName The site name. Required.
6
+ * @var string $siteURL The site URL. Required.
7
+ * @var string $verificationURL The verification URL. Required.
8
+ * @var bool $canEnable2FA Whether or not the user this is being sent to can enable 2FA. Optional
9
+ */
10
+ ?>
11
+ <strong><?php printf(__('Please verify a login attempt for your account on <a href="%s"><strong>%s</strong></a>.', 'wordfence-ls'), esc_url($siteURL), esc_html($siteName)); ?></strong>
12
+ <br><br>
13
+ <?php echo '<strong>' . __('Request Time:', 'wordfence-ls') . '</strong> ' . esc_html(\WordfenceLS\Controller_Time::format_local_time('F j, Y h:i:s A')); ?><br>
14
+ <?php echo '<strong>' . __('IP:', 'wordfence-ls') . '</strong> ' . esc_html($ip); ?>
15
+ <br><br>
16
+ <?php _e('The request was flagged as suspicious, and we need verification that you attempted to log in to allow it to proceed. This verification link <b>will be valid for 15 minutes</b> from the time it was sent. If you did not attempt this login, please change your password immediately.', 'wordfence-ls'); ?>
17
+ <br><br>
18
+ <?php if (isset($canEnable2FA) && $canEnable2FA): ?>
19
+ <?php _e('You may bypass this verification step permanently by enabling two-factor authentication on your account.', 'wordfence-ls'); ?>
20
+ <br><br>
21
+ <?php endif; ?>
22
+ <?php printf(__('<a href="%s"><b>Verify and Log In</b></a>', 'wordfence-ls'), esc_url($verificationURL)); ?>
views/manage/activate.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var string $secret The TOTP secret in binary. Required.
5
+ * @var string $base32Secret The base32-encoded TOTP secret. Required.
6
+ * @var string[] $recovery The binary recovery codes. Required.
7
+ * @var \WP_User $user The user being edited. Required.
8
+ */
9
+ ?>
10
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width">
11
+ <div class="wfls-block-header wfls-block-header-border-bottom">
12
+ <div class="wfls-block-header-content">
13
+ <div class="wfls-block-title">
14
+ <strong><?php _e('2. Enter Code from Authenticator App', 'wordfence-2fa'); ?></strong>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ <div class="wfls-block-content wfls-padding-add-bottom">
19
+ <p><?php _e('Download Recovery Codes', 'wordfence-2fa'); ?> <em class="wfls-text-small"><?php _e('Optional', 'wordfence-2fa'); ?></em></p>
20
+ <p><?php printf(__('Use one of these %d codes to log in if you lose access to your authenticator device. Codes are %d characters long plus optional spaces. Each one may be used only once.', 'wordfence-2fa'), count($recovery), \WordfenceLS\Model_Crypto::strlen($recovery[0]) * 2); ?></p>
21
+ <ul class="wfls-recovery-codes">
22
+ <?php
23
+ $recoveryCodeFileContents = sprintf(__('Two-Factor Authentication Recovery Codes - %s (%s)', 'wordfence-2fa'), home_url(), $user->user_login) . "\r\n";
24
+ $recoveryCodeFileContents .= "\r\n" . sprintf(__('Each line of %d letters and numbers is a single recovery code, with optional spaces for readability. To use a recovery code, after entering your username and password, enter the code like "1234 5678 90AB CDEF" at the 2FA prompt. If your site has a custom login prompt and does not show a 2FA prompt, you can use the single-step method by entering your password and the code together in the Password field, like "mypassword1234 5678 90AB CDEF". Your recovery codes are:', 'wordfence-2fa'), \WordfenceLS\Model_Crypto::strlen($recovery[0]) * 2) . "\r\n\r\n";
25
+ foreach ($recovery as $c) {
26
+ $hex = bin2hex($c);
27
+ $blocks = str_split($hex, 4);
28
+ echo '<li>' . implode(' ', $blocks) . '</li>';
29
+ $recoveryCodeFileContents .= implode(' ', $blocks) . "\r\n";
30
+ }
31
+ ?>
32
+ </ul>
33
+ <p class="wfls-center"><a href="#" class="wfls-btn wfls-btn-default" id="wfls-recovery-download" target="_blank" rel="noopener noreferrer"><i class="dashicons dashicons-download"></i> <?php _e('Download', 'wordfence-2fa'); ?></a></p>
34
+
35
+ <hr class="wfls-half">
36
+
37
+ <p><?php _e('Enter the code from your authenticator app below to verify and activate two-factor authentication for this account.', 'wordfence-2fa'); ?></p>
38
+ <p><input type="text" id="wfls-activate-field" value="" size="6" maxlength="6" placeholder="123456" autocomplete="off"></p>
39
+ </div>
40
+ <div class="wfls-block-footer">
41
+ <div class="wfls-block-footer-content">
42
+ <div class="wfls-block-title">
43
+ <a href="<?php echo \WordfenceLS\Controller_Support::esc_supportURL(\WordfenceLS\Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA); ?>" target="_blank" rel="noopener noreferrer"><?php _e('For help on setting up an app, visit our help article.', 'wordfence-2fa'); ?></a>
44
+ </div>
45
+ <div class="wfls-block-footer-action"><a href="#" id="wfls-activate" class="wfls-btn wfls-btn-default wfls-disabled"><?php _e('Activate', 'wordfence-2fa'); ?></a></div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <script type="application/javascript">
50
+ (function($) {
51
+ $(function() {
52
+ $('#wfls-activate-field').on('keyup', function(e) {
53
+ $('#wfls-activate').toggleClass('wfls-disabled', $('#wfls-activate-field').val().length != 6);
54
+
55
+ if (e.keyCode == 13) {
56
+ $('#wfls-activate').trigger('click');
57
+ }
58
+ });
59
+
60
+ $('#wfls-recovery-download').on('click', function(e) {
61
+ e.preventDefault();
62
+ e.stopPropagation();
63
+ saveAs(new Blob(["<?php echo str_replace("\n", "\\n", str_replace("\r", "\\r", addslashes($recoveryCodeFileContents))); ?>"], {type: "text/plain;charset=" + document.characterSet}), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(preg_replace('~^https?://~i', '', home_url())) . '_' . \WordfenceLS\Text\Model_JavaScript::esc_js($user->user_login) . '_recoverycodes.txt'; ?>');
64
+ WFLS.savedRecoveryCodes = true;
65
+ });
66
+
67
+ $('#wfls-activate').on('click', function(e) {
68
+ e.preventDefault();
69
+ e.stopPropagation();
70
+
71
+ var payload = {
72
+ secret: '<?php echo bin2hex($secret); ?>',
73
+ recovery: ['<?php echo implode('\', \'', array_map(function($c) { return bin2hex($c); }, $recovery)); ?>'],
74
+ code: $('#wfls-activate-field').val(),
75
+ user: <?php echo $user->ID; ?>,
76
+ };
77
+
78
+ WFLS.ajax(
79
+ 'wordfence_ls_activate',
80
+ payload,
81
+ function(response) {
82
+ if (response.error) {
83
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Activating 2FA', 'wordfence-2fa')); ?>', response.error);
84
+ }
85
+ else {
86
+ $('#wfls-activation-controls').crossfade($('#wfls-deactivation-controls'));
87
+ $('#wfls-recovery-code-count').text(response.text);
88
+ $('#wfls-activate-field').val('');
89
+
90
+ if (!WFLS.savedRecoveryCodes) {
91
+ var prompt = $('#wfls-tmpl-recovery-skipped-prompt').tmpl({});
92
+ var promptHTML = $("<div />").append(prompt).html();
93
+ WFLS.panelHTML((WFLS.screenSize(500) ? '300px' : '400px'), promptHTML, {overlayClose: false, closeButton: false, className: 'wfls-modal', onComplete: function() {
94
+ $('#wfls-recovery-skipped-download').on('click', function(e) {
95
+ e.preventDefault();
96
+ e.stopPropagation();
97
+ saveAs(new Blob(["<?php echo str_replace("\n", "\\n", str_replace("\r", "\\r", addslashes($recoveryCodeFileContents))); ?>"], {type: "text/plain;charset=" + document.characterSet}), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(preg_replace('~^https?://~i', '', home_url())) . '_' . \WordfenceLS\Text\Model_JavaScript::esc_js($user->user_login) . '_recoverycodes.txt'; ?>');
98
+ WFLS.panelClose();
99
+ });
100
+ $('#wfls-recovery-skipped-skip').on('click', function(e) {
101
+ e.preventDefault();
102
+ e.stopPropagation();
103
+ WFLS.panelClose();
104
+ });
105
+ }});
106
+ }
107
+ WFLS.savedRecoveryCodes = false;
108
+ }
109
+ },
110
+ function(error) {
111
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Activating 2FA', 'wordfence-2fa')); ?>', '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('An error was encountered while trying to activate two-factor authentication. Please try again.', 'wordfence-2fa')); ?>');
112
+ }
113
+ );
114
+ });
115
+ });
116
+ })(jQuery);
117
+ </script>
118
+ <script type="text/x-jquery-template" id="wfls-tmpl-recovery-skipped-prompt">
119
+ <?php
120
+ echo \WordfenceLS\Model_View::create('common/modal-prompt', array(
121
+ 'title' => __('Download Recovery Codes', 'wordfence-2fa'),
122
+ 'message' => __('Reminder: If you lose access to your authenticator device, you can use recovery codes to log in. If you have not saved a copy of your recovery codes, we recommend downloading them now.', 'wordfence-2fa'),
123
+ 'primaryButton' => array('id' => 'wfls-recovery-skipped-download', 'label' => __('Download', 'wordfence'), 'link' => '#'),
124
+ 'secondaryButtons' => array(array('id' => 'wfls-recovery-skipped-skip', 'label' => __('Skip', 'wordfence'), 'link' => '#')),
125
+ ))->render();
126
+ ?>
127
+ </script>
views/manage/code.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var string $secret The TOTP secret in binary. Required.
5
+ * @var string $base32Secret The base32-encoded TOTP secret. Required.
6
+ * @var string $totpURL The TOTP URL for the QR code content. Required.
7
+ */
8
+ ?>
9
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width">
10
+ <div class="wfls-block-header wfls-block-header-border-bottom">
11
+ <div class="wfls-block-header-content">
12
+ <div class="wfls-block-title">
13
+ <strong><?php _e('1. Scan Code or Enter Key', 'wordfence'); ?></strong>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ <div class="wfls-block-content wfls-padding-add-bottom">
18
+ <p>Scan the code below with your authenticator app to add this account. Some authenticator apps also allow you to type in the text version instead.</p>
19
+ <div id="wfls-qr-code"></div>
20
+ <p class="wfls-center wfls-no-bottom"><input id="wfls-qr-code-text" class="wfls-center" type="text" value="<?php echo esc_attr($base32Secret); ?>" onclick="this.select();" readonly></p>
21
+ </div>
22
+ </div>
23
+ <script type="application/javascript">
24
+ (function($) {
25
+ $(function() {
26
+ $('#wfls-qr-code').qrcode({text: '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js($totpURL); ?>', width: (WFLS.screenSize(500) ? 175 : 256), height: (WFLS.screenSize(500) ? 175 : 256)});
27
+ if (!WFLS.screenSize(500)) {
28
+ $('#wfls-qr-code-text').attr('size', 35).css('font-family', 'monospace');
29
+ }
30
+ });
31
+ })(jQuery);
32
+ </script>
views/manage/deactivate.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var \WP_User $user The user being edited. Required.
5
+ */
6
+
7
+ $ownAccount = false;
8
+ $ownUser = wp_get_current_user();
9
+ if ($ownUser->ID == $user->ID) {
10
+ $ownAccount = true;
11
+ }
12
+ ?>
13
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width">
14
+ <div class="wfls-block-header wfls-block-header-border-bottom">
15
+ <div class="wfls-block-header-content">
16
+ <div class="wfls-block-title">
17
+ <strong><?php _e('Wordfence 2FA Active', 'wordfence-2fa'); ?></strong>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <div class="wfls-block-content wfls-padding-add-bottom">
22
+ <p><?php if ($ownAccount) { _e('Wordfence two-factor authentication is currently active on your account. You may deactivate it by clicking the button below.', 'wordfence-2fa'); } else { printf(__('Wordfence two-factor authentication is currently active on the account <strong>%s</strong>. You may deactivate it by clicking the button below.', 'wordfence-2fa'), esc_html($user->user_login)); } ?></p>
23
+ <p class="wfls-center wfls-add-top"><a href="#" class="wfls-btn wfls-btn-default" id="wfls-deactivate" target="_blank" rel="noopener noreferrer"><?php _e('Deactivate', 'wordfence-2fa'); ?></a></p>
24
+ </div>
25
+ </div>
26
+ <script type="text/x-jquery-template" id="wfls-tmpl-deactivate-prompt">
27
+ <?php
28
+ echo \WordfenceLS\Model_View::create('common/modal-prompt', array(
29
+ 'title' => __('Deactivate 2FA', 'wordfence'),
30
+ 'message' => __('Are you sure you want to deactivate two-factor authentication?'),
31
+ 'primaryButton' => array('id' => 'wfls-deactivate-prompt-cancel', 'label' => __('Cancel', 'wordfence'), 'link' => '#'),
32
+ 'secondaryButtons' => array(array('id' => 'wfls-deactivate-prompt-confirm', 'label' => __('Deactivate', 'wordfence'), 'link' => '#')),
33
+ ))->render();
34
+ ?>
35
+ </script>
36
+ <script type="application/javascript">
37
+ (function($) {
38
+ $(function() {
39
+ $('#wfls-deactivate').on('click', function(e) {
40
+ e.preventDefault();
41
+ e.stopPropagation();
42
+
43
+ var prompt = $('#wfls-tmpl-deactivate-prompt').tmpl({});
44
+ var promptHTML = $("<div />").append(prompt).html();
45
+ WFLS.panelHTML((WFLS.screenSize(500) ? '300px' : '400px'), promptHTML, {overlayClose: false, closeButton: false, className: 'wfls-modal', onComplete: function() {
46
+ $('#wfls-deactivate-prompt-cancel').on('click', function(e) {
47
+ e.preventDefault();
48
+ e.stopPropagation();
49
+
50
+ WFLS.panelClose();
51
+ });
52
+
53
+ $('#wfls-deactivate-prompt-confirm').on('click', function(e) {
54
+ e.preventDefault();
55
+ e.stopPropagation();
56
+
57
+ var payload = {
58
+ user: <?php echo (int) $user->ID; ?>,
59
+ };
60
+
61
+ WFLS.ajax(
62
+ 'wordfence_ls_deactivate',
63
+ payload,
64
+ function(response) {
65
+ if (response.error) {
66
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Deactivating 2FA', 'wordfence-2fa')); ?>', response.error);
67
+ }
68
+ else {
69
+ $('#wfls-deactivation-controls').crossfade($('#wfls-activation-controls'));
70
+ }
71
+
72
+ WFLS.panelClose(); //The prompt
73
+ },
74
+ function(error) {
75
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Deactivating 2FA', 'wordfence-2fa')); ?>', '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('An error was encountered while trying to deactivate two-factor authentication. Please try again.', 'wordfence-2fa')); ?>');
76
+ WFLS.panelClose(); //The prompt
77
+ }
78
+ );
79
+ });
80
+ }});
81
+ });
82
+ });
83
+ })(jQuery);
84
+ </script>
views/manage/regenerate.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var \WP_User $user The user being edited. Required.
5
+ * @var int $remaining The number of unused recovery codes. Required.
6
+ */
7
+ ?>
8
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width">
9
+ <div class="wfls-block-header wfls-block-header-border-bottom">
10
+ <div class="wfls-block-header-content">
11
+ <div class="wfls-block-title">
12
+ <strong><?php _e('Recovery Codes', 'wordfence-2fa'); ?></strong>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ <div class="wfls-block-content wfls-padding-add-bottom">
17
+ <p id="wfls-recovery-code-count"><?php printf($remaining == 1 ? __('%d unused recovery code remains. You may generate a new set by clicking below.', 'wordfence-2fa') : __('%d unused recovery codes remain. You may generate a new set by clicking below.', 'wordfence-2fa'), $remaining); ?></p>
18
+ <p class="wfls-center wfls-add-top"><a href="#" class="wfls-btn wfls-btn-default" id="wfls-recovery" target="_blank" rel="noopener noreferrer"><?php _e('Generate New Codes', 'wordfence-2fa'); ?></a></p>
19
+ </div>
20
+ </div>
21
+ <script type="text/x-jquery-template" id="wfls-tmpl-recovery-prompt">
22
+ <?php
23
+ echo \WordfenceLS\Model_View::create('common/modal-prompt', array(
24
+ 'title' => __('Generate New Recovery Codes', 'wordfence'),
25
+ 'message' => __('Are you sure you want to generate new recovery codes? Any remaining unused codes will be disabled.'),
26
+ 'primaryButton' => array('id' => 'wfls-recovery-prompt-cancel', 'label' => __('Cancel', 'wordfence'), 'link' => '#'),
27
+ 'secondaryButtons' => array(array('id' => 'wfls-recovery-prompt-confirm', 'label' => __('Generate', 'wordfence'), 'link' => '#')),
28
+ ))->render();
29
+ ?>
30
+ </script>
31
+ <script type="application/javascript">
32
+ (function($) {
33
+ $(function() {
34
+ $('#wfls-recovery').on('click', function(e) {
35
+ e.preventDefault();
36
+ e.stopPropagation();
37
+
38
+ var prompt = $('#wfls-tmpl-recovery-prompt').tmpl({});
39
+ var promptHTML = $("<div />").append(prompt).html();
40
+ WFLS.panelHTML((WFLS.screenSize(500) ? '300px' : '400px'), promptHTML, {overlayClose: false, closeButton: false, className: 'wfls-modal', onComplete: function() {
41
+ $('#wfls-recovery-prompt-cancel').on('click', function(e) {
42
+ e.preventDefault();
43
+ e.stopPropagation();
44
+
45
+ WFLS.panelClose();
46
+ });
47
+
48
+ $('#wfls-recovery-prompt-confirm').on('click', function(e) {
49
+ e.preventDefault();
50
+ e.stopPropagation();
51
+
52
+ var payload = {
53
+ user: <?php echo (int) $user->ID; ?>,
54
+ };
55
+
56
+ WFLS.ajax(
57
+ 'wordfence_ls_regenerate',
58
+ payload,
59
+ function(response) {
60
+ if (response.error) {
61
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo esc_js(__('Error Generating New Codes', 'wordfence-2fa')); ?>', response.error);
62
+ }
63
+ else if (response.recovery) {
64
+ $('#wfls-recovery-code-count').text(response.text);
65
+
66
+ var message = '<p><?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(sprintf(__('Use one of these %d codes to log in if you lose access to your authenticator device. Codes are %d characters long plus optional spaces. Each one may be used only once.', 'wordfence-2fa'), \WordfenceLS\Controller_Users::RECOVERY_CODE_COUNT, \WordfenceLS\Controller_Users::RECOVERY_CODE_SIZE * 2)); ?></p><ul class="wfls-recovery-codes">';
67
+
68
+ var recoveryCodeFileContents = '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(sprintf(__('Two-Factor Authentication Recovery Codes - %s (%s)', 'wordfence-2fa'), preg_replace('~^https?://~i', '', home_url()), $user->user_login)); ?>' + "\r\n";
69
+ recoveryCodeFileContents = recoveryCodeFileContents + "\r\n" + '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(sprintf(__('Each line of %d letters and numbers is a single recovery code, with optional spaces for readability. To use a recovery code, after entering your username and password, enter the code like "1234 5678 90AB CDEF" at the 2FA prompt. If your site has a custom login prompt and does not show a 2FA prompt, you can use the single-step method by entering your password and the code together in the Password field, like "mypassword1234 5678 90AB CDEF". Your recovery codes are:', 'wordfence-2fa'), \WordfenceLS\Controller_Users::RECOVERY_CODE_SIZE * 2)); ?>' + "\r\n\r\n";
70
+ for (var i = 0; i < response.recovery.length; i++) {
71
+ message = message + '<li>' + response.recovery[i] + '</li>';
72
+ recoveryCodeFileContents = recoveryCodeFileContents + response.recovery[i] + "\r\n";
73
+ }
74
+
75
+ message = message + "</ul>";
76
+
77
+ message = message + "<p class=\"wfls-center\"><a href=\"#\" class=\"wfls-btn wfls-btn-default\" id=\"wfls-recovery-new-download\" target=\"_blank\" rel=\"noopener noreferrer\"><i class=\"dashicons dashicons-download\"></i> <?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Download', 'wordfence-2fa')); ?></a></p>";
78
+
79
+
80
+ WFLS.panelModalHTML((WFLS.screenSize(500) ? '300px' : '400px'), "<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('New Recovery Codes', 'wordfence-2fa')); ?>", message, {onComplete: function() {
81
+ $('#wfls-recovery-new-download').on('click', function(e) {
82
+ e.preventDefault();
83
+ e.stopPropagation();
84
+ saveAs(new Blob([recoveryCodeFileContents], {type: "text/plain;charset=" + document.characterSet}), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(preg_replace('~^https?://~i', '', home_url()) . '_' . $user->user_login . '_recoverycodes.txt'); ?>');
85
+ });
86
+ }});
87
+ }
88
+
89
+ WFLS.panelClose(); //The prompt
90
+ },
91
+ function(error) {
92
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Generating New Codes', 'wordfence-2fa')); ?>', '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('An error was encountered while trying to generate new recovery codes. Please try again.', 'wordfence-2fa')); ?>');
93
+ WFLS.panelClose(); //The prompt
94
+ }
95
+ );
96
+ });
97
+ }});
98
+ });
99
+ });
100
+ })(jQuery);
101
+ </script>
views/onboarding/standalone-header.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents the fresh install plugin header for standalone installations.
5
+ */
6
+ ?>
7
+ <div id="wfls-onboarding-standalone-modal">
8
+ <div id="wfls-onboarding-standalone-modal-header">
9
+ <div id="wfls-onboarding-standalone-modal-header-title"><?php _e('Wordfence Login Security Installed', 'wordfence-2fa'); ?></div>
10
+ <div id="wfls-onboarding-standalone-modal-header-accessory"><a href="#" id="wfls-onboarding-standalone-modal-dismiss">&times;</a></div>
11
+ </div>
12
+ <div id="wfls-onboarding-standalone-modal-content">
13
+ <p><?php _e('You have just installed the Wordfence Login Security plugin. It contains a subset of the functionality found in the full Wordfence plugin: Two-factor Authentication, XML-RPC Protection and Login Page CAPTCHA.', 'wordfence-2fa'); ?></p>
14
+ <p><?php printf(__('If you\'re looking for a more comprehensive solution, the <a href="%s" target="_blank" rel="noopener noreferrer">full Wordfence plugin</a> includes all of the features in this plugin as well as a full-featured WordPress firewall, a security scanner, live traffic, and more. The standard installation includes a robust set of free features that can be upgraded via a Premium license key.', 'wordfence-2fa'), 'https://wordpress.org/plugins/wordfence/'); ?></p>
15
+ </div>
16
+ </div>
17
+ <script type="application/javascript">
18
+ (function($) {
19
+ $(function() {
20
+ $('#wfls-onboarding-standalone-modal-dismiss').on('click', function(e) {
21
+ e.preventDefault();
22
+ e.stopPropagation();
23
+
24
+ $('#wfls-onboarding-standalone-modal').slideUp(400, function() {
25
+ $('#wfls-onboarding-standalone-modal').remove();
26
+ });
27
+
28
+ WFLS.setOptions({'dismissed-fresh-install-modal': true});
29
+ });
30
+ });
31
+ })(jQuery);
32
+ </script>
views/options/option-captcha.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+
4
+ $enableOptionName = \WordfenceLS\Controller_Settings::OPTION_ENABLE_AUTH_CAPTCHA;
5
+ $currentEnableValue = \WordfenceLS\Controller_Settings::shared()->get_bool($enableOptionName);
6
+
7
+ $siteKeyOptionName = \WordfenceLS\Controller_Settings::OPTION_RECAPTCHA_SITE_KEY;
8
+ $siteKeyValue = \WordfenceLS\Controller_Settings::shared()->get($siteKeyOptionName);
9
+
10
+ $secretOptionName = \WordfenceLS\Controller_Settings::OPTION_RECAPTCHA_SECRET;
11
+ $secretValue = \WordfenceLS\Controller_Settings::shared()->get($secretOptionName);
12
+ ?>
13
+ <ul id="wfls-option-enable-auth-captcha" data-option="<?php echo esc_attr($enableOptionName); ?>" data-enabled-value="1" data-disabled-value="0" data-original-value="<?php echo $currentEnableValue ? '1' : '0'; ?>">
14
+ <li>
15
+ <ul class="wfls-option wfls-padding-add-bottom-small">
16
+ <li id="wfls-enable-auth-captcha" class="wfls-option-checkbox<?php echo ($currentEnableValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($currentEnableValue ? 'true' : 'false'); ?>" tabindex="0"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true" aria-labelledby="wfls-enable-auth-captcha-label"></i></li>
17
+ <li class="wfls-option-title">
18
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
19
+ <li>
20
+ <strong id="wfls-enable-auth-captcha-label"><?php _e('Enable reCAPTCHA on the login and user registration pages', 'wordfence-2fa'); ?></strong>
21
+ </li>
22
+ <li class="wfls-option-subtitle"><?php _e('Note: This feature requires a free site key and secret for the <a href="https://www.google.com/recaptcha/intro/v3.html" target="_blank" rel="noopener noreferrer">Google reCAPTCHA v3 Service</a>.', 'wordfence-2fa'); ?></li>
23
+ </ul>
24
+ </li>
25
+ </ul>
26
+ </li>
27
+ <li>
28
+ <ul class="wfls-option wfls-padding-no-top">
29
+ <li class="wfls-option-spacer"></li>
30
+ <li>
31
+ <table>
32
+ <tr class="wfls-option wfls-option-text" data-original-value="<?php echo esc_attr($siteKeyValue); ?>" data-text-option="<?php echo esc_attr($siteKeyOptionName); ?>">
33
+ <th id="wfls-enable-captcha-site-key-label" class="wfls-padding-add-bottom"><?php _e('reCAPTCHA v3 Site Key', 'wordfence'); ?></th>
34
+ <td class="wfls-option-text wfls-padding-add-bottom"><input type="text" name="recaptchaSiteKey" id="input-recaptchaSiteKey" class="wfls-form-control" value="<?php echo esc_attr($siteKeyValue); ?>"<?php if (!$currentEnableValue) { echo ' disabled'; } ?>></td>
35
+ </tr>
36
+ <tr class="wfls-option wfls-option-text" data-original-value="<?php echo esc_attr($secretValue); ?>" data-text-option="<?php echo esc_attr($secretOptionName); ?>">
37
+ <th id="wfls-enable-captcha-secret-label"><?php _e('reCAPTCHA v3 Secret', 'wordfence'); ?></th>
38
+ <td class="wfls-option-text"><input type="text" name="recaptchaSecret" id="input-recaptchaSecret" class="wfls-form-control" value="<?php echo esc_attr($secretValue); ?>"<?php if (!$currentEnableValue) { echo ' disabled'; } ?>></td>
39
+ </tr>
40
+ </table>
41
+ </li>
42
+ </ul>
43
+ </li>
44
+ </ul>
45
+ <script type="application/javascript">
46
+ (function($) {
47
+ $(function() {
48
+ $('#wfls-enable-auth-captcha').on('keydown', function(e) {
49
+ if (e.keyCode == 32) {
50
+ e.preventDefault();
51
+ e.stopPropagation();
52
+
53
+ $(this).trigger('click');
54
+ }
55
+ });
56
+
57
+ $('#wfls-enable-auth-captcha').on('click', function(e) {
58
+ e.preventDefault();
59
+ e.stopPropagation();
60
+
61
+ var optionElement = $('#wfls-option-enable-auth-captcha');
62
+ if (optionElement.hasClass('wfls-disabled')) {
63
+ return;
64
+ }
65
+
66
+ var option = optionElement.data('option');
67
+ var value = false;
68
+ var isActive = $(this).hasClass('wfls-checked');
69
+ if (isActive) {
70
+ $(this).removeClass('wfls-checked').attr('aria-checked', 'false');
71
+ $('#input-recaptchaSiteKey, #input-recaptchaSecret').attr('disabled', true);
72
+ value = optionElement.data('disabledValue');
73
+ }
74
+ else {
75
+ $(this).addClass('wfls-checked').attr('aria-checked', 'true');
76
+ $('#input-recaptchaSiteKey, #input-recaptchaSecret').attr('disabled', false);
77
+ value = optionElement.data('enabledValue');
78
+ }
79
+
80
+ var originalValue = optionElement.data('originalValue');
81
+ if (originalValue == value) {
82
+ delete WFLS.pendingChanges[option];
83
+ }
84
+ else {
85
+ WFLS.pendingChanges[option] = value;
86
+ }
87
+
88
+ $(optionElement).trigger('change', [false]);
89
+ WFLS.updatePendingChanges();
90
+ });
91
+
92
+ $('#wfls-enable-auth-captcha-label').on('click', function(e) {
93
+ var links = $(this).find('a');
94
+ var buffer = 10;
95
+ for (var i = 0; i < links.length; i++) {
96
+ var t = $(links[i]).offset().top;
97
+ var l = $(links[i]).offset().left;
98
+ var b = t + $(links[i]).height();
99
+ var r = l + $(links[i]).width();
100
+
101
+ if (e.pageX > l - buffer && e.pageX < r + buffer && e.pageY > t - buffer && e.pageY < b + buffer) {
102
+ return;
103
+ }
104
+ }
105
+ $(this).closest('.wfls-option').find('.wfls-option-checkbox').trigger('click');
106
+ }).css('cursor', 'pointer');
107
+
108
+ $('#input-recaptchaSiteKey, #input-recaptchaSecret').on('change paste keyup', function() {
109
+ var e = this;
110
+
111
+ setTimeout(function() {
112
+ var optionElement = $(e).closest('.wfls-option');
113
+ var option = optionElement.data('textOption');
114
+
115
+ if (typeof option !== 'undefined') {
116
+ var value = $(e).val();
117
+
118
+ var originalValue = $(optionElement).data('originalValue');
119
+ if (originalValue == value) {
120
+ delete WFLS.pendingChanges[option];
121
+ }
122
+ else {
123
+ WFLS.pendingChanges[option] = value;
124
+ }
125
+
126
+ $(optionElement).trigger('change', [false]);
127
+ WFLS.updatePendingChanges();
128
+ }
129
+ }, 4);
130
+ });
131
+
132
+ $(window).on('wflsOptionsReset', function() {
133
+ $('#wfls-enable-auth-captcha').each(function() {
134
+ var enabledValue = $(this).data('enabledValue');
135
+ var disabledValue = $(this).data('disabledValue');
136
+ var originalValue = $(this).data('originalValue');
137
+ if (enabledValue == originalValue) {
138
+ $(this).find('#wfls-enable-auth-captcha.wfls-option-checkbox').addClass('wfls-checked').attr('aria-checked', 'true');
139
+ }
140
+ else {
141
+ $(this).find('#wfls-enable-auth-captcha.wfls-option-checkbox').removeClass('wfls-checked').attr('aria-checked', 'false');
142
+ }
143
+ $(this).trigger('change', [true]);
144
+ });
145
+ $('#input-recaptchaSiteKey, #input-recaptchaSecret').each(function() {
146
+ $(this).val($(this).data('originalValue'));
147
+ $(this).attr('disabled', !$('#wfls-enable-auth-captcha.wfls-option-checkbox').hasClass('wfls-checked'));
148
+ });
149
+ });
150
+ });
151
+ })(jQuery);
152
+ </script>
views/options/option-ip-source.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents the global option OPTION_IP_SOURCE with a value select menu and text area (hidden by default) for trusted proxies.
5
+ */
6
+
7
+ $selectOptions = array(
8
+ array('value' => \WordfenceLS\Model_Request::IP_SOURCE_AUTOMATIC, 'label' => esc_html__('Use the most secure method to get visitor IP addresses. Prevents spoofing and works with most sites.', 'wordfence-2fa') . ' <strong>' . esc_html__('(Recommended)', 'wordfence-2fa') . '</strong>'),
9
+ array('value' => \WordfenceLS\Model_Request::IP_SOURCE_REMOTE_ADDR, 'label' => esc_html__('Use PHP\'s built in REMOTE_ADDR and don\'t use anything else. Very secure if this is compatible with your site.', 'wordfence-2fa')),
10
+ array('value' => \WordfenceLS\Model_Request::IP_SOURCE_X_FORWARDED_FOR, 'label' => esc_html__('Use the X-Forwarded-For HTTP header. Only use if you have a front-end proxy or spoofing may result.', 'wordfence-2fa')),
11
+ array('value' => \WordfenceLS\Model_Request::IP_SOURCE_X_REAL_IP, 'label' => esc_html__('Use the X-Real-IP HTTP header. Only use if you have a front-end proxy or spoofing may result.', 'wordfence-2fa')),
12
+ );
13
+ ?>
14
+ <ul class="wfls-flex-vertical wfls-flex-full-width">
15
+ <li>
16
+ <ul id="wfls-option-ip-source" class="wfls-option wfls-option-ip-source" data-option="<?php echo esc_attr(\WordfenceLS\Controller_Settings::OPTION_IP_SOURCE); ?>" data-original-value="<?php echo esc_attr(\WordfenceLS\Controller_Settings::shared()->get(\WordfenceLS\Controller_Settings::OPTION_IP_SOURCE)); ?>" data-text-area-option="<?php echo esc_attr(\WordfenceLS\Controller_Settings::OPTION_IP_TRUSTED_PROXIES); ?>" data-original-text-area-value="<?php echo esc_attr(\WordfenceLS\Controller_Settings::shared()->get(\WordfenceLS\Controller_Settings::OPTION_IP_TRUSTED_PROXIES)); ?>">
17
+ <li class="wfls-option-content wfls-no-right">
18
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
19
+ <li class="wfls-option-title"><strong><?php _e('How to get IPs', 'wordfence-2fa'); ?></strong></li>
20
+ <li>
21
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
22
+ <li class="wfls-padding-add-left">
23
+ <ul class="wfls-flex-vertical wfls-flex-align-left" role="radiogroup">
24
+ <?php foreach ($selectOptions as $o): ?>
25
+ <li class="wfls-padding-add-top-small"><input type="radio" class="wfls-option-radio" name="wfls-ip-source" value="<?php echo esc_attr($o['value']); ?>" id="wfls-ip-source-<?php echo esc_attr(preg_replace('/[^a-z0-9]/i', '-', $o['value'])); ?>"<?php if ($o['value'] == \WordfenceLS\Controller_Settings::shared()->get(\WordfenceLS\Controller_Settings::OPTION_IP_SOURCE)) { echo ' checked'; } ?>><label for="wfls-ip-source-<?php echo esc_attr(preg_replace('/[^a-z0-9]/i', '-', $o['value'])); ?>">&nbsp;&nbsp;</label><?php echo $o['label']; ?></li>
26
+ <?php endforeach; ?>
27
+ </ul>
28
+ </li>
29
+ <li class="wfls-option-ip-source-details wfls-padding-add-top">
30
+ <div class="wfls-left">Detected IP(s): <span id="wfls-ip-source-preview-all"><?php echo \WordfenceLS\Model_Request::current()->detected_ip_preview(); ?></span></div>
31
+ <div class="wfls-left">Your IP with this setting: <span id="wfls-ip-source-preview-single"><?php echo esc_html(\WordfenceLS\Model_Request::current()->ip()); ?></span></div>
32
+ <div class="wfls-left"><a href="#" id="wfls-ip-source-trusted-proxies-show">+ Edit trusted proxies</a></div>
33
+ </li>
34
+ </ul>
35
+ </li>
36
+ </ul>
37
+ </li>
38
+ </ul>
39
+ </li>
40
+ <li id="wfls-ip-source-trusted-proxies">
41
+ <ul id="wfls-option-ip-source-trusted-proxies" class="wfls-option wfls-option-textarea" data-text-option="<?php echo esc_attr(\WordfenceLS\Controller_Settings::OPTION_IP_TRUSTED_PROXIES); ?>" data-original-text-value="<?php echo esc_attr(\WordfenceLS\Controller_Settings::shared()->get(\WordfenceLS\Controller_Settings::OPTION_IP_TRUSTED_PROXIES)); ?>">
42
+ <li class="wfls-option-spacer"></li>
43
+ <li class="wfls-option-content wfls-no-right">
44
+ <ul>
45
+ <li class="wfls-option-title">
46
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
47
+ <li><?php _e('Trusted Proxies', 'wordfence-2fa'); ?></li>
48
+ <li class="wfls-option-subtitle"><?php _e('These IPs (or CIDR ranges) will be ignored when determining the requesting IP via the X-Forwarded-For HTTP header. Enter one IP or CIDR range per line.', 'wordfence-2fa'); ?></li>
49
+ </ul>
50
+ </li>
51
+ <li class="wfls-option-textarea">
52
+ <textarea spellcheck="false" autocapitalize="none" autocomplete="off" name="howGetIPs_trusted_proxies"><?php echo esc_html(\WordfenceLS\Controller_Settings::shared()->get(\WordfenceLS\Controller_Settings::OPTION_IP_TRUSTED_PROXIES)); ?></textarea>
53
+ </li>
54
+ </ul>
55
+ </li>
56
+ </ul>
57
+ </li>
58
+ </ul>
59
+ <script type="application/javascript">
60
+ (function($) {
61
+ $(function() {
62
+ var updateIPPreview = function() {
63
+ WFLS.updateIPPreview({ip_source: $('input[name="wfls-ip-source"]:checked').val(), ip_source_trusted_proxies: $('#wfls-ip-source-trusted-proxies textarea').val()}, function(ret) {
64
+ if (ret && ret.ip) {
65
+ $('#wfls-ip-source-preview-all').html(ret.preview);
66
+ $('#wfls-ip-source-preview-single').html(ret.ip);
67
+ }
68
+ });
69
+ };
70
+
71
+ $('input[name="wfls-ip-source"]').on('change', function() {
72
+ var optionElement = $(this).closest('.wfls-option.wfls-option-ip-source');
73
+ var option = optionElement.data('option');
74
+ var value = $('input[name="wfls-ip-source"]:checked').val();
75
+
76
+ var originalValue = optionElement.data('originalValue');
77
+ if (originalValue == value) {
78
+ delete WFLS.pendingChanges[option];
79
+ }
80
+ else {
81
+ WFLS.pendingChanges[option] = value;
82
+ }
83
+
84
+ WFLS.updatePendingChanges();
85
+
86
+ updateIPPreview();
87
+ });
88
+
89
+ var coalescingUpdateTimer;
90
+ $('#wfls-ip-source-trusted-proxies textarea').on('change paste keyup', function() {
91
+ var e = this;
92
+
93
+ setTimeout(function() {
94
+ clearTimeout(coalescingUpdateTimer);
95
+ coalescingUpdateTimer = setTimeout(updateIPPreview, 1000);
96
+
97
+ var optionElement = $(e).closest('.wfls-option.wfls-option-textarea');
98
+ var option = optionElement.data('textOption');
99
+ var value = $(e).val();
100
+
101
+ var originalValue = optionElement.data('originalTextValue');
102
+ if (originalValue == value) {
103
+ delete WFLS.pendingChanges[option];
104
+ }
105
+ else {
106
+ WFLS.pendingChanges[option] = value;
107
+ }
108
+
109
+ WFLS.updatePendingChanges();
110
+ }, 4);
111
+ });
112
+
113
+ $(window).on('wflsOptionsReset', function() {
114
+ $('input[name="wfls-ip-source"]').each(function() {
115
+ var optionElement = $(this).closest('.wfls-option.wfls-option-ip-source');
116
+ var option = optionElement.data('option');
117
+ var originalValue = optionElement.data('originalValue');
118
+
119
+ $(this).attr('checked', originalValue == $(this).attr('value'));
120
+ });
121
+
122
+ $('#wfls-ip-source-trusted-proxies textarea').each(function() {
123
+ var optionElement = $(this).closest('.wfls-option.wfls-option-textarea');
124
+ var originalValue = optionElement.data('originalTextAreaValue');
125
+ $(this).val(originalValue);
126
+ });
127
+
128
+ updateIPPreview();
129
+ });
130
+
131
+ $('#wfls-ip-source-trusted-proxies-show').each(function() {
132
+ $(this).on('keydown', function(e) {
133
+ if (e.keyCode == 32) {
134
+ e.preventDefault();
135
+ e.stopPropagation();
136
+
137
+ $(this).trigger('click');
138
+ }
139
+ });
140
+
141
+ $(this).on('click', function(e) {
142
+ e.preventDefault();
143
+ e.stopPropagation();
144
+
145
+ var isActive = $('#wfls-ip-source-trusted-proxies').hasClass('wfls-active');
146
+ if (isActive) {
147
+ $('#wfls-ip-source-trusted-proxies').slideUp({
148
+ always: function() {
149
+ $('#wfls-ip-source-trusted-proxies').removeClass('wfls-active');
150
+ }
151
+ });
152
+ }
153
+ else {
154
+ $(this).parent().slideUp();
155
+ $('#wfls-ip-source-trusted-proxies').slideDown({
156
+ always: function() {
157
+ $('#wfls-ip-source-trusted-proxies').addClass('wfls-active');
158
+ }
159
+ });
160
+ }
161
+ });
162
+ });
163
+ });
164
+ })(jQuery);
165
+ </script>
views/options/option-label.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents an option-styled text value.
5
+ *
6
+ * Expects $title (or $titleHTML) to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $title The title shown for the option.
9
+ * @var string $titleHTML The raw HTML title shown for the option. This supersedes $title.
10
+ * @var string $helpLink If defined, the link to the corresponding external help page.
11
+ */
12
+
13
+ if (!isset($titleHTML)) {
14
+ $titleHTML = esc_html($title);
15
+ }
16
+ ?>
17
+ <ul class="wfls-option wfls-option-label">
18
+ <?php if (!isset($noSpacer) || !$noSpacer): ?>
19
+ <li class="wfls-option-spacer"></li>
20
+ <?php endif; ?>
21
+ <li class="wfls-option-content">
22
+ <ul>
23
+ <li class="wfls-option-title">
24
+ <?php if (isset($subtitle)): ?>
25
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
26
+ <li>
27
+ <?php endif; ?>
28
+ <?php echo $titleHTML; ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
29
+ <?php if (isset($subtitle)): ?>
30
+ </li>
31
+ <li class="wfls-option-subtitle"><?php echo esc_html($subtitle); ?></li>
32
+ </ul>
33
+ <?php endif; ?>
34
+ </li>
35
+ </ul>
36
+ </li>
37
+ </ul>
views/options/option-require-2fa.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+
4
+ $requireOptionName = \WordfenceLS\Controller_Settings::OPTION_REQUIRE_2FA_ADMIN;
5
+ $currentRequireValue = \WordfenceLS\Controller_Settings::shared()->get_bool($requireOptionName);
6
+
7
+ $gracePeriodEnabledOptionName = \WordfenceLS\Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED;
8
+ $currentGracePeriodEnabledValue = \WordfenceLS\Controller_Settings::shared()->get_bool($gracePeriodEnabledOptionName);
9
+
10
+ $gracePeriodDateOptionName = \WordfenceLS\Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD;
11
+ $currentGracePeriodDateValue = \WordfenceLS\Controller_Settings::shared()->get_int($gracePeriodDateOptionName, \WordfenceLS\Controller_Time::time() + 7 *84600);
12
+
13
+ if ($currentGracePeriodEnabledValue && $currentGracePeriodDateValue < \WordfenceLS\Controller_Time::time()) { //Clear the grace period settings if this is the first page view since it expired
14
+ \WordfenceLS\Controller_Settings::shared()->set($gracePeriodEnabledOptionName, false);
15
+ $currentGracePeriodEnabledValue = false;
16
+ \WordfenceLS\Controller_Settings::shared()->remove($gracePeriodDateOptionName);
17
+ $currentGracePeriodDateValue = \WordfenceLS\Controller_Settings::shared()->get_int($gracePeriodDateOptionName, \WordfenceLS\Controller_Time::time() + 7 *84600);
18
+ }
19
+
20
+ $timeZoneMinutes = 0;
21
+ $tz = get_option('timezone_string');
22
+ if (!empty($tz)) {
23
+ $timezone = new DateTimeZone($tz);
24
+ $dtStr = gmdate("c", (int) $currentGracePeriodDateValue); //Have to do it this way because of PHP 5.2
25
+ $dt = new DateTime($dtStr, $timezone);
26
+ $timeZoneMinutes = (int) ($timezone->getOffset($dt) / 60);
27
+ }
28
+ else {
29
+ $gmt = get_option('gmt_offset');
30
+ if (!empty($gmt)) {
31
+ $timeZoneMinutes = (int) ($gmt * 60);
32
+ }
33
+ }
34
+ ?>
35
+ <ul id="wfls-option-require-2fa" data-option="<?php echo esc_attr($requireOptionName); ?>" data-enabled-value="1" data-disabled-value="0" data-original-value="<?php echo $currentRequireValue ? '1' : '0'; ?>">
36
+ <li>
37
+ <ul class="wfls-option wfls-padding-add-bottom-small">
38
+ <li id="wfls-require-2fa-admin" class="wfls-option-checkbox<?php echo ($currentRequireValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($currentRequireValue ? 'true' : 'false'); ?>" tabindex="0"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true" aria-labelledby="wfls-require-2fa-admin-label"></i></li>
39
+ <li class="wfls-option-title">
40
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
41
+ <li>
42
+ <strong id="wfls-require-2fa-admin-label"><?php _e('Require 2FA for all administrators', 'wordfence-2fa'); ?></strong>
43
+ </li>
44
+ <li class="wfls-option-subtitle"><?php _e('Note: This setting requires at least one administrator to have 2FA active. On multisite, this option applies only to super admins.', 'wordfence-2fa'); ?></li>
45
+ </ul>
46
+ </li>
47
+ </ul>
48
+ </li>
49
+ <li>
50
+ <ul class="wfls-option wfls-padding-no-top">
51
+ <li class="wfls-option-spacer"></li>
52
+ <li id="wfls-require-2fa-grace-period" class="wfls-flex-horizontal wfls-option-date">
53
+ <div class="wfls-option-checkbox<?php echo $currentGracePeriodEnabledValue ? ' wfls-checked' : ''; ?><?php echo $currentRequireValue ? '' : ' wfls-disabled'; ?>" data-original-value="<?php echo $currentGracePeriodEnabledValue ? '1' : '0'; ?>"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true"></i></div>
54
+ <span id="wfls-require-2fa-grace-period-label" class="wfls-padding-add-left wfls-padding-add-right"><?php _e('Grace period to require 2FA', 'wordfence'); ?> </span>
55
+ <input type="text" name="require2FAGracePeriod" id="input-require2FAGracePeriod" class="wfls-datetime wfls-form-control" placeholder="Enabled on..." data-value="<?php echo $currentGracePeriodDateValue; ?>" data-original-value="<?php echo $currentGracePeriodDateValue; ?>"<?php echo $currentGracePeriodEnabledValue ? '' : ' disabled'; ?>>
56
+ <div class="wfls-padding-add-left"><a href="#" id="wfls-send-grace-period-notification" class="wfls-btn wfls-btn-sm wfls-btn-default<?php echo (\WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_REQUIRE_2FA_ADMIN) && \WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD_ENABLED) && \WordfenceLS\Controller_Time::time() < \WordfenceLS\Controller_Settings::shared()->get_int(\WordfenceLS\Controller_Settings::OPTION_REQUIRE_2FA_GRACE_PERIOD)) ? '' : ' wfls-disabled'; ?>"><?php _e('Send Notification', 'wordfence-2fa'); ?></a></div>
57
+ </li>
58
+ </ul>
59
+ </li>
60
+ </ul>
61
+ <script type="application/javascript">
62
+ (function($) {
63
+ $(function() {
64
+ $('#wfls-require-2fa-admin').on('keydown', function(e) {
65
+ if (e.keyCode == 32) {
66
+ e.preventDefault();
67
+ e.stopPropagation();
68
+
69
+ $(this).trigger('click');
70
+ }
71
+ });
72
+
73
+ $('#wfls-require-2fa-admin').on('click', function(e) {
74
+ e.preventDefault();
75
+ e.stopPropagation();
76
+
77
+ var optionElement = $('#wfls-option-require-2fa');
78
+ if (optionElement.hasClass('wfls-disabled')) {
79
+ return;
80
+ }
81
+
82
+ var option = optionElement.data('option');
83
+ var value = false;
84
+ var isActive = $(this).hasClass('wfls-checked');
85
+ if (isActive) {
86
+ $(this).removeClass('wfls-checked').attr('aria-checked', 'false');
87
+ $('#wfls-require-2fa-grace-period .wfls-option-checkbox').addClass('wfls-disabled');
88
+ $('#wfls-option-require-2fa .wfls-datetime').attr('disabled', true);
89
+ value = optionElement.data('disabledValue');
90
+ }
91
+ else {
92
+ $(this).addClass('wfls-checked').attr('aria-checked', 'true');
93
+ $('#wfls-require-2fa-grace-period .wfls-option-checkbox').removeClass('wfls-disabled');
94
+ if ($('#wfls-require-2fa-grace-period .wfls-option-checkbox').hasClass('wfls-checked')) {
95
+ $('#wfls-option-require-2fa .wfls-datetime').attr('disabled', false);
96
+ }
97
+ value = optionElement.data('enabledValue');
98
+ }
99
+
100
+ var originalValue = optionElement.data('originalValue');
101
+ if (originalValue == value) {
102
+ delete WFLS.pendingChanges[option];
103
+ }
104
+ else {
105
+ WFLS.pendingChanges[option] = value;
106
+ }
107
+
108
+ $(optionElement).trigger('change', [false]);
109
+ WFLS.updatePendingChanges();
110
+ });
111
+
112
+ $('#wfls-require-2fa-admin-label, #wfls-require-2fa-grace-period-label').on('click', function(e) {
113
+ var links = $(this).find('a');
114
+ var buffer = 10;
115
+ for (var i = 0; i < links.length; i++) {
116
+ var t = $(links[i]).offset().top;
117
+ var l = $(links[i]).offset().left;
118
+ var b = t + $(links[i]).height();
119
+ var r = l + $(links[i]).width();
120
+
121
+ if (e.pageX > l - buffer && e.pageX < r + buffer && e.pageY > t - buffer && e.pageY < b + buffer) {
122
+ return;
123
+ }
124
+ }
125
+ $(this).closest('.wfls-option').find('.wfls-option-checkbox').trigger('click');
126
+ }).css('cursor', 'pointer');
127
+
128
+ $('#wfls-option-require-2fa .wfls-datetime').datetimepicker({
129
+ dateFormat: 'yy-mm-dd',
130
+ timezone: <?php echo $timeZoneMinutes; ?>,
131
+ showTime: false,
132
+ showTimepicker: false,
133
+ showMonthAfterYear: true
134
+ }).each(function() {
135
+ var el = $(this);
136
+ if (el.attr('data-value')) {
137
+ el.datetimepicker('setDate', new Date(el.attr('data-value') * 1000));
138
+ }
139
+ }).on('change', function() {
140
+ var value = Math.floor($(this).datetimepicker('getDate').getTime() / 1000);
141
+ var originalValue = $('#input-require2FAGracePeriod').data('originalValue');
142
+ if (originalValue == value) {
143
+ delete WFLS.pendingChanges['<?php echo esc_js($gracePeriodDateOptionName); ?>'];
144
+ }
145
+ else {
146
+ WFLS.pendingChanges['<?php echo esc_js($gracePeriodDateOptionName); ?>'] = $(this).val();
147
+ }
148
+ WFLS.updatePendingChanges();
149
+ });
150
+
151
+ $('#wfls-require-2fa-grace-period .wfls-option-checkbox').on('click', function(e) {
152
+ e.preventDefault();
153
+ e.stopPropagation();
154
+
155
+ if ($(this).hasClass('wfls-disabled')) {
156
+ return;
157
+ }
158
+
159
+ var originalValue = $(this).data('originalValue');
160
+ var value = originalValue;
161
+ var isActive = $(this).hasClass('wfls-checked');
162
+ if (isActive) {
163
+ $(this).removeClass('wfls-checked');
164
+ $('#wfls-option-require-2fa .wfls-datetime').attr('disabled', true);
165
+ value = 0;
166
+ }
167
+ else {
168
+ $(this).addClass('wfls-checked');
169
+ $('#wfls-option-require-2fa .wfls-datetime').attr('disabled', false);
170
+ value = 1;
171
+
172
+ if (!$('#input-require2FAGracePeriod').val()) {
173
+ var date = new Date();
174
+ date.setDate(date.getDate() + 7);
175
+ $('#input-require2FAGracePeriod').datetimepicker('setDate', date);
176
+ }
177
+ }
178
+
179
+ if (originalValue == value) {
180
+ delete WFLS.pendingChanges['<?php echo esc_js($gracePeriodEnabledOptionName); ?>'];
181
+ }
182
+ else {
183
+ WFLS.pendingChanges['<?php echo esc_js($gracePeriodEnabledOptionName); ?>'] = value;
184
+ }
185
+
186
+ $('#wfls-option-require-2fa .wfls-datetime').trigger('change');
187
+
188
+ WFLS.updatePendingChanges();
189
+ });
190
+
191
+ $(window).on('wflsOptionsReset', function() {
192
+ $('#wfls-option-require-2fa').each(function() {
193
+ var enabledValue = $(this).data('enabledValue');
194
+ var disabledValue = $(this).data('disabledValue');
195
+ var originalValue = $(this).data('originalValue');
196
+ if (enabledValue == originalValue) {
197
+ $(this).find('#wfls-require-2fa-admin.wfls-option-checkbox').addClass('wfls-checked').attr('aria-checked', 'true');
198
+ }
199
+ else {
200
+ $(this).find('#wfls-require-2fa-admin.wfls-option-checkbox').removeClass('wfls-checked').attr('aria-checked', 'false');
201
+ }
202
+ $(this).trigger('change', [true]);
203
+ });
204
+ $('#wfls-require-2fa-grace-period .wfls-option-checkbox').each(function() {
205
+ var originalValue = $(this).data('originalValue');
206
+ $(this).toggleClass('wfls-checked', !!originalValue);
207
+ $('#wfls-option-require-2fa .wfls-datetime').attr('disabled', !originalValue);
208
+ });
209
+ $('.wfls-datetime').each(function() {
210
+ var el = $(this);
211
+ if (el.attr('data-value')) {
212
+ el.datetimepicker('setDate', new Date(el.attr('data-value') * 1000));
213
+ }
214
+ else {
215
+ el.val('');
216
+ }
217
+ });
218
+ });
219
+
220
+ $('#wfls-send-grace-period-notification').on('click', function(e) {
221
+ e.preventDefault();
222
+ e.stopPropagation();
223
+
224
+ WFLS.ajax('wordfence_ls_send_grace_period_notification', [],
225
+ function(response) {
226
+ if (response.error) {
227
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Sending Notification', 'wordfence-2fa')); ?>', response.error);
228
+ }
229
+ else {
230
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Notification Sent', 'wordfence-2fa')); ?>', response.confirmation);
231
+ }
232
+ },
233
+ function (error) {
234
+ WFLS.panelModal((WFLS.screenSize(500) ? '300px' : '400px'), '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('Error Sending Notification', 'wordfence-2fa')); ?>', '<?php echo \WordfenceLS\Text\Model_JavaScript::esc_js(__('An error was encountered while trying to send the notification. Please try again.', 'wordfence-2fa')); ?>');
235
+ });
236
+ });
237
+ });
238
+ })(jQuery);
239
+ </script>
views/options/option-select.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents an option with a popup menu for detailed value selection.
5
+ *
6
+ * Expects $selectOptionName, $selectOptions, $selectValue, and $title to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $selectOptionName The option name for the select portion.
9
+ * @var array $selectOptions An array of the possible values for $selectOptionName. The array is of the format array(array('value' => <the internal value>, 'label' => <a display label>), ...)
10
+ * @var string $selectValue The current value of $selectOptionName.
11
+ * @var string $title The title shown for the option.
12
+ * @var string $helpLink If defined, the link to the corresponding external help page.
13
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
14
+ */
15
+
16
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $selectOptionName);
17
+ ?>
18
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-select<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-select-option="<?php echo esc_attr($selectOptionName); ?>" data-original-select-value="<?php echo esc_attr($selectValue); ?>">
19
+ <li class="wfls-option-spacer"></li>
20
+ <li class="wfls-option-content">
21
+ <ul>
22
+ <li class="wfls-option-title"><span id="<?php echo esc_attr($id); ?>-label"><?php echo esc_html($title); ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?></li>
23
+ <li class="wfls-option-select wfls-padding-add-top-xs-small">
24
+ <select<?php echo (!(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?> aria-labelledby="<?php echo esc_attr($id); ?>-label">
25
+ <?php foreach ($selectOptions as $o): ?>
26
+ <option class="wfls-option-select-option" value="<?php echo esc_attr($o['value']); ?>"<?php if ($o['value'] == $selectValue) { echo ' selected'; } ?>><?php echo esc_html($o['label']); ?></option>
27
+ <?php endforeach; ?>
28
+ </select>
29
+ </li>
30
+ </ul>
31
+ </li>
32
+ </ul>
views/options/option-switch.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a switch option.
5
+ *
6
+ * @var string $optionName The option name for the switch. Required.
7
+ * @var string $value The current value of $optionName. Required.
8
+ * @var string|\WordfenceLS\Text\Model_HTML $title The title shown for the option. Required.
9
+ * @var array $states An array of the possible states for the switch. The array matches the format array('value' => <value>, 'label' => <label>) Required.
10
+ * @var string $helpLink If defined, the link to the corresponding external help page. Optional.
11
+ * @var string $alignment If defined, controls the alignment of the switch control. Optional.
12
+ */
13
+
14
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $optionName);
15
+ ?>
16
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-switch" data-option-name="<?php echo esc_attr($optionName); ?>" data-original-value="<?php echo esc_attr($value); ?>">
17
+ <?php if (!isset($noSpacer) || !$noSpacer): ?>
18
+ <li class="wfls-option-spacer"></li>
19
+ <?php endif; ?>
20
+ <li class="wfls-option-content wfls-no-right">
21
+ <ul>
22
+ <li class="wfls-option-title">
23
+ <?php if (isset($subtitle)): ?>
24
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
25
+ <li>
26
+ <?php endif; ?>
27
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($title); ?></span><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
28
+ <?php if (isset($subtitle)): ?>
29
+ </li>
30
+ <li class="wfls-option-subtitle"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($subtitle); ?></li>
31
+ </ul>
32
+ <?php endif; ?>
33
+ </li>
34
+ <li class="wfls-option-switch<?php if (isset($alignment)) { echo ' ' . $alignment; } ?> wfls-padding-add-top-xs-small">
35
+ <ul class="wfls-switch" role="radiogroup" aria-labelledby="<?php echo esc_attr($id); ?>-label">
36
+ <?php foreach ($states as $s): ?>
37
+ <li<?php if ($s['value'] == $value) { echo ' class="wfls-active"'; } ?> data-option-value="<?php echo esc_attr($s['value']); ?>" role="radio" aria-checked="<?php echo ($s['value'] == $value ? 'true' : 'false'); ?>" tabindex="0"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($s['label']); ?></li>
38
+ <?php endforeach; ?>
39
+ </ul>
40
+ </li>
41
+ </ul>
42
+ </li>
43
+ </ul>
views/options/option-text.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a text field option.
5
+ *
6
+ * Expects $textOptionName, $textValue, and $title to be defined. $placeholder and $helpLink may also be defined.
7
+ *
8
+ * @var string $textOptionName The option name for the text field.
9
+ * @var string $textValue The current value of $textOptionName.
10
+ * @var string $title The title shown for the option.
11
+ * @var string $placeholder If defined, the placeholder for the text field.
12
+ * @var string $helpLink If defined, the link to the corresponding external help page.
13
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
14
+ */
15
+
16
+ if (!isset($placeholder)) {
17
+ $placeholder = '';
18
+ }
19
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $textOptionName);
20
+ ?>
21
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-text<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-text-option="<?php echo esc_attr($textOptionName); ?>" data-original-text-value="<?php echo esc_attr($textValue); ?>">
22
+ <li class="wfls-option-spacer"></li>
23
+ <li class="wfls-option-content">
24
+ <ul>
25
+ <li class="wfls-option-title">
26
+ <?php if (isset($subtitle)): ?>
27
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
28
+ <li>
29
+ <?php endif; ?>
30
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo esc_html($title); ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
31
+ <?php if (isset($subtitle)): ?>
32
+ </li>
33
+ <li class="wfls-option-subtitle"><?php echo esc_html($subtitle); ?></li>
34
+ </ul>
35
+ <?php endif; ?>
36
+ </li>
37
+ <li class="wfls-option-text">
38
+ <input type="text" value="<?php echo esc_attr($textValue); ?>" placeholder="<?php echo esc_attr($placeholder); ?>"<?php echo (!(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?> aria-labelledby="<?php echo esc_attr($id); ?>-label">
39
+ </li>
40
+ </ul>
41
+ </li>
42
+ </ul>
views/options/option-textarea.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a text area option.
5
+ *
6
+ * Expects $textOptionName, $textValue, and $title to be defined. $helpLink, $premium, and $noSpacer may also be defined.
7
+ *
8
+ * @var string $textOptionName The option name for the text field. Required.
9
+ * @var string $textValue The current value of $textOptionName. Required.
10
+ * @var string|\WordfenceLS\Text\Model_HTML $title The title shown for the option. Required.
11
+ * @var string|\WordfenceLS\Text\Model_HTML $subtitle The title shown for the option. Optional.
12
+ * @var string $subtitlePosition The position for the subtitle: 'value' for below the value, 'title' for below the title. Optional.
13
+ * @var string $helpLink If defined, the link to the corresponding external help page. Optional.
14
+ * @var bool $noSpacer If defined and truthy, the spacer will be omitted. Optional.
15
+ */
16
+
17
+ if (!isset($subtitlePosition)) { //May be 'title' to appear below the title or 'value' to appear below the field
18
+ $subtitlePosition = 'title';
19
+ }
20
+
21
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $textOptionName);
22
+ ?>
23
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-textarea" data-text-option="<?php echo esc_attr($textOptionName); ?>" data-original-text-value="<?php echo esc_attr($textValue); ?>">
24
+ <?php if (!isset($noSpacer) || !$noSpacer): ?>
25
+ <li class="wfls-option-spacer"></li>
26
+ <?php endif; ?>
27
+ <li class="wfls-option-content wfls-no-right">
28
+ <ul>
29
+ <li class="wfls-option-title<?php if (isset($alignTitle)) { echo $alignTitle == 'top' ? ' wfls-option-title-top' : ($alignTitle == 'bottom' ? 'wfls-option-title-bottom' : ''); } ?>">
30
+ <?php if (isset($subtitleHTML) && $subtitlePosition == 'title'): ?>
31
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
32
+ <li>
33
+ <?php endif; ?>
34
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($title); ?></span><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
35
+ <?php if (isset($subtitle) && $subtitlePosition == 'title'): ?>
36
+ </li>
37
+ <li class="wfls-option-subtitle"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($subtitle); ?></li>
38
+ </ul>
39
+ <?php endif; ?>
40
+ </li>
41
+ <li class="wfls-option-textarea">
42
+ <?php if (isset($subtitle) && $subtitlePosition == 'value'): ?>
43
+ <ul class="wfls-flex-vertical wfls-flex-align-left wfls-flex-full-width">
44
+ <li>
45
+ <?php endif; ?>
46
+ <textarea aria-labelledby="<?php echo esc_attr($id); ?>-label"><?php echo esc_html($textValue); ?></textarea>
47
+ <?php if (isset($subtitle) && $subtitlePosition == 'value'): ?>
48
+ </li>
49
+ <li class="wfls-option-subtitle"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($subtitle); ?></li>
50
+ </ul>
51
+ <?php endif; ?>
52
+ </li>
53
+ </ul>
54
+ </li>
55
+ </ul>
views/options/option-toggled-boolean-switch.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a boolean option with a switch toggle control.
5
+ *
6
+ * Expects $optionName, $enabledValue, $disabledValue, $value, and $title to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $optionName The option name.
9
+ * @var string $enabledValue The value to save in $option if the toggle is enabled.
10
+ * @var string $disabledValue The value to save in $option if the toggle is disabled.
11
+ * @var string $value The current value of $optionName.
12
+ * @var string $title The title shown for the option.
13
+ * @var string $htmlTitle The unescaped title shown for the option.
14
+ * @var string $helpLink If defined, the link to the corresponding external help page.
15
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
16
+ * @var bool $disabled If defined and truthy, the option will start out disabled.
17
+ */
18
+
19
+ if (isset($subtitle) && !isset($subtitleHTML)) {
20
+ $subtitleHTML = esc_html($subtitle);
21
+ }
22
+
23
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $optionName);
24
+ ?>
25
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-toggled-boolean-switch<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?><?php if (isset($disabled) && $disabled) { echo ' wfls-disabled'; } ?>" data-option="<?php echo esc_attr($optionName); ?>" data-enabled-value="<?php echo esc_attr($enabledValue); ?>" data-disabled-value="<?php echo esc_attr($disabledValue); ?>" data-original-value="<?php echo esc_attr($value == $enabledValue ? $enabledValue : $disabledValue); ?>">
26
+ <li class="wfls-boolean-switch<?php echo ($value == $enabledValue ? ' wfls-active' : ''); ?>" role="checkbox" aria-checked="<?php echo ($value == $enabledValue ? 'true' : 'false'); ?>" tabindex="0" aria-labelledby="<?php echo esc_attr($id); ?>-label"><a href="#" class="wfls-boolean-switch-handle"></a></li>
27
+ <li class="wfls-option-title">
28
+ <?php if (isset($subtitleHTML)): ?>
29
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
30
+ <li>
31
+ <?php endif; ?>
32
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo (!empty($title)) ? esc_html($title) : ''; echo (!empty($htmlTitle)) ? wp_kses($htmlTitle, 'post') : ''; ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
33
+ <?php if (isset($subtitleHTML)): ?>
34
+ </li>
35
+ <li class="wfls-option-subtitle"><?php echo $subtitleHTML; ?></li>
36
+ </ul>
37
+ <?php endif; ?>
38
+ </li>
39
+ </ul>
views/options/option-toggled-multiple.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents multiple boolean options under a single heading with a checkbox toggle control for each.
5
+ *
6
+ * @var array $options The options shown. The structure is defined below. Required.
7
+ * @var string|\WordfenceLS\Text\Model_HTML $title The overall title shown for the options. Required.
8
+ * @var string $helpLink The link to the corresponding external help page. Optional.
9
+ * @var bool $wrap Whether or not the options should be allowed to wrap. Optional, defaults to false.
10
+ *
11
+ * $options is an array of
12
+ * array(
13
+ * 'name' => string <option name>,
14
+ * 'enabledValue' => string <value saved if the toggle is enabled>,
15
+ * 'disabledValue' => string <value saved if the toggle is disabled>,
16
+ * 'value' => string <current value of the option>,
17
+ * 'title' => string|\Wordfence2FA\Text\Model_HTML <title displayed to label the checkbox>,
18
+ * 'editable' => bool Whether or not the option can be edited, defaults to true.
19
+ * )
20
+ */
21
+ ?>
22
+ <ul class="wfls-option wfls-option-toggled-multiple">
23
+ <li class="wfls-option-title"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($title); ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?></li>
24
+ <li class="wfls-option-checkboxes<?php if (isset($wrap) && $wrap) { echo ' wfls-option-checkboxes-wrap'; } ?>">
25
+ <?php
26
+ foreach ($options as $o):
27
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $o['name']);
28
+ ?>
29
+ <ul id="<?php echo esc_attr($id); ?>" data-option="<?php echo esc_attr($o['name']); ?>" data-enabled-value="<?php echo esc_attr($o['enabledValue']); ?>" data-disabled-value="<?php echo esc_attr($o['disabledValue']); ?>" data-original-value="<?php echo esc_attr($o['value'] == $o['enabledValue'] ? $o['enabledValue'] : $o['disabledValue']); ?>">
30
+ <li class="wfls-option-checkbox<?php echo ($o['value'] == $o['enabledValue'] ? ' wfls-checked' : ''); ?><?php echo (isset($o['editable']) && !$o['editable'] ? ' wfls-disabled' : ''); ?>" role="checkbox" aria-checked="<?php echo ($o['value'] == $o['enabledValue'] ? 'true' : 'false'); ?>" tabindex="0" aria-labelledby="<?php echo esc_attr($id); ?>-label"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true"></i></li>
31
+ <li id="<?php echo esc_attr($id); ?>-label" class="wfls-option-title"><?php echo esc_html($o['title']); ?></li>
32
+ </ul>
33
+ <?php endforeach; ?>
34
+ </li>
35
+ </ul>
views/options/option-toggled-segmented.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a boolean option with a checkbox toggle control.
5
+ *
6
+ * Expects $optionName, $enabledValue, $disabledValue, $value, and $title to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $optionName The option name.
9
+ * @var string $enabledValue The value to save in $option if the toggle is enabled.
10
+ * @var string $disabledValue The value to save in $option if the toggle is disabled.
11
+ * @var string $value The current value of $optionName.
12
+ * @var string $title The title shown for the option.
13
+ * @var string $htmlTitle The unescaped title shown for the option.
14
+ * @var string $helpLink If defined, the link to the corresponding external help page.
15
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
16
+ */
17
+
18
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $optionName);
19
+ ?>
20
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-toggled-segmented<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-option="<?php echo esc_attr($optionName); ?>" data-enabled-value="<?php echo esc_attr($enabledValue); ?>" data-disabled-value="<?php echo esc_attr($disabledValue); ?>" data-original-value="<?php echo esc_attr($value == $enabledValue ? $enabledValue : $disabledValue); ?>">
21
+ <li class="wfls-option-title"><?php echo (!empty($title)) ? esc_html($title) : ''; echo (!empty($htmlTitle)) ? wp_kses($htmlTitle, 'post') : ''; ?><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?></li>
22
+ <li class="wfls-option-segments">
23
+ <?php
24
+ $onId = sanitize_key('wfls-segment-' . $optionName . '-on');
25
+ $offId = sanitize_key('wfls-segment-' . $optionName . '-off');
26
+ ?>
27
+ <input id="<?php echo esc_attr($onId) ?>" type="radio" name="<?php echo esc_attr($optionName) ?>" value="<?php echo esc_attr($enabledValue) ?>"<?php echo ($value == $enabledValue ? ' checked' : ''); ?><?php echo (!(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?>>
28
+ <label class="wfls-segment-first" for="<?php echo esc_attr($onId) ?>">On</label>
29
+
30
+ <input id="<?php echo esc_attr($offId) ?>" type="radio" name="<?php echo esc_attr($optionName) ?>" value="<?php echo esc_attr($disabledValue) ?>"<?php echo ($value == $disabledValue ? ' checked' : ''); ?><?php echo (!(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?>>
31
+ <label class="wfls-segment-last" for="<?php echo esc_attr($offId) ?>">Off</label>
32
+ </li>
33
+ </ul>
views/options/option-toggled-select.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents an option with a boolean on/off toggle checkbox and popup menu for detailed value selection.
5
+ *
6
+ * Expects $toggleOptionName, $enabledToggleValue, $disabledToggleValue, $toggleValue, $selectOptionName, $selectOptions, $selectValue, and $title to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $toggleOptionName The option name for the toggle portion.
9
+ * @var string $enabledToggleValue The value to save in $toggleOption if the toggle is enabled.
10
+ * @var string $disabledToggleValue The value to save in $toggleOption if the toggle is disabled.
11
+ * @var string $toggleValue The current value of $toggleOptionName.
12
+ * @var string $selectOptionName The option name for the select portion.
13
+ * @var array $selectOptions An array of the possible values for $selectOptionName. The array is of the format array(array('value' => <the internal value>, 'label' => <a display label>), ...)
14
+ * @var string $selectValue The current value of $selectOptionName.
15
+ * @var string $title The title shown for the option.
16
+ * @var string $helpLink If defined, the link to the corresponding external help page.
17
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
18
+ */
19
+
20
+ $toggleID = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $toggleOptionName);
21
+ $selectID = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $selectOptionName);
22
+ ?>
23
+ <ul class="wfls-option wfls-option-toggled-select<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-toggle-option="<?php echo esc_attr($toggleOptionName); ?>" data-enabled-toggle-value="<?php echo esc_attr($enabledToggleValue); ?>" data-disabled-toggle-value="<?php echo esc_attr($disabledToggleValue); ?>" data-original-toggle-value="<?php echo esc_attr($toggleValue == $enabledToggleValue ? $enabledToggleValue : $disabledToggleValue); ?>" data-select-option="<?php echo esc_attr($selectOptionName); ?>" data-original-select-value="<?php echo esc_attr($selectValue); ?>">
24
+ <li id="<?php echo esc_attr($toggleID); ?>" class="wfls-option-checkbox<?php echo ($toggleValue == $enabledToggleValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($toggleValue == $enabledToggleValue ? 'true' : 'false'); ?>" tabindex="0"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true"></i></li>
25
+ <li class="wfls-option-content">
26
+ <ul id="<?php echo esc_attr($selectID); ?>">
27
+ <li class="wfls-option-title"><span id="<?php echo esc_attr($selectID); ?>-label"><?php echo esc_html($title); ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?></li>
28
+ <li class="wfls-option-select wfls-padding-add-top-xs-small">
29
+ <select<?php echo ($toggleValue == $enabledToggleValue && !(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?> aria-labelledby="<?php echo esc_attr($selectID); ?>-label">
30
+ <?php foreach ($selectOptions as $o): ?>
31
+ <option class="wfls-option-select-option" value="<?php echo esc_attr($o['value']); ?>"<?php if ($o['value'] == $selectValue) { echo ' selected'; } ?>><?php echo esc_html($o['label']); ?></option>
32
+ <?php endforeach; ?>
33
+ </select>
34
+ </li>
35
+ </ul>
36
+ </li>
37
+ </ul>
views/options/option-toggled-sub.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a boolean option with a checkbox toggle control and a sub-option toggle.
5
+ *
6
+ * Expects $optionName, $enabledValue, $disabledValue, $value, and $title to be defined for the primary option. $helpLink may also be defined.
7
+ * Expects $subOptionName, $subEnabledValue, $subDisabledValue, $subValue, and $subTitle to be defined for the sub-option. $subHelpLink may also be defined.
8
+ *
9
+ * @var string $optionName The option name.
10
+ * @var string $enabledValue The value to save in $optionName if the toggle is enabled.
11
+ * @var string $disabledValue The value to save in $optionName if the toggle is disabled.
12
+ * @var string $value The current value of $optionName.
13
+ * @var string $title The title shown for the option.
14
+ * @var string $htmlTitle The unescaped title shown for the option.
15
+ * @var string $helpLink If defined, the link to the corresponding external help page.
16
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
17
+ *
18
+ * @var string $subOptionName The sub-option name.
19
+ * @var string $subEnabledValue The value to save in $subOptionName if the toggle is enabled.
20
+ * @var string $subDisabledValue The value to save in $subOptionName if the toggle is disabled.
21
+ * @var string $subValue The current value of $subOptionName.
22
+ * @var string $subTitle The title shown for the sub-option.
23
+ * @var string $subHtmlTitle The unescaped title shown for the sub-option.
24
+ * @var string $subHelpLink If defined, the link to the corresponding external help page for the sub-option.
25
+ * @var bool $subPremium If defined, the sub-option will be tagged as premium only and not allow its value to change for free users.
26
+ */
27
+
28
+ if (isset($title) && !isset($htmlTitle)) {
29
+ $htmlTitle = esc_html($title);
30
+ }
31
+
32
+ if (isset($subTitle) && !isset($subHtmlTitle)) {
33
+ $subHtmlTitle = esc_html($subTitle);
34
+ }
35
+
36
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $optionName);
37
+ $subID = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $subOptionName);
38
+ ?>
39
+ <ul class="wfls-flex-vertical wfls-flex-full-width">
40
+ <li>
41
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-toggled<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-option="<?php echo esc_attr($optionName); ?>" data-enabled-value="<?php echo esc_attr($enabledValue); ?>" data-disabled-value="<?php echo esc_attr($disabledValue); ?>" data-original-value="<?php echo esc_attr($value == $enabledValue ? $enabledValue : $disabledValue); ?>">
42
+ <li class="wfls-option-checkbox<?php echo ($value == $enabledValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($value == $enabledValue ? 'true' : 'false'); ?>" tabindex="0" aria-labelledby="<?php echo esc_attr($id); ?>-label"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true"></i></li>
43
+ <li class="wfls-option-title">
44
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo $htmlTitle; ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
45
+ </li>
46
+ </ul>
47
+ </li>
48
+ <li class="wfls-option-sub">
49
+ <ul id="<?php echo esc_attr($subID); ?>" class="wfls-option wfls-option-toggled<?php if (!wfConfig::p() && isset($subPremium) && $subPremium) { echo ' wfls-option-premium'; } ?>" data-option="<?php echo esc_attr($subOptionName); ?>" data-enabled-value="<?php echo esc_attr($subEnabledValue); ?>" data-disabled-value="<?php echo esc_attr($subDisabledValue); ?>" data-original-value="<?php echo esc_attr($subValue == $subEnabledValue ? $subEnabledValue : $subDisabledValue); ?>">
50
+ <li class="wfls-option-checkbox<?php echo ($subValue == $subEnabledValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($subValue == $subEnabledValue ? 'true' : 'false'); ?>" tabindex="0" aria-labelledby="<?php echo esc_attr($subID); ?>-label"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true"></i></li>
51
+ <li class="wfls-option-title">
52
+ <span id="<?php echo esc_attr($subID); ?>-label"><?php echo $subHtmlTitle; ?></span><?php if (!wfConfig::p() && isset($subPremium) && $subPremium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($subHelpLink)) { echo ' <a href="' . esc_attr($subHelpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
53
+ </li>
54
+ </ul>
55
+ </li>
56
+ </ul>
views/options/option-toggled-textarea.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents an option with a boolean on/off toggle checkbox and text area for detailed value entry.
5
+ *
6
+ * Expects $toggleOptionName, $enabledToggleValue, $disabledToggleValue, $toggleValue, $textAreaOptionName, $textAreaValue, and $title to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $toggleOptionName The option name for the toggle portion.
9
+ * @var string $enabledToggleValue The value to save in $toggleOption if the toggle is enabled.
10
+ * @var string $disabledToggleValue The value to save in $toggleOption if the toggle is disabled.
11
+ * @var string $toggleValue The current value of $toggleOptionName.
12
+ * @var string $textAreaOptionName The option name for the text area portion.
13
+ * @var string $textAreaValue The current value of $textAreaOptionName.
14
+ * @var string $title The title shown for the option.
15
+ * @var string $helpLink If defined, the link to the corresponding external help page.
16
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
17
+ */
18
+
19
+ $toggleID = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $toggleOptionName);
20
+ $textAreaID = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $textAreaOptionName);
21
+ ?>
22
+ <ul class="wfls-option wfls-option-toggled-textarea<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-toggle-option="<?php echo esc_attr($toggleOptionName); ?>" data-enabled-toggle-value="<?php echo esc_attr($enabledToggleValue); ?>" data-disabled-toggle-value="<?php echo esc_attr($disabledToggleValue); ?>" data-original-toggle-value="<?php echo esc_attr($toggleValue == $enabledToggleValue ? $enabledToggleValue : $disabledToggleValue); ?>" data-text-area-option="<?php echo esc_attr($textAreaOptionName); ?>" data-original-text-area-value="<?php echo esc_attr($textAreaValue); ?>">
23
+ <li id="<?php echo esc_attr($toggleID); ?>" class="wfls-option-checkbox<?php echo ($toggleValue == $enabledToggleValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($toggleValue == $enabledToggleValue ? 'true' : 'false'); ?>" tabindex="0"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true" aria-labelledby="<?php echo esc_attr($toggleID); ?>-label"></i></li>
24
+ <li class="wfls-option-title"><span id="<?php echo esc_attr($toggleID); ?>-label"><?php echo esc_html($title); ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?></li>
25
+ <li id="<?php echo esc_attr($textAreaID); ?>" class="wfls-option-textarea">
26
+ <select<?php echo ($toggleValue == $enabledToggleValue && !(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?> aria-labelledby="<?php echo esc_attr($toggleID); ?>-label">
27
+ <textarea<?php echo (!(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?>><?php echo esc_html($textAreaValue); ?></textarea>
28
+ </select>
29
+ </li>
30
+ </ul>
views/options/option-toggled.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents a boolean option with a checkbox toggle control.
5
+ *
6
+ * @var string $optionName The option name. Required.
7
+ * @var string $enabledValue The value to save in $option if the toggle is enabled. Required.
8
+ * @var string $disabledValue The value to save in $option if the toggle is disabled. Required.
9
+ * @var string $value The current value of $optionName. Required.
10
+ * @var string|\WordfenceLS\Text\Model_HTML $title The title shown for the option. Required.
11
+ * @var string|\WordfenceLS\Text\Model_HTML $subtitle The title shown for the option. Optional.
12
+ * @var string $helpLink If defined, the link to the corresponding external help page. Optional.
13
+ * @var bool $disabled If defined and truthy, the option will start out disabled. Optional.
14
+ */
15
+
16
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $optionName);
17
+ ?>
18
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-toggled<?php if (isset($disabled) && $disabled) { echo ' wfls-disabled'; } ?>" data-option="<?php echo esc_attr($optionName); ?>" data-enabled-value="<?php echo esc_attr($enabledValue); ?>" data-disabled-value="<?php echo esc_attr($disabledValue); ?>" data-original-value="<?php echo esc_attr($value == $enabledValue ? $enabledValue : $disabledValue); ?>">
19
+ <li class="wfls-option-checkbox<?php echo ($value == $enabledValue ? ' wfls-checked' : ''); ?>" role="checkbox" aria-checked="<?php echo ($value == $enabledValue ? 'true' : 'false'); ?>" tabindex="0" aria-labelledby="<?php echo esc_attr($id); ?>-label"><i class="wfls-ion-ios-checkmark-empty" aria-hidden="true"></i></li>
20
+ <li class="wfls-option-title">
21
+ <?php if (isset($subtitle)): ?>
22
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
23
+ <li>
24
+ <?php endif; ?>
25
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($title); ?></span><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
26
+ <?php if (isset($subtitle)): ?>
27
+ </li>
28
+ <li class="wfls-option-subtitle"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($subtitle); ?></li>
29
+ </ul>
30
+ <?php endif; ?>
31
+ </li>
32
+ </ul>
views/options/option-token.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * Presents an option with a token field for value entry.
5
+ *
6
+ * Expects $tokenOptionName, $tokenValue, and $title to be defined. $helpLink may also be defined.
7
+ *
8
+ * @var string $tokenOptionName The option name.
9
+ * @var array $tokenValue The current value of $tokenOptionName. It will be JSON-encoded as an array of strings.
10
+ * @var string $title The title shown for the option.
11
+ * @var string $helpLink If defined, the link to the corresponding external help page.
12
+ * @var bool $premium If defined, the option will be tagged as premium only and not allow its value to change for free users.
13
+ */
14
+
15
+ $id = 'wfls-option-' . preg_replace('/[^a-z0-9]/i', '-', $tokenOptionName);
16
+ ?>
17
+ <ul id="<?php echo esc_attr($id); ?>" class="wfls-option wfls-option-token<?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' wfls-option-premium'; } ?>" data-token-option="<?php echo esc_attr($tokenOptionName); ?>" data-original-token-value="<?php echo esc_attr(json_encode($tokenValue)); ?>">
18
+ <li class="wfls-option-spacer"></li>
19
+ <li class="wfls-flex-vertical wfls-flex-align-left">
20
+ <div class="wfls-option-title">
21
+ <?php if (isset($subtitle)): ?>
22
+ <ul class="wfls-flex-vertical wfls-flex-align-left">
23
+ <li>
24
+ <?php endif; ?>
25
+ <span id="<?php echo esc_attr($id); ?>-label"><?php echo esc_html($title); ?></span><?php if (!wfConfig::p() && isset($premium) && $premium) { echo ' <a href="https://www.wordfence.com/gnl1optionUpgrade/wordfence-signup/" target="_blank" rel="noopener noreferrer" class="wfls-premium-link">' . __('Premium Feature', 'wordfence') . '</a>'; } ?><?php if (isset($helpLink)) { echo ' <a href="' . esc_attr($helpLink) . '" target="_blank" rel="noopener noreferrer" class="wfls-inline-help"><i class="' . (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-question-circle-o' : 'wfls-fa wfls-fa-question-circle-o') . '" aria-hidden="true"></i></a>'; } ?>
26
+ <?php if (isset($subtitle)): ?>
27
+ </li>
28
+ <li class="wfls-option-subtitle"><?php echo esc_html($subtitle); ?></li>
29
+ </ul>
30
+ <?php endif; ?>
31
+ </div>
32
+ <select multiple<?php echo (!(!wfConfig::p() && isset($premium) && $premium) ? '' : ' disabled'); ?> aria-labelledby="<?php echo esc_attr($id); ?>-label">
33
+ <?php foreach ($tokenValue as $o): ?>
34
+ <option value="<?php echo esc_attr($o); ?>" selected><?php echo esc_html($o); ?></option>
35
+ <?php endforeach; ?>
36
+ </select>
37
+ <div class="wfls-option-token-tags"></div>
38
+ </li>
39
+ </ul>
views/page/manage.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+
4
+ /**
5
+ * @var \WP_User $user The user being edited. Required.
6
+ * @var bool $canEditUsers Whether or not the viewer of the page can edit other users. Optional, defaults to false.
7
+ */
8
+
9
+ if (!isset($canEditUsers)) {
10
+ $canEditUsers = false;
11
+ }
12
+
13
+ $ownAccount = false;
14
+ $ownUser = wp_get_current_user();
15
+ if ($ownUser->ID == $user->ID) {
16
+ $ownAccount = true;
17
+ }
18
+
19
+ $enabled = \WordfenceLS\Controller_Users::shared()->has_2fa_active($user);
20
+
21
+ ?>
22
+ <p><?php printf(__('Two-Factor Authentication, or 2FA, significantly improves login security for your website. Wordfence 2FA works with a number of TOTP-based apps like Google Authenticator, FreeOTP, and Authy. For a full list of tested TOTP-based apps, <a href="%s" target="_blank" rel="noopener noreferrer">click here</a>.', 'wordfence-2fa'), \WordfenceLS\Controller_Support::esc_supportURL(\WordfenceLS\Controller_Support::ITEM_MODULE_LOGIN_SECURITY_2FA)); ?></p>
23
+ <?php if ($canEditUsers): ?>
24
+ <div id="wfls-editing-display" class="wfls-flex-row wfls-flex-row-xs-wrappable wfls-flex-row-equal-heights">
25
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width wfls-add-bottom">
26
+ <div class="wfls-block-header wfls-block-header-border-bottom">
27
+ <div class="wfls-block-header-content">
28
+ <div class="wfls-block-title">
29
+ <strong><?php printf(__('Editing User:&nbsp;&nbsp;%s <span class="wfls-text-plain">%s</span>', 'wordfence-2fa'), get_avatar($user->ID, 16, '', $user->user_login), \WordfenceLS\Text\Model_HTML::esc_html($user->user_login) . ($ownAccount ? ' ' . __('(you)', 'wordfence-2fa') : '')); ?></strong>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <?php endif; ?>
36
+ <div id="wfls-deactivation-controls" class="wfls-flex-row wfls-flex-row-wrappable wfls-flex-row-equal-heights"<?php if (!$enabled) { echo ' style="display: none;"'; } ?>>
37
+ <!-- begin status content -->
38
+ <div class="wfls-flex-row wfls-flex-row-equal-heights wfls-flex-item-xs-100">
39
+ <?php
40
+ echo \WordfenceLS\Model_View::create('manage/deactivate', array(
41
+ 'user' => $user,
42
+ ))->render();
43
+ ?>
44
+ </div>
45
+ <!-- end status content -->
46
+ <!-- begin regenerate codes -->
47
+ <div class="wfls-flex-row wfls-flex-row-equal-heights wfls-flex-item-xs-100">
48
+ <?php
49
+ echo \WordfenceLS\Model_View::create('manage/regenerate', array(
50
+ 'user' => $user,
51
+ 'remaining' => \WordfenceLS\Controller_Users::shared()->recovery_code_count($user),
52
+ ))->render();
53
+ ?>
54
+ </div>
55
+ <!-- end regenerate codes -->
56
+ </div>
57
+ <div id="wfls-activation-controls" class="wfls-flex-row wfls-flex-row-xs-wrappable wfls-flex-row-equal-heights"<?php if ($enabled) { echo ' style="display: none;"'; } ?>>
58
+ <?php
59
+ $secret = \WordfenceLS\Model_Crypto::random_bytes(20);
60
+ $base32 = new \WordfenceLS\Crypto\Model_Base2n(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', false, true, true);
61
+ $base32Secret = $base32->encode($secret);
62
+ $totpURL = "otpauth://totp/" . rawurlencode(preg_replace('~^https?://~i', '', home_url()) . ' (' . $user->user_login . ')') . '?secret=' . $base32Secret . '&algorithm=SHA1&digits=6&period=30&issuer=Wordfence';
63
+ $codes = \WordfenceLS\Controller_Users::shared()->regenerate_recovery_codes();
64
+ ?>
65
+ <!-- begin qr code -->
66
+ <div class="wfls-flex-row wfls-flex-row-equal-heights wfls-col-sm-half-padding-right wfls-flex-item-xs-100 wfls-flex-item-sm-50">
67
+ <?php
68
+ echo \WordfenceLS\Model_View::create('manage/code', array(
69
+ 'secret' => $secret,
70
+ 'base32Secret' => $base32Secret,
71
+ 'totpURL' => $totpURL,
72
+ ))->render();
73
+ ?>
74
+ </div>
75
+ <!-- end qr code -->
76
+ <!-- begin activation -->
77
+ <div class="wfls-flex-row wfls-flex-row-equal-heights wfls-col-sm-half-padding-left wfls-flex-item-xs-100 wfls-flex-item-sm-50">
78
+ <?php
79
+ echo \WordfenceLS\Model_View::create('manage/activate', array(
80
+ 'secret' => $secret,
81
+ 'base32Secret' => $base32Secret,
82
+ 'recovery' => $codes,
83
+ 'user' => $user,
84
+ ))->render();
85
+ ?>
86
+ </div>
87
+ <!-- end activation -->
88
+ </div>
89
+ <?php
90
+ /**
91
+ * Fires after the main content of the activation page has been output.
92
+ */
93
+ do_action('wfls_activation_page_footer');
94
+ $time = time();
95
+ $correctedTime = \WordfenceLS\Controller_Time::time($time);
96
+ $tz = get_option('timezone_string');
97
+ if (empty($tz)) {
98
+ $offset = get_option('gmt_offset');
99
+ $tz = 'UTC' . ($offset >= 0 ? '+' . $offset : $offset);
100
+ }
101
+ ?>
102
+ <?php if (\WordfenceLS\Controller_Permissions::shared()->can_manage_settings()): ?>
103
+ <p><?php _e('Server Time:', 'wordfence-2fa'); ?> <?php echo date('Y-m-d H:i:s', $time); ?> UTC (<?php echo \WordfenceLS\Controller_Time::format_local_time('Y-m-d H:i:s', $time) . ' ' . $tz; ?>)<br>
104
+ <?php _e('Browser Time:', 'wordfence-2fa'); ?> <script type="application/javascript">var date = new Date(); document.write(date.toUTCString() + ' (' + date.toString() + ')');</script><br>
105
+ <?php
106
+ if (\WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_USE_NTP)) {
107
+ echo __('Corrected Time (NTP):', 'wordfence-2fa') . ' ' . date('Y-m-d H:i:s', $correctedTime) . ' UTC (' . \WordfenceLS\Controller_Time::format_local_time('Y-m-d H:i:s', $correctedTime) . ' ' . $tz . ')<br>';
108
+ }
109
+ else if (WORDFENCE_LS_FROM_CORE && $correctedTime != $time) {
110
+ echo __('Corrected Time (WF):', 'wordfence-2fa') . ' ' . date('Y-m-d H:i:s', $correctedTime) . ' UTC (' . \WordfenceLS\Controller_Time::format_local_time('Y-m-d H:i:s', $correctedTime) . ' ' . $tz . ')<br>';
111
+ }
112
+ ?>
113
+ <?php _e('Detected IP:', 'wordfence-2fa'); ?> <?php echo \WordfenceLS\Text\Model_HTML::esc_html(\WordfenceLS\Model_Request::current()->ip()); if (\WordfenceLS\Controller_Whitelist::shared()->is_whitelisted(\WordfenceLS\Model_Request::current()->ip())) { echo ' (' . __('whitelisted', 'wordfence-2fa') . ')'; } ?></p>
114
+ <?php endif; ?>
views/page/page.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+
4
+ /**
5
+ * @var array $sections The content tabs, each element is an array of the syntax array('tab' => Model_Tab instance, 'title' => Title instance, 'content' => HTML content). Required.
6
+ */
7
+ ?>
8
+ <div class="wrap wordfence-ls">
9
+ <?php
10
+ if (\WordfenceLS\Controller_Permissions::shared()->can_manage_settings() && !\WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_DISMISSED_FRESH_INSTALL_MODAL) && !WORDFENCE_LS_FROM_CORE) {
11
+ echo \WordfenceLS\Model_View::create('onboarding/standalone-header')->render();
12
+ }
13
+ ?>
14
+ <div class="wfls-container-fluid">
15
+ <?php
16
+ $tabs = array_map(function($t) { return $t['tab']; }, $sections);
17
+ echo \WordfenceLS\Model_View::create('page/tabbar', array(
18
+ 'tabs' => $tabs,
19
+ ))->render();
20
+ ?>
21
+ <div class="wfls-row">
22
+ <div class="wfls-col-xs-12">
23
+ <?php foreach ($sections as $s): ?>
24
+ <div id="<?php echo esc_attr($s['tab']->id); ?>" class="wfls-tab-content" data-title="<?php echo esc_attr($s['tab']->pageTitle); ?>">
25
+ <?php
26
+ echo \WordfenceLS\Model_View::create('page/section-title', array(
27
+ 'title' => $s['title'],
28
+ ))->render();
29
+ echo $s['content'];
30
+ ?>
31
+ </div> <!-- end <?php echo \WordfenceLS\Text\Model_HTML::esc_html($s['tab']->id); ?> block -->
32
+ <?php endforeach; ?>
33
+ </div> <!-- end content block -->
34
+ </div> <!-- end row -->
35
+ </div> <!-- end container -->
36
+ </div>
views/page/section-title.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var \WordfenceLS\Page\Model_Title $title The page title parameters.
5
+ * @var bool $showIcon Whether or not to show the header icon. Optional, defaults to false.
6
+ */
7
+ ?>
8
+ <div class="wfls-section-title">
9
+ <?php if (isset($showIcon) && $showIcon): ?>
10
+ <div class="wfls-header-icon wfls-hidden-xs"></div>
11
+ <?php endif; ?>
12
+ <h2 class="wfls-center-xs" id="section-title-<?php echo esc_attr($title->id); ?>"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($title->title); ?></h2>
13
+ <?php if ($title->helpURL !== null && $title->helpLink !== null): ?>
14
+ <span class="wfls-hidden-xs"><a href="<?php echo esc_url($title->helpURL); ?>" target="_blank" rel="noopener noreferrer" class="wfls-help-link"><?php echo \WordfenceLS\Text\Model_HTML::esc_html($title->helpLink); ?> <i class="<?php echo (WORDFENCE_LS_FROM_CORE ? 'wf-fa wf-fa-external-link' : 'wfls-fa wfls-fa-external-link'); ?>" aria-hidden="true"></i></a></span>
15
+ <?php endif; ?>
16
+ </div>
views/page/settings.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ ?>
4
+ <div id="wfls-settings" class="wfls-flex-row wfls-flex-row-wrappable wfls-flex-row-equal-heights">
5
+ <!-- begin status content -->
6
+ <div id="wfls-user-stats" class="wfls-flex-row wfls-flex-row-equal-heights wfls-flex-item-xs-100">
7
+ <?php
8
+ echo \WordfenceLS\Model_View::create('settings/user-stats', array(
9
+ 'counts' => \WordfenceLS\Controller_Users::shared()->detailed_user_counts(),
10
+ ))->render();
11
+ ?>
12
+ </div>
13
+ <!-- end status content -->
14
+ <!-- begin options content -->
15
+ <div id="wfls-options" class="wfls-flex-row wfls-flex-row-equal-heights wfls-flex-item-xs-100">
16
+ <?php
17
+ echo \WordfenceLS\Model_View::create('settings/options', array(
18
+
19
+ ))->render();
20
+ ?>
21
+ </div>
22
+ <!-- end options content -->
23
+ </div>
views/page/tabbar.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var array $tabs An array of Tab instances. Required.
5
+ */
6
+ ?>
7
+ <div class="wfls-row wfls-tab-container">
8
+ <div class="wfls-col-xs-12">
9
+ <div class="wp-header-end"></div>
10
+ <ul class="wfls-page-tabs">
11
+ <li class="wfls-header-icon"></li>
12
+ <?php foreach ($tabs as $t): ?>
13
+ <?php
14
+ $a = $t->a;
15
+ if (!preg_match('/^https?:\/\//i', $a)) {
16
+ $a = '#top#' . urlencode($a);
17
+ }
18
+ ?>
19
+ <li class="wfls-tab" id="wfls-tab-<?php echo esc_attr($t->id); ?>" data-target="<?php echo esc_attr($t->id); ?>" data-page-title="<?php echo esc_attr($t->pageTitle); ?>"><a href="<?php echo esc_url($a); ?>"><?php echo esc_html($t->tabTitle); ?></a></li>
20
+ <?php endforeach; ?>
21
+ </ul>
22
+ </div>
23
+ </div>
views/settings/options.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ ?>
4
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width">
5
+ <div class="wfls-block-header wfls-block-header-border-bottom">
6
+ <div class="wfls-block-header-content">
7
+ <div class="wfls-block-title">
8
+ <strong><?php _e('Settings', 'wordfence-2fa'); ?></strong>
9
+ </div>
10
+ </div>
11
+ <div class="wfls-block-header-action wfls-block-header-action-text wfls-nowrap wfls-padding-add-right-responsive">
12
+ <a href="#" id="wfls-cancel-changes" class="wfls-btn wfls-btn-sm wfls-btn-default wfls-disabled"><?php _e('Cancel Changes', 'wordfence-2fa'); ?></a>&nbsp;&nbsp;<a href="#" id="wfls-save-changes" class="wfls-btn wfls-btn-sm wfls-btn-primary wfls-disabled"><?php _e('Save Changes', 'wordfence-2fa'); ?></a>
13
+ </div>
14
+ </div>
15
+ <div class="wfls-block-content">
16
+ <ul class="wfls-block-list">
17
+ <li>
18
+ <?php
19
+ $roles = new \WP_Roles();
20
+ $options = array();
21
+ if (is_multisite()) {
22
+ $options[] = array(
23
+ 'name' => 'enabled-roles.super-admin',
24
+ 'enabledValue' => '1',
25
+ 'disabledValue' => '0',
26
+ 'value' => '1',
27
+ 'title' => __('Super Administrator', 'wordfence-2fa'),
28
+ 'editable' => false,
29
+ );
30
+ }
31
+
32
+ foreach ($roles->role_objects as $name => $r) {
33
+ /** @var \WP_Role $r */
34
+ $options[] = array(
35
+ 'name' => 'enabled-roles.' . $name,
36
+ 'enabledValue' => '1',
37
+ 'disabledValue' => '0',
38
+ 'value' => $r->has_cap(\WordfenceLS\Controller_Permissions::CAP_ACTIVATE_2FA_SELF) ? '1' : '0',
39
+ 'title' => $roles->role_names[$name],
40
+ 'editable' => (!is_multisite() && $name == 'administrator' ? false : true),
41
+ );
42
+ }
43
+
44
+ echo \WordfenceLS\Model_View::create('options/option-toggled-multiple', array(
45
+ 'title' => new \WordfenceLS\Text\Model_HTML('<strong>' . __('Enable 2FA for these roles', 'wordfence-2fa') . '</strong>'),
46
+ 'options' => $options,
47
+ 'wrap' => true,
48
+ ))->render();
49
+ ?>
50
+ </li>
51
+ <li>
52
+ <?php
53
+ echo \WordfenceLS\Model_View::create('options/option-require-2fa', array(
54
+ ))->render();
55
+ ?>
56
+ </li>
57
+ <li>
58
+ <?php
59
+ echo \WordfenceLS\Model_View::create('options/option-toggled', array(
60
+ 'optionName' => \WordfenceLS\Controller_Settings::OPTION_REMEMBER_DEVICE_ENABLED,
61
+ 'enabledValue' => '1',
62
+ 'disabledValue' => '0',
63
+ 'value' => \WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_REMEMBER_DEVICE_ENABLED) ? '1': '0',
64
+ 'title' => new \WordfenceLS\Text\Model_HTML('<strong>' . __('Allow remembering device for 30 days', 'wordfence-2fa') . '</strong>'),
65
+ 'subtitle' => __('If enabled, users with 2FA enabled may choose to be prompted for a code only once every 30 days per device.', 'wordfence-2fa'),
66
+ ))->render();
67
+ ?>
68
+ </li>
69
+ <li>
70
+ <?php
71
+ echo \WordfenceLS\Model_View::create('options/option-switch', array(
72
+ 'optionName' => \WordfenceLS\Controller_Settings::OPTION_XMLRPC_ENABLED,
73
+ 'value' => \WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_XMLRPC_ENABLED) ? '1': '0',
74
+ 'title' => new \WordfenceLS\Text\Model_HTML('<strong>' . __('Require 2FA for XML-RPC call authentication', 'wordfence-2fa') . '</strong>'),
75
+ 'subtitle' => __('If enabled, XML-RPC calls that require authentication will also require a valid 2FA code to be appended to the password. You must choose the "Skipped" option if you use the WordPress app, the Jetpack plugin, or other services that require XML-RPC.', 'wordfence-2fa'),
76
+ 'states' => array(
77
+ array('value' => '0', 'label' => __('Skipped', 'wordfence-2fa')),
78
+ array('value' => '1', 'label' => __('Required', 'wordfence-2fa')),
79
+ ),
80
+ 'noSpacer' => true,
81
+ 'alignment' => 'wfls-right',
82
+ ))->render();
83
+ ?>
84
+ </li>
85
+ <li>
86
+ <?php
87
+ echo \WordfenceLS\Model_View::create('options/option-toggled', array(
88
+ 'optionName' => \WordfenceLS\Controller_Settings::OPTION_ALLOW_XML_RPC,
89
+ 'enabledValue' => '0',
90
+ 'disabledValue' => '1',
91
+ 'value' => \WordfenceLS\Controller_Settings::shared()->get_bool(\WordfenceLS\Controller_Settings::OPTION_ALLOW_XML_RPC) ? '1': '0',
92
+ 'title' => new \WordfenceLS\Text\Model_HTML('<strong>' . __('Disable XML-RPC authentication', 'wordfence-2fa') . '</strong>'),
93
+ 'subtitle' => __('If disabled, XML-RPC requests that attempt authentication will be rejected.', 'wordfence-2fa'),
94
+ ))->render();
95
+ ?>
96
+ </li>
97
+ <li>
98
+ <?php
99
+ echo \WordfenceLS\Model_View::create('options/option-textarea', array(
100
+ 'textOptionName' => \WordfenceLS\Controller_Settings::OPTION_2FA_WHITELISTED,
101
+ 'textValue' => implode("\n", \WordfenceLS\Controller_Settings::shared()->whitelisted_ips()),
102
+ 'title' => new \WordfenceLS\Text\Model_HTML('<strong>' . __('Whitelisted IP addresses that bypass 2FA', 'wordfence-2fa') . '</strong>'),
103
+ 'alignTitle' => 'top',
104
+ 'subtitle' => __('Whitelisted IPs must be placed on separate lines. You can specify ranges using the following formats: 127.0.0.1/24, 127.0.0.[1-100], or 127.0.0.1-127.0.1.100.', 'wordfence-2fa'),
105
+ 'subtitlePosition' => 'value',
106
+ 'noSpacer' => true,
107
+ ))->render();
108
+ ?>
109
+ </li>
110
+ <li>
111
+ <?php
112
+ echo \WordfenceLS\Model_View::create('options/option-captcha', array(
113
+ ))->render();
114
+ ?>
115
+ </li>
116
+ <?php if (!WORDFENCE_LS_FROM_CORE): ?>
117
+ <li>
118
+ <?php
119
+ echo \WordfenceLS\Model_View::create('options/option-ip-source', array())->render();
120
+ ?>
121
+ </li>
122
+ <?php endif; ?>
123
+ </ul>
124
+ </div>
125
+ </div>
views/settings/user-stats.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!defined('WORDFENCE_LS_VERSION')) { exit; }
3
+ /**
4
+ * @var array $counts The counts to display. Required.
5
+ */
6
+ ?>
7
+ <div class="wfls-block wfls-always-active wfls-flex-item-full-width">
8
+ <div class="wfls-block-header wfls-block-header-border-bottom">
9
+ <div class="wfls-block-header-content">
10
+ <div class="wfls-block-title">
11
+ <strong><?php _e('User Summary', 'wordfence-2fa'); ?></strong>
12
+ </div>
13
+ </div>
14
+ <div class="wfls-block-header-action wfls-block-header-action-text wfls-nowrap wfls-padding-add-right-responsive">
15
+ <a href="users.php"><?php _e('Manage Users', 'wordfence'); ?></a>
16
+ </div>
17
+ </div>
18
+ <div class="wfls-block-content wfls-padding-no-left wfls-padding-no-right">
19
+ <table class="wfls-table wfls-table-striped wfls-table-header-separators wfls-table-expanded wfls-no-bottom">
20
+ <thead>
21
+ <tr>
22
+ <th><?php _e('Role', 'wordfence-2fa'); ?></th>
23
+ <th class="wfls-center"><?php _e('Total Users', 'wordfence-2fa'); ?></th>
24
+ <th class="wfls-center"><?php _e('2FA Active', 'wordfence-2fa'); ?></th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <?php
29
+ $roles = new WP_Roles();
30
+ foreach ($counts['avail_roles'] as $roleTag => $count):
31
+ $role = $roles->get_role($roleTag);
32
+ if (!$role) { continue; }
33
+ $names = $roles->get_names();
34
+ $roleName = $names[$roleTag];
35
+ ?>
36
+ <tr>
37
+ <td><?php echo \WordfenceLS\Text\Model_HTML::esc_html(translate_user_role($roleName)); ?></td>
38
+ <td class="wfls-center"><?php echo number_format($count); ?></td>
39
+ <td class="wfls-center"><?php echo (isset($counts['active_avail_roles'][$roleTag]) ? number_format($counts['active_avail_roles'][$roleTag]) : 0); ?></td>
40
+ </tr>
41
+ <?php endforeach; ?>
42
+ </tbody>
43
+ <tfoot>
44
+ <tr>
45
+ <th><?php _e('Total', 'wordfence-2fa'); ?></th>
46
+ <th class="wfls-center"><?php echo number_format($counts['total_users']); ?></th>
47
+ <th class="wfls-center"><?php echo number_format($counts['active_total_users']); ?></th>
48
+ </tr>
49
+ <?php if (is_multisite()): ?>
50
+ <tr>
51
+ <td colspan="3" class="wfls-text-small"><?php _e('* User counts currently only reflect the main site on multisite installations.', 'wordfence-2fa'); ?></td>
52
+ </tr>
53
+ <?php endif; ?>
54
+ </tfoot>
55
+ </table>
56
+ </div>
57
+ </div>
wordfence-login-security.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Wordfence Login Security
4
+ Description: Wordfence Login Security
5
+ Author: Wordfence
6
+ Author URI: http://www.wordfence.com/
7
+ Version: 1.0.2
8
+ Network: true
9
+ */
10
+ if (defined('WP_INSTALLING') && WP_INSTALLING) { return; }
11
+ if (!defined('ABSPATH')) { exit; }
12
+
13
+ $wfCoreActive = false;
14
+ $plugins = (array) get_option('active_plugins', array()); //Used in lieu of is_plugin_active since that's not loaded until admin_init
15
+ if (is_multisite()) {
16
+ $sitePlugins = array_keys((array) get_site_option('active_sitewide_plugins', array()));
17
+ $plugins = array_merge($plugins, $sitePlugins);
18
+ }
19
+
20
+ $wfVersion = ((is_multisite() && function_exists('get_network_option')) ? get_network_option(null, 'wordfence_version', false) : get_option('wordfence_version', false));
21
+ if (version_compare($wfVersion, '7.3.1', '>=')) {
22
+ foreach ($plugins as $p) {
23
+ if (preg_match('~^wordfence[^/]*/wordfence\.php$~i', $p)) {
24
+ $wfCoreActive = true;
25
+ break;
26
+ }
27
+ }
28
+ }
29
+
30
+ if ($wfCoreActive && !(isset($wfCoreLoading) && $wfCoreLoading)) {
31
+ return; //Wordfence core will load this, prevent the standalone one from also loading if active
32
+ }
33
+ else {
34
+ define('WORDFENCE_LS_FROM_CORE', ($wfCoreActive && isset($wfCoreLoading) && $wfCoreLoading));
35
+
36
+ define('WORDFENCE_LS_VERSION', '1.0.2');
37
+ define('WORDFENCE_LS_BUILD_NUMBER', '1559237323');
38
+
39
+ if (!WORDFENCE_LS_FROM_CORE) {
40
+ global $wp_plugin_paths;
41
+ foreach ($wp_plugin_paths as $dir => $realdir) {
42
+ if (strpos(__FILE__, $realdir) === 0) {
43
+ define('WORDFENCE_LS_FCPATH', $dir . '/' . basename(__FILE__));
44
+ define('WORDFENCE_LS_PATH', trailingslashit($dir));
45
+ break;
46
+ }
47
+ }
48
+ }
49
+
50
+ if (!defined('WORDFENCE_LS_FCPATH')) {
51
+ /** @noinspection PhpConstantReassignmentInspection */
52
+ define('WORDFENCE_LS_FCPATH', __FILE__);
53
+ /** @noinspection PhpConstantReassignmentInspection */
54
+ define('WORDFENCE_LS_PATH', trailingslashit(dirname(WORDFENCE_LS_FCPATH)));
55
+ }
56
+
57
+ if (!function_exists('wordfence_ls_autoload')) {
58
+ function wordfence_ls_autoload($class) {
59
+ $class = str_replace('\\', '/', $class);
60
+ $class = str_replace('\\\\', '/', $class);
61
+ $components = explode('/', $class);
62
+ if (count($components) < 2) {
63
+ return false;
64
+ }
65
+
66
+ if ($components[0] != 'WordfenceLS') {
67
+ return false;
68
+ }
69
+
70
+ $path = '';
71
+ for ($i = 1; $i < count($components) - 1; $i++) {
72
+ $path .= '/' . strtolower($components[$i]);
73
+ }
74
+
75
+ if (preg_match('/^Controller_([a-z0-9]+)$/i', $components[count($components) - 1], $matches)) {
76
+ $path = dirname(__FILE__) . '/classes/controller' . $path . '/' . strtolower($matches[1]) . '.php';
77
+ if (file_exists($path)) {
78
+ require_once($path);
79
+ return true;
80
+ }
81
+ }
82
+ else if (preg_match('/^Model_([a-z0-9]+)$/i', $components[count($components) - 1], $matches)) {
83
+ $path = dirname(__FILE__) . '/classes/model' . $path . '/' . strtolower($matches[1]) . '.php';
84
+ if (file_exists($path)) {
85
+ require_once($path);
86
+ return true;
87
+ }
88
+ }
89
+
90
+ return false;
91
+ }
92
+ }
93
+
94
+ if (!defined('WORDFENCE_LS_AUTOLOADER_REGISTERED')) {
95
+ define('WORDFENCE_LS_AUTOLOADER_REGISTERED', true);
96
+ spl_autoload_register('wordfence_ls_autoload');
97
+ }
98
+
99
+ if (!defined('WORDFENCE_LS_VERSIONONLY_MODE') && (!defined('WORDFENCE_USE_LEGACY_2FA') || (defined('WORDFENCE_USE_LEGACY_2FA') && !WORDFENCE_USE_LEGACY_2FA))) { //Used to get version from file
100
+ \WordfenceLS\Controller_WordfenceLS::shared()->init();
101
+ }
102
+ }