Shield Security for WordPress - Version 9.2.0

Version Description

Download this release

Release Info

Developer paultgoodchild
Plugin Icon 128x128 Shield Security for WordPress
Version 9.2.0
Comparing to
See all releases

Code changes from version 9.1.0 to 9.2.0

Files changed (139) hide show
  1. icwp-wpsf.php +1 -1
  2. plugin-spec.php +6 -4
  3. readme.txt +27 -24
  4. resources/css/bootstrap4.css +31 -50
  5. resources/css/bootstrap4.min.css +3 -3
  6. resources/css/plugin.css +3 -0
  7. resources/js/bootstrap4.bundle.js +100 -110
  8. resources/js/bootstrap4.bundle.min.js +3 -3
  9. resources/js/bootstrap4.js +79 -89
  10. resources/js/bootstrap4.min.js +3 -3
  11. resources/js/global-plugin.js +26 -10
  12. resources/js/plugin.js +14 -12
  13. src/config/feature-autoupdates.php +3 -3
  14. src/config/feature-comments_filter.php +0 -1
  15. src/config/feature-hack_protect.php +4 -0
  16. src/config/feature-ips.php +35 -32
  17. src/config/feature-lockdown.php +21 -10
  18. src/config/feature-login_protect.php +2 -2
  19. src/config/feature-plugin.php +8 -4
  20. src/features/admin_access_restriction.php +37 -160
  21. src/features/audit_trail.php +0 -73
  22. src/features/autoupdates.php +0 -112
  23. src/features/base.php +106 -415
  24. src/features/base_wpsf.php +2 -64
  25. src/features/comments_filter.php +23 -59
  26. src/features/firewall.php +0 -48
  27. src/features/hack_protect.php +37 -352
  28. src/features/headers.php +0 -48
  29. src/features/insights.php +92 -90
  30. src/features/ips.php +0 -36
  31. src/features/license.php +0 -79
  32. src/features/lockdown.php +12 -90
  33. src/features/login_protect.php +2 -118
  34. src/features/plugin.php +9 -119
  35. src/features/traffic.php +0 -31
  36. src/features/user_management.php +11 -128
  37. src/lib/src/Controller/Controller.php +18 -55
  38. src/lib/src/Controller/Utilities/Upgrade.php +4 -4
  39. src/lib/src/Databases/AdminNotes/Handler.php +13 -7
  40. src/lib/src/Databases/AuditTrail/Handler.php +17 -11
  41. src/lib/src/Databases/Base/Handler.php +51 -52
  42. src/lib/src/Databases/ChangeTracking/Handler.php +13 -7
  43. src/lib/src/Databases/Events/Handler.php +16 -10
  44. src/lib/src/Databases/FileLocker/Handler.php +13 -7
  45. src/lib/src/Databases/GeoIp/Handler.php +14 -10
  46. src/lib/src/Databases/IPs/Handler.php +20 -25
  47. src/lib/src/Databases/Reports/Handler.php +14 -8
  48. src/lib/src/Databases/ScanQueue/Handler.php +13 -7
  49. src/lib/src/Databases/Scanner/Handler.php +13 -7
  50. src/lib/src/Databases/Session/Handler.php +14 -8
  51. src/lib/src/Databases/Tally/Handler.php +13 -7
  52. src/lib/src/Databases/Traffic/Handler.php +17 -11
  53. src/lib/src/Helpers/QuickAccess.php +19 -0
  54. src/lib/src/Modules/AuditTrail/AjaxHandler.php +4 -4
  55. src/lib/src/Modules/AuditTrail/Options.php +2 -0
  56. src/lib/src/Modules/AuditTrail/Strings.php +17 -19
  57. src/lib/src/Modules/AuditTrail/UI.php +80 -0
  58. src/lib/src/Modules/Autoupdates/Strings.php +8 -8
  59. src/lib/src/Modules/Autoupdates/UI.php +112 -0
  60. src/lib/src/Modules/Base/AdminNotices.php +63 -68
  61. src/lib/src/Modules/Base/AjaxHandlerBase.php +2 -4
  62. src/lib/src/Modules/Base/AjaxHandlerShield.php +9 -9
  63. src/lib/src/Modules/Base/BaseModCon.php +0 -224
  64. src/lib/src/Modules/Base/BaseProcessor.php +1 -5
  65. src/lib/src/Modules/Base/Options.php +3 -15
  66. src/lib/src/Modules/Base/ShieldUI.php +61 -0
  67. src/lib/src/Modules/Base/Strings.php +12 -12
  68. src/lib/src/Modules/Base/UI.php +364 -0
  69. src/lib/src/Modules/BaseShield/ShieldProcessor.php +2 -2
  70. src/lib/src/Modules/CommentsFilter/AdminNotices.php +6 -4
  71. src/lib/src/Modules/CommentsFilter/AjaxHandler.php +4 -4
  72. src/lib/src/Modules/CommentsFilter/Options.php +41 -0
  73. src/lib/src/Modules/CommentsFilter/Scan/Bot.php +4 -4
  74. src/lib/src/Modules/CommentsFilter/Scan/Scanner.php +20 -16
  75. src/lib/src/Modules/CommentsFilter/Strings.php +8 -8
  76. src/lib/src/Modules/CommentsFilter/UI.php +53 -0
  77. src/lib/src/Modules/Events/AjaxHandler.php +4 -4
  78. src/lib/src/Modules/Events/Options.php +1 -0
  79. src/lib/src/Modules/Firewall/Strings.php +8 -8
  80. src/lib/src/Modules/Firewall/UI.php +56 -0
  81. src/lib/src/Modules/HackGuard/AjaxHandler.php +5 -5
  82. src/lib/src/Modules/HackGuard/Lib/FileLocker/File.php +15 -15
  83. src/lib/src/Modules/HackGuard/Lib/FileLocker/FileLockerController.php +19 -7
  84. src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/CleanAll.php +0 -2
  85. src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Delete.php +0 -2
  86. src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/TouchAll.php +0 -2
  87. src/lib/src/Modules/HackGuard/Options.php +5 -2
  88. src/lib/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php +11 -10
  89. src/lib/src/Modules/HackGuard/Scan/Queue/ConvertBetweenTypes.php +1 -1
  90. src/lib/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php +0 -2
  91. src/lib/src/Modules/HackGuard/Strings.php +15 -14
  92. src/lib/src/Modules/HackGuard/UI.php +703 -0
  93. src/lib/src/Modules/Headers/Strings.php +8 -8
  94. src/lib/src/Modules/Headers/UI.php +56 -0
  95. src/lib/src/Modules/IPs/AjaxHandler.php +12 -12
  96. src/lib/src/Modules/IPs/BotTrack/TrackLinkCheese.php +11 -13
  97. src/lib/src/Modules/IPs/BotTrack/TrackLoginFailed.php +1 -1
  98. src/lib/src/Modules/IPs/Components/ProcessOffense.php +12 -14
  99. src/lib/src/Modules/IPs/Components/UnblockIpByMagicLink.php +37 -0
  100. src/lib/src/Modules/IPs/Lib/AutoUnblock.php +213 -0
  101. src/lib/src/Modules/IPs/Lib/BlacklistHandler.php +32 -26
  102. src/lib/src/Modules/IPs/Lib/BlockRequest.php +103 -77
  103. src/lib/src/Modules/IPs/Lib/Ops/DeleteIp.php +0 -21
  104. src/lib/src/Modules/IPs/Lib/{BlackmarkRequest.php → ProcessOffenses.php} +15 -14
  105. src/lib/src/Modules/IPs/Options.php +45 -19
  106. src/lib/src/Modules/IPs/Strings.php +31 -19
  107. src/lib/src/Modules/IPs/UI.php +43 -0
  108. src/lib/src/Modules/IPs/Upgrade.php +26 -0
  109. src/lib/src/Modules/License/AjaxHandler.php +4 -4
  110. src/lib/src/Modules/License/Lib/WpHashes/ApiTokenManager.php +0 -8
  111. src/lib/src/Modules/License/UI.php +96 -0
  112. src/lib/src/Modules/Lockdown/Lib/CleanRubbish.php +38 -0
  113. src/lib/src/Modules/Lockdown/Options.php +28 -0
  114. src/lib/src/Modules/Lockdown/Strings.php +19 -8
  115. src/lib/src/Modules/Lockdown/UI.php +97 -0
  116. src/lib/src/Modules/LoginGuard/AjaxHandler.php +4 -4
  117. src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php +17 -15
  118. src/lib/src/Modules/LoginGuard/Lib/AntiBot/FormProviders/MemberPress.php +3 -4
  119. src/lib/src/Modules/LoginGuard/Lib/AntiBot/FormProviders/WPMembers.php +51 -0
  120. src/lib/src/Modules/LoginGuard/Lib/AntiBot/ProtectionProviders/GaspJs.php +10 -10
  121. src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php +28 -25
  122. src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/CustomForms.php +67 -0
  123. src/lib/src/Modules/LoginGuard/Strings.php +14 -14
  124. src/lib/src/Modules/LoginGuard/UI.php +123 -0
  125. src/lib/src/Modules/Plugin/AdminNotices.php +8 -9
  126. src/lib/src/Modules/Plugin/AjaxHandler.php +4 -4
  127. src/lib/src/Modules/Plugin/Lib/ImportExport/Export.php +12 -12
  128. src/lib/src/Modules/Plugin/Lib/ImportExport/Import.php +5 -5
  129. src/lib/src/Modules/Plugin/Lib/Ops/ResetPlugin.php +5 -5
  130. src/lib/src/Modules/Plugin/Options.php +2 -0
  131. src/lib/src/Modules/Plugin/Strings.php +31 -21
  132. src/lib/src/Modules/Plugin/UI.php +122 -0
  133. src/lib/src/Modules/Reporting/Options.php +1 -0
  134. src/lib/src/Modules/Reporting/Strings.php +8 -8
  135. src/lib/src/Modules/SecurityAdmin/AdminNotices.php +1 -3
  136. src/lib/src/Modules/SecurityAdmin/AjaxHandler.php +4 -4
  137. src/lib/src/Modules/SecurityAdmin/Lib/Actions/RemoveSecAdmin.php +4 -4
  138. src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php +0 -2
  139. src/lib/src/Modules/SecurityAdmin/Options.php +10 -11
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 9.1.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://shsec.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 9.2.0
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages
9
  * Author: Shield Security
plugin-spec.php CHANGED
@@ -1,8 +1,8 @@
1
  {
2
  "properties": {
3
- "version": "9.1.0",
4
- "release_timestamp": 1592902029,
5
- "build": "202006.2301",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield",
@@ -111,7 +111,9 @@
111
  "version_upgrades": [
112
  "9.0.0",
113
  "9.0.3",
114
- "9.0.5"
 
 
115
  ],
116
  "action_links": {
117
  "remove": null,
1
  {
2
  "properties": {
3
+ "version": "9.2.0",
4
+ "release_timestamp": 1599122123,
5
+ "build": "202009.0301",
6
  "slug_parent": "icwp",
7
  "slug_plugin": "wpsf",
8
  "human_name": "Shield",
111
  "version_upgrades": [
112
  "9.0.0",
113
  "9.0.3",
114
+ "9.0.5",
115
+ "9.1.1",
116
+ "9.2.0"
117
  ],
118
  "action_links": {
119
  "remove": null,
readme.txt CHANGED
@@ -7,8 +7,8 @@ Tags: scan, malware, firewall, two factor authentication, login protection
7
  Requires at least: 3.5.2
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
- Tested up to: 5.5
11
- Stable tag: 9.1.0
12
 
13
  Smarter security protection from hackers through automation. Powerful scanners, 2-Factor Auth, limit logins, auto IP blocks & more.
14
 
@@ -216,7 +216,7 @@ protection for your site and you should choose which you need based on your own
216
  Why do we do this? It's simple: performance and optimization - there is no reason to automatically turn on features for people that don't
217
  need it as each site and set of requirements is different.
218
 
219
- This plugin should install as any other WordPress.org respository plugin.
220
 
221
  1. Browse to Plugins -> Add Plugin
222
  1. Search: Shield
@@ -368,26 +368,29 @@ You'll also have access to our email technical support team.
368
 
369
  You will always be able to use Shield Security and its free features in-full.
370
 
371
- [Go Pro for just $1/month](https://shsec.io/aa).
372
-
373
- **Important**: The 9.0 Series is the last major version to support PHP 5.x. Shield 10+ will require a minimum of PHP 7.0.
374
-
375
- #### 9.1 Series
376
- *Released: 23rd April 2020* - [Release Announcement](https://shsec.io/shieldrelease91)
377
-
378
- ##### [Please review the full Shield 9.1 Upgrade Guide here](https://shsec.io/shieldupgradeguide91).
379
-
380
- * **(.0) NEW**: [*PRO*] [WP-CLI](https://shsec.io/hw) Support for WP-CLI (beta).
381
- * **(.0) NEW**: [*PRO*] [U2F Login](https://shsec.io/hv) - Support for registration and use of U2F keys for 2-factor authentication.
382
- * **(.0) NEW**: [*PRO*] [Custom Email Templates](https://shsec.io/hy) - Support for custom email templates, starting with 2FA.
383
- * **(.0) NEW**: [*PRO*] [Affiliate Rewards](https://shsec.io/hz) - We now offer affiliate rewards with ShieldPRO.
384
- * **(.0) IMPROVED**: WP-Config File Locker protection now correctly display the file diff for empty lines.
385
- * **(.0) IMPROVED**: 2-Factor Authentication "Remember Me" now uses the visitor IP address as a factor.
386
- * **(.0) IMPROVED**: Restored the option search but turned it into a modal dialog.
387
- * **(.0) IMPROVED**: Plugin upgrade handling.
388
- * **(.0) CHANGED**: To avoid confusion, "Security Admin Key" has been renamed to "Security Admin PIN" throughout.
389
- * **(.0) FIXED**: Adding IPv6 address ranges didn't work in all cases.
390
- * **(.0) FIXED**: Errors while trying to access an uninitialised database.
391
- * **(.0) FIXED**: Upgrade Carbon PHP library to latest available (v1.39).
 
 
 
392
 
393
  ##### [Entire Shield Security Changelog](https://shsec.io/shieldwporgfullchangelog)
7
  Requires at least: 3.5.2
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
+ Tested up to: 5.4
11
+ Stable tag: 9.2.0
12
 
13
  Smarter security protection from hackers through automation. Powerful scanners, 2-Factor Auth, limit logins, auto IP blocks & more.
14
 
216
  Why do we do this? It's simple: performance and optimization - there is no reason to automatically turn on features for people that don't
217
  need it as each site and set of requirements is different.
218
 
219
+ This plugin should install as any other WordPress.org repository plugin.
220
 
221
  1. Browse to Plugins -> Add Plugin
222
  1. Search: Shield
368
 
369
  You will always be able to use Shield Security and its free features in-full.
370
 
371
+ [Go Pro from just $1/month](https://shsec.io/aa).
372
+
373
+ #### 9.2 Series
374
+ *Released: 2nd September 2020* - [Release Announcement](https://shsec.io/shieldrelease92)
375
+
376
+ **Important**: 9.2 is the *final* release to support PHP 5.x. Shield 10+ will require a minimum of PHP 7.0.
377
+
378
+ ##### [Please review the full Shield 9.2 Upgrade Guide here](https://shsec.io/shieldupgradeguide92).
379
+
380
+ * **(.0) NEW**: [*PRO*] Allow logged-in users to automatically unblock their IP address.
381
+ * **(.0) NEW**: Add feature to allow Shield to automatically delete files such as `wp-config-sample.php`.
382
+ * **(.0) ADDED**: Provide native support for protection on WP Members plugin login/registration forms.
383
+ * **(.0) IMPROVED**: Automatic updates notification email is now only sent if on WordPress < 5.5.
384
+ * **(.0) IMPROVED**: Automatic updates notification email setting also applies to plugin/theme update emails.
385
+ * **(.0) IMPROVED**: Use WP Fastest Cache method to prevent caching of block pages. Whether it makes a difference is another thing.
386
+ * **(.0) IMPROVED**: Prevent spurious output from errors not relating to this plugin from affecting display of our admin pages.
387
+ * **(.0) IMPROVED**: `forceoff` file detection improved.
388
+ * **(.0) IMPROVED**: The File Locker is less likely to trigger an `open_basedir` warning.
389
+ * **(.0) IMPROVED**: Lots of code optimisation.
390
+ * **(.0) CHANGED**: Session cookie renamed from `icwp-wpsf` to `wp-icwp-wpsf` because some plugin devs feel a cookie is only important if it begins with `wp-`.
391
+ * **(.0) CHANGED**: Upgraded shipped Bootstrap libraries to latest available (v4.5.2).
392
+ * **(.0) FIXED**: Upgraded the database to support much larger values for the IP offenses counter.
393
+ * **(.0) FIXED**: MemberPress support had a bug where certain forms weren't checked for bots.
394
+ * **(.0) FIXED**: Cleaned some WP-CLI PHP notices on certain commands.
395
 
396
  ##### [Entire Shield Security Changelog](https://shsec.io/shieldwporgfullchangelog)
resources/css/bootstrap4.css CHANGED
@@ -1,8 +1,8 @@
1
  /*!
2
- * Bootstrap v4.5.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors
4
  * Copyright 2011-2020 Twitter, Inc.
5
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
  */
7
  :root {
8
  --blue: #007bff;
@@ -163,12 +163,12 @@ a:hover {
163
  text-decoration: underline;
164
  }
165
 
166
- a:not([href]) {
167
  color: inherit;
168
  text-decoration: none;
169
  }
170
 
171
- a:not([href]):hover {
172
  color: inherit;
173
  text-decoration: none;
174
  }
@@ -539,39 +539,12 @@ pre code {
539
  overflow-y: scroll;
540
  }
541
 
542
- .container {
543
- width: 100%;
544
- padding-right: 15px;
545
- padding-left: 15px;
546
- margin-right: auto;
547
- margin-left: auto;
548
- }
549
-
550
- @media (min-width: 576px) {
551
- .container {
552
- max-width: 540px;
553
- }
554
- }
555
-
556
- @media (min-width: 768px) {
557
- .container {
558
- max-width: 720px;
559
- }
560
- }
561
-
562
- @media (min-width: 992px) {
563
- .container {
564
- max-width: 960px;
565
- }
566
- }
567
-
568
- @media (min-width: 1200px) {
569
- .container {
570
- max-width: 1140px;
571
- }
572
- }
573
-
574
- .container-fluid, .container-sm, .container-md, .container-lg, .container-xl {
575
  width: 100%;
576
  padding-right: 15px;
577
  padding-left: 15px;
@@ -640,7 +613,6 @@ pre code {
640
  flex-basis: 0;
641
  -ms-flex-positive: 1;
642
  flex-grow: 1;
643
- min-width: 0;
644
  max-width: 100%;
645
  }
646
 
@@ -884,7 +856,6 @@ pre code {
884
  flex-basis: 0;
885
  -ms-flex-positive: 1;
886
  flex-grow: 1;
887
- min-width: 0;
888
  max-width: 100%;
889
  }
890
  .row-cols-sm-1 > * {
@@ -1087,7 +1058,6 @@ pre code {
1087
  flex-basis: 0;
1088
  -ms-flex-positive: 1;
1089
  flex-grow: 1;
1090
- min-width: 0;
1091
  max-width: 100%;
1092
  }
1093
  .row-cols-md-1 > * {
@@ -1290,7 +1260,6 @@ pre code {
1290
  flex-basis: 0;
1291
  -ms-flex-positive: 1;
1292
  flex-grow: 1;
1293
- min-width: 0;
1294
  max-width: 100%;
1295
  }
1296
  .row-cols-lg-1 > * {
@@ -1493,7 +1462,6 @@ pre code {
1493
  flex-basis: 0;
1494
  -ms-flex-positive: 1;
1495
  flex-grow: 1;
1496
- min-width: 0;
1497
  max-width: 100%;
1498
  }
1499
  .row-cols-xl-1 > * {
@@ -2259,6 +2227,7 @@ textarea.form-control {
2259
  .valid-tooltip {
2260
  position: absolute;
2261
  top: 100%;
 
2262
  z-index: 5;
2263
  display: none;
2264
  max-width: 100%;
@@ -2359,6 +2328,7 @@ textarea.form-control {
2359
  .invalid-tooltip {
2360
  position: absolute;
2361
  top: 100%;
 
2362
  z-index: 5;
2363
  display: none;
2364
  max-width: 100%;
@@ -3776,6 +3746,7 @@ input[type="button"].btn-block {
3776
 
3777
  .custom-control {
3778
  position: relative;
 
3779
  display: block;
3780
  min-height: 1.5rem;
3781
  padding-left: 1.5rem;
@@ -4312,12 +4283,14 @@ input[type="button"].btn-block {
4312
  background-color: #007bff;
4313
  }
4314
 
 
4315
  .nav-fill .nav-item {
4316
  -ms-flex: 1 1 auto;
4317
  flex: 1 1 auto;
4318
  text-align: center;
4319
  }
4320
 
 
4321
  .nav-justified .nav-item {
4322
  -ms-flex-preferred-size: 0;
4323
  flex-basis: 0;
@@ -4775,6 +4748,11 @@ input[type="button"].btn-block {
4775
  border-bottom-left-radius: calc(0.25rem - 1px);
4776
  }
4777
 
 
 
 
 
 
4778
  .card-body {
4779
  -ms-flex: 1 1 auto;
4780
  flex: 1 1 auto;
@@ -4814,10 +4792,6 @@ input[type="button"].btn-block {
4814
  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
4815
  }
4816
 
4817
- .card-header + .list-group .list-group-item:first-child {
4818
- border-top: 0;
4819
- }
4820
-
4821
  .card-footer {
4822
  padding: 0.75rem 1.25rem;
4823
  background-color: rgba(0, 0, 0, 0.03);
@@ -4847,6 +4821,7 @@ input[type="button"].btn-block {
4847
  bottom: 0;
4848
  left: 0;
4849
  padding: 1.25rem;
 
4850
  }
4851
 
4852
  .card-img,
@@ -4958,6 +4933,10 @@ input[type="button"].btn-block {
4958
  }
4959
  }
4960
 
 
 
 
 
4961
  .accordion > .card {
4962
  overflow: hidden;
4963
  }
@@ -5876,15 +5855,14 @@ a.close.disabled {
5876
  }
5877
 
5878
  .toast {
 
 
5879
  max-width: 350px;
5880
- overflow: hidden;
5881
  font-size: 0.875rem;
5882
  background-color: rgba(255, 255, 255, 0.85);
5883
  background-clip: padding-box;
5884
  border: 1px solid rgba(0, 0, 0, 0.1);
5885
  box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
5886
- -webkit-backdrop-filter: blur(10px);
5887
- backdrop-filter: blur(10px);
5888
  opacity: 0;
5889
  border-radius: 0.25rem;
5890
  }
@@ -5916,6 +5894,8 @@ a.close.disabled {
5916
  background-color: rgba(255, 255, 255, 0.85);
5917
  background-clip: padding-box;
5918
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
 
 
5919
  }
5920
 
5921
  .toast-body {
@@ -10182,7 +10162,8 @@ a.text-dark:hover, a.text-dark:focus {
10182
  }
10183
 
10184
  .text-break {
10185
- word-wrap: break-word !important;
 
10186
  }
10187
 
10188
  .text-reset {
1
  /*!
2
+ * Bootstrap v4.5.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors
4
  * Copyright 2011-2020 Twitter, Inc.
5
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6
  */
7
  :root {
8
  --blue: #007bff;
163
  text-decoration: underline;
164
  }
165
 
166
+ a:not([href]):not([class]) {
167
  color: inherit;
168
  text-decoration: none;
169
  }
170
 
171
+ a:not([href]):not([class]):hover {
172
  color: inherit;
173
  text-decoration: none;
174
  }
539
  overflow-y: scroll;
540
  }
541
 
542
+ .container,
543
+ .container-fluid,
544
+ .container-sm,
545
+ .container-md,
546
+ .container-lg,
547
+ .container-xl {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  width: 100%;
549
  padding-right: 15px;
550
  padding-left: 15px;
613
  flex-basis: 0;
614
  -ms-flex-positive: 1;
615
  flex-grow: 1;
 
616
  max-width: 100%;
617
  }
618
 
856
  flex-basis: 0;
857
  -ms-flex-positive: 1;
858
  flex-grow: 1;
 
859
  max-width: 100%;
860
  }
861
  .row-cols-sm-1 > * {
1058
  flex-basis: 0;
1059
  -ms-flex-positive: 1;
1060
  flex-grow: 1;
 
1061
  max-width: 100%;
1062
  }
1063
  .row-cols-md-1 > * {
1260
  flex-basis: 0;
1261
  -ms-flex-positive: 1;
1262
  flex-grow: 1;
 
1263
  max-width: 100%;
1264
  }
1265
  .row-cols-lg-1 > * {
1462
  flex-basis: 0;
1463
  -ms-flex-positive: 1;
1464
  flex-grow: 1;
 
1465
  max-width: 100%;
1466
  }
1467
  .row-cols-xl-1 > * {
2227
  .valid-tooltip {
2228
  position: absolute;
2229
  top: 100%;
2230
+ left: 0;
2231
  z-index: 5;
2232
  display: none;
2233
  max-width: 100%;
2328
  .invalid-tooltip {
2329
  position: absolute;
2330
  top: 100%;
2331
+ left: 0;
2332
  z-index: 5;
2333
  display: none;
2334
  max-width: 100%;
3746
 
3747
  .custom-control {
3748
  position: relative;
3749
+ z-index: 1;
3750
  display: block;
3751
  min-height: 1.5rem;
3752
  padding-left: 1.5rem;
4283
  background-color: #007bff;
4284
  }
4285
 
4286
+ .nav-fill > .nav-link,
4287
  .nav-fill .nav-item {
4288
  -ms-flex: 1 1 auto;
4289
  flex: 1 1 auto;
4290
  text-align: center;
4291
  }
4292
 
4293
+ .nav-justified > .nav-link,
4294
  .nav-justified .nav-item {
4295
  -ms-flex-preferred-size: 0;
4296
  flex-basis: 0;
4748
  border-bottom-left-radius: calc(0.25rem - 1px);
4749
  }
4750
 
4751
+ .card > .card-header + .list-group,
4752
+ .card > .list-group + .card-footer {
4753
+ border-top: 0;
4754
+ }
4755
+
4756
  .card-body {
4757
  -ms-flex: 1 1 auto;
4758
  flex: 1 1 auto;
4792
  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
4793
  }
4794
 
 
 
 
 
4795
  .card-footer {
4796
  padding: 0.75rem 1.25rem;
4797
  background-color: rgba(0, 0, 0, 0.03);
4821
  bottom: 0;
4822
  left: 0;
4823
  padding: 1.25rem;
4824
+ border-radius: calc(0.25rem - 1px);
4825
  }
4826
 
4827
  .card-img,
4933
  }
4934
  }
4935
 
4936
+ .accordion {
4937
+ overflow-anchor: none;
4938
+ }
4939
+
4940
  .accordion > .card {
4941
  overflow: hidden;
4942
  }
5855
  }
5856
 
5857
  .toast {
5858
+ -ms-flex-preferred-size: 350px;
5859
+ flex-basis: 350px;
5860
  max-width: 350px;
 
5861
  font-size: 0.875rem;
5862
  background-color: rgba(255, 255, 255, 0.85);
5863
  background-clip: padding-box;
5864
  border: 1px solid rgba(0, 0, 0, 0.1);
5865
  box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
 
 
5866
  opacity: 0;
5867
  border-radius: 0.25rem;
5868
  }
5894
  background-color: rgba(255, 255, 255, 0.85);
5895
  background-clip: padding-box;
5896
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
5897
+ border-top-left-radius: calc(0.25rem - 1px);
5898
+ border-top-right-radius: calc(0.25rem - 1px);
5899
  }
5900
 
5901
  .toast-body {
10162
  }
10163
 
10164
  .text-break {
10165
+ word-break: break-word !important;
10166
+ overflow-wrap: break-word !important;
10167
  }
10168
 
10169
  .text-reset {
resources/css/bootstrap4.min.css CHANGED
@@ -1,7 +1,7 @@
1
  /*!
2
- * Bootstrap v4.5.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors
4
  * Copyright 2011-2020 Twitter, Inc.
5
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6
- */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item{display:-ms-flexbox;display:flex}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;-ms-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}
7
  /*# sourceMappingURL=bootstrap.min.css.map */
1
  /*!
2
+ * Bootstrap v4.5.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors
4
  * Copyright 2011-2020 Twitter, Inc.
5
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6
+ */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item{display:-ms-flexbox;display:flex}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{-ms-flex-preferred-size:350px;flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;-ms-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}
7
  /*# sourceMappingURL=bootstrap.min.css.map */
resources/css/plugin.css CHANGED
@@ -1102,6 +1102,9 @@ input[type=checkbox].form-check-input {
1102
  .content-options .option-description {
1103
  border-left: 1px solid rgba(0, 0, 0, 0.1);
1104
  }
 
 
 
1105
  .content-options .option_label_name {
1106
  position: relative;
1107
  /*display: block;*/
1102
  .content-options .option-description {
1103
  border-left: 1px solid rgba(0, 0, 0, 0.1);
1104
  }
1105
+ .content-options .option-description p {
1106
+ margin-bottom: 5px;
1107
+ }
1108
  .content-options .option_label_name {
1109
  position: relative;
1110
  /*display: block;*/
resources/js/bootstrap4.bundle.js CHANGED
@@ -1,12 +1,12 @@
1
  /*!
2
- * Bootstrap v4.5.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
  */
6
  (function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) :
8
  typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) :
9
- (global = global || self, factory(global.bootstrap = {}, global.jQuery));
10
  }(this, (function (exports, $) { 'use strict';
11
 
12
  $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
@@ -27,53 +27,22 @@
27
  return Constructor;
28
  }
29
 
30
- function _defineProperty(obj, key, value) {
31
- if (key in obj) {
32
- Object.defineProperty(obj, key, {
33
- value: value,
34
- enumerable: true,
35
- configurable: true,
36
- writable: true
37
- });
38
- } else {
39
- obj[key] = value;
40
- }
41
 
42
- return obj;
43
- }
44
-
45
- function ownKeys(object, enumerableOnly) {
46
- var keys = Object.keys(object);
47
-
48
- if (Object.getOwnPropertySymbols) {
49
- var symbols = Object.getOwnPropertySymbols(object);
50
- if (enumerableOnly) symbols = symbols.filter(function (sym) {
51
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
52
- });
53
- keys.push.apply(keys, symbols);
54
- }
55
-
56
- return keys;
57
- }
58
-
59
- function _objectSpread2(target) {
60
- for (var i = 1; i < arguments.length; i++) {
61
- var source = arguments[i] != null ? arguments[i] : {};
62
-
63
- if (i % 2) {
64
- ownKeys(Object(source), true).forEach(function (key) {
65
- _defineProperty(target, key, source[key]);
66
- });
67
- } else if (Object.getOwnPropertyDescriptors) {
68
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
69
- } else {
70
- ownKeys(Object(source)).forEach(function (key) {
71
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
72
- });
73
  }
74
- }
75
 
76
- return target;
 
 
 
77
  }
78
 
79
  function _inheritsLoose(subClass, superClass) {
@@ -84,8 +53,8 @@
84
 
85
  /**
86
  * --------------------------------------------------------------------------
87
- * Bootstrap (v4.5.0): util.js
88
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
89
  * --------------------------------------------------------------------------
90
  */
91
  /**
@@ -265,7 +234,7 @@
265
  */
266
 
267
  var NAME = 'alert';
268
- var VERSION = '4.5.0';
269
  var DATA_KEY = 'bs.alert';
270
  var EVENT_KEY = "." + DATA_KEY;
271
  var DATA_API_KEY = '.data-api';
@@ -421,7 +390,7 @@
421
  */
422
 
423
  var NAME$1 = 'button';
424
- var VERSION$1 = '4.5.0';
425
  var DATA_KEY$1 = 'bs.button';
426
  var EVENT_KEY$1 = "." + DATA_KEY$1;
427
  var DATA_API_KEY$1 = '.data-api';
@@ -556,11 +525,9 @@
556
  return;
557
  }
558
 
559
- if (initialButton.tagName === 'LABEL' && inputBtn && inputBtn.type === 'checkbox') {
560
- event.preventDefault(); // work around event sent to label and input
561
  }
562
-
563
- Button._jQueryInterface.call($(button), 'toggle');
564
  }
565
  }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {
566
  var button = $(event.target).closest(SELECTOR_BUTTON)[0];
@@ -616,7 +583,7 @@
616
  */
617
 
618
  var NAME$2 = 'carousel';
619
- var VERSION$2 = '4.5.0';
620
  var DATA_KEY$2 = 'bs.carousel';
621
  var EVENT_KEY$2 = "." + DATA_KEY$2;
622
  var DATA_API_KEY$2 = '.data-api';
@@ -803,7 +770,7 @@
803
  ;
804
 
805
  _proto._getConfig = function _getConfig(config) {
806
- config = _objectSpread2(_objectSpread2({}, Default), config);
807
  Util.typeCheckConfig(NAME$2, config, DefaultType);
808
  return config;
809
  };
@@ -1093,10 +1060,10 @@
1093
  return this.each(function () {
1094
  var data = $(this).data(DATA_KEY$2);
1095
 
1096
- var _config = _objectSpread2(_objectSpread2({}, Default), $(this).data());
1097
 
1098
  if (typeof config === 'object') {
1099
- _config = _objectSpread2(_objectSpread2({}, _config), config);
1100
  }
1101
 
1102
  var action = typeof config === 'string' ? config : _config.slide;
@@ -1134,7 +1101,7 @@
1134
  return;
1135
  }
1136
 
1137
- var config = _objectSpread2(_objectSpread2({}, $(target).data()), $(this).data());
1138
 
1139
  var slideIndex = this.getAttribute('data-slide-to');
1140
 
@@ -1203,7 +1170,7 @@
1203
  */
1204
 
1205
  var NAME$3 = 'collapse';
1206
- var VERSION$3 = '4.5.0';
1207
  var DATA_KEY$3 = 'bs.collapse';
1208
  var EVENT_KEY$3 = "." + DATA_KEY$3;
1209
  var DATA_API_KEY$3 = '.data-api';
@@ -1418,7 +1385,7 @@
1418
  ;
1419
 
1420
  _proto._getConfig = function _getConfig(config) {
1421
- config = _objectSpread2(_objectSpread2({}, Default$1), config);
1422
  config.toggle = Boolean(config.toggle); // Coerce string values
1423
 
1424
  Util.typeCheckConfig(NAME$3, config, DefaultType$1);
@@ -1472,7 +1439,7 @@
1472
  var $this = $(this);
1473
  var data = $this.data(DATA_KEY$3);
1474
 
1475
- var _config = _objectSpread2(_objectSpread2(_objectSpread2({}, Default$1), $this.data()), typeof config === 'object' && config ? config : {});
1476
 
1477
  if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
1478
  _config.toggle = false;
@@ -1547,7 +1514,7 @@
1547
 
1548
  /**!
1549
  * @fileOverview Kickass library to create and place poppers near their reference elements.
1550
- * @version 1.16.0
1551
  * @license
1552
  * Copyright (c) 2016 Federico Zivolo and contributors
1553
  *
@@ -1893,7 +1860,7 @@
1893
  var sideA = axis === 'x' ? 'Left' : 'Top';
1894
  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
1895
 
1896
- return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
1897
  }
1898
 
1899
  function getSize(axis, body, html, computedStyle) {
@@ -1954,7 +1921,7 @@
1954
  return obj;
1955
  };
1956
 
1957
- var _extends = Object.assign || function (target) {
1958
  for (var i = 1; i < arguments.length; i++) {
1959
  var source = arguments[i];
1960
 
@@ -1976,7 +1943,7 @@
1976
  * @returns {Object} ClientRect like output
1977
  */
1978
  function getClientRect(offsets) {
1979
- return _extends({}, offsets, {
1980
  right: offsets.left + offsets.width,
1981
  bottom: offsets.top + offsets.height
1982
  });
@@ -2048,8 +2015,8 @@
2048
  var scrollParent = getScrollParent(children);
2049
 
2050
  var styles = getStyleComputedProperty(parent);
2051
- var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
2052
- var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
2053
 
2054
  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
2055
  if (fixedPosition && isHTML) {
@@ -2070,8 +2037,8 @@
2070
  // differently when margins are applied to it. The margins are included in
2071
  // the box of the documentElement, in the other cases not.
2072
  if (!isIE10 && isHTML) {
2073
- var marginTop = parseFloat(styles.marginTop, 10);
2074
- var marginLeft = parseFloat(styles.marginLeft, 10);
2075
 
2076
  offsets.top -= borderTopWidth - marginTop;
2077
  offsets.bottom -= borderTopWidth - marginTop;
@@ -2264,7 +2231,7 @@
2264
  };
2265
 
2266
  var sortedAreas = Object.keys(rects).map(function (key) {
2267
- return _extends({
2268
  key: key
2269
  }, rects[key], {
2270
  area: getArea(rects[key])
@@ -2906,9 +2873,9 @@
2906
  };
2907
 
2908
  // Update `data` attributes, styles and arrowStyles
2909
- data.attributes = _extends({}, attributes, data.attributes);
2910
- data.styles = _extends({}, styles, data.styles);
2911
- data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
2912
 
2913
  return data;
2914
  }
@@ -3010,8 +2977,8 @@
3010
  // Compute the sideValue using the updated popper offsets
3011
  // take popper margin in account because we don't have this info available
3012
  var css = getStyleComputedProperty(data.instance.popper);
3013
- var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
3014
- var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
3015
  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
3016
 
3017
  // prevent arrowElement from being placed not contiguously to its popper
@@ -3188,7 +3155,7 @@
3188
 
3189
  // this object contains `position`, we want to preserve it along with
3190
  // any additional property we may add in the future
3191
- data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
3192
 
3193
  data = runModifiers(data.instance.modifiers, data, 'flip');
3194
  }
@@ -3462,7 +3429,7 @@
3462
 
3463
  order.forEach(function (placement) {
3464
  var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
3465
- popper = _extends({}, popper, check[side](placement));
3466
  });
3467
 
3468
  data.offsets.popper = popper;
@@ -3497,7 +3464,7 @@
3497
  end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
3498
  };
3499
 
3500
- data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
3501
  }
3502
 
3503
  return data;
@@ -4029,7 +3996,7 @@
4029
  this.update = debounce(this.update.bind(this));
4030
 
4031
  // with {} we create a new object with the options inside it
4032
- this.options = _extends({}, Popper.Defaults, options);
4033
 
4034
  // init state
4035
  this.state = {
@@ -4044,13 +4011,13 @@
4044
 
4045
  // Deep merge modifiers options
4046
  this.options.modifiers = {};
4047
- Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
4048
- _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
4049
  });
4050
 
4051
  // Refactoring modifiers' list (Object => Array)
4052
  this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
4053
- return _extends({
4054
  name: name
4055
  }, _this.options.modifiers[name]);
4056
  })
@@ -4166,7 +4133,7 @@
4166
  */
4167
 
4168
  var NAME$4 = 'dropdown';
4169
- var VERSION$4 = '4.5.0';
4170
  var DATA_KEY$4 = 'bs.dropdown';
4171
  var EVENT_KEY$4 = "." + DATA_KEY$4;
4172
  var DATA_API_KEY$4 = '.data-api';
@@ -4393,7 +4360,7 @@
4393
  };
4394
 
4395
  _proto._getConfig = function _getConfig(config) {
4396
- config = _objectSpread2(_objectSpread2(_objectSpread2({}, this.constructor.Default), $(this._element).data()), config);
4397
  Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);
4398
  return config;
4399
  };
@@ -4438,7 +4405,7 @@
4438
 
4439
  if (typeof this._config.offset === 'function') {
4440
  offset.fn = function (data) {
4441
- data.offsets = _objectSpread2(_objectSpread2({}, data.offsets), _this2._config.offset(data.offsets, _this2._element) || {});
4442
  return data;
4443
  };
4444
  } else {
@@ -4468,7 +4435,7 @@
4468
  };
4469
  }
4470
 
4471
- return _objectSpread2(_objectSpread2({}, popperConfig), this._config.popperConfig);
4472
  } // Static
4473
  ;
4474
 
@@ -4680,7 +4647,7 @@
4680
  */
4681
 
4682
  var NAME$5 = 'modal';
4683
- var VERSION$5 = '4.5.0';
4684
  var DATA_KEY$5 = 'bs.modal';
4685
  var EVENT_KEY$5 = "." + DATA_KEY$5;
4686
  var DATA_API_KEY$5 = '.data-api';
@@ -4872,7 +4839,7 @@
4872
  ;
4873
 
4874
  _proto._getConfig = function _getConfig(config) {
4875
- config = _objectSpread2(_objectSpread2({}, Default$3), config);
4876
  Util.typeCheckConfig(NAME$5, config, DefaultType$3);
4877
  return config;
4878
  };
@@ -4888,11 +4855,24 @@
4888
  return;
4889
  }
4890
 
 
 
 
 
 
 
4891
  this._element.classList.add(CLASS_NAME_STATIC);
4892
 
4893
- var modalTransitionDuration = Util.getTransitionDurationFromElement(this._element);
 
4894
  $(this._element).one(Util.TRANSITION_END, function () {
4895
  _this3._element.classList.remove(CLASS_NAME_STATIC);
 
 
 
 
 
 
4896
  }).emulateTransitionEnd(modalTransitionDuration);
4897
 
4898
  this._element.focus();
@@ -4918,6 +4898,8 @@
4918
 
4919
  this._element.setAttribute('aria-modal', true);
4920
 
 
 
4921
  if ($(this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {
4922
  modalBody.scrollTop = 0;
4923
  } else {
@@ -5005,6 +4987,8 @@
5005
 
5006
  this._element.removeAttribute('aria-modal');
5007
 
 
 
5008
  this._isTransitioning = false;
5009
 
5010
  this._showBackdrop(function () {
@@ -5186,7 +5170,7 @@
5186
  return this.each(function () {
5187
  var data = $(this).data(DATA_KEY$5);
5188
 
5189
- var _config = _objectSpread2(_objectSpread2(_objectSpread2({}, Default$3), $(this).data()), typeof config === 'object' && config ? config : {});
5190
 
5191
  if (!data) {
5192
  data = new Modal(this, _config);
@@ -5236,7 +5220,7 @@
5236
  target = document.querySelector(selector);
5237
  }
5238
 
5239
- var config = $(target).data(DATA_KEY$5) ? 'toggle' : _objectSpread2(_objectSpread2({}, $(target).data()), $(this).data());
5240
 
5241
  if (this.tagName === 'A' || this.tagName === 'AREA') {
5242
  event.preventDefault();
@@ -5273,8 +5257,8 @@
5273
 
5274
  /**
5275
  * --------------------------------------------------------------------------
5276
- * Bootstrap (v4.5.0): tools/sanitizer.js
5277
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5278
  * --------------------------------------------------------------------------
5279
  */
5280
  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];
@@ -5399,7 +5383,7 @@
5399
  */
5400
 
5401
  var NAME$6 = 'tooltip';
5402
- var VERSION$6 = '4.5.0';
5403
  var DATA_KEY$6 = 'bs.tooltip';
5404
  var EVENT_KEY$6 = "." + DATA_KEY$6;
5405
  var JQUERY_NO_CONFLICT$6 = $.fn[NAME$6];
@@ -5787,7 +5771,7 @@
5787
  return _this3._handlePopperPlacementChange(data);
5788
  }
5789
  };
5790
- return _objectSpread2(_objectSpread2({}, defaultBsConfig), this.config.popperConfig);
5791
  };
5792
 
5793
  _proto._getOffset = function _getOffset() {
@@ -5797,7 +5781,7 @@
5797
 
5798
  if (typeof this.config.offset === 'function') {
5799
  offset.fn = function (data) {
5800
- data.offsets = _objectSpread2(_objectSpread2({}, data.offsets), _this4.config.offset(data.offsets, _this4.element) || {});
5801
  return data;
5802
  };
5803
  } else {
@@ -5852,7 +5836,7 @@
5852
  $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);
5853
 
5854
  if (this.config.selector) {
5855
- this.config = _objectSpread2(_objectSpread2({}, this.config), {}, {
5856
  trigger: 'manual',
5857
  selector: ''
5858
  });
@@ -5952,7 +5936,7 @@
5952
  delete dataAttributes[dataAttr];
5953
  }
5954
  });
5955
- config = _objectSpread2(_objectSpread2(_objectSpread2({}, this.constructor.Default), dataAttributes), typeof config === 'object' && config ? config : {});
5956
 
5957
  if (typeof config.delay === 'number') {
5958
  config.delay = {
@@ -6111,21 +6095,21 @@
6111
  */
6112
 
6113
  var NAME$7 = 'popover';
6114
- var VERSION$7 = '4.5.0';
6115
  var DATA_KEY$7 = 'bs.popover';
6116
  var EVENT_KEY$7 = "." + DATA_KEY$7;
6117
  var JQUERY_NO_CONFLICT$7 = $.fn[NAME$7];
6118
  var CLASS_PREFIX$1 = 'bs-popover';
6119
  var BSCLS_PREFIX_REGEX$1 = new RegExp("(^|\\s)" + CLASS_PREFIX$1 + "\\S+", 'g');
6120
 
6121
- var Default$5 = _objectSpread2(_objectSpread2({}, Tooltip.Default), {}, {
6122
  placement: 'right',
6123
  trigger: 'click',
6124
  content: '',
6125
  template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
6126
  });
6127
 
6128
- var DefaultType$5 = _objectSpread2(_objectSpread2({}, Tooltip.DefaultType), {}, {
6129
  content: '(string|element|function)'
6130
  });
6131
 
@@ -6291,7 +6275,7 @@
6291
  */
6292
 
6293
  var NAME$8 = 'scrollspy';
6294
- var VERSION$8 = '4.5.0';
6295
  var DATA_KEY$8 = 'bs.scrollspy';
6296
  var EVENT_KEY$8 = "." + DATA_KEY$8;
6297
  var DATA_API_KEY$6 = '.data-api';
@@ -6405,7 +6389,7 @@
6405
  ;
6406
 
6407
  _proto._getConfig = function _getConfig(config) {
6408
- config = _objectSpread2(_objectSpread2({}, Default$6), typeof config === 'object' && config ? config : {});
6409
 
6410
  if (typeof config.target !== 'string' && Util.isElement(config.target)) {
6411
  var id = $(config.target).attr('id');
@@ -6583,7 +6567,7 @@
6583
  */
6584
 
6585
  var NAME$9 = 'tab';
6586
- var VERSION$9 = '4.5.0';
6587
  var DATA_KEY$9 = 'bs.tab';
6588
  var EVENT_KEY$9 = "." + DATA_KEY$9;
6589
  var DATA_API_KEY$7 = '.data-api';
@@ -6809,7 +6793,7 @@
6809
  */
6810
 
6811
  var NAME$a = 'toast';
6812
- var VERSION$a = '4.5.0';
6813
  var DATA_KEY$a = 'bs.toast';
6814
  var EVENT_KEY$a = "." + DATA_KEY$a;
6815
  var JQUERY_NO_CONFLICT$a = $.fn[NAME$a];
@@ -6862,6 +6846,8 @@
6862
  return;
6863
  }
6864
 
 
 
6865
  if (this._config.animation) {
6866
  this._element.classList.add(CLASS_NAME_FADE$5);
6867
  }
@@ -6910,8 +6896,7 @@
6910
  };
6911
 
6912
  _proto.dispose = function dispose() {
6913
- clearTimeout(this._timeout);
6914
- this._timeout = null;
6915
 
6916
  if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {
6917
  this._element.classList.remove(CLASS_NAME_SHOW$7);
@@ -6925,7 +6910,7 @@
6925
  ;
6926
 
6927
  _proto._getConfig = function _getConfig(config) {
6928
- config = _objectSpread2(_objectSpread2(_objectSpread2({}, Default$7), $(this._element).data()), typeof config === 'object' && config ? config : {});
6929
  Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);
6930
  return config;
6931
  };
@@ -6955,6 +6940,11 @@
6955
  } else {
6956
  complete();
6957
  }
 
 
 
 
 
6958
  } // Static
6959
  ;
6960
 
1
  /*!
2
+ * Bootstrap v4.5.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
  (function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) :
8
  typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bootstrap = {}, global.jQuery));
10
  }(this, (function (exports, $) { 'use strict';
11
 
12
  $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
27
  return Constructor;
28
  }
29
 
30
+ function _extends() {
31
+ _extends = Object.assign || function (target) {
32
+ for (var i = 1; i < arguments.length; i++) {
33
+ var source = arguments[i];
 
 
 
 
 
 
 
34
 
35
+ for (var key in source) {
36
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
37
+ target[key] = source[key];
38
+ }
39
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
 
41
 
42
+ return target;
43
+ };
44
+
45
+ return _extends.apply(this, arguments);
46
  }
47
 
48
  function _inheritsLoose(subClass, superClass) {
53
 
54
  /**
55
  * --------------------------------------------------------------------------
56
+ * Bootstrap (v4.5.2): util.js
57
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
58
  * --------------------------------------------------------------------------
59
  */
60
  /**
234
  */
235
 
236
  var NAME = 'alert';
237
+ var VERSION = '4.5.2';
238
  var DATA_KEY = 'bs.alert';
239
  var EVENT_KEY = "." + DATA_KEY;
240
  var DATA_API_KEY = '.data-api';
390
  */
391
 
392
  var NAME$1 = 'button';
393
+ var VERSION$1 = '4.5.2';
394
  var DATA_KEY$1 = 'bs.button';
395
  var EVENT_KEY$1 = "." + DATA_KEY$1;
396
  var DATA_API_KEY$1 = '.data-api';
525
  return;
526
  }
527
 
528
+ if (initialButton.tagName !== 'LABEL' || inputBtn && inputBtn.type !== 'checkbox') {
529
+ Button._jQueryInterface.call($(button), 'toggle');
530
  }
 
 
531
  }
532
  }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {
533
  var button = $(event.target).closest(SELECTOR_BUTTON)[0];
583
  */
584
 
585
  var NAME$2 = 'carousel';
586
+ var VERSION$2 = '4.5.2';
587
  var DATA_KEY$2 = 'bs.carousel';
588
  var EVENT_KEY$2 = "." + DATA_KEY$2;
589
  var DATA_API_KEY$2 = '.data-api';
770
  ;
771
 
772
  _proto._getConfig = function _getConfig(config) {
773
+ config = _extends({}, Default, config);
774
  Util.typeCheckConfig(NAME$2, config, DefaultType);
775
  return config;
776
  };
1060
  return this.each(function () {
1061
  var data = $(this).data(DATA_KEY$2);
1062
 
1063
+ var _config = _extends({}, Default, $(this).data());
1064
 
1065
  if (typeof config === 'object') {
1066
+ _config = _extends({}, _config, config);
1067
  }
1068
 
1069
  var action = typeof config === 'string' ? config : _config.slide;
1101
  return;
1102
  }
1103
 
1104
+ var config = _extends({}, $(target).data(), $(this).data());
1105
 
1106
  var slideIndex = this.getAttribute('data-slide-to');
1107
 
1170
  */
1171
 
1172
  var NAME$3 = 'collapse';
1173
+ var VERSION$3 = '4.5.2';
1174
  var DATA_KEY$3 = 'bs.collapse';
1175
  var EVENT_KEY$3 = "." + DATA_KEY$3;
1176
  var DATA_API_KEY$3 = '.data-api';
1385
  ;
1386
 
1387
  _proto._getConfig = function _getConfig(config) {
1388
+ config = _extends({}, Default$1, config);
1389
  config.toggle = Boolean(config.toggle); // Coerce string values
1390
 
1391
  Util.typeCheckConfig(NAME$3, config, DefaultType$1);
1439
  var $this = $(this);
1440
  var data = $this.data(DATA_KEY$3);
1441
 
1442
+ var _config = _extends({}, Default$1, $this.data(), typeof config === 'object' && config ? config : {});
1443
 
1444
  if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
1445
  _config.toggle = false;
1514
 
1515
  /**!
1516
  * @fileOverview Kickass library to create and place poppers near their reference elements.
1517
+ * @version 1.16.1
1518
  * @license
1519
  * Copyright (c) 2016 Federico Zivolo and contributors
1520
  *
1860
  var sideA = axis === 'x' ? 'Left' : 'Top';
1861
  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
1862
 
1863
+ return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);
1864
  }
1865
 
1866
  function getSize(axis, body, html, computedStyle) {
1921
  return obj;
1922
  };
1923
 
1924
+ var _extends$1 = Object.assign || function (target) {
1925
  for (var i = 1; i < arguments.length; i++) {
1926
  var source = arguments[i];
1927
 
1943
  * @returns {Object} ClientRect like output
1944
  */
1945
  function getClientRect(offsets) {
1946
+ return _extends$1({}, offsets, {
1947
  right: offsets.left + offsets.width,
1948
  bottom: offsets.top + offsets.height
1949
  });
2015
  var scrollParent = getScrollParent(children);
2016
 
2017
  var styles = getStyleComputedProperty(parent);
2018
+ var borderTopWidth = parseFloat(styles.borderTopWidth);
2019
+ var borderLeftWidth = parseFloat(styles.borderLeftWidth);
2020
 
2021
  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
2022
  if (fixedPosition && isHTML) {
2037
  // differently when margins are applied to it. The margins are included in
2038
  // the box of the documentElement, in the other cases not.
2039
  if (!isIE10 && isHTML) {
2040
+ var marginTop = parseFloat(styles.marginTop);
2041
+ var marginLeft = parseFloat(styles.marginLeft);
2042
 
2043
  offsets.top -= borderTopWidth - marginTop;
2044
  offsets.bottom -= borderTopWidth - marginTop;
2231
  };
2232
 
2233
  var sortedAreas = Object.keys(rects).map(function (key) {
2234
+ return _extends$1({
2235
  key: key
2236
  }, rects[key], {
2237
  area: getArea(rects[key])
2873
  };
2874
 
2875
  // Update `data` attributes, styles and arrowStyles
2876
+ data.attributes = _extends$1({}, attributes, data.attributes);
2877
+ data.styles = _extends$1({}, styles, data.styles);
2878
+ data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles);
2879
 
2880
  return data;
2881
  }
2977
  // Compute the sideValue using the updated popper offsets
2978
  // take popper margin in account because we don't have this info available
2979
  var css = getStyleComputedProperty(data.instance.popper);
2980
+ var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);
2981
+ var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);
2982
  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
2983
 
2984
  // prevent arrowElement from being placed not contiguously to its popper
3155
 
3156
  // this object contains `position`, we want to preserve it along with
3157
  // any additional property we may add in the future
3158
+ data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
3159
 
3160
  data = runModifiers(data.instance.modifiers, data, 'flip');
3161
  }
3429
 
3430
  order.forEach(function (placement) {
3431
  var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
3432
+ popper = _extends$1({}, popper, check[side](placement));
3433
  });
3434
 
3435
  data.offsets.popper = popper;
3464
  end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
3465
  };
3466
 
3467
+ data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]);
3468
  }
3469
 
3470
  return data;
3996
  this.update = debounce(this.update.bind(this));
3997
 
3998
  // with {} we create a new object with the options inside it
3999
+ this.options = _extends$1({}, Popper.Defaults, options);
4000
 
4001
  // init state
4002
  this.state = {
4011
 
4012
  // Deep merge modifiers options
4013
  this.options.modifiers = {};
4014
+ Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
4015
+ _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
4016
  });
4017
 
4018
  // Refactoring modifiers' list (Object => Array)
4019
  this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
4020
+ return _extends$1({
4021
  name: name
4022
  }, _this.options.modifiers[name]);
4023
  })
4133
  */
4134
 
4135
  var NAME$4 = 'dropdown';
4136
+ var VERSION$4 = '4.5.2';
4137
  var DATA_KEY$4 = 'bs.dropdown';
4138
  var EVENT_KEY$4 = "." + DATA_KEY$4;
4139
  var DATA_API_KEY$4 = '.data-api';
4360
  };
4361
 
4362
  _proto._getConfig = function _getConfig(config) {
4363
+ config = _extends({}, this.constructor.Default, $(this._element).data(), config);
4364
  Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);
4365
  return config;
4366
  };
4405
 
4406
  if (typeof this._config.offset === 'function') {
4407
  offset.fn = function (data) {
4408
+ data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {});
4409
  return data;
4410
  };
4411
  } else {
4435
  };
4436
  }
4437
 
4438
+ return _extends({}, popperConfig, this._config.popperConfig);
4439
  } // Static
4440
  ;
4441
 
4647
  */
4648
 
4649
  var NAME$5 = 'modal';
4650
+ var VERSION$5 = '4.5.2';
4651
  var DATA_KEY$5 = 'bs.modal';
4652
  var EVENT_KEY$5 = "." + DATA_KEY$5;
4653
  var DATA_API_KEY$5 = '.data-api';
4839
  ;
4840
 
4841
  _proto._getConfig = function _getConfig(config) {
4842
+ config = _extends({}, Default$3, config);
4843
  Util.typeCheckConfig(NAME$5, config, DefaultType$3);
4844
  return config;
4845
  };
4855
  return;
4856
  }
4857
 
4858
+ var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
4859
+
4860
+ if (!isModalOverflowing) {
4861
+ this._element.style.overflowY = 'hidden';
4862
+ }
4863
+
4864
  this._element.classList.add(CLASS_NAME_STATIC);
4865
 
4866
+ var modalTransitionDuration = Util.getTransitionDurationFromElement(this._dialog);
4867
+ $(this._element).off(Util.TRANSITION_END);
4868
  $(this._element).one(Util.TRANSITION_END, function () {
4869
  _this3._element.classList.remove(CLASS_NAME_STATIC);
4870
+
4871
+ if (!isModalOverflowing) {
4872
+ $(_this3._element).one(Util.TRANSITION_END, function () {
4873
+ _this3._element.style.overflowY = '';
4874
+ }).emulateTransitionEnd(_this3._element, modalTransitionDuration);
4875
+ }
4876
  }).emulateTransitionEnd(modalTransitionDuration);
4877
 
4878
  this._element.focus();
4898
 
4899
  this._element.setAttribute('aria-modal', true);
4900
 
4901
+ this._element.setAttribute('role', 'dialog');
4902
+
4903
  if ($(this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {
4904
  modalBody.scrollTop = 0;
4905
  } else {
4987
 
4988
  this._element.removeAttribute('aria-modal');
4989
 
4990
+ this._element.removeAttribute('role');
4991
+
4992
  this._isTransitioning = false;
4993
 
4994
  this._showBackdrop(function () {
5170
  return this.each(function () {
5171
  var data = $(this).data(DATA_KEY$5);
5172
 
5173
+ var _config = _extends({}, Default$3, $(this).data(), typeof config === 'object' && config ? config : {});
5174
 
5175
  if (!data) {
5176
  data = new Modal(this, _config);
5220
  target = document.querySelector(selector);
5221
  }
5222
 
5223
+ var config = $(target).data(DATA_KEY$5) ? 'toggle' : _extends({}, $(target).data(), $(this).data());
5224
 
5225
  if (this.tagName === 'A' || this.tagName === 'AREA') {
5226
  event.preventDefault();
5257
 
5258
  /**
5259
  * --------------------------------------------------------------------------
5260
+ * Bootstrap (v4.5.2): tools/sanitizer.js
5261
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5262
  * --------------------------------------------------------------------------
5263
  */
5264
  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];
5383
  */
5384
 
5385
  var NAME$6 = 'tooltip';
5386
+ var VERSION$6 = '4.5.2';
5387
  var DATA_KEY$6 = 'bs.tooltip';
5388
  var EVENT_KEY$6 = "." + DATA_KEY$6;
5389
  var JQUERY_NO_CONFLICT$6 = $.fn[NAME$6];
5771
  return _this3._handlePopperPlacementChange(data);
5772
  }
5773
  };
5774
+ return _extends({}, defaultBsConfig, this.config.popperConfig);
5775
  };
5776
 
5777
  _proto._getOffset = function _getOffset() {
5781
 
5782
  if (typeof this.config.offset === 'function') {
5783
  offset.fn = function (data) {
5784
+ data.offsets = _extends({}, data.offsets, _this4.config.offset(data.offsets, _this4.element) || {});
5785
  return data;
5786
  };
5787
  } else {
5836
  $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);
5837
 
5838
  if (this.config.selector) {
5839
+ this.config = _extends({}, this.config, {
5840
  trigger: 'manual',
5841
  selector: ''
5842
  });
5936
  delete dataAttributes[dataAttr];
5937
  }
5938
  });
5939
+ config = _extends({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});
5940
 
5941
  if (typeof config.delay === 'number') {
5942
  config.delay = {
6095
  */
6096
 
6097
  var NAME$7 = 'popover';
6098
+ var VERSION$7 = '4.5.2';
6099
  var DATA_KEY$7 = 'bs.popover';
6100
  var EVENT_KEY$7 = "." + DATA_KEY$7;
6101
  var JQUERY_NO_CONFLICT$7 = $.fn[NAME$7];
6102
  var CLASS_PREFIX$1 = 'bs-popover';
6103
  var BSCLS_PREFIX_REGEX$1 = new RegExp("(^|\\s)" + CLASS_PREFIX$1 + "\\S+", 'g');
6104
 
6105
+ var Default$5 = _extends({}, Tooltip.Default, {
6106
  placement: 'right',
6107
  trigger: 'click',
6108
  content: '',
6109
  template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
6110
  });
6111
 
6112
+ var DefaultType$5 = _extends({}, Tooltip.DefaultType, {
6113
  content: '(string|element|function)'
6114
  });
6115
 
6275
  */
6276
 
6277
  var NAME$8 = 'scrollspy';
6278
+ var VERSION$8 = '4.5.2';
6279
  var DATA_KEY$8 = 'bs.scrollspy';
6280
  var EVENT_KEY$8 = "." + DATA_KEY$8;
6281
  var DATA_API_KEY$6 = '.data-api';
6389
  ;
6390
 
6391
  _proto._getConfig = function _getConfig(config) {
6392
+ config = _extends({}, Default$6, typeof config === 'object' && config ? config : {});
6393
 
6394
  if (typeof config.target !== 'string' && Util.isElement(config.target)) {
6395
  var id = $(config.target).attr('id');
6567
  */
6568
 
6569
  var NAME$9 = 'tab';
6570
+ var VERSION$9 = '4.5.2';
6571
  var DATA_KEY$9 = 'bs.tab';
6572
  var EVENT_KEY$9 = "." + DATA_KEY$9;
6573
  var DATA_API_KEY$7 = '.data-api';
6793
  */
6794
 
6795
  var NAME$a = 'toast';
6796
+ var VERSION$a = '4.5.2';
6797
  var DATA_KEY$a = 'bs.toast';
6798
  var EVENT_KEY$a = "." + DATA_KEY$a;
6799
  var JQUERY_NO_CONFLICT$a = $.fn[NAME$a];
6846
  return;
6847
  }
6848
 
6849
+ this._clearTimeout();
6850
+
6851
  if (this._config.animation) {
6852
  this._element.classList.add(CLASS_NAME_FADE$5);
6853
  }
6896
  };
6897
 
6898
  _proto.dispose = function dispose() {
6899
+ this._clearTimeout();
 
6900
 
6901
  if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {
6902
  this._element.classList.remove(CLASS_NAME_SHOW$7);
6910
  ;
6911
 
6912
  _proto._getConfig = function _getConfig(config) {
6913
+ config = _extends({}, Default$7, $(this._element).data(), typeof config === 'object' && config ? config : {});
6914
  Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);
6915
  return config;
6916
  };
6940
  } else {
6941
  complete();
6942
  }
6943
+ };
6944
+
6945
+ _proto._clearTimeout = function _clearTimeout() {
6946
+ clearTimeout(this._timeout);
6947
+ this._timeout = null;
6948
  } // Static
6949
  ;
6950
 
resources/js/bootstrap4.bundle.min.js CHANGED
@@ -1,7 +1,7 @@
1
  /*!
2
- * Bootstrap v4.5.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
  */
6
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery")):"function"==typeof define&&define.amd?define(["exports","jquery"],e):e((t=t||self).bootstrap={},t.jQuery)}(this,(function(t,e){"use strict";function n(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function i(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}function o(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function s(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?r(Object(n),!0).forEach((function(e){o(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e;function a(t){var n=this,i=!1;return e(this).one(l.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||l.triggerTransitionEnd(n)}),t),this}var l={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),i=e(t).css("transition-delay"),o=parseFloat(n),r=parseFloat(i);return o||r?(n=n.split(",")[0],i=i.split(",")[0],1e3*(parseFloat(n)+parseFloat(i))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],r=e[i],s=r&&l.isElement(r)?"element":null===(a=r)||"undefined"==typeof a?""+a:{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(s))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?l.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if("undefined"==typeof e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};l.jQueryDetection(),e.fn.emulateTransitionEnd=a,e.event.special[l.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var c="alert",u=e.fn[c],h=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=l.getSelectorFromElement(t),i=!1;return n&&(i=document.querySelector(n)),i||(i=e(t).closest(".alert")[0]),i},n._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},n._removeElement=function(t){var n=this;if(e(t).removeClass("show"),e(t).hasClass("fade")){var i=l.getTransitionDurationFromElement(t);e(t).one(l.TRANSITION_END,(function(e){return n._destroyElement(t,e)})).emulateTransitionEnd(i)}else this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.alert");o||(o=new t(this),i.data("bs.alert",o)),"close"===n&&o[n](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',h._handleDismiss(new h)),e.fn[c]=h._jQueryInterface,e.fn[c].Constructor=h,e.fn[c].noConflict=function(){return e.fn[c]=u,h._jQueryInterface};var f=e.fn.button,d=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,i=e(this._element).closest('[data-toggle="buttons"]')[0];if(i){var o=this._element.querySelector('input:not([type="hidden"])');if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains("active"))t=!1;else{var r=i.querySelector(".active");r&&e(r).removeClass("active")}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains("active")),e(o).trigger("change")),o.focus(),n=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(n&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&e(this._element).toggleClass("active"))},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=t.target,i=n;if(e(n).hasClass("btn")||(n=e(n).closest(".btn")[0]),!n||n.hasAttribute("disabled")||n.classList.contains("disabled"))t.preventDefault();else{var o=n.querySelector('input:not([type="hidden"])');if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();"LABEL"===i.tagName&&o&&"checkbox"===o.type&&t.preventDefault(),d._jQueryInterface.call(e(n),"toggle")}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=e(t.target).closest(".btn")[0];e(n).toggleClass("focus",/^focus(in)?$/.test(t.type))})),e(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e<n;e++){var i=t[e],o=i.querySelector('input:not([type="hidden"])');o.checked||o.hasAttribute("checked")?i.classList.add("active"):i.classList.remove("active")}for(var r=0,s=(t=[].slice.call(document.querySelectorAll('[data-toggle="button"]'))).length;r<s;r++){var a=t[r];"true"===a.getAttribute("aria-pressed")?a.classList.add("active"):a.classList.remove("active")}})),e.fn.button=d._jQueryInterface,e.fn.button.Constructor=d,e.fn.button.noConflict=function(){return e.fn.button=f,d._jQueryInterface};var p="carousel",m=".bs.carousel",g=e.fn[p],v={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},_={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},b={TOUCH:"touch",PEN:"pen"},y=function(){function t(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(".carousel-indicators"),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var n=t.prototype;return n.next=function(){this._isSliding||this._slide("next")},n.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},n.prev=function(){this._isSliding||this._slide("prev")},n.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(l.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},n.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},n.to=function(t){var n=this;this._activeElement=this._element.querySelector(".active.carousel-item");var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one("slid.bs.carousel",(function(){return n.to(t)}));else{if(i===t)return this.pause(),void this.cycle();var o=t>i?"next":"prev";this._slide(o,this._items[t])}},n.dispose=function(){e(this._element).off(m),e.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},n._getConfig=function(t){return t=s(s({},v),t),l.typeCheckConfig(p,t,_),t},n._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},n._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&e(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},n._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var n=function(e){t._pointerEvent&&b[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},i=function(e){t._pointerEvent&&b[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};e(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(e(this._element).on("pointerdown.bs.carousel",(function(t){return n(t)})),e(this._element).on("pointerup.bs.carousel",(function(t){return i(t)})),this._element.classList.add("pointer-event")):(e(this._element).on("touchstart.bs.carousel",(function(t){return n(t)})),e(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),e(this._element).on("touchend.bs.carousel",(function(t){return i(t)})))}},n._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},n._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},n._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+("prev"===t?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},n._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(".active.carousel-item")),r=e.Event("slide.bs.carousel",{relatedTarget:t,direction:n,from:o,to:i});return e(this._element).trigger(r),r},n._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var n=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));e(n).removeClass("active");var i=this._indicatorsElement.children[this._getItemIndex(t)];i&&e(i).addClass("active")}},n._slide=function(t,n){var i,o,r,s=this,a=this._element.querySelector(".active.carousel-item"),c=this._getItemIndex(a),u=n||a&&this._getItemByDirection(t,a),h=this._getItemIndex(u),f=Boolean(this._interval);if("next"===t?(i="carousel-item-left",o="carousel-item-next",r="left"):(i="carousel-item-right",o="carousel-item-prev",r="right"),u&&e(u).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(u,r).isDefaultPrevented()&&a&&u){this._isSliding=!0,f&&this.pause(),this._setActiveIndicatorElement(u);var d=e.Event("slid.bs.carousel",{relatedTarget:u,direction:r,from:c,to:h});if(e(this._element).hasClass("slide")){e(u).addClass(o),l.reflow(u),e(a).addClass(i),e(u).addClass(i);var p=parseInt(u.getAttribute("data-interval"),10);p?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=p):this._config.interval=this._config.defaultInterval||this._config.interval;var m=l.getTransitionDurationFromElement(a);e(a).one(l.TRANSITION_END,(function(){e(u).removeClass(i+" "+o).addClass("active"),e(a).removeClass("active "+o+" "+i),s._isSliding=!1,setTimeout((function(){return e(s._element).trigger(d)}),0)})).emulateTransitionEnd(m)}else e(a).removeClass("active"),e(u).addClass("active"),this._isSliding=!1,e(this._element).trigger(d);f&&this.cycle()}},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.carousel"),o=s(s({},v),e(this).data());"object"==typeof n&&(o=s(s({},o),n));var r="string"==typeof n?n:o.slide;if(i||(i=new t(this,o),e(this).data("bs.carousel",i)),"number"==typeof n)i.to(n);else if("string"==typeof r){if("undefined"==typeof i[r])throw new TypeError('No method named "'+r+'"');i[r]()}else o.interval&&o.ride&&(i.pause(),i.cycle())}))},t._dataApiClickHandler=function(n){var i=l.getSelectorFromElement(this);if(i){var o=e(i)[0];if(o&&e(o).hasClass("carousel")){var r=s(s({},e(o).data()),e(this).data()),a=this.getAttribute("data-slide-to");a&&(r.interval=!1),t._jQueryInterface.call(e(o),r),a&&e(o).data("bs.carousel").to(a),n.preventDefault()}}},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return v}}]),t}();e(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",y._dataApiClickHandler),e(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),n=0,i=t.length;n<i;n++){var o=e(t[n]);y._jQueryInterface.call(o,o.data())}})),e.fn[p]=y._jQueryInterface,e.fn[p].Constructor=y,e.fn[p].noConflict=function(){return e.fn[p]=g,y._jQueryInterface};var w="collapse",E=e.fn[w],T={toggle:!0,parent:""},C={toggle:"boolean",parent:"(string|element)"},S=function(){function t(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=n.length;i<o;i++){var r=n[i],s=l.getSelectorFromElement(r),a=[].slice.call(document.querySelectorAll(s)).filter((function(e){return e===t}));null!==s&&a.length>0&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var n=t.prototype;return n.toggle=function(){e(this._element).hasClass("show")?this.hide():this.show()},n.show=function(){var n,i,o=this;if(!this._isTransitioning&&!e(this._element).hasClass("show")&&(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),!(n&&(i=e(n).not(this._selector).data("bs.collapse"))&&i._isTransitioning))){var r=e.Event("show.bs.collapse");if(e(this._element).trigger(r),!r.isDefaultPrevented()){n&&(t._jQueryInterface.call(e(n).not(this._selector),"hide"),i||e(n).data("bs.collapse",null));var s=this._getDimension();e(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[s]=0,this._triggerArray.length&&e(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var a="scroll"+(s[0].toUpperCase()+s.slice(1)),c=l.getTransitionDurationFromElement(this._element);e(this._element).one(l.TRANSITION_END,(function(){e(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[s]="",o.setTransitioning(!1),e(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(c),this._element.style[s]=this._element[a]+"px"}}},n.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass("show")){var n=e.Event("hide.bs.collapse");if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",l.reflow(this._element),e(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var r=0;r<o;r++){var s=this._triggerArray[r],a=l.getSelectorFromElement(s);if(null!==a)e([].slice.call(document.querySelectorAll(a))).hasClass("show")||e(s).addClass("collapsed").attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[i]="";var c=l.getTransitionDurationFromElement(this._element);e(this._element).one(l.TRANSITION_END,(function(){t.setTransitioning(!1),e(t._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(c)}}},n.setTransitioning=function(t){this._isTransitioning=t},n.dispose=function(){e.removeData(this._element,"bs.collapse"),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},n._getConfig=function(t){return(t=s(s({},T),t)).toggle=Boolean(t.toggle),l.typeCheckConfig(w,t,C),t},n._getDimension=function(){return e(this._element).hasClass("width")?"width":"height"},n._getParent=function(){var n,i=this;l.isElement(this._config.parent)?(n=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(n=this._config.parent[0])):n=document.querySelector(this._config.parent);var o='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',r=[].slice.call(n.querySelectorAll(o));return e(r).each((function(e,n){i._addAriaAndCollapsedClass(t._getTargetFromElement(n),[n])})),n},n._addAriaAndCollapsedClass=function(t,n){var i=e(t).hasClass("show");n.length&&e(n).toggleClass("collapsed",!i).attr("aria-expanded",i)},t._getTargetFromElement=function(t){var e=l.getSelectorFromElement(t);return e?document.querySelector(e):null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.collapse"),r=s(s(s({},T),i.data()),"object"==typeof n&&n?n:{});if(!o&&r.toggle&&"string"==typeof n&&/show|hide/.test(n)&&(r.toggle=!1),o||(o=new t(this,r),i.data("bs.collapse",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return T}}]),t}();e(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=e(this),i=l.getSelectorFromElement(this),o=[].slice.call(document.querySelectorAll(i));e(o).each((function(){var t=e(this),i=t.data("bs.collapse")?"toggle":n.data();S._jQueryInterface.call(t,i)}))})),e.fn[w]=S._jQueryInterface,e.fn[w].Constructor=S,e.fn[w].noConflict=function(){return e.fn[w]=E,S._jQueryInterface};var D="undefined"!=typeof window&&"undefined"!=typeof document&&"undefined"!=typeof navigator,k=function(){for(var t=["Edge","Trident","Firefox"],e=0;e<t.length;e+=1)if(D&&navigator.userAgent.indexOf(t[e])>=0)return 1;return 0}();var N=D&&window.Promise?function(t){var e=!1;return function(){e||(e=!0,window.Promise.resolve().then((function(){e=!1,t()})))}}:function(t){var e=!1;return function(){e||(e=!0,setTimeout((function(){e=!1,t()}),k))}};function O(t){return t&&"[object Function]"==={}.toString.call(t)}function A(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function I(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function x(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=A(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/(auto|scroll|overlay)/.test(n+o+i)?t:x(I(t))}function j(t){return t&&t.referenceNode?t.referenceNode:t}var L=D&&!(!window.MSInputMethodContext||!document.documentMode),P=D&&/MSIE 10/.test(navigator.userAgent);function F(t){return 11===t?L:10===t?P:L||P}function R(t){if(!t)return document.documentElement;for(var e=F(10)?document.body:null,n=t.offsetParent||null;n===e&&t.nextElementSibling;)n=(t=t.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&"BODY"!==i&&"HTML"!==i?-1!==["TH","TD","TABLE"].indexOf(n.nodeName)&&"static"===A(n,"position")?R(n):n:t?t.ownerDocument.documentElement:document.documentElement}function M(t){return null!==t.parentNode?M(t.parentNode):t}function B(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,i=n?t:e,o=n?e:t,r=document.createRange();r.setStart(i,0),r.setEnd(o,0);var s,a,l=r.commonAncestorContainer;if(t!==l&&e!==l||i.contains(o))return"BODY"===(a=(s=l).nodeName)||"HTML"!==a&&R(s.firstElementChild)!==s?R(l):l;var c=M(t);return c.host?B(c.host,e):B(t,M(e).host)}function q(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",n="top"===e?"scrollTop":"scrollLeft",i=t.nodeName;if("BODY"===i||"HTML"===i){var o=t.ownerDocument.documentElement,r=t.ownerDocument.scrollingElement||o;return r[n]}return t[n]}function H(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=q(e,"top"),o=q(e,"left"),r=n?-1:1;return t.top+=i*r,t.bottom+=i*r,t.left+=o*r,t.right+=o*r,t}function Q(t,e){var n="x"===e?"Left":"Top",i="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"],10)+parseFloat(t["border"+i+"Width"],10)}function W(t,e,n,i){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],F(10)?parseInt(n["offset"+t])+parseInt(i["margin"+("Height"===t?"Top":"Left")])+parseInt(i["margin"+("Height"===t?"Bottom":"Right")]):0)}function U(t){var e=t.body,n=t.documentElement,i=F(10)&&getComputedStyle(n);return{height:W("Height",e,n,i),width:W("Width",e,n,i)}}var V=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},Y=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),z=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t},X=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t};function K(t){return X({},t,{right:t.left+t.width,bottom:t.top+t.height})}function G(t){var e={};try{if(F(10)){e=t.getBoundingClientRect();var n=q(t,"top"),i=q(t,"left");e.top+=n,e.left+=i,e.bottom+=n,e.right+=i}else e=t.getBoundingClientRect()}catch(t){}var o={left:e.left,top:e.top,width:e.right-e.left,height:e.bottom-e.top},r="HTML"===t.nodeName?U(t.ownerDocument):{},s=r.width||t.clientWidth||o.width,a=r.height||t.clientHeight||o.height,l=t.offsetWidth-s,c=t.offsetHeight-a;if(l||c){var u=A(t);l-=Q(u,"x"),c-=Q(u,"y"),o.width-=l,o.height-=c}return K(o)}function $(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=F(10),o="HTML"===e.nodeName,r=G(t),s=G(e),a=x(t),l=A(e),c=parseFloat(l.borderTopWidth,10),u=parseFloat(l.borderLeftWidth,10);n&&o&&(s.top=Math.max(s.top,0),s.left=Math.max(s.left,0));var h=K({top:r.top-s.top-c,left:r.left-s.left-u,width:r.width,height:r.height});if(h.marginTop=0,h.marginLeft=0,!i&&o){var f=parseFloat(l.marginTop,10),d=parseFloat(l.marginLeft,10);h.top-=c-f,h.bottom-=c-f,h.left-=u-d,h.right-=u-d,h.marginTop=f,h.marginLeft=d}return(i&&!n?e.contains(a):e===a&&"BODY"!==a.nodeName)&&(h=H(h,e)),h}function J(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.ownerDocument.documentElement,i=$(t,n),o=Math.max(n.clientWidth,window.innerWidth||0),r=Math.max(n.clientHeight,window.innerHeight||0),s=e?0:q(n),a=e?0:q(n,"left"),l={top:s-i.top+i.marginTop,left:a-i.left+i.marginLeft,width:o,height:r};return K(l)}function Z(t){var e=t.nodeName;if("BODY"===e||"HTML"===e)return!1;if("fixed"===A(t,"position"))return!0;var n=I(t);return!!n&&Z(n)}function tt(t){if(!t||!t.parentElement||F())return document.documentElement;for(var e=t.parentElement;e&&"none"===A(e,"transform");)e=e.parentElement;return e||document.documentElement}function et(t,e,n,i){var o=arguments.length>4&&void 0!==arguments[4]&&arguments[4],r={top:0,left:0},s=o?tt(t):B(t,j(e));if("viewport"===i)r=J(s,o);else{var a=void 0;"scrollParent"===i?"BODY"===(a=x(I(e))).nodeName&&(a=t.ownerDocument.documentElement):a="window"===i?t.ownerDocument.documentElement:i;var l=$(a,s,o);if("HTML"!==a.nodeName||Z(s))r=l;else{var c=U(t.ownerDocument),u=c.height,h=c.width;r.top+=l.top-l.marginTop,r.bottom=u+l.top,r.left+=l.left-l.marginLeft,r.right=h+l.left}}var f="number"==typeof(n=n||0);return r.left+=f?n:n.left||0,r.top+=f?n:n.top||0,r.right-=f?n:n.right||0,r.bottom-=f?n:n.bottom||0,r}function nt(t){return t.width*t.height}function it(t,e,n,i,o){var r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;if(-1===t.indexOf("auto"))return t;var s=et(n,i,r,o),a={top:{width:s.width,height:e.top-s.top},right:{width:s.right-e.right,height:s.height},bottom:{width:s.width,height:s.bottom-e.bottom},left:{width:e.left-s.left,height:s.height}},l=Object.keys(a).map((function(t){return X({key:t},a[t],{area:nt(a[t])})})).sort((function(t,e){return e.area-t.area})),c=l.filter((function(t){var e=t.width,i=t.height;return e>=n.clientWidth&&i>=n.clientHeight})),u=c.length>0?c[0].key:l[0].key,h=t.split("-")[1];return u+(h?"-"+h:"")}function ot(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=i?tt(e):B(e,j(n));return $(n,o,i)}function rt(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),i=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:t.offsetWidth+i,height:t.offsetHeight+n}}function st(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,(function(t){return e[t]}))}function at(t,e,n){n=n.split("-")[0];var i=rt(t),o={width:i.width,height:i.height},r=-1!==["right","left"].indexOf(n),s=r?"top":"left",a=r?"left":"top",l=r?"height":"width",c=r?"width":"height";return o[s]=e[s]+e[l]/2-i[l]/2,o[a]=n===a?e[a]-i[c]:e[st(a)],o}function lt(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function ct(t,e,n){return(void 0===n?t:t.slice(0,function(t,e,n){if(Array.prototype.findIndex)return t.findIndex((function(t){return t[e]===n}));var i=lt(t,(function(t){return t[e]===n}));return t.indexOf(i)}(t,"name",n))).forEach((function(t){t.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var n=t.function||t.fn;t.enabled&&O(n)&&(e.offsets.popper=K(e.offsets.popper),e.offsets.reference=K(e.offsets.reference),e=n(e,t))})),e}function ut(){if(!this.state.isDestroyed){var t={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};t.offsets.reference=ot(this.state,this.popper,this.reference,this.options.positionFixed),t.placement=it(this.options.placement,t.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),t.originalPlacement=t.placement,t.positionFixed=this.options.positionFixed,t.offsets.popper=at(this.popper,t.offsets.reference,t.placement),t.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",t=ct(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}function ht(t,e){return t.some((function(t){var n=t.name;return t.enabled&&n===e}))}function ft(t){for(var e=[!1,"ms","Webkit","Moz","O"],n=t.charAt(0).toUpperCase()+t.slice(1),i=0;i<e.length;i++){var o=e[i],r=o?""+o+n:t;if("undefined"!=typeof document.body.style[r])return r}return null}function dt(){return this.state.isDestroyed=!0,ht(this.modifiers,"applyStyle")&&(this.popper.removeAttribute("x-placement"),this.popper.style.position="",this.popper.style.top="",this.popper.style.left="",this.popper.style.right="",this.popper.style.bottom="",this.popper.style.willChange="",this.popper.style[ft("transform")]=""),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}function pt(t){var e=t.ownerDocument;return e?e.defaultView:window}function mt(t,e,n,i){n.updateBound=i,pt(t).addEventListener("resize",n.updateBound,{passive:!0});var o=x(t);return function t(e,n,i,o){var r="BODY"===e.nodeName,s=r?e.ownerDocument.defaultView:e;s.addEventListener(n,i,{passive:!0}),r||t(x(s.parentNode),n,i,o),o.push(s)}(o,"scroll",n.updateBound,n.scrollParents),n.scrollElement=o,n.eventsEnabled=!0,n}function gt(){this.state.eventsEnabled||(this.state=mt(this.reference,this.options,this.state,this.scheduleUpdate))}function vt(){var t,e;this.state.eventsEnabled&&(cancelAnimationFrame(this.scheduleUpdate),this.state=(t=this.reference,e=this.state,pt(t).removeEventListener("resize",e.updateBound),e.scrollParents.forEach((function(t){t.removeEventListener("scroll",e.updateBound)})),e.updateBound=null,e.scrollParents=[],e.scrollElement=null,e.eventsEnabled=!1,e))}function _t(t){return""!==t&&!isNaN(parseFloat(t))&&isFinite(t)}function bt(t,e){Object.keys(e).forEach((function(n){var i="";-1!==["width","height","top","right","bottom","left"].indexOf(n)&&_t(e[n])&&(i="px"),t.style[n]=e[n]+i}))}var yt=D&&/Firefox/i.test(navigator.userAgent);function wt(t,e,n){var i=lt(t,(function(t){return t.name===e})),o=!!i&&t.some((function(t){return t.name===n&&t.enabled&&t.order<i.order}));if(!o){var r="`"+e+"`",s="`"+n+"`";console.warn(s+" modifier is required by "+r+" modifier in order to work, be sure to include it before "+r+"!")}return o}var Et=["auto-start","auto","auto-end","top-start","top","top-end","right-start","right","right-end","bottom-end","bottom","bottom-start","left-end","left","left-start"],Tt=Et.slice(3);function Ct(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=Tt.indexOf(t),i=Tt.slice(n+1).concat(Tt.slice(0,n));return e?i.reverse():i}var St="flip",Dt="clockwise",kt="counterclockwise";function Nt(t,e,n,i){var o=[0,0],r=-1!==["right","left"].indexOf(i),s=t.split(/(\+|\-)/).map((function(t){return t.trim()})),a=s.indexOf(lt(s,(function(t){return-1!==t.search(/,|\s/)})));s[a]&&-1===s[a].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,c=-1!==a?[s.slice(0,a).concat([s[a].split(l)[0]]),[s[a].split(l)[1]].concat(s.slice(a+1))]:[s];return(c=c.map((function(t,i){var o=(1===i?!r:r)?"height":"width",s=!1;return t.reduce((function(t,e){return""===t[t.length-1]&&-1!==["+","-"].indexOf(e)?(t[t.length-1]=e,s=!0,t):s?(t[t.length-1]+=e,s=!1,t):t.concat(e)}),[]).map((function(t){return function(t,e,n,i){var o=t.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+o[1],s=o[2];if(!r)return t;if(0===s.indexOf("%")){var a=void 0;switch(s){case"%p":a=n;break;case"%":case"%r":default:a=i}return K(a)[e]/100*r}if("vh"===s||"vw"===s){return("vh"===s?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*r}return r}(t,o,e,n)}))}))).forEach((function(t,e){t.forEach((function(n,i){_t(n)&&(o[e]+=n*("-"===t[i-1]?-1:1))}))})),o}var Ot={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(t){var e=t.placement,n=e.split("-")[0],i=e.split("-")[1];if(i){var o=t.offsets,r=o.reference,s=o.popper,a=-1!==["bottom","top"].indexOf(n),l=a?"left":"top",c=a?"width":"height",u={start:z({},l,r[l]),end:z({},l,r[l]+r[c]-s[c])};t.offsets.popper=X({},s,u[i])}return t}},offset:{order:200,enabled:!0,fn:function(t,e){var n=e.offset,i=t.placement,o=t.offsets,r=o.popper,s=o.reference,a=i.split("-")[0],l=void 0;return l=_t(+n)?[+n,0]:Nt(n,r,s,a),"left"===a?(r.top+=l[0],r.left-=l[1]):"right"===a?(r.top+=l[0],r.left+=l[1]):"top"===a?(r.left+=l[0],r.top-=l[1]):"bottom"===a&&(r.left+=l[0],r.top+=l[1]),t.popper=r,t},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(t,e){var n=e.boundariesElement||R(t.instance.popper);t.instance.reference===n&&(n=R(n));var i=ft("transform"),o=t.instance.popper.style,r=o.top,s=o.left,a=o[i];o.top="",o.left="",o[i]="";var l=et(t.instance.popper,t.instance.reference,e.padding,n,t.positionFixed);o.top=r,o.left=s,o[i]=a,e.boundaries=l;var c=e.priority,u=t.offsets.popper,h={primary:function(t){var n=u[t];return u[t]<l[t]&&!e.escapeWithReference&&(n=Math.max(u[t],l[t])),z({},t,n)},secondary:function(t){var n="right"===t?"left":"top",i=u[n];return u[t]>l[t]&&!e.escapeWithReference&&(i=Math.min(u[n],l[t]-("right"===t?u.width:u.height))),z({},n,i)}};return c.forEach((function(t){var e=-1!==["left","top"].indexOf(t)?"primary":"secondary";u=X({},u,h[e](t))})),t.offsets.popper=u,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,n=e.popper,i=e.reference,o=t.placement.split("-")[0],r=Math.floor,s=-1!==["top","bottom"].indexOf(o),a=s?"right":"bottom",l=s?"left":"top",c=s?"width":"height";return n[a]<r(i[l])&&(t.offsets.popper[l]=r(i[l])-n[c]),n[l]>r(i[a])&&(t.offsets.popper[l]=r(i[a])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var n;if(!wt(t.instance.modifiers,"arrow","keepTogether"))return t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var o=t.placement.split("-")[0],r=t.offsets,s=r.popper,a=r.reference,l=-1!==["left","right"].indexOf(o),c=l?"height":"width",u=l?"Top":"Left",h=u.toLowerCase(),f=l?"left":"top",d=l?"bottom":"right",p=rt(i)[c];a[d]-p<s[h]&&(t.offsets.popper[h]-=s[h]-(a[d]-p)),a[h]+p>s[d]&&(t.offsets.popper[h]+=a[h]+p-s[d]),t.offsets.popper=K(t.offsets.popper);var m=a[h]+a[c]/2-p/2,g=A(t.instance.popper),v=parseFloat(g["margin"+u],10),_=parseFloat(g["border"+u+"Width"],10),b=m-t.offsets.popper[h]-v-_;return b=Math.max(Math.min(s[c]-p,b),0),t.arrowElement=i,t.offsets.arrow=(z(n={},h,Math.round(b)),z(n,f,""),n),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(t,e){if(ht(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var n=et(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),i=t.placement.split("-")[0],o=st(i),r=t.placement.split("-")[1]||"",s=[];switch(e.behavior){case St:s=[i,o];break;case Dt:s=Ct(i);break;case kt:s=Ct(i,!0);break;default:s=e.behavior}return s.forEach((function(a,l){if(i!==a||s.length===l+1)return t;i=t.placement.split("-")[0],o=st(i);var c=t.offsets.popper,u=t.offsets.reference,h=Math.floor,f="left"===i&&h(c.right)>h(u.left)||"right"===i&&h(c.left)<h(u.right)||"top"===i&&h(c.bottom)>h(u.top)||"bottom"===i&&h(c.top)<h(u.bottom),d=h(c.left)<h(n.left),p=h(c.right)>h(n.right),m=h(c.top)<h(n.top),g=h(c.bottom)>h(n.bottom),v="left"===i&&d||"right"===i&&p||"top"===i&&m||"bottom"===i&&g,_=-1!==["top","bottom"].indexOf(i),b=!!e.flipVariations&&(_&&"start"===r&&d||_&&"end"===r&&p||!_&&"start"===r&&m||!_&&"end"===r&&g),y=!!e.flipVariationsByContent&&(_&&"start"===r&&p||_&&"end"===r&&d||!_&&"start"===r&&g||!_&&"end"===r&&m),w=b||y;(f||v||w)&&(t.flipped=!0,(f||v)&&(i=s[l+1]),w&&(r=function(t){return"end"===t?"start":"start"===t?"end":t}(r)),t.placement=i+(r?"-"+r:""),t.offsets.popper=X({},t.offsets.popper,at(t.instance.popper,t.offsets.reference,t.placement)),t=ct(t.instance.modifiers,t,"flip"))})),t},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,n=e.split("-")[0],i=t.offsets,o=i.popper,r=i.reference,s=-1!==["left","right"].indexOf(n),a=-1===["top","left"].indexOf(n);return o[s?"left":"top"]=r[n]-(a?o[s?"width":"height"]:0),t.placement=st(e),t.offsets.popper=K(o),t}},hide:{order:800,enabled:!0,fn:function(t){if(!wt(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,n=lt(t.instance.modifiers,(function(t){return"preventOverflow"===t.name})).boundaries;if(e.bottom<n.top||e.left>n.right||e.top>n.bottom||e.right<n.left){if(!0===t.hide)return t;t.hide=!0,t.attributes["x-out-of-boundaries"]=""}else{if(!1===t.hide)return t;t.hide=!1,t.attributes["x-out-of-boundaries"]=!1}return t}},computeStyle:{order:850,enabled:!0,fn:function(t,e){var n=e.x,i=e.y,o=t.offsets.popper,r=lt(t.instance.modifiers,(function(t){return"applyStyle"===t.name})).gpuAcceleration;void 0!==r&&console.warn("WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!");var s=void 0!==r?r:e.gpuAcceleration,a=R(t.instance.popper),l=G(a),c={position:o.position},u=function(t,e){var n=t.offsets,i=n.popper,o=n.reference,r=Math.round,s=Math.floor,a=function(t){return t},l=r(o.width),c=r(i.width),u=-1!==["left","right"].indexOf(t.placement),h=-1!==t.placement.indexOf("-"),f=e?u||h||l%2==c%2?r:s:a,d=e?r:a;return{left:f(l%2==1&&c%2==1&&!h&&e?i.left-1:i.left),top:d(i.top),bottom:d(i.bottom),right:f(i.right)}}(t,window.devicePixelRatio<2||!yt),h="bottom"===n?"top":"bottom",f="right"===i?"left":"right",d=ft("transform"),p=void 0,m=void 0;if(m="bottom"===h?"HTML"===a.nodeName?-a.clientHeight+u.bottom:-l.height+u.bottom:u.top,p="right"===f?"HTML"===a.nodeName?-a.clientWidth+u.right:-l.width+u.right:u.left,s&&d)c[d]="translate3d("+p+"px, "+m+"px, 0)",c[h]=0,c[f]=0,c.willChange="transform";else{var g="bottom"===h?-1:1,v="right"===f?-1:1;c[h]=m*g,c[f]=p*v,c.willChange=h+", "+f}var _={"x-placement":t.placement};return t.attributes=X({},_,t.attributes),t.styles=X({},c,t.styles),t.arrowStyles=X({},t.offsets.arrow,t.arrowStyles),t},gpuAcceleration:!0,x:"bottom",y:"right"},applyStyle:{order:900,enabled:!0,fn:function(t){var e,n;return bt(t.instance.popper,t.styles),e=t.instance.popper,n=t.attributes,Object.keys(n).forEach((function(t){!1!==n[t]?e.setAttribute(t,n[t]):e.removeAttribute(t)})),t.arrowElement&&Object.keys(t.arrowStyles).length&&bt(t.arrowElement,t.arrowStyles),t},onLoad:function(t,e,n,i,o){var r=ot(o,e,t,n.positionFixed),s=it(n.placement,r,e,t,n.modifiers.flip.boundariesElement,n.modifiers.flip.padding);return e.setAttribute("x-placement",s),bt(e,{position:n.positionFixed?"fixed":"absolute"}),n},gpuAcceleration:void 0}}},At=function(){function t(e,n){var i=this,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};V(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=N(this.update.bind(this)),this.options=X({},t.Defaults,o),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(X({},t.Defaults.modifiers,o.modifiers)).forEach((function(e){i.options.modifiers[e]=X({},t.Defaults.modifiers[e]||{},o.modifiers?o.modifiers[e]:{})})),this.modifiers=Object.keys(this.options.modifiers).map((function(t){return X({name:t},i.options.modifiers[t])})).sort((function(t,e){return t.order-e.order})),this.modifiers.forEach((function(t){t.enabled&&O(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)})),this.update();var r=this.options.eventsEnabled;r&&this.enableEventListeners(),this.state.eventsEnabled=r}return Y(t,[{key:"update",value:function(){return ut.call(this)}},{key:"destroy",value:function(){return dt.call(this)}},{key:"enableEventListeners",value:function(){return gt.call(this)}},{key:"disableEventListeners",value:function(){return vt.call(this)}}]),t}();At.Utils=("undefined"!=typeof window?window:global).PopperUtils,At.placements=Et,At.Defaults=Ot;var It="dropdown",xt=e.fn[It],jt=new RegExp("38|40|27"),Lt={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},Pt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},Ft=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var n=t.prototype;return n.toggle=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")){var n=e(this._menu).hasClass("show");t._clearMenus(),n||this.show(!0)}},n.show=function(n){if(void 0===n&&(n=!1),!(this._element.disabled||e(this._element).hasClass("disabled")||e(this._menu).hasClass("show"))){var i={relatedTarget:this._element},o=e.Event("show.bs.dropdown",i),r=t._getParentFromElement(this._element);if(e(r).trigger(o),!o.isDefaultPrevented()){if(!this._inNavbar&&n){if("undefined"==typeof At)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var s=this._element;"parent"===this._config.reference?s=r:l.isElement(this._config.reference)&&(s=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(s=this._config.reference[0])),"scrollParent"!==this._config.boundary&&e(r).addClass("position-static"),this._popper=new At(s,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===e(r).closest(".navbar-nav").length&&e(document.body).children().on("mouseover",null,e.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),e(this._menu).toggleClass("show"),e(r).toggleClass("show").trigger(e.Event("shown.bs.dropdown",i))}}},n.hide=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")&&e(this._menu).hasClass("show")){var n={relatedTarget:this._element},i=e.Event("hide.bs.dropdown",n),o=t._getParentFromElement(this._element);e(o).trigger(i),i.isDefaultPrevented()||(this._popper&&this._popper.destroy(),e(this._menu).toggleClass("show"),e(o).toggleClass("show").trigger(e.Event("hidden.bs.dropdown",n)))}},n.dispose=function(){e.removeData(this._element,"bs.dropdown"),e(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},n.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},n._addEventListeners=function(){var t=this;e(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},n._getConfig=function(t){return t=s(s(s({},this.constructor.Default),e(this._element).data()),t),l.typeCheckConfig(It,t,this.constructor.DefaultType),t},n._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(".dropdown-menu"))}return this._menu},n._getPlacement=function(){var t=e(this._element.parentNode),n="bottom-start";return t.hasClass("dropup")?n=e(this._menu).hasClass("dropdown-menu-right")?"top-end":"top-start":t.hasClass("dropright")?n="right-start":t.hasClass("dropleft")?n="left-start":e(this._menu).hasClass("dropdown-menu-right")&&(n="bottom-end"),n},n._detectNavbar=function(){return e(this._element).closest(".navbar").length>0},n._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=s(s({},e.offsets),t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},n._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),s(s({},t),this._config.popperConfig)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.dropdown");if(i||(i=new t(this,"object"==typeof n?n:null),e(this).data("bs.dropdown",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},t._clearMenus=function(n){if(!n||3!==n.which&&("keyup"!==n.type||9===n.which))for(var i=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),o=0,r=i.length;o<r;o++){var s=t._getParentFromElement(i[o]),a=e(i[o]).data("bs.dropdown"),l={relatedTarget:i[o]};if(n&&"click"===n.type&&(l.clickEvent=n),a){var c=a._menu;if(e(s).hasClass("show")&&!(n&&("click"===n.type&&/input|textarea/i.test(n.target.tagName)||"keyup"===n.type&&9===n.which)&&e.contains(s,n.target))){var u=e.Event("hide.bs.dropdown",l);e(s).trigger(u),u.isDefaultPrevented()||("ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),i[o].setAttribute("aria-expanded","false"),a._popper&&a._popper.destroy(),e(c).removeClass("show"),e(s).removeClass("show").trigger(e.Event("hidden.bs.dropdown",l)))}}}},t._getParentFromElement=function(t){var e,n=l.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},t._dataApiKeydownHandler=function(n){if(!(/input|textarea/i.test(n.target.tagName)?32===n.which||27!==n.which&&(40!==n.which&&38!==n.which||e(n.target).closest(".dropdown-menu").length):!jt.test(n.which))&&!this.disabled&&!e(this).hasClass("disabled")){var i=t._getParentFromElement(this),o=e(i).hasClass("show");if(o||27!==n.which){if(n.preventDefault(),n.stopPropagation(),!o||o&&(27===n.which||32===n.which))return 27===n.which&&e(i.querySelector('[data-toggle="dropdown"]')).trigger("focus"),void e(this).trigger("click");var r=[].slice.call(i.querySelectorAll(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)")).filter((function(t){return e(t).is(":visible")}));if(0!==r.length){var s=r.indexOf(n.target);38===n.which&&s>0&&s--,40===n.which&&s<r.length-1&&s++,s<0&&(s=0),r[s].focus()}}}},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return Lt}},{key:"DefaultType",get:function(){return Pt}}]),t}();e(document).on("keydown.bs.dropdown.data-api",'[data-toggle="dropdown"]',Ft._dataApiKeydownHandler).on("keydown.bs.dropdown.data-api",".dropdown-menu",Ft._dataApiKeydownHandler).on("click.bs.dropdown.data-api keyup.bs.dropdown.data-api",Ft._clearMenus).on("click.bs.dropdown.data-api",'[data-toggle="dropdown"]',(function(t){t.preventDefault(),t.stopPropagation(),Ft._jQueryInterface.call(e(this),"toggle")})).on("click.bs.dropdown.data-api",".dropdown form",(function(t){t.stopPropagation()})),e.fn[It]=Ft._jQueryInterface,e.fn[It].Constructor=Ft,e.fn[It].noConflict=function(){return e.fn[It]=xt,Ft._jQueryInterface};var Rt=e.fn.modal,Mt={backdrop:!0,keyboard:!0,focus:!0,show:!0},Bt={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},qt=function(){function t(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(".modal-dialog"),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var n=t.prototype;return n.toggle=function(t){return this._isShown?this.hide():this.show(t)},n.show=function(t){var n=this;if(!this._isShown&&!this._isTransitioning){e(this._element).hasClass("fade")&&(this._isTransitioning=!0);var i=e.Event("show.bs.modal",{relatedTarget:t});e(this._element).trigger(i),this._isShown||i.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),e(this._element).on("click.dismiss.bs.modal",'[data-dismiss="modal"]',(function(t){return n.hide(t)})),e(this._dialog).on("mousedown.dismiss.bs.modal",(function(){e(n._element).one("mouseup.dismiss.bs.modal",(function(t){e(t.target).is(n._element)&&(n._ignoreBackdropClick=!0)}))})),this._showBackdrop((function(){return n._showElement(t)})))}},n.hide=function(t){var n=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var i=e.Event("hide.bs.modal");if(e(this._element).trigger(i),this._isShown&&!i.isDefaultPrevented()){this._isShown=!1;var o=e(this._element).hasClass("fade");if(o&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),e(document).off("focusin.bs.modal"),e(this._element).removeClass("show"),e(this._element).off("click.dismiss.bs.modal"),e(this._dialog).off("mousedown.dismiss.bs.modal"),o){var r=l.getTransitionDurationFromElement(this._element);e(this._element).one(l.TRANSITION_END,(function(t){return n._hideModal(t)})).emulateTransitionEnd(r)}else this._hideModal()}}},n.dispose=function(){[window,this._element,this._dialog].forEach((function(t){return e(t).off(".bs.modal")})),e(document).off("focusin.bs.modal"),e.removeData(this._element,"bs.modal"),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},n.handleUpdate=function(){this._adjustDialog()},n._getConfig=function(t){return t=s(s({},Mt),t),l.typeCheckConfig("modal",t,Bt),t},n._triggerBackdropTransition=function(){var t=this;if("static"===this._config.backdrop){var n=e.Event("hidePrevented.bs.modal");if(e(this._element).trigger(n),n.defaultPrevented)return;this._element.classList.add("modal-static");var i=l.getTransitionDurationFromElement(this._element);e(this._element).one(l.TRANSITION_END,(function(){t._element.classList.remove("modal-static")})).emulateTransitionEnd(i),this._element.focus()}else this.hide()},n._showElement=function(t){var n=this,i=e(this._element).hasClass("fade"),o=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),e(this._dialog).hasClass("modal-dialog-scrollable")&&o?o.scrollTop=0:this._element.scrollTop=0,i&&l.reflow(this._element),e(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var r=e.Event("shown.bs.modal",{relatedTarget:t}),s=function(){n._config.focus&&n._element.focus(),n._isTransitioning=!1,e(n._element).trigger(r)};if(i){var a=l.getTransitionDurationFromElement(this._dialog);e(this._dialog).one(l.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},n._enforceFocus=function(){var t=this;e(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(n){document!==n.target&&t._element!==n.target&&0===e(t._element).has(n.target).length&&t._element.focus()}))},n._setEscapeEvent=function(){var t=this;this._isShown?e(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||e(this._element).off("keydown.dismiss.bs.modal")},n._setResizeEvent=function(){var t=this;this._isShown?e(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):e(window).off("resize.bs.modal")},n._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop((function(){e(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),e(t._element).trigger("hidden.bs.modal")}))},n._removeBackdrop=function(){this._backdrop&&(e(this._backdrop).remove(),this._backdrop=null)},n._showBackdrop=function(t){var n=this,i=e(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",i&&this._backdrop.classList.add(i),e(this._backdrop).appendTo(document.body),e(this._element).on("click.dismiss.bs.modal",(function(t){n._ignoreBackdropClick?n._ignoreBackdropClick=!1:t.target===t.currentTarget&&n._triggerBackdropTransition()})),i&&l.reflow(this._backdrop),e(this._backdrop).addClass("show"),!t)return;if(!i)return void t();var o=l.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(l.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){e(this._backdrop).removeClass("show");var r=function(){n._removeBackdrop(),t&&t()};if(e(this._element).hasClass("fade")){var s=l.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(l.TRANSITION_END,r).emulateTransitionEnd(s)}else r()}else t&&t()},n._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},n._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},n._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},n._setScrollbar=function(){var t=this;if(this._isBodyOverflowing){var n=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top")),i=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(n,i){var o=i.style.paddingRight,r=e(i).css("padding-right");e(i).data("padding-right",o).css("padding-right",parseFloat(r)+t._scrollbarWidth+"px")})),e(i).each((function(n,i){var o=i.style.marginRight,r=e(i).css("margin-right");e(i).data("margin-right",o).css("margin-right",parseFloat(r)-t._scrollbarWidth+"px")}));var o=document.body.style.paddingRight,r=e(document.body).css("padding-right");e(document.body).data("padding-right",o).css("padding-right",parseFloat(r)+this._scrollbarWidth+"px")}e(document.body).addClass("modal-open")},n._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top"));e(t).each((function(t,n){var i=e(n).data("padding-right");e(n).removeData("padding-right"),n.style.paddingRight=i||""}));var n=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(t,n){var i=e(n).data("margin-right");"undefined"!=typeof i&&e(n).css("margin-right",i).removeData("margin-right")}));var i=e(document.body).data("padding-right");e(document.body).removeData("padding-right"),document.body.style.paddingRight=i||""},n._getScrollbarWidth=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},t._jQueryInterface=function(n,i){return this.each((function(){var o=e(this).data("bs.modal"),r=s(s(s({},Mt),e(this).data()),"object"==typeof n&&n?n:{});if(o||(o=new t(this,r),e(this).data("bs.modal",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](i)}else r.show&&o.show(i)}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return Mt}}]),t}();e(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',(function(t){var n,i=this,o=l.getSelectorFromElement(this);o&&(n=document.querySelector(o));var r=e(n).data("bs.modal")?"toggle":s(s({},e(n).data()),e(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var a=e(n).one("show.bs.modal",(function(t){t.isDefaultPrevented()||a.one("hidden.bs.modal",(function(){e(i).is(":visible")&&i.focus()}))}));qt._jQueryInterface.call(e(n),r,this)})),e.fn.modal=qt._jQueryInterface,e.fn.modal.Constructor=qt,e.fn.modal.noConflict=function(){return e.fn.modal=Rt,qt._jQueryInterface};var Ht=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],Qt={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Wt=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,Ut=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function Vt(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var i=(new window.DOMParser).parseFromString(t,"text/html"),o=Object.keys(e),r=[].slice.call(i.body.querySelectorAll("*")),s=function(t,n){var i=r[t],s=i.nodeName.toLowerCase();if(-1===o.indexOf(i.nodeName.toLowerCase()))return i.parentNode.removeChild(i),"continue";var a=[].slice.call(i.attributes),l=[].concat(e["*"]||[],e[s]||[]);a.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===Ht.indexOf(n)||Boolean(t.nodeValue.match(Wt)||t.nodeValue.match(Ut));for(var i=e.filter((function(t){return t instanceof RegExp})),o=0,r=i.length;o<r;o++)if(n.match(i[o]))return!0;return!1})(t,l)||i.removeAttribute(t.nodeName)}))},a=0,l=r.length;a<l;a++)s(a);return i.body.innerHTML}var Yt="tooltip",zt=e.fn[Yt],Xt=new RegExp("(^|\\s)bs-tooltip\\S+","g"),Kt=["sanitize","whiteList","sanitizeFn"],Gt={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},$t={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Jt={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Qt,popperConfig:null},Zt={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},te=function(){function t(t,e){if("undefined"==typeof At)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var n=t.prototype;return n.enable=function(){this._isEnabled=!0},n.disable=function(){this._isEnabled=!1},n.toggleEnabled=function(){this._isEnabled=!this._isEnabled},n.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},n.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},n.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var n=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(n);var i=l.findShadowRoot(this.element),o=e.contains(null!==i?i:this.element.ownerDocument.documentElement,this.element);if(n.isDefaultPrevented()||!o)return;var r=this.getTipElement(),s=l.getUID(this.constructor.NAME);r.setAttribute("id",s),this.element.setAttribute("aria-describedby",s),this.setContent(),this.config.animation&&e(r).addClass("fade");var a="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,c=this._getAttachment(a);this.addAttachmentClass(c);var u=this._getContainer();e(r).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(r).appendTo(u),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new At(this.element,r,this._getPopperConfig(c)),e(r).addClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().on("mouseover",null,e.noop);var h=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),"out"===n&&t._leave(null,t)};if(e(this.tip).hasClass("fade")){var f=l.getTransitionDurationFromElement(this.tip);e(this.tip).one(l.TRANSITION_END,h).emulateTransitionEnd(f)}else h()}},n.hide=function(t){var n=this,i=this.getTipElement(),o=e.Event(this.constructor.Event.HIDE),r=function(){"show"!==n._hoverState&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};if(e(this.element).trigger(o),!o.isDefaultPrevented()){if(e(i).removeClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,e(this.tip).hasClass("fade")){var s=l.getTransitionDurationFromElement(i);e(i).one(l.TRANSITION_END,r).emulateTransitionEnd(s)}else r();this._hoverState=""}},n.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},n.isWithContent=function(){return Boolean(this.getTitle())},n.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},n.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},n.setContent=function(){var t=this.getTipElement();this.setElementContent(e(t.querySelectorAll(".tooltip-inner")),this.getTitle()),e(t).removeClass("fade show")},n.setElementContent=function(t,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=Vt(n,this.config.whiteList,this.config.sanitizeFn)),t.html(n)):t.text(n):this.config.html?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text())},n.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},n._getPopperConfig=function(t){var e=this;return s(s({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),this.config.popperConfig)},n._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=s(s({},e.offsets),t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},n._getContainer=function(){return!1===this.config.container?document.body:l.isElement(this.config.container)?e(this.config.container):e(document).find(this.config.container)},n._getAttachment=function(t){return $t[t.toUpperCase()]},n._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==n){var i="hover"===n?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===n?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},e(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=s(s({},this.config),{},{trigger:"manual",selector:""}):this._fixTitle()},n._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},n._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},n._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},n._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},n._getConfig=function(t){var n=e(this.element).data();return Object.keys(n).forEach((function(t){-1!==Kt.indexOf(t)&&delete n[t]})),"number"==typeof(t=s(s(s({},this.constructor.Default),n),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),l.typeCheckConfig(Yt,t,this.constructor.DefaultType),t.sanitize&&(t.template=Vt(t.template,t.whiteList,t.sanitizeFn)),t},n._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},n._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(Xt);null!==n&&n.length&&t.removeClass(n.join(""))},n._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},n._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.tooltip"),o="object"==typeof n&&n;if((i||!/dispose|hide/.test(n))&&(i||(i=new t(this,o),e(this).data("bs.tooltip",i)),"string"==typeof n)){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return Jt}},{key:"NAME",get:function(){return Yt}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return Zt}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Gt}}]),t}();e.fn[Yt]=te._jQueryInterface,e.fn[Yt].Constructor=te,e.fn[Yt].noConflict=function(){return e.fn[Yt]=zt,te._jQueryInterface};var ee="popover",ne=e.fn[ee],ie=new RegExp("(^|\\s)bs-popover\\S+","g"),oe=s(s({},te.Default),{},{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),re=s(s({},te.DefaultType),{},{content:"(string|element|function)"}),se={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},ae=function(t){var n,o;function r(){return t.apply(this,arguments)||this}o=t,(n=r).prototype=Object.create(o.prototype),n.prototype.constructor=n,n.__proto__=o;var s=r.prototype;return s.isWithContent=function(){return this.getTitle()||this._getContent()},s.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},s.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},s.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(t.find(".popover-body"),n),t.removeClass("fade show")},s._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},s._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(ie);null!==n&&n.length>0&&t.removeClass(n.join(""))},r._jQueryInterface=function(t){return this.each((function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new r(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},i(r,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return oe}},{key:"NAME",get:function(){return ee}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return se}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return re}}]),r}(te);e.fn[ee]=ae._jQueryInterface,e.fn[ee].Constructor=ae,e.fn[ee].noConflict=function(){return e.fn[ee]=ne,ae._jQueryInterface};var le="scrollspy",ce=e.fn[le],ue={offset:10,method:"auto",target:""},he={offset:"number",method:"string",target:"(string|element)"},fe=function(){function t(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return i._process(t)})),this.refresh(),this._process()}var n=t.prototype;return n.refresh=function(){var t=this,n=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?n:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var n,r=l.getSelectorFromElement(t);if(r&&(n=document.querySelector(r)),n){var s=n.getBoundingClientRect();if(s.width||s.height)return[e(n)[i]().top+o,r]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},n.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},n._getConfig=function(t){if("string"!=typeof(t=s(s({},ue),"object"==typeof t&&t?t:{})).target&&l.isElement(t.target)){var n=e(t.target).attr("id");n||(n=l.getUID(le),e(t.target).attr("id",n)),t.target="#"+n}return l.typeCheckConfig(le,t,he),t},n._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},n._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},n._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},n._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},n._activate=function(t){this._activeTarget=t,this._clear();var n=this._selector.split(",").map((function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'})),i=e([].slice.call(document.querySelectorAll(n.join(","))));i.hasClass("dropdown-item")?(i.closest(".dropdown").find(".dropdown-toggle").addClass("active"),i.addClass("active")):(i.addClass("active"),i.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),i.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),e(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:t})},n._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.scrollspy");if(i||(i=new t(this,"object"==typeof n&&n),e(this).data("bs.scrollspy",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return ue}}]),t}();e(window).on("load.bs.scrollspy.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),n=t.length;n--;){var i=e(t[n]);fe._jQueryInterface.call(i,i.data())}})),e.fn[le]=fe._jQueryInterface,e.fn[le].Constructor=fe,e.fn[le].noConflict=function(){return e.fn[le]=ce,fe._jQueryInterface};var de=e.fn.tab,pe=function(){function t(t){this._element=t}var n=t.prototype;return n.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&e(this._element).hasClass("active")||e(this._element).hasClass("disabled"))){var n,i,o=e(this._element).closest(".nav, .list-group")[0],r=l.getSelectorFromElement(this._element);if(o){var s="UL"===o.nodeName||"OL"===o.nodeName?"> li > .active":".active";i=(i=e.makeArray(e(o).find(s)))[i.length-1]}var a=e.Event("hide.bs.tab",{relatedTarget:this._element}),c=e.Event("show.bs.tab",{relatedTarget:i});if(i&&e(i).trigger(a),e(this._element).trigger(c),!c.isDefaultPrevented()&&!a.isDefaultPrevented()){r&&(n=document.querySelector(r)),this._activate(this._element,o);var u=function(){var n=e.Event("hidden.bs.tab",{relatedTarget:t._element}),o=e.Event("shown.bs.tab",{relatedTarget:i});e(i).trigger(n),e(t._element).trigger(o)};n?this._activate(n,n.parentNode,u):u()}}},n.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},n._activate=function(t,n,i){var o=this,r=(!n||"UL"!==n.nodeName&&"OL"!==n.nodeName?e(n).children(".active"):e(n).find("> li > .active"))[0],s=i&&r&&e(r).hasClass("fade"),a=function(){return o._transitionComplete(t,r,i)};if(r&&s){var c=l.getTransitionDurationFromElement(r);e(r).removeClass("show").one(l.TRANSITION_END,a).emulateTransitionEnd(c)}else a()},n._transitionComplete=function(t,n,i){if(n){e(n).removeClass("active");var o=e(n.parentNode).find("> .dropdown-menu .active")[0];o&&e(o).removeClass("active"),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),l.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&e(t.parentNode).hasClass("dropdown-menu")){var r=e(t).closest(".dropdown")[0];if(r){var s=[].slice.call(r.querySelectorAll(".dropdown-toggle"));e(s).addClass("active")}t.setAttribute("aria-expanded",!0)}i&&i()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.tab");if(o||(o=new t(this),i.data("bs.tab",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),pe._jQueryInterface.call(e(this),"show")})),e.fn.tab=pe._jQueryInterface,e.fn.tab.Constructor=pe,e.fn.tab.noConflict=function(){return e.fn.tab=de,pe._jQueryInterface};var me=e.fn.toast,ge={animation:"boolean",autohide:"boolean",delay:"number"},ve={animation:!0,autohide:!0,delay:500},_e=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var n=t.prototype;return n.show=function(){var t=this,n=e.Event("show.bs.toast");if(e(this._element).trigger(n),!n.isDefaultPrevented()){this._config.animation&&this._element.classList.add("fade");var i=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),e(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),l.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=l.getTransitionDurationFromElement(this._element);e(this._element).one(l.TRANSITION_END,i).emulateTransitionEnd(o)}else i()}},n.hide=function(){if(this._element.classList.contains("show")){var t=e.Event("hide.bs.toast");e(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},n.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains("show")&&this._element.classList.remove("show"),e(this._element).off("click.dismiss.bs.toast"),e.removeData(this._element,"bs.toast"),this._element=null,this._config=null},n._getConfig=function(t){return t=s(s(s({},ve),e(this._element).data()),"object"==typeof t&&t?t:{}),l.typeCheckConfig("toast",t,this.constructor.DefaultType),t},n._setListeners=function(){var t=this;e(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},n._close=function(){var t=this,n=function(){t._element.classList.add("hide"),e(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var i=l.getTransitionDurationFromElement(this._element);e(this._element).one(l.TRANSITION_END,n).emulateTransitionEnd(i)}else n()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.toast");if(o||(o=new t(this,"object"==typeof n&&n),i.data("bs.toast",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](this)}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"DefaultType",get:function(){return ge}},{key:"Default",get:function(){return ve}}]),t}();e.fn.toast=_e._jQueryInterface,e.fn.toast.Constructor=_e,e.fn.toast.noConflict=function(){return e.fn.toast=me,_e._jQueryInterface},t.Alert=h,t.Button=d,t.Carousel=y,t.Collapse=S,t.Dropdown=Ft,t.Modal=qt,t.Popover=ae,t.Scrollspy=fe,t.Tab=pe,t.Toast=_e,t.Tooltip=te,t.Util=l,Object.defineProperty(t,"__esModule",{value:!0})}));
7
  //# sourceMappingURL=bootstrap.bundle.min.js.map
1
  /*!
2
+ * Bootstrap v4.5.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery")):"function"==typeof define&&define.amd?define(["exports","jquery"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery)}(this,(function(t,e){"use strict";function n(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function i(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}function o(){return(o=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t}).apply(this,arguments)}e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e;function r(t){var n=this,i=!1;return e(this).one(s.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||s.triggerTransitionEnd(n)}),t),this}var s={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),i=e(t).css("transition-delay"),o=parseFloat(n),r=parseFloat(i);return o||r?(n=n.split(",")[0],i=i.split(",")[0],1e3*(parseFloat(n)+parseFloat(i))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],r=e[i],a=r&&s.isElement(r)?"element":null===(l=r)||"undefined"==typeof l?""+l:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(a))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+a+'" but expected type "'+o+'".')}var l},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?s.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if("undefined"==typeof e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};s.jQueryDetection(),e.fn.emulateTransitionEnd=r,e.event.special[s.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var a="alert",l=e.fn[a],c=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=s.getSelectorFromElement(t),i=!1;return n&&(i=document.querySelector(n)),i||(i=e(t).closest(".alert")[0]),i},n._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},n._removeElement=function(t){var n=this;if(e(t).removeClass("show"),e(t).hasClass("fade")){var i=s.getTransitionDurationFromElement(t);e(t).one(s.TRANSITION_END,(function(e){return n._destroyElement(t,e)})).emulateTransitionEnd(i)}else this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.alert");o||(o=new t(this),i.data("bs.alert",o)),"close"===n&&o[n](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}}]),t}();e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',c._handleDismiss(new c)),e.fn[a]=c._jQueryInterface,e.fn[a].Constructor=c,e.fn[a].noConflict=function(){return e.fn[a]=l,c._jQueryInterface};var h=e.fn.button,u=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,i=e(this._element).closest('[data-toggle="buttons"]')[0];if(i){var o=this._element.querySelector('input:not([type="hidden"])');if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains("active"))t=!1;else{var r=i.querySelector(".active");r&&e(r).removeClass("active")}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains("active")),e(o).trigger("change")),o.focus(),n=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(n&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&e(this._element).toggleClass("active"))},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}}]),t}();e(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=t.target,i=n;if(e(n).hasClass("btn")||(n=e(n).closest(".btn")[0]),!n||n.hasAttribute("disabled")||n.classList.contains("disabled"))t.preventDefault();else{var o=n.querySelector('input:not([type="hidden"])');if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();("LABEL"!==i.tagName||o&&"checkbox"!==o.type)&&u._jQueryInterface.call(e(n),"toggle")}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=e(t.target).closest(".btn")[0];e(n).toggleClass("focus",/^focus(in)?$/.test(t.type))})),e(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e<n;e++){var i=t[e],o=i.querySelector('input:not([type="hidden"])');o.checked||o.hasAttribute("checked")?i.classList.add("active"):i.classList.remove("active")}for(var r=0,s=(t=[].slice.call(document.querySelectorAll('[data-toggle="button"]'))).length;r<s;r++){var a=t[r];"true"===a.getAttribute("aria-pressed")?a.classList.add("active"):a.classList.remove("active")}})),e.fn.button=u._jQueryInterface,e.fn.button.Constructor=u,e.fn.button.noConflict=function(){return e.fn.button=h,u._jQueryInterface};var f="carousel",d=".bs.carousel",p=e.fn[f],m={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},g={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},_={TOUCH:"touch",PEN:"pen"},v=function(){function t(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(".carousel-indicators"),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var n=t.prototype;return n.next=function(){this._isSliding||this._slide("next")},n.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},n.prev=function(){this._isSliding||this._slide("prev")},n.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(s.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},n.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},n.to=function(t){var n=this;this._activeElement=this._element.querySelector(".active.carousel-item");var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one("slid.bs.carousel",(function(){return n.to(t)}));else{if(i===t)return this.pause(),void this.cycle();var o=t>i?"next":"prev";this._slide(o,this._items[t])}},n.dispose=function(){e(this._element).off(d),e.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},n._getConfig=function(t){return t=o({},m,t),s.typeCheckConfig(f,t,g),t},n._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},n._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&e(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},n._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var n=function(e){t._pointerEvent&&_[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},i=function(e){t._pointerEvent&&_[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};e(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(e(this._element).on("pointerdown.bs.carousel",(function(t){return n(t)})),e(this._element).on("pointerup.bs.carousel",(function(t){return i(t)})),this._element.classList.add("pointer-event")):(e(this._element).on("touchstart.bs.carousel",(function(t){return n(t)})),e(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),e(this._element).on("touchend.bs.carousel",(function(t){return i(t)})))}},n._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},n._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},n._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+("prev"===t?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},n._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(".active.carousel-item")),r=e.Event("slide.bs.carousel",{relatedTarget:t,direction:n,from:o,to:i});return e(this._element).trigger(r),r},n._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var n=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));e(n).removeClass("active");var i=this._indicatorsElement.children[this._getItemIndex(t)];i&&e(i).addClass("active")}},n._slide=function(t,n){var i,o,r,a=this,l=this._element.querySelector(".active.carousel-item"),c=this._getItemIndex(l),h=n||l&&this._getItemByDirection(t,l),u=this._getItemIndex(h),f=Boolean(this._interval);if("next"===t?(i="carousel-item-left",o="carousel-item-next",r="left"):(i="carousel-item-right",o="carousel-item-prev",r="right"),h&&e(h).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(h,r).isDefaultPrevented()&&l&&h){this._isSliding=!0,f&&this.pause(),this._setActiveIndicatorElement(h);var d=e.Event("slid.bs.carousel",{relatedTarget:h,direction:r,from:c,to:u});if(e(this._element).hasClass("slide")){e(h).addClass(o),s.reflow(h),e(l).addClass(i),e(h).addClass(i);var p=parseInt(h.getAttribute("data-interval"),10);p?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=p):this._config.interval=this._config.defaultInterval||this._config.interval;var m=s.getTransitionDurationFromElement(l);e(l).one(s.TRANSITION_END,(function(){e(h).removeClass(i+" "+o).addClass("active"),e(l).removeClass("active "+o+" "+i),a._isSliding=!1,setTimeout((function(){return e(a._element).trigger(d)}),0)})).emulateTransitionEnd(m)}else e(l).removeClass("active"),e(h).addClass("active"),this._isSliding=!1,e(this._element).trigger(d);f&&this.cycle()}},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.carousel"),r=o({},m,e(this).data());"object"==typeof n&&(r=o({},r,n));var s="string"==typeof n?n:r.slide;if(i||(i=new t(this,r),e(this).data("bs.carousel",i)),"number"==typeof n)i.to(n);else if("string"==typeof s){if("undefined"==typeof i[s])throw new TypeError('No method named "'+s+'"');i[s]()}else r.interval&&r.ride&&(i.pause(),i.cycle())}))},t._dataApiClickHandler=function(n){var i=s.getSelectorFromElement(this);if(i){var r=e(i)[0];if(r&&e(r).hasClass("carousel")){var a=o({},e(r).data(),e(this).data()),l=this.getAttribute("data-slide-to");l&&(a.interval=!1),t._jQueryInterface.call(e(r),a),l&&e(r).data("bs.carousel").to(l),n.preventDefault()}}},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return m}}]),t}();e(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",v._dataApiClickHandler),e(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),n=0,i=t.length;n<i;n++){var o=e(t[n]);v._jQueryInterface.call(o,o.data())}})),e.fn[f]=v._jQueryInterface,e.fn[f].Constructor=v,e.fn[f].noConflict=function(){return e.fn[f]=p,v._jQueryInterface};var b="collapse",y=e.fn[b],w={toggle:!0,parent:""},E={toggle:"boolean",parent:"(string|element)"},T=function(){function t(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=n.length;i<o;i++){var r=n[i],a=s.getSelectorFromElement(r),l=[].slice.call(document.querySelectorAll(a)).filter((function(e){return e===t}));null!==a&&l.length>0&&(this._selector=a,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var n=t.prototype;return n.toggle=function(){e(this._element).hasClass("show")?this.hide():this.show()},n.show=function(){var n,i,o=this;if(!this._isTransitioning&&!e(this._element).hasClass("show")&&(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),!(n&&(i=e(n).not(this._selector).data("bs.collapse"))&&i._isTransitioning))){var r=e.Event("show.bs.collapse");if(e(this._element).trigger(r),!r.isDefaultPrevented()){n&&(t._jQueryInterface.call(e(n).not(this._selector),"hide"),i||e(n).data("bs.collapse",null));var a=this._getDimension();e(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[a]=0,this._triggerArray.length&&e(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(a[0].toUpperCase()+a.slice(1)),c=s.getTransitionDurationFromElement(this._element);e(this._element).one(s.TRANSITION_END,(function(){e(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[a]="",o.setTransitioning(!1),e(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(c),this._element.style[a]=this._element[l]+"px"}}},n.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass("show")){var n=e.Event("hide.bs.collapse");if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",s.reflow(this._element),e(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var r=0;r<o;r++){var a=this._triggerArray[r],l=s.getSelectorFromElement(a);if(null!==l)e([].slice.call(document.querySelectorAll(l))).hasClass("show")||e(a).addClass("collapsed").attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[i]="";var c=s.getTransitionDurationFromElement(this._element);e(this._element).one(s.TRANSITION_END,(function(){t.setTransitioning(!1),e(t._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(c)}}},n.setTransitioning=function(t){this._isTransitioning=t},n.dispose=function(){e.removeData(this._element,"bs.collapse"),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},n._getConfig=function(t){return(t=o({},w,t)).toggle=Boolean(t.toggle),s.typeCheckConfig(b,t,E),t},n._getDimension=function(){return e(this._element).hasClass("width")?"width":"height"},n._getParent=function(){var n,i=this;s.isElement(this._config.parent)?(n=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(n=this._config.parent[0])):n=document.querySelector(this._config.parent);var o='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',r=[].slice.call(n.querySelectorAll(o));return e(r).each((function(e,n){i._addAriaAndCollapsedClass(t._getTargetFromElement(n),[n])})),n},n._addAriaAndCollapsedClass=function(t,n){var i=e(t).hasClass("show");n.length&&e(n).toggleClass("collapsed",!i).attr("aria-expanded",i)},t._getTargetFromElement=function(t){var e=s.getSelectorFromElement(t);return e?document.querySelector(e):null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),r=i.data("bs.collapse"),s=o({},w,i.data(),"object"==typeof n&&n?n:{});if(!r&&s.toggle&&"string"==typeof n&&/show|hide/.test(n)&&(s.toggle=!1),r||(r=new t(this,s),i.data("bs.collapse",r)),"string"==typeof n){if("undefined"==typeof r[n])throw new TypeError('No method named "'+n+'"');r[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return w}}]),t}();e(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=e(this),i=s.getSelectorFromElement(this),o=[].slice.call(document.querySelectorAll(i));e(o).each((function(){var t=e(this),i=t.data("bs.collapse")?"toggle":n.data();T._jQueryInterface.call(t,i)}))})),e.fn[b]=T._jQueryInterface,e.fn[b].Constructor=T,e.fn[b].noConflict=function(){return e.fn[b]=y,T._jQueryInterface};var C="undefined"!=typeof window&&"undefined"!=typeof document&&"undefined"!=typeof navigator,S=function(){for(var t=["Edge","Trident","Firefox"],e=0;e<t.length;e+=1)if(C&&navigator.userAgent.indexOf(t[e])>=0)return 1;return 0}();var D=C&&window.Promise?function(t){var e=!1;return function(){e||(e=!0,window.Promise.resolve().then((function(){e=!1,t()})))}}:function(t){var e=!1;return function(){e||(e=!0,setTimeout((function(){e=!1,t()}),S))}};function N(t){return t&&"[object Function]"==={}.toString.call(t)}function k(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function A(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function I(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=k(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/(auto|scroll|overlay)/.test(n+o+i)?t:I(A(t))}function O(t){return t&&t.referenceNode?t.referenceNode:t}var x=C&&!(!window.MSInputMethodContext||!document.documentMode),j=C&&/MSIE 10/.test(navigator.userAgent);function L(t){return 11===t?x:10===t?j:x||j}function P(t){if(!t)return document.documentElement;for(var e=L(10)?document.body:null,n=t.offsetParent||null;n===e&&t.nextElementSibling;)n=(t=t.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&"BODY"!==i&&"HTML"!==i?-1!==["TH","TD","TABLE"].indexOf(n.nodeName)&&"static"===k(n,"position")?P(n):n:t?t.ownerDocument.documentElement:document.documentElement}function F(t){return null!==t.parentNode?F(t.parentNode):t}function R(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,i=n?t:e,o=n?e:t,r=document.createRange();r.setStart(i,0),r.setEnd(o,0);var s,a,l=r.commonAncestorContainer;if(t!==l&&e!==l||i.contains(o))return"BODY"===(a=(s=l).nodeName)||"HTML"!==a&&P(s.firstElementChild)!==s?P(l):l;var c=F(t);return c.host?R(c.host,e):R(t,F(e).host)}function H(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",n="top"===e?"scrollTop":"scrollLeft",i=t.nodeName;if("BODY"===i||"HTML"===i){var o=t.ownerDocument.documentElement,r=t.ownerDocument.scrollingElement||o;return r[n]}return t[n]}function M(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=H(e,"top"),o=H(e,"left"),r=n?-1:1;return t.top+=i*r,t.bottom+=i*r,t.left+=o*r,t.right+=o*r,t}function B(t,e){var n="x"===e?"Left":"Top",i="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"])+parseFloat(t["border"+i+"Width"])}function q(t,e,n,i){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],L(10)?parseInt(n["offset"+t])+parseInt(i["margin"+("Height"===t?"Top":"Left")])+parseInt(i["margin"+("Height"===t?"Bottom":"Right")]):0)}function Q(t){var e=t.body,n=t.documentElement,i=L(10)&&getComputedStyle(n);return{height:q("Height",e,n,i),width:q("Width",e,n,i)}}var W=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},U=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),V=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t},Y=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t};function z(t){return Y({},t,{right:t.left+t.width,bottom:t.top+t.height})}function X(t){var e={};try{if(L(10)){e=t.getBoundingClientRect();var n=H(t,"top"),i=H(t,"left");e.top+=n,e.left+=i,e.bottom+=n,e.right+=i}else e=t.getBoundingClientRect()}catch(t){}var o={left:e.left,top:e.top,width:e.right-e.left,height:e.bottom-e.top},r="HTML"===t.nodeName?Q(t.ownerDocument):{},s=r.width||t.clientWidth||o.width,a=r.height||t.clientHeight||o.height,l=t.offsetWidth-s,c=t.offsetHeight-a;if(l||c){var h=k(t);l-=B(h,"x"),c-=B(h,"y"),o.width-=l,o.height-=c}return z(o)}function K(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=L(10),o="HTML"===e.nodeName,r=X(t),s=X(e),a=I(t),l=k(e),c=parseFloat(l.borderTopWidth),h=parseFloat(l.borderLeftWidth);n&&o&&(s.top=Math.max(s.top,0),s.left=Math.max(s.left,0));var u=z({top:r.top-s.top-c,left:r.left-s.left-h,width:r.width,height:r.height});if(u.marginTop=0,u.marginLeft=0,!i&&o){var f=parseFloat(l.marginTop),d=parseFloat(l.marginLeft);u.top-=c-f,u.bottom-=c-f,u.left-=h-d,u.right-=h-d,u.marginTop=f,u.marginLeft=d}return(i&&!n?e.contains(a):e===a&&"BODY"!==a.nodeName)&&(u=M(u,e)),u}function G(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.ownerDocument.documentElement,i=K(t,n),o=Math.max(n.clientWidth,window.innerWidth||0),r=Math.max(n.clientHeight,window.innerHeight||0),s=e?0:H(n),a=e?0:H(n,"left"),l={top:s-i.top+i.marginTop,left:a-i.left+i.marginLeft,width:o,height:r};return z(l)}function $(t){var e=t.nodeName;if("BODY"===e||"HTML"===e)return!1;if("fixed"===k(t,"position"))return!0;var n=A(t);return!!n&&$(n)}function J(t){if(!t||!t.parentElement||L())return document.documentElement;for(var e=t.parentElement;e&&"none"===k(e,"transform");)e=e.parentElement;return e||document.documentElement}function Z(t,e,n,i){var o=arguments.length>4&&void 0!==arguments[4]&&arguments[4],r={top:0,left:0},s=o?J(t):R(t,O(e));if("viewport"===i)r=G(s,o);else{var a=void 0;"scrollParent"===i?"BODY"===(a=I(A(e))).nodeName&&(a=t.ownerDocument.documentElement):a="window"===i?t.ownerDocument.documentElement:i;var l=K(a,s,o);if("HTML"!==a.nodeName||$(s))r=l;else{var c=Q(t.ownerDocument),h=c.height,u=c.width;r.top+=l.top-l.marginTop,r.bottom=h+l.top,r.left+=l.left-l.marginLeft,r.right=u+l.left}}var f="number"==typeof(n=n||0);return r.left+=f?n:n.left||0,r.top+=f?n:n.top||0,r.right-=f?n:n.right||0,r.bottom-=f?n:n.bottom||0,r}function tt(t){return t.width*t.height}function et(t,e,n,i,o){var r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;if(-1===t.indexOf("auto"))return t;var s=Z(n,i,r,o),a={top:{width:s.width,height:e.top-s.top},right:{width:s.right-e.right,height:s.height},bottom:{width:s.width,height:s.bottom-e.bottom},left:{width:e.left-s.left,height:s.height}},l=Object.keys(a).map((function(t){return Y({key:t},a[t],{area:tt(a[t])})})).sort((function(t,e){return e.area-t.area})),c=l.filter((function(t){var e=t.width,i=t.height;return e>=n.clientWidth&&i>=n.clientHeight})),h=c.length>0?c[0].key:l[0].key,u=t.split("-")[1];return h+(u?"-"+u:"")}function nt(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,o=i?J(e):R(e,O(n));return K(n,o,i)}function it(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),i=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:t.offsetWidth+i,height:t.offsetHeight+n}}function ot(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,(function(t){return e[t]}))}function rt(t,e,n){n=n.split("-")[0];var i=it(t),o={width:i.width,height:i.height},r=-1!==["right","left"].indexOf(n),s=r?"top":"left",a=r?"left":"top",l=r?"height":"width",c=r?"width":"height";return o[s]=e[s]+e[l]/2-i[l]/2,o[a]=n===a?e[a]-i[c]:e[ot(a)],o}function st(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function at(t,e,n){return(void 0===n?t:t.slice(0,function(t,e,n){if(Array.prototype.findIndex)return t.findIndex((function(t){return t[e]===n}));var i=st(t,(function(t){return t[e]===n}));return t.indexOf(i)}(t,"name",n))).forEach((function(t){t.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var n=t.function||t.fn;t.enabled&&N(n)&&(e.offsets.popper=z(e.offsets.popper),e.offsets.reference=z(e.offsets.reference),e=n(e,t))})),e}function lt(){if(!this.state.isDestroyed){var t={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};t.offsets.reference=nt(this.state,this.popper,this.reference,this.options.positionFixed),t.placement=et(this.options.placement,t.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),t.originalPlacement=t.placement,t.positionFixed=this.options.positionFixed,t.offsets.popper=rt(this.popper,t.offsets.reference,t.placement),t.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",t=at(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}function ct(t,e){return t.some((function(t){var n=t.name;return t.enabled&&n===e}))}function ht(t){for(var e=[!1,"ms","Webkit","Moz","O"],n=t.charAt(0).toUpperCase()+t.slice(1),i=0;i<e.length;i++){var o=e[i],r=o?""+o+n:t;if("undefined"!=typeof document.body.style[r])return r}return null}function ut(){return this.state.isDestroyed=!0,ct(this.modifiers,"applyStyle")&&(this.popper.removeAttribute("x-placement"),this.popper.style.position="",this.popper.style.top="",this.popper.style.left="",this.popper.style.right="",this.popper.style.bottom="",this.popper.style.willChange="",this.popper.style[ht("transform")]=""),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}function ft(t){var e=t.ownerDocument;return e?e.defaultView:window}function dt(t,e,n,i){n.updateBound=i,ft(t).addEventListener("resize",n.updateBound,{passive:!0});var o=I(t);return function t(e,n,i,o){var r="BODY"===e.nodeName,s=r?e.ownerDocument.defaultView:e;s.addEventListener(n,i,{passive:!0}),r||t(I(s.parentNode),n,i,o),o.push(s)}(o,"scroll",n.updateBound,n.scrollParents),n.scrollElement=o,n.eventsEnabled=!0,n}function pt(){this.state.eventsEnabled||(this.state=dt(this.reference,this.options,this.state,this.scheduleUpdate))}function mt(){var t,e;this.state.eventsEnabled&&(cancelAnimationFrame(this.scheduleUpdate),this.state=(t=this.reference,e=this.state,ft(t).removeEventListener("resize",e.updateBound),e.scrollParents.forEach((function(t){t.removeEventListener("scroll",e.updateBound)})),e.updateBound=null,e.scrollParents=[],e.scrollElement=null,e.eventsEnabled=!1,e))}function gt(t){return""!==t&&!isNaN(parseFloat(t))&&isFinite(t)}function _t(t,e){Object.keys(e).forEach((function(n){var i="";-1!==["width","height","top","right","bottom","left"].indexOf(n)&&gt(e[n])&&(i="px"),t.style[n]=e[n]+i}))}var vt=C&&/Firefox/i.test(navigator.userAgent);function bt(t,e,n){var i=st(t,(function(t){return t.name===e})),o=!!i&&t.some((function(t){return t.name===n&&t.enabled&&t.order<i.order}));if(!o){var r="`"+e+"`",s="`"+n+"`";console.warn(s+" modifier is required by "+r+" modifier in order to work, be sure to include it before "+r+"!")}return o}var yt=["auto-start","auto","auto-end","top-start","top","top-end","right-start","right","right-end","bottom-end","bottom","bottom-start","left-end","left","left-start"],wt=yt.slice(3);function Et(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=wt.indexOf(t),i=wt.slice(n+1).concat(wt.slice(0,n));return e?i.reverse():i}var Tt="flip",Ct="clockwise",St="counterclockwise";function Dt(t,e,n,i){var o=[0,0],r=-1!==["right","left"].indexOf(i),s=t.split(/(\+|\-)/).map((function(t){return t.trim()})),a=s.indexOf(st(s,(function(t){return-1!==t.search(/,|\s/)})));s[a]&&-1===s[a].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,c=-1!==a?[s.slice(0,a).concat([s[a].split(l)[0]]),[s[a].split(l)[1]].concat(s.slice(a+1))]:[s];return(c=c.map((function(t,i){var o=(1===i?!r:r)?"height":"width",s=!1;return t.reduce((function(t,e){return""===t[t.length-1]&&-1!==["+","-"].indexOf(e)?(t[t.length-1]=e,s=!0,t):s?(t[t.length-1]+=e,s=!1,t):t.concat(e)}),[]).map((function(t){return function(t,e,n,i){var o=t.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),r=+o[1],s=o[2];if(!r)return t;if(0===s.indexOf("%")){var a=void 0;switch(s){case"%p":a=n;break;case"%":case"%r":default:a=i}return z(a)[e]/100*r}if("vh"===s||"vw"===s){return("vh"===s?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*r}return r}(t,o,e,n)}))}))).forEach((function(t,e){t.forEach((function(n,i){gt(n)&&(o[e]+=n*("-"===t[i-1]?-1:1))}))})),o}var Nt={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(t){var e=t.placement,n=e.split("-")[0],i=e.split("-")[1];if(i){var o=t.offsets,r=o.reference,s=o.popper,a=-1!==["bottom","top"].indexOf(n),l=a?"left":"top",c=a?"width":"height",h={start:V({},l,r[l]),end:V({},l,r[l]+r[c]-s[c])};t.offsets.popper=Y({},s,h[i])}return t}},offset:{order:200,enabled:!0,fn:function(t,e){var n=e.offset,i=t.placement,o=t.offsets,r=o.popper,s=o.reference,a=i.split("-")[0],l=void 0;return l=gt(+n)?[+n,0]:Dt(n,r,s,a),"left"===a?(r.top+=l[0],r.left-=l[1]):"right"===a?(r.top+=l[0],r.left+=l[1]):"top"===a?(r.left+=l[0],r.top-=l[1]):"bottom"===a&&(r.left+=l[0],r.top+=l[1]),t.popper=r,t},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(t,e){var n=e.boundariesElement||P(t.instance.popper);t.instance.reference===n&&(n=P(n));var i=ht("transform"),o=t.instance.popper.style,r=o.top,s=o.left,a=o[i];o.top="",o.left="",o[i]="";var l=Z(t.instance.popper,t.instance.reference,e.padding,n,t.positionFixed);o.top=r,o.left=s,o[i]=a,e.boundaries=l;var c=e.priority,h=t.offsets.popper,u={primary:function(t){var n=h[t];return h[t]<l[t]&&!e.escapeWithReference&&(n=Math.max(h[t],l[t])),V({},t,n)},secondary:function(t){var n="right"===t?"left":"top",i=h[n];return h[t]>l[t]&&!e.escapeWithReference&&(i=Math.min(h[n],l[t]-("right"===t?h.width:h.height))),V({},n,i)}};return c.forEach((function(t){var e=-1!==["left","top"].indexOf(t)?"primary":"secondary";h=Y({},h,u[e](t))})),t.offsets.popper=h,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,n=e.popper,i=e.reference,o=t.placement.split("-")[0],r=Math.floor,s=-1!==["top","bottom"].indexOf(o),a=s?"right":"bottom",l=s?"left":"top",c=s?"width":"height";return n[a]<r(i[l])&&(t.offsets.popper[l]=r(i[l])-n[c]),n[l]>r(i[a])&&(t.offsets.popper[l]=r(i[a])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var n;if(!bt(t.instance.modifiers,"arrow","keepTogether"))return t;var i=e.element;if("string"==typeof i){if(!(i=t.instance.popper.querySelector(i)))return t}else if(!t.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var o=t.placement.split("-")[0],r=t.offsets,s=r.popper,a=r.reference,l=-1!==["left","right"].indexOf(o),c=l?"height":"width",h=l?"Top":"Left",u=h.toLowerCase(),f=l?"left":"top",d=l?"bottom":"right",p=it(i)[c];a[d]-p<s[u]&&(t.offsets.popper[u]-=s[u]-(a[d]-p)),a[u]+p>s[d]&&(t.offsets.popper[u]+=a[u]+p-s[d]),t.offsets.popper=z(t.offsets.popper);var m=a[u]+a[c]/2-p/2,g=k(t.instance.popper),_=parseFloat(g["margin"+h]),v=parseFloat(g["border"+h+"Width"]),b=m-t.offsets.popper[u]-_-v;return b=Math.max(Math.min(s[c]-p,b),0),t.arrowElement=i,t.offsets.arrow=(V(n={},u,Math.round(b)),V(n,f,""),n),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(t,e){if(ct(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var n=Z(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),i=t.placement.split("-")[0],o=ot(i),r=t.placement.split("-")[1]||"",s=[];switch(e.behavior){case Tt:s=[i,o];break;case Ct:s=Et(i);break;case St:s=Et(i,!0);break;default:s=e.behavior}return s.forEach((function(a,l){if(i!==a||s.length===l+1)return t;i=t.placement.split("-")[0],o=ot(i);var c=t.offsets.popper,h=t.offsets.reference,u=Math.floor,f="left"===i&&u(c.right)>u(h.left)||"right"===i&&u(c.left)<u(h.right)||"top"===i&&u(c.bottom)>u(h.top)||"bottom"===i&&u(c.top)<u(h.bottom),d=u(c.left)<u(n.left),p=u(c.right)>u(n.right),m=u(c.top)<u(n.top),g=u(c.bottom)>u(n.bottom),_="left"===i&&d||"right"===i&&p||"top"===i&&m||"bottom"===i&&g,v=-1!==["top","bottom"].indexOf(i),b=!!e.flipVariations&&(v&&"start"===r&&d||v&&"end"===r&&p||!v&&"start"===r&&m||!v&&"end"===r&&g),y=!!e.flipVariationsByContent&&(v&&"start"===r&&p||v&&"end"===r&&d||!v&&"start"===r&&g||!v&&"end"===r&&m),w=b||y;(f||_||w)&&(t.flipped=!0,(f||_)&&(i=s[l+1]),w&&(r=function(t){return"end"===t?"start":"start"===t?"end":t}(r)),t.placement=i+(r?"-"+r:""),t.offsets.popper=Y({},t.offsets.popper,rt(t.instance.popper,t.offsets.reference,t.placement)),t=at(t.instance.modifiers,t,"flip"))})),t},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,n=e.split("-")[0],i=t.offsets,o=i.popper,r=i.reference,s=-1!==["left","right"].indexOf(n),a=-1===["top","left"].indexOf(n);return o[s?"left":"top"]=r[n]-(a?o[s?"width":"height"]:0),t.placement=ot(e),t.offsets.popper=z(o),t}},hide:{order:800,enabled:!0,fn:function(t){if(!bt(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,n=st(t.instance.modifiers,(function(t){return"preventOverflow"===t.name})).boundaries;if(e.bottom<n.top||e.left>n.right||e.top>n.bottom||e.right<n.left){if(!0===t.hide)return t;t.hide=!0,t.attributes["x-out-of-boundaries"]=""}else{if(!1===t.hide)return t;t.hide=!1,t.attributes["x-out-of-boundaries"]=!1}return t}},computeStyle:{order:850,enabled:!0,fn:function(t,e){var n=e.x,i=e.y,o=t.offsets.popper,r=st(t.instance.modifiers,(function(t){return"applyStyle"===t.name})).gpuAcceleration;void 0!==r&&console.warn("WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!");var s=void 0!==r?r:e.gpuAcceleration,a=P(t.instance.popper),l=X(a),c={position:o.position},h=function(t,e){var n=t.offsets,i=n.popper,o=n.reference,r=Math.round,s=Math.floor,a=function(t){return t},l=r(o.width),c=r(i.width),h=-1!==["left","right"].indexOf(t.placement),u=-1!==t.placement.indexOf("-"),f=e?h||u||l%2==c%2?r:s:a,d=e?r:a;return{left:f(l%2==1&&c%2==1&&!u&&e?i.left-1:i.left),top:d(i.top),bottom:d(i.bottom),right:f(i.right)}}(t,window.devicePixelRatio<2||!vt),u="bottom"===n?"top":"bottom",f="right"===i?"left":"right",d=ht("transform"),p=void 0,m=void 0;if(m="bottom"===u?"HTML"===a.nodeName?-a.clientHeight+h.bottom:-l.height+h.bottom:h.top,p="right"===f?"HTML"===a.nodeName?-a.clientWidth+h.right:-l.width+h.right:h.left,s&&d)c[d]="translate3d("+p+"px, "+m+"px, 0)",c[u]=0,c[f]=0,c.willChange="transform";else{var g="bottom"===u?-1:1,_="right"===f?-1:1;c[u]=m*g,c[f]=p*_,c.willChange=u+", "+f}var v={"x-placement":t.placement};return t.attributes=Y({},v,t.attributes),t.styles=Y({},c,t.styles),t.arrowStyles=Y({},t.offsets.arrow,t.arrowStyles),t},gpuAcceleration:!0,x:"bottom",y:"right"},applyStyle:{order:900,enabled:!0,fn:function(t){var e,n;return _t(t.instance.popper,t.styles),e=t.instance.popper,n=t.attributes,Object.keys(n).forEach((function(t){!1!==n[t]?e.setAttribute(t,n[t]):e.removeAttribute(t)})),t.arrowElement&&Object.keys(t.arrowStyles).length&&_t(t.arrowElement,t.arrowStyles),t},onLoad:function(t,e,n,i,o){var r=nt(o,e,t,n.positionFixed),s=et(n.placement,r,e,t,n.modifiers.flip.boundariesElement,n.modifiers.flip.padding);return e.setAttribute("x-placement",s),_t(e,{position:n.positionFixed?"fixed":"absolute"}),n},gpuAcceleration:void 0}}},kt=function(){function t(e,n){var i=this,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};W(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(i.update)},this.update=D(this.update.bind(this)),this.options=Y({},t.Defaults,o),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(Y({},t.Defaults.modifiers,o.modifiers)).forEach((function(e){i.options.modifiers[e]=Y({},t.Defaults.modifiers[e]||{},o.modifiers?o.modifiers[e]:{})})),this.modifiers=Object.keys(this.options.modifiers).map((function(t){return Y({name:t},i.options.modifiers[t])})).sort((function(t,e){return t.order-e.order})),this.modifiers.forEach((function(t){t.enabled&&N(t.onLoad)&&t.onLoad(i.reference,i.popper,i.options,t,i.state)})),this.update();var r=this.options.eventsEnabled;r&&this.enableEventListeners(),this.state.eventsEnabled=r}return U(t,[{key:"update",value:function(){return lt.call(this)}},{key:"destroy",value:function(){return ut.call(this)}},{key:"enableEventListeners",value:function(){return pt.call(this)}},{key:"disableEventListeners",value:function(){return mt.call(this)}}]),t}();kt.Utils=("undefined"!=typeof window?window:global).PopperUtils,kt.placements=yt,kt.Defaults=Nt;var At="dropdown",It=e.fn[At],Ot=new RegExp("38|40|27"),xt={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},jt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},Lt=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var n=t.prototype;return n.toggle=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")){var n=e(this._menu).hasClass("show");t._clearMenus(),n||this.show(!0)}},n.show=function(n){if(void 0===n&&(n=!1),!(this._element.disabled||e(this._element).hasClass("disabled")||e(this._menu).hasClass("show"))){var i={relatedTarget:this._element},o=e.Event("show.bs.dropdown",i),r=t._getParentFromElement(this._element);if(e(r).trigger(o),!o.isDefaultPrevented()){if(!this._inNavbar&&n){if("undefined"==typeof kt)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var a=this._element;"parent"===this._config.reference?a=r:s.isElement(this._config.reference)&&(a=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(a=this._config.reference[0])),"scrollParent"!==this._config.boundary&&e(r).addClass("position-static"),this._popper=new kt(a,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===e(r).closest(".navbar-nav").length&&e(document.body).children().on("mouseover",null,e.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),e(this._menu).toggleClass("show"),e(r).toggleClass("show").trigger(e.Event("shown.bs.dropdown",i))}}},n.hide=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")&&e(this._menu).hasClass("show")){var n={relatedTarget:this._element},i=e.Event("hide.bs.dropdown",n),o=t._getParentFromElement(this._element);e(o).trigger(i),i.isDefaultPrevented()||(this._popper&&this._popper.destroy(),e(this._menu).toggleClass("show"),e(o).toggleClass("show").trigger(e.Event("hidden.bs.dropdown",n)))}},n.dispose=function(){e.removeData(this._element,"bs.dropdown"),e(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},n.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},n._addEventListeners=function(){var t=this;e(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},n._getConfig=function(t){return t=o({},this.constructor.Default,e(this._element).data(),t),s.typeCheckConfig(At,t,this.constructor.DefaultType),t},n._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(".dropdown-menu"))}return this._menu},n._getPlacement=function(){var t=e(this._element.parentNode),n="bottom-start";return t.hasClass("dropup")?n=e(this._menu).hasClass("dropdown-menu-right")?"top-end":"top-start":t.hasClass("dropright")?n="right-start":t.hasClass("dropleft")?n="left-start":e(this._menu).hasClass("dropdown-menu-right")&&(n="bottom-end"),n},n._detectNavbar=function(){return e(this._element).closest(".navbar").length>0},n._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=o({},e.offsets,t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},n._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),o({},t,this._config.popperConfig)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.dropdown");if(i||(i=new t(this,"object"==typeof n?n:null),e(this).data("bs.dropdown",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},t._clearMenus=function(n){if(!n||3!==n.which&&("keyup"!==n.type||9===n.which))for(var i=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),o=0,r=i.length;o<r;o++){var s=t._getParentFromElement(i[o]),a=e(i[o]).data("bs.dropdown"),l={relatedTarget:i[o]};if(n&&"click"===n.type&&(l.clickEvent=n),a){var c=a._menu;if(e(s).hasClass("show")&&!(n&&("click"===n.type&&/input|textarea/i.test(n.target.tagName)||"keyup"===n.type&&9===n.which)&&e.contains(s,n.target))){var h=e.Event("hide.bs.dropdown",l);e(s).trigger(h),h.isDefaultPrevented()||("ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),i[o].setAttribute("aria-expanded","false"),a._popper&&a._popper.destroy(),e(c).removeClass("show"),e(s).removeClass("show").trigger(e.Event("hidden.bs.dropdown",l)))}}}},t._getParentFromElement=function(t){var e,n=s.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},t._dataApiKeydownHandler=function(n){if(!(/input|textarea/i.test(n.target.tagName)?32===n.which||27!==n.which&&(40!==n.which&&38!==n.which||e(n.target).closest(".dropdown-menu").length):!Ot.test(n.which))&&!this.disabled&&!e(this).hasClass("disabled")){var i=t._getParentFromElement(this),o=e(i).hasClass("show");if(o||27!==n.which){if(n.preventDefault(),n.stopPropagation(),!o||o&&(27===n.which||32===n.which))return 27===n.which&&e(i.querySelector('[data-toggle="dropdown"]')).trigger("focus"),void e(this).trigger("click");var r=[].slice.call(i.querySelectorAll(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)")).filter((function(t){return e(t).is(":visible")}));if(0!==r.length){var s=r.indexOf(n.target);38===n.which&&s>0&&s--,40===n.which&&s<r.length-1&&s++,s<0&&(s=0),r[s].focus()}}}},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return xt}},{key:"DefaultType",get:function(){return jt}}]),t}();e(document).on("keydown.bs.dropdown.data-api",'[data-toggle="dropdown"]',Lt._dataApiKeydownHandler).on("keydown.bs.dropdown.data-api",".dropdown-menu",Lt._dataApiKeydownHandler).on("click.bs.dropdown.data-api keyup.bs.dropdown.data-api",Lt._clearMenus).on("click.bs.dropdown.data-api",'[data-toggle="dropdown"]',(function(t){t.preventDefault(),t.stopPropagation(),Lt._jQueryInterface.call(e(this),"toggle")})).on("click.bs.dropdown.data-api",".dropdown form",(function(t){t.stopPropagation()})),e.fn[At]=Lt._jQueryInterface,e.fn[At].Constructor=Lt,e.fn[At].noConflict=function(){return e.fn[At]=It,Lt._jQueryInterface};var Pt=e.fn.modal,Ft={backdrop:!0,keyboard:!0,focus:!0,show:!0},Rt={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},Ht=function(){function t(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(".modal-dialog"),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var n=t.prototype;return n.toggle=function(t){return this._isShown?this.hide():this.show(t)},n.show=function(t){var n=this;if(!this._isShown&&!this._isTransitioning){e(this._element).hasClass("fade")&&(this._isTransitioning=!0);var i=e.Event("show.bs.modal",{relatedTarget:t});e(this._element).trigger(i),this._isShown||i.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),e(this._element).on("click.dismiss.bs.modal",'[data-dismiss="modal"]',(function(t){return n.hide(t)})),e(this._dialog).on("mousedown.dismiss.bs.modal",(function(){e(n._element).one("mouseup.dismiss.bs.modal",(function(t){e(t.target).is(n._element)&&(n._ignoreBackdropClick=!0)}))})),this._showBackdrop((function(){return n._showElement(t)})))}},n.hide=function(t){var n=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var i=e.Event("hide.bs.modal");if(e(this._element).trigger(i),this._isShown&&!i.isDefaultPrevented()){this._isShown=!1;var o=e(this._element).hasClass("fade");if(o&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),e(document).off("focusin.bs.modal"),e(this._element).removeClass("show"),e(this._element).off("click.dismiss.bs.modal"),e(this._dialog).off("mousedown.dismiss.bs.modal"),o){var r=s.getTransitionDurationFromElement(this._element);e(this._element).one(s.TRANSITION_END,(function(t){return n._hideModal(t)})).emulateTransitionEnd(r)}else this._hideModal()}}},n.dispose=function(){[window,this._element,this._dialog].forEach((function(t){return e(t).off(".bs.modal")})),e(document).off("focusin.bs.modal"),e.removeData(this._element,"bs.modal"),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},n.handleUpdate=function(){this._adjustDialog()},n._getConfig=function(t){return t=o({},Ft,t),s.typeCheckConfig("modal",t,Rt),t},n._triggerBackdropTransition=function(){var t=this;if("static"===this._config.backdrop){var n=e.Event("hidePrevented.bs.modal");if(e(this._element).trigger(n),n.defaultPrevented)return;var i=this._element.scrollHeight>document.documentElement.clientHeight;i||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");var o=s.getTransitionDurationFromElement(this._dialog);e(this._element).off(s.TRANSITION_END),e(this._element).one(s.TRANSITION_END,(function(){t._element.classList.remove("modal-static"),i||e(t._element).one(s.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,o)})).emulateTransitionEnd(o),this._element.focus()}else this.hide()},n._showElement=function(t){var n=this,i=e(this._element).hasClass("fade"),o=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),e(this._dialog).hasClass("modal-dialog-scrollable")&&o?o.scrollTop=0:this._element.scrollTop=0,i&&s.reflow(this._element),e(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var r=e.Event("shown.bs.modal",{relatedTarget:t}),a=function(){n._config.focus&&n._element.focus(),n._isTransitioning=!1,e(n._element).trigger(r)};if(i){var l=s.getTransitionDurationFromElement(this._dialog);e(this._dialog).one(s.TRANSITION_END,a).emulateTransitionEnd(l)}else a()},n._enforceFocus=function(){var t=this;e(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(n){document!==n.target&&t._element!==n.target&&0===e(t._element).has(n.target).length&&t._element.focus()}))},n._setEscapeEvent=function(){var t=this;this._isShown?e(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||e(this._element).off("keydown.dismiss.bs.modal")},n._setResizeEvent=function(){var t=this;this._isShown?e(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):e(window).off("resize.bs.modal")},n._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){e(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),e(t._element).trigger("hidden.bs.modal")}))},n._removeBackdrop=function(){this._backdrop&&(e(this._backdrop).remove(),this._backdrop=null)},n._showBackdrop=function(t){var n=this,i=e(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",i&&this._backdrop.classList.add(i),e(this._backdrop).appendTo(document.body),e(this._element).on("click.dismiss.bs.modal",(function(t){n._ignoreBackdropClick?n._ignoreBackdropClick=!1:t.target===t.currentTarget&&n._triggerBackdropTransition()})),i&&s.reflow(this._backdrop),e(this._backdrop).addClass("show"),!t)return;if(!i)return void t();var o=s.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(s.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){e(this._backdrop).removeClass("show");var r=function(){n._removeBackdrop(),t&&t()};if(e(this._element).hasClass("fade")){var a=s.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(s.TRANSITION_END,r).emulateTransitionEnd(a)}else r()}else t&&t()},n._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},n._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},n._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},n._setScrollbar=function(){var t=this;if(this._isBodyOverflowing){var n=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top")),i=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(n,i){var o=i.style.paddingRight,r=e(i).css("padding-right");e(i).data("padding-right",o).css("padding-right",parseFloat(r)+t._scrollbarWidth+"px")})),e(i).each((function(n,i){var o=i.style.marginRight,r=e(i).css("margin-right");e(i).data("margin-right",o).css("margin-right",parseFloat(r)-t._scrollbarWidth+"px")}));var o=document.body.style.paddingRight,r=e(document.body).css("padding-right");e(document.body).data("padding-right",o).css("padding-right",parseFloat(r)+this._scrollbarWidth+"px")}e(document.body).addClass("modal-open")},n._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top"));e(t).each((function(t,n){var i=e(n).data("padding-right");e(n).removeData("padding-right"),n.style.paddingRight=i||""}));var n=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(t,n){var i=e(n).data("margin-right");"undefined"!=typeof i&&e(n).css("margin-right",i).removeData("margin-right")}));var i=e(document.body).data("padding-right");e(document.body).removeData("padding-right"),document.body.style.paddingRight=i||""},n._getScrollbarWidth=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},t._jQueryInterface=function(n,i){return this.each((function(){var r=e(this).data("bs.modal"),s=o({},Ft,e(this).data(),"object"==typeof n&&n?n:{});if(r||(r=new t(this,s),e(this).data("bs.modal",r)),"string"==typeof n){if("undefined"==typeof r[n])throw new TypeError('No method named "'+n+'"');r[n](i)}else s.show&&r.show(i)}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return Ft}}]),t}();e(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',(function(t){var n,i=this,r=s.getSelectorFromElement(this);r&&(n=document.querySelector(r));var a=e(n).data("bs.modal")?"toggle":o({},e(n).data(),e(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var l=e(n).one("show.bs.modal",(function(t){t.isDefaultPrevented()||l.one("hidden.bs.modal",(function(){e(i).is(":visible")&&i.focus()}))}));Ht._jQueryInterface.call(e(n),a,this)})),e.fn.modal=Ht._jQueryInterface,e.fn.modal.Constructor=Ht,e.fn.modal.noConflict=function(){return e.fn.modal=Pt,Ht._jQueryInterface};var Mt=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],Bt={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},qt=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,Qt=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function Wt(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var i=(new window.DOMParser).parseFromString(t,"text/html"),o=Object.keys(e),r=[].slice.call(i.body.querySelectorAll("*")),s=function(t,n){var i=r[t],s=i.nodeName.toLowerCase();if(-1===o.indexOf(i.nodeName.toLowerCase()))return i.parentNode.removeChild(i),"continue";var a=[].slice.call(i.attributes),l=[].concat(e["*"]||[],e[s]||[]);a.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===Mt.indexOf(n)||Boolean(t.nodeValue.match(qt)||t.nodeValue.match(Qt));for(var i=e.filter((function(t){return t instanceof RegExp})),o=0,r=i.length;o<r;o++)if(n.match(i[o]))return!0;return!1})(t,l)||i.removeAttribute(t.nodeName)}))},a=0,l=r.length;a<l;a++)s(a);return i.body.innerHTML}var Ut="tooltip",Vt=e.fn[Ut],Yt=new RegExp("(^|\\s)bs-tooltip\\S+","g"),zt=["sanitize","whiteList","sanitizeFn"],Xt={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},Kt={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Gt={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Bt,popperConfig:null},$t={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Jt=function(){function t(t,e){if("undefined"==typeof kt)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var n=t.prototype;return n.enable=function(){this._isEnabled=!0},n.disable=function(){this._isEnabled=!1},n.toggleEnabled=function(){this._isEnabled=!this._isEnabled},n.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},n.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},n.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var n=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(n);var i=s.findShadowRoot(this.element),o=e.contains(null!==i?i:this.element.ownerDocument.documentElement,this.element);if(n.isDefaultPrevented()||!o)return;var r=this.getTipElement(),a=s.getUID(this.constructor.NAME);r.setAttribute("id",a),this.element.setAttribute("aria-describedby",a),this.setContent(),this.config.animation&&e(r).addClass("fade");var l="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,c=this._getAttachment(l);this.addAttachmentClass(c);var h=this._getContainer();e(r).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(r).appendTo(h),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new kt(this.element,r,this._getPopperConfig(c)),e(r).addClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().on("mouseover",null,e.noop);var u=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),"out"===n&&t._leave(null,t)};if(e(this.tip).hasClass("fade")){var f=s.getTransitionDurationFromElement(this.tip);e(this.tip).one(s.TRANSITION_END,u).emulateTransitionEnd(f)}else u()}},n.hide=function(t){var n=this,i=this.getTipElement(),o=e.Event(this.constructor.Event.HIDE),r=function(){"show"!==n._hoverState&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};if(e(this.element).trigger(o),!o.isDefaultPrevented()){if(e(i).removeClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,e(this.tip).hasClass("fade")){var a=s.getTransitionDurationFromElement(i);e(i).one(s.TRANSITION_END,r).emulateTransitionEnd(a)}else r();this._hoverState=""}},n.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},n.isWithContent=function(){return Boolean(this.getTitle())},n.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},n.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},n.setContent=function(){var t=this.getTipElement();this.setElementContent(e(t.querySelectorAll(".tooltip-inner")),this.getTitle()),e(t).removeClass("fade show")},n.setElementContent=function(t,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=Wt(n,this.config.whiteList,this.config.sanitizeFn)),t.html(n)):t.text(n):this.config.html?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text())},n.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},n._getPopperConfig=function(t){var e=this;return o({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},n._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=o({},e.offsets,t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},n._getContainer=function(){return!1===this.config.container?document.body:s.isElement(this.config.container)?e(this.config.container):e(document).find(this.config.container)},n._getAttachment=function(t){return Kt[t.toUpperCase()]},n._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==n){var i="hover"===n?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===n?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},e(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=o({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},n._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},n._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},n._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},n._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},n._getConfig=function(t){var n=e(this.element).data();return Object.keys(n).forEach((function(t){-1!==zt.indexOf(t)&&delete n[t]})),"number"==typeof(t=o({},this.constructor.Default,n,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),s.typeCheckConfig(Ut,t,this.constructor.DefaultType),t.sanitize&&(t.template=Wt(t.template,t.whiteList,t.sanitizeFn)),t},n._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},n._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(Yt);null!==n&&n.length&&t.removeClass(n.join(""))},n._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},n._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.tooltip"),o="object"==typeof n&&n;if((i||!/dispose|hide/.test(n))&&(i||(i=new t(this,o),e(this).data("bs.tooltip",i)),"string"==typeof n)){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return Gt}},{key:"NAME",get:function(){return Ut}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return $t}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Xt}}]),t}();e.fn[Ut]=Jt._jQueryInterface,e.fn[Ut].Constructor=Jt,e.fn[Ut].noConflict=function(){return e.fn[Ut]=Vt,Jt._jQueryInterface};var Zt="popover",te=e.fn[Zt],ee=new RegExp("(^|\\s)bs-popover\\S+","g"),ne=o({},Jt.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),ie=o({},Jt.DefaultType,{content:"(string|element|function)"}),oe={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},re=function(t){var n,o;function r(){return t.apply(this,arguments)||this}o=t,(n=r).prototype=Object.create(o.prototype),n.prototype.constructor=n,n.__proto__=o;var s=r.prototype;return s.isWithContent=function(){return this.getTitle()||this._getContent()},s.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},s.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},s.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(t.find(".popover-body"),n),t.removeClass("fade show")},s._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},s._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(ee);null!==n&&n.length>0&&t.removeClass(n.join(""))},r._jQueryInterface=function(t){return this.each((function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new r(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},i(r,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return ne}},{key:"NAME",get:function(){return Zt}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return oe}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return ie}}]),r}(Jt);e.fn[Zt]=re._jQueryInterface,e.fn[Zt].Constructor=re,e.fn[Zt].noConflict=function(){return e.fn[Zt]=te,re._jQueryInterface};var se="scrollspy",ae=e.fn[se],le={offset:10,method:"auto",target:""},ce={offset:"number",method:"string",target:"(string|element)"},he=function(){function t(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return i._process(t)})),this.refresh(),this._process()}var n=t.prototype;return n.refresh=function(){var t=this,n=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?n:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var n,r=s.getSelectorFromElement(t);if(r&&(n=document.querySelector(r)),n){var a=n.getBoundingClientRect();if(a.width||a.height)return[e(n)[i]().top+o,r]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},n.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},n._getConfig=function(t){if("string"!=typeof(t=o({},le,"object"==typeof t&&t?t:{})).target&&s.isElement(t.target)){var n=e(t.target).attr("id");n||(n=s.getUID(se),e(t.target).attr("id",n)),t.target="#"+n}return s.typeCheckConfig(se,t,ce),t},n._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},n._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},n._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},n._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},n._activate=function(t){this._activeTarget=t,this._clear();var n=this._selector.split(",").map((function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'})),i=e([].slice.call(document.querySelectorAll(n.join(","))));i.hasClass("dropdown-item")?(i.closest(".dropdown").find(".dropdown-toggle").addClass("active"),i.addClass("active")):(i.addClass("active"),i.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),i.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),e(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:t})},n._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.scrollspy");if(i||(i=new t(this,"object"==typeof n&&n),e(this).data("bs.scrollspy",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return le}}]),t}();e(window).on("load.bs.scrollspy.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),n=t.length;n--;){var i=e(t[n]);he._jQueryInterface.call(i,i.data())}})),e.fn[se]=he._jQueryInterface,e.fn[se].Constructor=he,e.fn[se].noConflict=function(){return e.fn[se]=ae,he._jQueryInterface};var ue=e.fn.tab,fe=function(){function t(t){this._element=t}var n=t.prototype;return n.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&e(this._element).hasClass("active")||e(this._element).hasClass("disabled"))){var n,i,o=e(this._element).closest(".nav, .list-group")[0],r=s.getSelectorFromElement(this._element);if(o){var a="UL"===o.nodeName||"OL"===o.nodeName?"> li > .active":".active";i=(i=e.makeArray(e(o).find(a)))[i.length-1]}var l=e.Event("hide.bs.tab",{relatedTarget:this._element}),c=e.Event("show.bs.tab",{relatedTarget:i});if(i&&e(i).trigger(l),e(this._element).trigger(c),!c.isDefaultPrevented()&&!l.isDefaultPrevented()){r&&(n=document.querySelector(r)),this._activate(this._element,o);var h=function(){var n=e.Event("hidden.bs.tab",{relatedTarget:t._element}),o=e.Event("shown.bs.tab",{relatedTarget:i});e(i).trigger(n),e(t._element).trigger(o)};n?this._activate(n,n.parentNode,h):h()}}},n.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},n._activate=function(t,n,i){var o=this,r=(!n||"UL"!==n.nodeName&&"OL"!==n.nodeName?e(n).children(".active"):e(n).find("> li > .active"))[0],a=i&&r&&e(r).hasClass("fade"),l=function(){return o._transitionComplete(t,r,i)};if(r&&a){var c=s.getTransitionDurationFromElement(r);e(r).removeClass("show").one(s.TRANSITION_END,l).emulateTransitionEnd(c)}else l()},n._transitionComplete=function(t,n,i){if(n){e(n).removeClass("active");var o=e(n.parentNode).find("> .dropdown-menu .active")[0];o&&e(o).removeClass("active"),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),s.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&e(t.parentNode).hasClass("dropdown-menu")){var r=e(t).closest(".dropdown")[0];if(r){var a=[].slice.call(r.querySelectorAll(".dropdown-toggle"));e(a).addClass("active")}t.setAttribute("aria-expanded",!0)}i&&i()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.tab");if(o||(o=new t(this),i.data("bs.tab",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}}]),t}();e(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),fe._jQueryInterface.call(e(this),"show")})),e.fn.tab=fe._jQueryInterface,e.fn.tab.Constructor=fe,e.fn.tab.noConflict=function(){return e.fn.tab=ue,fe._jQueryInterface};var de=e.fn.toast,pe={animation:"boolean",autohide:"boolean",delay:"number"},me={animation:!0,autohide:!0,delay:500},ge=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var n=t.prototype;return n.show=function(){var t=this,n=e.Event("show.bs.toast");if(e(this._element).trigger(n),!n.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var i=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),e(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),s.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=s.getTransitionDurationFromElement(this._element);e(this._element).one(s.TRANSITION_END,i).emulateTransitionEnd(o)}else i()}},n.hide=function(){if(this._element.classList.contains("show")){var t=e.Event("hide.bs.toast");e(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},n.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),e(this._element).off("click.dismiss.bs.toast"),e.removeData(this._element,"bs.toast"),this._element=null,this._config=null},n._getConfig=function(t){return t=o({},me,e(this._element).data(),"object"==typeof t&&t?t:{}),s.typeCheckConfig("toast",t,this.constructor.DefaultType),t},n._setListeners=function(){var t=this;e(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},n._close=function(){var t=this,n=function(){t._element.classList.add("hide"),e(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var i=s.getTransitionDurationFromElement(this._element);e(this._element).one(s.TRANSITION_END,n).emulateTransitionEnd(i)}else n()},n._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.toast");if(o||(o=new t(this,"object"==typeof n&&n),i.data("bs.toast",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](this)}}))},i(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"DefaultType",get:function(){return pe}},{key:"Default",get:function(){return me}}]),t}();e.fn.toast=ge._jQueryInterface,e.fn.toast.Constructor=ge,e.fn.toast.noConflict=function(){return e.fn.toast=de,ge._jQueryInterface},t.Alert=c,t.Button=u,t.Carousel=v,t.Collapse=T,t.Dropdown=Lt,t.Modal=Ht,t.Popover=re,t.Scrollspy=he,t.Tab=fe,t.Toast=ge,t.Tooltip=Jt,t.Util=s,Object.defineProperty(t,"__esModule",{value:!0})}));
7
  //# sourceMappingURL=bootstrap.bundle.min.js.map
resources/js/bootstrap4.js CHANGED
@@ -1,12 +1,12 @@
1
  /*!
2
- * Bootstrap v4.5.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
  */
6
  (function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery'), require('popper.js')) :
8
  typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) :
9
- (global = global || self, factory(global.bootstrap = {}, global.jQuery, global.Popper));
10
  }(this, (function (exports, $, Popper) { 'use strict';
11
 
12
  $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
@@ -28,53 +28,22 @@
28
  return Constructor;
29
  }
30
 
31
- function _defineProperty(obj, key, value) {
32
- if (key in obj) {
33
- Object.defineProperty(obj, key, {
34
- value: value,
35
- enumerable: true,
36
- configurable: true,
37
- writable: true
38
- });
39
- } else {
40
- obj[key] = value;
41
- }
42
-
43
- return obj;
44
- }
45
-
46
- function ownKeys(object, enumerableOnly) {
47
- var keys = Object.keys(object);
48
-
49
- if (Object.getOwnPropertySymbols) {
50
- var symbols = Object.getOwnPropertySymbols(object);
51
- if (enumerableOnly) symbols = symbols.filter(function (sym) {
52
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
53
- });
54
- keys.push.apply(keys, symbols);
55
- }
56
 
57
- return keys;
58
- }
59
-
60
- function _objectSpread2(target) {
61
- for (var i = 1; i < arguments.length; i++) {
62
- var source = arguments[i] != null ? arguments[i] : {};
63
-
64
- if (i % 2) {
65
- ownKeys(Object(source), true).forEach(function (key) {
66
- _defineProperty(target, key, source[key]);
67
- });
68
- } else if (Object.getOwnPropertyDescriptors) {
69
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
70
- } else {
71
- ownKeys(Object(source)).forEach(function (key) {
72
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
73
- });
74
  }
75
- }
76
 
77
- return target;
 
 
 
78
  }
79
 
80
  function _inheritsLoose(subClass, superClass) {
@@ -85,8 +54,8 @@
85
 
86
  /**
87
  * --------------------------------------------------------------------------
88
- * Bootstrap (v4.5.0): util.js
89
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
90
  * --------------------------------------------------------------------------
91
  */
92
  /**
@@ -266,7 +235,7 @@
266
  */
267
 
268
  var NAME = 'alert';
269
- var VERSION = '4.5.0';
270
  var DATA_KEY = 'bs.alert';
271
  var EVENT_KEY = "." + DATA_KEY;
272
  var DATA_API_KEY = '.data-api';
@@ -422,7 +391,7 @@
422
  */
423
 
424
  var NAME$1 = 'button';
425
- var VERSION$1 = '4.5.0';
426
  var DATA_KEY$1 = 'bs.button';
427
  var EVENT_KEY$1 = "." + DATA_KEY$1;
428
  var DATA_API_KEY$1 = '.data-api';
@@ -557,11 +526,9 @@
557
  return;
558
  }
559
 
560
- if (initialButton.tagName === 'LABEL' && inputBtn && inputBtn.type === 'checkbox') {
561
- event.preventDefault(); // work around event sent to label and input
562
  }
563
-
564
- Button._jQueryInterface.call($(button), 'toggle');
565
  }
566
  }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {
567
  var button = $(event.target).closest(SELECTOR_BUTTON)[0];
@@ -617,7 +584,7 @@
617
  */
618
 
619
  var NAME$2 = 'carousel';
620
- var VERSION$2 = '4.5.0';
621
  var DATA_KEY$2 = 'bs.carousel';
622
  var EVENT_KEY$2 = "." + DATA_KEY$2;
623
  var DATA_API_KEY$2 = '.data-api';
@@ -804,7 +771,7 @@
804
  ;
805
 
806
  _proto._getConfig = function _getConfig(config) {
807
- config = _objectSpread2(_objectSpread2({}, Default), config);
808
  Util.typeCheckConfig(NAME$2, config, DefaultType);
809
  return config;
810
  };
@@ -1094,10 +1061,10 @@
1094
  return this.each(function () {
1095
  var data = $(this).data(DATA_KEY$2);
1096
 
1097
- var _config = _objectSpread2(_objectSpread2({}, Default), $(this).data());
1098
 
1099
  if (typeof config === 'object') {
1100
- _config = _objectSpread2(_objectSpread2({}, _config), config);
1101
  }
1102
 
1103
  var action = typeof config === 'string' ? config : _config.slide;
@@ -1135,7 +1102,7 @@
1135
  return;
1136
  }
1137
 
1138
- var config = _objectSpread2(_objectSpread2({}, $(target).data()), $(this).data());
1139
 
1140
  var slideIndex = this.getAttribute('data-slide-to');
1141
 
@@ -1204,7 +1171,7 @@
1204
  */
1205
 
1206
  var NAME$3 = 'collapse';
1207
- var VERSION$3 = '4.5.0';
1208
  var DATA_KEY$3 = 'bs.collapse';
1209
  var EVENT_KEY$3 = "." + DATA_KEY$3;
1210
  var DATA_API_KEY$3 = '.data-api';
@@ -1419,7 +1386,7 @@
1419
  ;
1420
 
1421
  _proto._getConfig = function _getConfig(config) {
1422
- config = _objectSpread2(_objectSpread2({}, Default$1), config);
1423
  config.toggle = Boolean(config.toggle); // Coerce string values
1424
 
1425
  Util.typeCheckConfig(NAME$3, config, DefaultType$1);
@@ -1473,7 +1440,7 @@
1473
  var $this = $(this);
1474
  var data = $this.data(DATA_KEY$3);
1475
 
1476
- var _config = _objectSpread2(_objectSpread2(_objectSpread2({}, Default$1), $this.data()), typeof config === 'object' && config ? config : {});
1477
 
1478
  if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
1479
  _config.toggle = false;
@@ -1553,7 +1520,7 @@
1553
  */
1554
 
1555
  var NAME$4 = 'dropdown';
1556
- var VERSION$4 = '4.5.0';
1557
  var DATA_KEY$4 = 'bs.dropdown';
1558
  var EVENT_KEY$4 = "." + DATA_KEY$4;
1559
  var DATA_API_KEY$4 = '.data-api';
@@ -1780,7 +1747,7 @@
1780
  };
1781
 
1782
  _proto._getConfig = function _getConfig(config) {
1783
- config = _objectSpread2(_objectSpread2(_objectSpread2({}, this.constructor.Default), $(this._element).data()), config);
1784
  Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);
1785
  return config;
1786
  };
@@ -1825,7 +1792,7 @@
1825
 
1826
  if (typeof this._config.offset === 'function') {
1827
  offset.fn = function (data) {
1828
- data.offsets = _objectSpread2(_objectSpread2({}, data.offsets), _this2._config.offset(data.offsets, _this2._element) || {});
1829
  return data;
1830
  };
1831
  } else {
@@ -1855,7 +1822,7 @@
1855
  };
1856
  }
1857
 
1858
- return _objectSpread2(_objectSpread2({}, popperConfig), this._config.popperConfig);
1859
  } // Static
1860
  ;
1861
 
@@ -2067,7 +2034,7 @@
2067
  */
2068
 
2069
  var NAME$5 = 'modal';
2070
- var VERSION$5 = '4.5.0';
2071
  var DATA_KEY$5 = 'bs.modal';
2072
  var EVENT_KEY$5 = "." + DATA_KEY$5;
2073
  var DATA_API_KEY$5 = '.data-api';
@@ -2259,7 +2226,7 @@
2259
  ;
2260
 
2261
  _proto._getConfig = function _getConfig(config) {
2262
- config = _objectSpread2(_objectSpread2({}, Default$3), config);
2263
  Util.typeCheckConfig(NAME$5, config, DefaultType$3);
2264
  return config;
2265
  };
@@ -2275,11 +2242,24 @@
2275
  return;
2276
  }
2277
 
 
 
 
 
 
 
2278
  this._element.classList.add(CLASS_NAME_STATIC);
2279
 
2280
- var modalTransitionDuration = Util.getTransitionDurationFromElement(this._element);
 
2281
  $(this._element).one(Util.TRANSITION_END, function () {
2282
  _this3._element.classList.remove(CLASS_NAME_STATIC);
 
 
 
 
 
 
2283
  }).emulateTransitionEnd(modalTransitionDuration);
2284
 
2285
  this._element.focus();
@@ -2305,6 +2285,8 @@
2305
 
2306
  this._element.setAttribute('aria-modal', true);
2307
 
 
 
2308
  if ($(this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {
2309
  modalBody.scrollTop = 0;
2310
  } else {
@@ -2392,6 +2374,8 @@
2392
 
2393
  this._element.removeAttribute('aria-modal');
2394
 
 
 
2395
  this._isTransitioning = false;
2396
 
2397
  this._showBackdrop(function () {
@@ -2573,7 +2557,7 @@
2573
  return this.each(function () {
2574
  var data = $(this).data(DATA_KEY$5);
2575
 
2576
- var _config = _objectSpread2(_objectSpread2(_objectSpread2({}, Default$3), $(this).data()), typeof config === 'object' && config ? config : {});
2577
 
2578
  if (!data) {
2579
  data = new Modal(this, _config);
@@ -2623,7 +2607,7 @@
2623
  target = document.querySelector(selector);
2624
  }
2625
 
2626
- var config = $(target).data(DATA_KEY$5) ? 'toggle' : _objectSpread2(_objectSpread2({}, $(target).data()), $(this).data());
2627
 
2628
  if (this.tagName === 'A' || this.tagName === 'AREA') {
2629
  event.preventDefault();
@@ -2660,8 +2644,8 @@
2660
 
2661
  /**
2662
  * --------------------------------------------------------------------------
2663
- * Bootstrap (v4.5.0): tools/sanitizer.js
2664
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2665
  * --------------------------------------------------------------------------
2666
  */
2667
  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];
@@ -2786,7 +2770,7 @@
2786
  */
2787
 
2788
  var NAME$6 = 'tooltip';
2789
- var VERSION$6 = '4.5.0';
2790
  var DATA_KEY$6 = 'bs.tooltip';
2791
  var EVENT_KEY$6 = "." + DATA_KEY$6;
2792
  var JQUERY_NO_CONFLICT$6 = $.fn[NAME$6];
@@ -3174,7 +3158,7 @@
3174
  return _this3._handlePopperPlacementChange(data);
3175
  }
3176
  };
3177
- return _objectSpread2(_objectSpread2({}, defaultBsConfig), this.config.popperConfig);
3178
  };
3179
 
3180
  _proto._getOffset = function _getOffset() {
@@ -3184,7 +3168,7 @@
3184
 
3185
  if (typeof this.config.offset === 'function') {
3186
  offset.fn = function (data) {
3187
- data.offsets = _objectSpread2(_objectSpread2({}, data.offsets), _this4.config.offset(data.offsets, _this4.element) || {});
3188
  return data;
3189
  };
3190
  } else {
@@ -3239,7 +3223,7 @@
3239
  $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);
3240
 
3241
  if (this.config.selector) {
3242
- this.config = _objectSpread2(_objectSpread2({}, this.config), {}, {
3243
  trigger: 'manual',
3244
  selector: ''
3245
  });
@@ -3339,7 +3323,7 @@
3339
  delete dataAttributes[dataAttr];
3340
  }
3341
  });
3342
- config = _objectSpread2(_objectSpread2(_objectSpread2({}, this.constructor.Default), dataAttributes), typeof config === 'object' && config ? config : {});
3343
 
3344
  if (typeof config.delay === 'number') {
3345
  config.delay = {
@@ -3498,21 +3482,21 @@
3498
  */
3499
 
3500
  var NAME$7 = 'popover';
3501
- var VERSION$7 = '4.5.0';
3502
  var DATA_KEY$7 = 'bs.popover';
3503
  var EVENT_KEY$7 = "." + DATA_KEY$7;
3504
  var JQUERY_NO_CONFLICT$7 = $.fn[NAME$7];
3505
  var CLASS_PREFIX$1 = 'bs-popover';
3506
  var BSCLS_PREFIX_REGEX$1 = new RegExp("(^|\\s)" + CLASS_PREFIX$1 + "\\S+", 'g');
3507
 
3508
- var Default$5 = _objectSpread2(_objectSpread2({}, Tooltip.Default), {}, {
3509
  placement: 'right',
3510
  trigger: 'click',
3511
  content: '',
3512
  template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
3513
  });
3514
 
3515
- var DefaultType$5 = _objectSpread2(_objectSpread2({}, Tooltip.DefaultType), {}, {
3516
  content: '(string|element|function)'
3517
  });
3518
 
@@ -3678,7 +3662,7 @@
3678
  */
3679
 
3680
  var NAME$8 = 'scrollspy';
3681
- var VERSION$8 = '4.5.0';
3682
  var DATA_KEY$8 = 'bs.scrollspy';
3683
  var EVENT_KEY$8 = "." + DATA_KEY$8;
3684
  var DATA_API_KEY$6 = '.data-api';
@@ -3792,7 +3776,7 @@
3792
  ;
3793
 
3794
  _proto._getConfig = function _getConfig(config) {
3795
- config = _objectSpread2(_objectSpread2({}, Default$6), typeof config === 'object' && config ? config : {});
3796
 
3797
  if (typeof config.target !== 'string' && Util.isElement(config.target)) {
3798
  var id = $(config.target).attr('id');
@@ -3970,7 +3954,7 @@
3970
  */
3971
 
3972
  var NAME$9 = 'tab';
3973
- var VERSION$9 = '4.5.0';
3974
  var DATA_KEY$9 = 'bs.tab';
3975
  var EVENT_KEY$9 = "." + DATA_KEY$9;
3976
  var DATA_API_KEY$7 = '.data-api';
@@ -4196,7 +4180,7 @@
4196
  */
4197
 
4198
  var NAME$a = 'toast';
4199
- var VERSION$a = '4.5.0';
4200
  var DATA_KEY$a = 'bs.toast';
4201
  var EVENT_KEY$a = "." + DATA_KEY$a;
4202
  var JQUERY_NO_CONFLICT$a = $.fn[NAME$a];
@@ -4249,6 +4233,8 @@
4249
  return;
4250
  }
4251
 
 
 
4252
  if (this._config.animation) {
4253
  this._element.classList.add(CLASS_NAME_FADE$5);
4254
  }
@@ -4297,8 +4283,7 @@
4297
  };
4298
 
4299
  _proto.dispose = function dispose() {
4300
- clearTimeout(this._timeout);
4301
- this._timeout = null;
4302
 
4303
  if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {
4304
  this._element.classList.remove(CLASS_NAME_SHOW$7);
@@ -4312,7 +4297,7 @@
4312
  ;
4313
 
4314
  _proto._getConfig = function _getConfig(config) {
4315
- config = _objectSpread2(_objectSpread2(_objectSpread2({}, Default$7), $(this._element).data()), typeof config === 'object' && config ? config : {});
4316
  Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);
4317
  return config;
4318
  };
@@ -4342,6 +4327,11 @@
4342
  } else {
4343
  complete();
4344
  }
 
 
 
 
 
4345
  } // Static
4346
  ;
4347
 
1
  /*!
2
+ * Bootstrap v4.5.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
  (function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery'), require('popper.js')) :
8
  typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bootstrap = {}, global.jQuery, global.Popper));
10
  }(this, (function (exports, $, Popper) { 'use strict';
11
 
12
  $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
28
  return Constructor;
29
  }
30
 
31
+ function _extends() {
32
+ _extends = Object.assign || function (target) {
33
+ for (var i = 1; i < arguments.length; i++) {
34
+ var source = arguments[i];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ for (var key in source) {
37
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
38
+ target[key] = source[key];
39
+ }
40
+ }
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
 
42
 
43
+ return target;
44
+ };
45
+
46
+ return _extends.apply(this, arguments);
47
  }
48
 
49
  function _inheritsLoose(subClass, superClass) {
54
 
55
  /**
56
  * --------------------------------------------------------------------------
57
+ * Bootstrap (v4.5.2): util.js
58
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
59
  * --------------------------------------------------------------------------
60
  */
61
  /**
235
  */
236
 
237
  var NAME = 'alert';
238
+ var VERSION = '4.5.2';
239
  var DATA_KEY = 'bs.alert';
240
  var EVENT_KEY = "." + DATA_KEY;
241
  var DATA_API_KEY = '.data-api';
391
  */
392
 
393
  var NAME$1 = 'button';
394
+ var VERSION$1 = '4.5.2';
395
  var DATA_KEY$1 = 'bs.button';
396
  var EVENT_KEY$1 = "." + DATA_KEY$1;
397
  var DATA_API_KEY$1 = '.data-api';
526
  return;
527
  }
528
 
529
+ if (initialButton.tagName !== 'LABEL' || inputBtn && inputBtn.type !== 'checkbox') {
530
+ Button._jQueryInterface.call($(button), 'toggle');
531
  }
 
 
532
  }
533
  }).on(EVENT_FOCUS_BLUR_DATA_API, SELECTOR_DATA_TOGGLE_CARROT, function (event) {
534
  var button = $(event.target).closest(SELECTOR_BUTTON)[0];
584
  */
585
 
586
  var NAME$2 = 'carousel';
587
+ var VERSION$2 = '4.5.2';
588
  var DATA_KEY$2 = 'bs.carousel';
589
  var EVENT_KEY$2 = "." + DATA_KEY$2;
590
  var DATA_API_KEY$2 = '.data-api';
771
  ;
772
 
773
  _proto._getConfig = function _getConfig(config) {
774
+ config = _extends({}, Default, config);
775
  Util.typeCheckConfig(NAME$2, config, DefaultType);
776
  return config;
777
  };
1061
  return this.each(function () {
1062
  var data = $(this).data(DATA_KEY$2);
1063
 
1064
+ var _config = _extends({}, Default, $(this).data());
1065
 
1066
  if (typeof config === 'object') {
1067
+ _config = _extends({}, _config, config);
1068
  }
1069
 
1070
  var action = typeof config === 'string' ? config : _config.slide;
1102
  return;
1103
  }
1104
 
1105
+ var config = _extends({}, $(target).data(), $(this).data());
1106
 
1107
  var slideIndex = this.getAttribute('data-slide-to');
1108
 
1171
  */
1172
 
1173
  var NAME$3 = 'collapse';
1174
+ var VERSION$3 = '4.5.2';
1175
  var DATA_KEY$3 = 'bs.collapse';
1176
  var EVENT_KEY$3 = "." + DATA_KEY$3;
1177
  var DATA_API_KEY$3 = '.data-api';
1386
  ;
1387
 
1388
  _proto._getConfig = function _getConfig(config) {
1389
+ config = _extends({}, Default$1, config);
1390
  config.toggle = Boolean(config.toggle); // Coerce string values
1391
 
1392
  Util.typeCheckConfig(NAME$3, config, DefaultType$1);
1440
  var $this = $(this);
1441
  var data = $this.data(DATA_KEY$3);
1442
 
1443
+ var _config = _extends({}, Default$1, $this.data(), typeof config === 'object' && config ? config : {});
1444
 
1445
  if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) {
1446
  _config.toggle = false;
1520
  */
1521
 
1522
  var NAME$4 = 'dropdown';
1523
+ var VERSION$4 = '4.5.2';
1524
  var DATA_KEY$4 = 'bs.dropdown';
1525
  var EVENT_KEY$4 = "." + DATA_KEY$4;
1526
  var DATA_API_KEY$4 = '.data-api';
1747
  };
1748
 
1749
  _proto._getConfig = function _getConfig(config) {
1750
+ config = _extends({}, this.constructor.Default, $(this._element).data(), config);
1751
  Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType);
1752
  return config;
1753
  };
1792
 
1793
  if (typeof this._config.offset === 'function') {
1794
  offset.fn = function (data) {
1795
+ data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets, _this2._element) || {});
1796
  return data;
1797
  };
1798
  } else {
1822
  };
1823
  }
1824
 
1825
+ return _extends({}, popperConfig, this._config.popperConfig);
1826
  } // Static
1827
  ;
1828
 
2034
  */
2035
 
2036
  var NAME$5 = 'modal';
2037
+ var VERSION$5 = '4.5.2';
2038
  var DATA_KEY$5 = 'bs.modal';
2039
  var EVENT_KEY$5 = "." + DATA_KEY$5;
2040
  var DATA_API_KEY$5 = '.data-api';
2226
  ;
2227
 
2228
  _proto._getConfig = function _getConfig(config) {
2229
+ config = _extends({}, Default$3, config);
2230
  Util.typeCheckConfig(NAME$5, config, DefaultType$3);
2231
  return config;
2232
  };
2242
  return;
2243
  }
2244
 
2245
+ var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
2246
+
2247
+ if (!isModalOverflowing) {
2248
+ this._element.style.overflowY = 'hidden';
2249
+ }
2250
+
2251
  this._element.classList.add(CLASS_NAME_STATIC);
2252
 
2253
+ var modalTransitionDuration = Util.getTransitionDurationFromElement(this._dialog);
2254
+ $(this._element).off(Util.TRANSITION_END);
2255
  $(this._element).one(Util.TRANSITION_END, function () {
2256
  _this3._element.classList.remove(CLASS_NAME_STATIC);
2257
+
2258
+ if (!isModalOverflowing) {
2259
+ $(_this3._element).one(Util.TRANSITION_END, function () {
2260
+ _this3._element.style.overflowY = '';
2261
+ }).emulateTransitionEnd(_this3._element, modalTransitionDuration);
2262
+ }
2263
  }).emulateTransitionEnd(modalTransitionDuration);
2264
 
2265
  this._element.focus();
2285
 
2286
  this._element.setAttribute('aria-modal', true);
2287
 
2288
+ this._element.setAttribute('role', 'dialog');
2289
+
2290
  if ($(this._dialog).hasClass(CLASS_NAME_SCROLLABLE) && modalBody) {
2291
  modalBody.scrollTop = 0;
2292
  } else {
2374
 
2375
  this._element.removeAttribute('aria-modal');
2376
 
2377
+ this._element.removeAttribute('role');
2378
+
2379
  this._isTransitioning = false;
2380
 
2381
  this._showBackdrop(function () {
2557
  return this.each(function () {
2558
  var data = $(this).data(DATA_KEY$5);
2559
 
2560
+ var _config = _extends({}, Default$3, $(this).data(), typeof config === 'object' && config ? config : {});
2561
 
2562
  if (!data) {
2563
  data = new Modal(this, _config);
2607
  target = document.querySelector(selector);
2608
  }
2609
 
2610
+ var config = $(target).data(DATA_KEY$5) ? 'toggle' : _extends({}, $(target).data(), $(this).data());
2611
 
2612
  if (this.tagName === 'A' || this.tagName === 'AREA') {
2613
  event.preventDefault();
2644
 
2645
  /**
2646
  * --------------------------------------------------------------------------
2647
+ * Bootstrap (v4.5.2): tools/sanitizer.js
2648
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
2649
  * --------------------------------------------------------------------------
2650
  */
2651
  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];
2770
  */
2771
 
2772
  var NAME$6 = 'tooltip';
2773
+ var VERSION$6 = '4.5.2';
2774
  var DATA_KEY$6 = 'bs.tooltip';
2775
  var EVENT_KEY$6 = "." + DATA_KEY$6;
2776
  var JQUERY_NO_CONFLICT$6 = $.fn[NAME$6];
3158
  return _this3._handlePopperPlacementChange(data);
3159
  }
3160
  };
3161
+ return _extends({}, defaultBsConfig, this.config.popperConfig);
3162
  };
3163
 
3164
  _proto._getOffset = function _getOffset() {
3168
 
3169
  if (typeof this.config.offset === 'function') {
3170
  offset.fn = function (data) {
3171
+ data.offsets = _extends({}, data.offsets, _this4.config.offset(data.offsets, _this4.element) || {});
3172
  return data;
3173
  };
3174
  } else {
3223
  $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);
3224
 
3225
  if (this.config.selector) {
3226
+ this.config = _extends({}, this.config, {
3227
  trigger: 'manual',
3228
  selector: ''
3229
  });
3323
  delete dataAttributes[dataAttr];
3324
  }
3325
  });
3326
+ config = _extends({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});
3327
 
3328
  if (typeof config.delay === 'number') {
3329
  config.delay = {
3482
  */
3483
 
3484
  var NAME$7 = 'popover';
3485
+ var VERSION$7 = '4.5.2';
3486
  var DATA_KEY$7 = 'bs.popover';
3487
  var EVENT_KEY$7 = "." + DATA_KEY$7;
3488
  var JQUERY_NO_CONFLICT$7 = $.fn[NAME$7];
3489
  var CLASS_PREFIX$1 = 'bs-popover';
3490
  var BSCLS_PREFIX_REGEX$1 = new RegExp("(^|\\s)" + CLASS_PREFIX$1 + "\\S+", 'g');
3491
 
3492
+ var Default$5 = _extends({}, Tooltip.Default, {
3493
  placement: 'right',
3494
  trigger: 'click',
3495
  content: '',
3496
  template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
3497
  });
3498
 
3499
+ var DefaultType$5 = _extends({}, Tooltip.DefaultType, {
3500
  content: '(string|element|function)'
3501
  });
3502
 
3662
  */
3663
 
3664
  var NAME$8 = 'scrollspy';
3665
+ var VERSION$8 = '4.5.2';
3666
  var DATA_KEY$8 = 'bs.scrollspy';
3667
  var EVENT_KEY$8 = "." + DATA_KEY$8;
3668
  var DATA_API_KEY$6 = '.data-api';
3776
  ;
3777
 
3778
  _proto._getConfig = function _getConfig(config) {
3779
+ config = _extends({}, Default$6, typeof config === 'object' && config ? config : {});
3780
 
3781
  if (typeof config.target !== 'string' && Util.isElement(config.target)) {
3782
  var id = $(config.target).attr('id');
3954
  */
3955
 
3956
  var NAME$9 = 'tab';
3957
+ var VERSION$9 = '4.5.2';
3958
  var DATA_KEY$9 = 'bs.tab';
3959
  var EVENT_KEY$9 = "." + DATA_KEY$9;
3960
  var DATA_API_KEY$7 = '.data-api';
4180
  */
4181
 
4182
  var NAME$a = 'toast';
4183
+ var VERSION$a = '4.5.2';
4184
  var DATA_KEY$a = 'bs.toast';
4185
  var EVENT_KEY$a = "." + DATA_KEY$a;
4186
  var JQUERY_NO_CONFLICT$a = $.fn[NAME$a];
4233
  return;
4234
  }
4235
 
4236
+ this._clearTimeout();
4237
+
4238
  if (this._config.animation) {
4239
  this._element.classList.add(CLASS_NAME_FADE$5);
4240
  }
4283
  };
4284
 
4285
  _proto.dispose = function dispose() {
4286
+ this._clearTimeout();
 
4287
 
4288
  if (this._element.classList.contains(CLASS_NAME_SHOW$7)) {
4289
  this._element.classList.remove(CLASS_NAME_SHOW$7);
4297
  ;
4298
 
4299
  _proto._getConfig = function _getConfig(config) {
4300
+ config = _extends({}, Default$7, $(this._element).data(), typeof config === 'object' && config ? config : {});
4301
  Util.typeCheckConfig(NAME$a, config, this.constructor.DefaultType);
4302
  return config;
4303
  };
4327
  } else {
4328
  complete();
4329
  }
4330
+ };
4331
+
4332
+ _proto._clearTimeout = function _clearTimeout() {
4333
+ clearTimeout(this._timeout);
4334
+ this._timeout = null;
4335
  } // Static
4336
  ;
4337
 
resources/js/bootstrap4.min.js CHANGED
@@ -1,7 +1,7 @@
1
  /*!
2
- * Bootstrap v4.5.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
  */
6
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function o(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function s(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function r(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function a(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?r(Object(n),!0).forEach((function(e){s(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;function l(t){var n=this,i=!1;return e(this).one(c.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||c.triggerTransitionEnd(n)}),t),this}var c={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),i=e(t).css("transition-delay"),o=parseFloat(n),s=parseFloat(i);return o||s?(n=n.split(",")[0],i=i.split(",")[0],1e3*(parseFloat(n)+parseFloat(i))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],s=e[i],r=s&&c.isElement(s)?"element":null===(a=s)||"undefined"==typeof a?""+a:{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(r))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+r+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if("undefined"==typeof e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};c.jQueryDetection(),e.fn.emulateTransitionEnd=l,e.event.special[c.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var h="alert",u=e.fn[h],d=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=c.getSelectorFromElement(t),i=!1;return n&&(i=document.querySelector(n)),i||(i=e(t).closest(".alert")[0]),i},n._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},n._removeElement=function(t){var n=this;if(e(t).removeClass("show"),e(t).hasClass("fade")){var i=c.getTransitionDurationFromElement(t);e(t).one(c.TRANSITION_END,(function(e){return n._destroyElement(t,e)})).emulateTransitionEnd(i)}else this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.alert");o||(o=new t(this),i.data("bs.alert",o)),"close"===n&&o[n](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',d._handleDismiss(new d)),e.fn[h]=d._jQueryInterface,e.fn[h].Constructor=d,e.fn[h].noConflict=function(){return e.fn[h]=u,d._jQueryInterface};var f=e.fn.button,g=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,i=e(this._element).closest('[data-toggle="buttons"]')[0];if(i){var o=this._element.querySelector('input:not([type="hidden"])');if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains("active"))t=!1;else{var s=i.querySelector(".active");s&&e(s).removeClass("active")}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains("active")),e(o).trigger("change")),o.focus(),n=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(n&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&e(this._element).toggleClass("active"))},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=t.target,i=n;if(e(n).hasClass("btn")||(n=e(n).closest(".btn")[0]),!n||n.hasAttribute("disabled")||n.classList.contains("disabled"))t.preventDefault();else{var o=n.querySelector('input:not([type="hidden"])');if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();"LABEL"===i.tagName&&o&&"checkbox"===o.type&&t.preventDefault(),g._jQueryInterface.call(e(n),"toggle")}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=e(t.target).closest(".btn")[0];e(n).toggleClass("focus",/^focus(in)?$/.test(t.type))})),e(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e<n;e++){var i=t[e],o=i.querySelector('input:not([type="hidden"])');o.checked||o.hasAttribute("checked")?i.classList.add("active"):i.classList.remove("active")}for(var s=0,r=(t=[].slice.call(document.querySelectorAll('[data-toggle="button"]'))).length;s<r;s++){var a=t[s];"true"===a.getAttribute("aria-pressed")?a.classList.add("active"):a.classList.remove("active")}})),e.fn.button=g._jQueryInterface,e.fn.button.Constructor=g,e.fn.button.noConflict=function(){return e.fn.button=f,g._jQueryInterface};var m="carousel",p=".bs.carousel",_=e.fn[m],v={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},b={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},y={TOUCH:"touch",PEN:"pen"},E=function(){function t(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(".carousel-indicators"),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var n=t.prototype;return n.next=function(){this._isSliding||this._slide("next")},n.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},n.prev=function(){this._isSliding||this._slide("prev")},n.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(c.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},n.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},n.to=function(t){var n=this;this._activeElement=this._element.querySelector(".active.carousel-item");var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one("slid.bs.carousel",(function(){return n.to(t)}));else{if(i===t)return this.pause(),void this.cycle();var o=t>i?"next":"prev";this._slide(o,this._items[t])}},n.dispose=function(){e(this._element).off(p),e.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},n._getConfig=function(t){return t=a(a({},v),t),c.typeCheckConfig(m,t,b),t},n._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},n._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&e(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},n._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var n=function(e){t._pointerEvent&&y[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},i=function(e){t._pointerEvent&&y[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};e(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(e(this._element).on("pointerdown.bs.carousel",(function(t){return n(t)})),e(this._element).on("pointerup.bs.carousel",(function(t){return i(t)})),this._element.classList.add("pointer-event")):(e(this._element).on("touchstart.bs.carousel",(function(t){return n(t)})),e(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),e(this._element).on("touchend.bs.carousel",(function(t){return i(t)})))}},n._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},n._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},n._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),s=this._items.length-1;if((i&&0===o||n&&o===s)&&!this._config.wrap)return e;var r=(o+("prev"===t?-1:1))%this._items.length;return-1===r?this._items[this._items.length-1]:this._items[r]},n._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(".active.carousel-item")),s=e.Event("slide.bs.carousel",{relatedTarget:t,direction:n,from:o,to:i});return e(this._element).trigger(s),s},n._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var n=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));e(n).removeClass("active");var i=this._indicatorsElement.children[this._getItemIndex(t)];i&&e(i).addClass("active")}},n._slide=function(t,n){var i,o,s,r=this,a=this._element.querySelector(".active.carousel-item"),l=this._getItemIndex(a),h=n||a&&this._getItemByDirection(t,a),u=this._getItemIndex(h),d=Boolean(this._interval);if("next"===t?(i="carousel-item-left",o="carousel-item-next",s="left"):(i="carousel-item-right",o="carousel-item-prev",s="right"),h&&e(h).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(h,s).isDefaultPrevented()&&a&&h){this._isSliding=!0,d&&this.pause(),this._setActiveIndicatorElement(h);var f=e.Event("slid.bs.carousel",{relatedTarget:h,direction:s,from:l,to:u});if(e(this._element).hasClass("slide")){e(h).addClass(o),c.reflow(h),e(a).addClass(i),e(h).addClass(i);var g=parseInt(h.getAttribute("data-interval"),10);g?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=g):this._config.interval=this._config.defaultInterval||this._config.interval;var m=c.getTransitionDurationFromElement(a);e(a).one(c.TRANSITION_END,(function(){e(h).removeClass(i+" "+o).addClass("active"),e(a).removeClass("active "+o+" "+i),r._isSliding=!1,setTimeout((function(){return e(r._element).trigger(f)}),0)})).emulateTransitionEnd(m)}else e(a).removeClass("active"),e(h).addClass("active"),this._isSliding=!1,e(this._element).trigger(f);d&&this.cycle()}},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.carousel"),o=a(a({},v),e(this).data());"object"==typeof n&&(o=a(a({},o),n));var s="string"==typeof n?n:o.slide;if(i||(i=new t(this,o),e(this).data("bs.carousel",i)),"number"==typeof n)i.to(n);else if("string"==typeof s){if("undefined"==typeof i[s])throw new TypeError('No method named "'+s+'"');i[s]()}else o.interval&&o.ride&&(i.pause(),i.cycle())}))},t._dataApiClickHandler=function(n){var i=c.getSelectorFromElement(this);if(i){var o=e(i)[0];if(o&&e(o).hasClass("carousel")){var s=a(a({},e(o).data()),e(this).data()),r=this.getAttribute("data-slide-to");r&&(s.interval=!1),t._jQueryInterface.call(e(o),s),r&&e(o).data("bs.carousel").to(r),n.preventDefault()}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return v}}]),t}();e(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",E._dataApiClickHandler),e(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),n=0,i=t.length;n<i;n++){var o=e(t[n]);E._jQueryInterface.call(o,o.data())}})),e.fn[m]=E._jQueryInterface,e.fn[m].Constructor=E,e.fn[m].noConflict=function(){return e.fn[m]=_,E._jQueryInterface};var w="collapse",T=e.fn[w],C={toggle:!0,parent:""},S={toggle:"boolean",parent:"(string|element)"},D=function(){function t(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=n.length;i<o;i++){var s=n[i],r=c.getSelectorFromElement(s),a=[].slice.call(document.querySelectorAll(r)).filter((function(e){return e===t}));null!==r&&a.length>0&&(this._selector=r,this._triggerArray.push(s))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var n=t.prototype;return n.toggle=function(){e(this._element).hasClass("show")?this.hide():this.show()},n.show=function(){var n,i,o=this;if(!this._isTransitioning&&!e(this._element).hasClass("show")&&(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),!(n&&(i=e(n).not(this._selector).data("bs.collapse"))&&i._isTransitioning))){var s=e.Event("show.bs.collapse");if(e(this._element).trigger(s),!s.isDefaultPrevented()){n&&(t._jQueryInterface.call(e(n).not(this._selector),"hide"),i||e(n).data("bs.collapse",null));var r=this._getDimension();e(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[r]=0,this._triggerArray.length&&e(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var a="scroll"+(r[0].toUpperCase()+r.slice(1)),l=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){e(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[r]="",o.setTransitioning(!1),e(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(l),this._element.style[r]=this._element[a]+"px"}}},n.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass("show")){var n=e.Event("hide.bs.collapse");if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",c.reflow(this._element),e(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var s=0;s<o;s++){var r=this._triggerArray[s],a=c.getSelectorFromElement(r);if(null!==a)e([].slice.call(document.querySelectorAll(a))).hasClass("show")||e(r).addClass("collapsed").attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[i]="";var l=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){t.setTransitioning(!1),e(t._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(l)}}},n.setTransitioning=function(t){this._isTransitioning=t},n.dispose=function(){e.removeData(this._element,"bs.collapse"),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},n._getConfig=function(t){return(t=a(a({},C),t)).toggle=Boolean(t.toggle),c.typeCheckConfig(w,t,S),t},n._getDimension=function(){return e(this._element).hasClass("width")?"width":"height"},n._getParent=function(){var n,i=this;c.isElement(this._config.parent)?(n=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(n=this._config.parent[0])):n=document.querySelector(this._config.parent);var o='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',s=[].slice.call(n.querySelectorAll(o));return e(s).each((function(e,n){i._addAriaAndCollapsedClass(t._getTargetFromElement(n),[n])})),n},n._addAriaAndCollapsedClass=function(t,n){var i=e(t).hasClass("show");n.length&&e(n).toggleClass("collapsed",!i).attr("aria-expanded",i)},t._getTargetFromElement=function(t){var e=c.getSelectorFromElement(t);return e?document.querySelector(e):null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.collapse"),s=a(a(a({},C),i.data()),"object"==typeof n&&n?n:{});if(!o&&s.toggle&&"string"==typeof n&&/show|hide/.test(n)&&(s.toggle=!1),o||(o=new t(this,s),i.data("bs.collapse",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return C}}]),t}();e(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=e(this),i=c.getSelectorFromElement(this),o=[].slice.call(document.querySelectorAll(i));e(o).each((function(){var t=e(this),i=t.data("bs.collapse")?"toggle":n.data();D._jQueryInterface.call(t,i)}))})),e.fn[w]=D._jQueryInterface,e.fn[w].Constructor=D,e.fn[w].noConflict=function(){return e.fn[w]=T,D._jQueryInterface};var k="dropdown",N=e.fn[k],A=new RegExp("38|40|27"),I={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},O={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},j=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var i=t.prototype;return i.toggle=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")){var n=e(this._menu).hasClass("show");t._clearMenus(),n||this.show(!0)}},i.show=function(i){if(void 0===i&&(i=!1),!(this._element.disabled||e(this._element).hasClass("disabled")||e(this._menu).hasClass("show"))){var o={relatedTarget:this._element},s=e.Event("show.bs.dropdown",o),r=t._getParentFromElement(this._element);if(e(r).trigger(s),!s.isDefaultPrevented()){if(!this._inNavbar&&i){if("undefined"==typeof n)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var a=this._element;"parent"===this._config.reference?a=r:c.isElement(this._config.reference)&&(a=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(a=this._config.reference[0])),"scrollParent"!==this._config.boundary&&e(r).addClass("position-static"),this._popper=new n(a,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===e(r).closest(".navbar-nav").length&&e(document.body).children().on("mouseover",null,e.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),e(this._menu).toggleClass("show"),e(r).toggleClass("show").trigger(e.Event("shown.bs.dropdown",o))}}},i.hide=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")&&e(this._menu).hasClass("show")){var n={relatedTarget:this._element},i=e.Event("hide.bs.dropdown",n),o=t._getParentFromElement(this._element);e(o).trigger(i),i.isDefaultPrevented()||(this._popper&&this._popper.destroy(),e(this._menu).toggleClass("show"),e(o).toggleClass("show").trigger(e.Event("hidden.bs.dropdown",n)))}},i.dispose=function(){e.removeData(this._element,"bs.dropdown"),e(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},i.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},i._addEventListeners=function(){var t=this;e(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},i._getConfig=function(t){return t=a(a(a({},this.constructor.Default),e(this._element).data()),t),c.typeCheckConfig(k,t,this.constructor.DefaultType),t},i._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(".dropdown-menu"))}return this._menu},i._getPlacement=function(){var t=e(this._element.parentNode),n="bottom-start";return t.hasClass("dropup")?n=e(this._menu).hasClass("dropdown-menu-right")?"top-end":"top-start":t.hasClass("dropright")?n="right-start":t.hasClass("dropleft")?n="left-start":e(this._menu).hasClass("dropdown-menu-right")&&(n="bottom-end"),n},i._detectNavbar=function(){return e(this._element).closest(".navbar").length>0},i._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=a(a({},e.offsets),t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},i._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),a(a({},t),this._config.popperConfig)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.dropdown");if(i||(i=new t(this,"object"==typeof n?n:null),e(this).data("bs.dropdown",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},t._clearMenus=function(n){if(!n||3!==n.which&&("keyup"!==n.type||9===n.which))for(var i=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),o=0,s=i.length;o<s;o++){var r=t._getParentFromElement(i[o]),a=e(i[o]).data("bs.dropdown"),l={relatedTarget:i[o]};if(n&&"click"===n.type&&(l.clickEvent=n),a){var c=a._menu;if(e(r).hasClass("show")&&!(n&&("click"===n.type&&/input|textarea/i.test(n.target.tagName)||"keyup"===n.type&&9===n.which)&&e.contains(r,n.target))){var h=e.Event("hide.bs.dropdown",l);e(r).trigger(h),h.isDefaultPrevented()||("ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),i[o].setAttribute("aria-expanded","false"),a._popper&&a._popper.destroy(),e(c).removeClass("show"),e(r).removeClass("show").trigger(e.Event("hidden.bs.dropdown",l)))}}}},t._getParentFromElement=function(t){var e,n=c.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},t._dataApiKeydownHandler=function(n){if(!(/input|textarea/i.test(n.target.tagName)?32===n.which||27!==n.which&&(40!==n.which&&38!==n.which||e(n.target).closest(".dropdown-menu").length):!A.test(n.which))&&!this.disabled&&!e(this).hasClass("disabled")){var i=t._getParentFromElement(this),o=e(i).hasClass("show");if(o||27!==n.which){if(n.preventDefault(),n.stopPropagation(),!o||o&&(27===n.which||32===n.which))return 27===n.which&&e(i.querySelector('[data-toggle="dropdown"]')).trigger("focus"),void e(this).trigger("click");var s=[].slice.call(i.querySelectorAll(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)")).filter((function(t){return e(t).is(":visible")}));if(0!==s.length){var r=s.indexOf(n.target);38===n.which&&r>0&&r--,40===n.which&&r<s.length-1&&r++,r<0&&(r=0),s[r].focus()}}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return I}},{key:"DefaultType",get:function(){return O}}]),t}();e(document).on("keydown.bs.dropdown.data-api",'[data-toggle="dropdown"]',j._dataApiKeydownHandler).on("keydown.bs.dropdown.data-api",".dropdown-menu",j._dataApiKeydownHandler).on("click.bs.dropdown.data-api keyup.bs.dropdown.data-api",j._clearMenus).on("click.bs.dropdown.data-api",'[data-toggle="dropdown"]',(function(t){t.preventDefault(),t.stopPropagation(),j._jQueryInterface.call(e(this),"toggle")})).on("click.bs.dropdown.data-api",".dropdown form",(function(t){t.stopPropagation()})),e.fn[k]=j._jQueryInterface,e.fn[k].Constructor=j,e.fn[k].noConflict=function(){return e.fn[k]=N,j._jQueryInterface};var P=e.fn.modal,x={backdrop:!0,keyboard:!0,focus:!0,show:!0},L={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},R=function(){function t(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(".modal-dialog"),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var n=t.prototype;return n.toggle=function(t){return this._isShown?this.hide():this.show(t)},n.show=function(t){var n=this;if(!this._isShown&&!this._isTransitioning){e(this._element).hasClass("fade")&&(this._isTransitioning=!0);var i=e.Event("show.bs.modal",{relatedTarget:t});e(this._element).trigger(i),this._isShown||i.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),e(this._element).on("click.dismiss.bs.modal",'[data-dismiss="modal"]',(function(t){return n.hide(t)})),e(this._dialog).on("mousedown.dismiss.bs.modal",(function(){e(n._element).one("mouseup.dismiss.bs.modal",(function(t){e(t.target).is(n._element)&&(n._ignoreBackdropClick=!0)}))})),this._showBackdrop((function(){return n._showElement(t)})))}},n.hide=function(t){var n=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var i=e.Event("hide.bs.modal");if(e(this._element).trigger(i),this._isShown&&!i.isDefaultPrevented()){this._isShown=!1;var o=e(this._element).hasClass("fade");if(o&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),e(document).off("focusin.bs.modal"),e(this._element).removeClass("show"),e(this._element).off("click.dismiss.bs.modal"),e(this._dialog).off("mousedown.dismiss.bs.modal"),o){var s=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(t){return n._hideModal(t)})).emulateTransitionEnd(s)}else this._hideModal()}}},n.dispose=function(){[window,this._element,this._dialog].forEach((function(t){return e(t).off(".bs.modal")})),e(document).off("focusin.bs.modal"),e.removeData(this._element,"bs.modal"),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},n.handleUpdate=function(){this._adjustDialog()},n._getConfig=function(t){return t=a(a({},x),t),c.typeCheckConfig("modal",t,L),t},n._triggerBackdropTransition=function(){var t=this;if("static"===this._config.backdrop){var n=e.Event("hidePrevented.bs.modal");if(e(this._element).trigger(n),n.defaultPrevented)return;this._element.classList.add("modal-static");var i=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,(function(){t._element.classList.remove("modal-static")})).emulateTransitionEnd(i),this._element.focus()}else this.hide()},n._showElement=function(t){var n=this,i=e(this._element).hasClass("fade"),o=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),e(this._dialog).hasClass("modal-dialog-scrollable")&&o?o.scrollTop=0:this._element.scrollTop=0,i&&c.reflow(this._element),e(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var s=e.Event("shown.bs.modal",{relatedTarget:t}),r=function(){n._config.focus&&n._element.focus(),n._isTransitioning=!1,e(n._element).trigger(s)};if(i){var a=c.getTransitionDurationFromElement(this._dialog);e(this._dialog).one(c.TRANSITION_END,r).emulateTransitionEnd(a)}else r()},n._enforceFocus=function(){var t=this;e(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(n){document!==n.target&&t._element!==n.target&&0===e(t._element).has(n.target).length&&t._element.focus()}))},n._setEscapeEvent=function(){var t=this;this._isShown?e(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||e(this._element).off("keydown.dismiss.bs.modal")},n._setResizeEvent=function(){var t=this;this._isShown?e(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):e(window).off("resize.bs.modal")},n._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop((function(){e(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),e(t._element).trigger("hidden.bs.modal")}))},n._removeBackdrop=function(){this._backdrop&&(e(this._backdrop).remove(),this._backdrop=null)},n._showBackdrop=function(t){var n=this,i=e(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",i&&this._backdrop.classList.add(i),e(this._backdrop).appendTo(document.body),e(this._element).on("click.dismiss.bs.modal",(function(t){n._ignoreBackdropClick?n._ignoreBackdropClick=!1:t.target===t.currentTarget&&n._triggerBackdropTransition()})),i&&c.reflow(this._backdrop),e(this._backdrop).addClass("show"),!t)return;if(!i)return void t();var o=c.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(c.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){e(this._backdrop).removeClass("show");var s=function(){n._removeBackdrop(),t&&t()};if(e(this._element).hasClass("fade")){var r=c.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(c.TRANSITION_END,s).emulateTransitionEnd(r)}else s()}else t&&t()},n._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},n._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},n._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},n._setScrollbar=function(){var t=this;if(this._isBodyOverflowing){var n=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top")),i=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(n,i){var o=i.style.paddingRight,s=e(i).css("padding-right");e(i).data("padding-right",o).css("padding-right",parseFloat(s)+t._scrollbarWidth+"px")})),e(i).each((function(n,i){var o=i.style.marginRight,s=e(i).css("margin-right");e(i).data("margin-right",o).css("margin-right",parseFloat(s)-t._scrollbarWidth+"px")}));var o=document.body.style.paddingRight,s=e(document.body).css("padding-right");e(document.body).data("padding-right",o).css("padding-right",parseFloat(s)+this._scrollbarWidth+"px")}e(document.body).addClass("modal-open")},n._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top"));e(t).each((function(t,n){var i=e(n).data("padding-right");e(n).removeData("padding-right"),n.style.paddingRight=i||""}));var n=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(t,n){var i=e(n).data("margin-right");"undefined"!=typeof i&&e(n).css("margin-right",i).removeData("margin-right")}));var i=e(document.body).data("padding-right");e(document.body).removeData("padding-right"),document.body.style.paddingRight=i||""},n._getScrollbarWidth=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},t._jQueryInterface=function(n,i){return this.each((function(){var o=e(this).data("bs.modal"),s=a(a(a({},x),e(this).data()),"object"==typeof n&&n?n:{});if(o||(o=new t(this,s),e(this).data("bs.modal",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](i)}else s.show&&o.show(i)}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return x}}]),t}();e(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',(function(t){var n,i=this,o=c.getSelectorFromElement(this);o&&(n=document.querySelector(o));var s=e(n).data("bs.modal")?"toggle":a(a({},e(n).data()),e(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var r=e(n).one("show.bs.modal",(function(t){t.isDefaultPrevented()||r.one("hidden.bs.modal",(function(){e(i).is(":visible")&&i.focus()}))}));R._jQueryInterface.call(e(n),s,this)})),e.fn.modal=R._jQueryInterface,e.fn.modal.Constructor=R,e.fn.modal.noConflict=function(){return e.fn.modal=P,R._jQueryInterface};var q=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],F={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Q=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,B=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function H(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var i=(new window.DOMParser).parseFromString(t,"text/html"),o=Object.keys(e),s=[].slice.call(i.body.querySelectorAll("*")),r=function(t,n){var i=s[t],r=i.nodeName.toLowerCase();if(-1===o.indexOf(i.nodeName.toLowerCase()))return i.parentNode.removeChild(i),"continue";var a=[].slice.call(i.attributes),l=[].concat(e["*"]||[],e[r]||[]);a.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===q.indexOf(n)||Boolean(t.nodeValue.match(Q)||t.nodeValue.match(B));for(var i=e.filter((function(t){return t instanceof RegExp})),o=0,s=i.length;o<s;o++)if(n.match(i[o]))return!0;return!1})(t,l)||i.removeAttribute(t.nodeName)}))},a=0,l=s.length;a<l;a++)r(a);return i.body.innerHTML}var U="tooltip",M=e.fn[U],W=new RegExp("(^|\\s)bs-tooltip\\S+","g"),V=["sanitize","whiteList","sanitizeFn"],z={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},K={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},X={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:F,popperConfig:null},Y={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},$=function(){function t(t,e){if("undefined"==typeof n)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var i=t.prototype;return i.enable=function(){this._isEnabled=!0},i.disable=function(){this._isEnabled=!1},i.toggleEnabled=function(){this._isEnabled=!this._isEnabled},i.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},i.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},i.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var i=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(i);var o=c.findShadowRoot(this.element),s=e.contains(null!==o?o:this.element.ownerDocument.documentElement,this.element);if(i.isDefaultPrevented()||!s)return;var r=this.getTipElement(),a=c.getUID(this.constructor.NAME);r.setAttribute("id",a),this.element.setAttribute("aria-describedby",a),this.setContent(),this.config.animation&&e(r).addClass("fade");var l="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,h=this._getAttachment(l);this.addAttachmentClass(h);var u=this._getContainer();e(r).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(r).appendTo(u),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new n(this.element,r,this._getPopperConfig(h)),e(r).addClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().on("mouseover",null,e.noop);var d=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),"out"===n&&t._leave(null,t)};if(e(this.tip).hasClass("fade")){var f=c.getTransitionDurationFromElement(this.tip);e(this.tip).one(c.TRANSITION_END,d).emulateTransitionEnd(f)}else d()}},i.hide=function(t){var n=this,i=this.getTipElement(),o=e.Event(this.constructor.Event.HIDE),s=function(){"show"!==n._hoverState&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};if(e(this.element).trigger(o),!o.isDefaultPrevented()){if(e(i).removeClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,e(this.tip).hasClass("fade")){var r=c.getTransitionDurationFromElement(i);e(i).one(c.TRANSITION_END,s).emulateTransitionEnd(r)}else s();this._hoverState=""}},i.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},i.isWithContent=function(){return Boolean(this.getTitle())},i.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},i.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},i.setContent=function(){var t=this.getTipElement();this.setElementContent(e(t.querySelectorAll(".tooltip-inner")),this.getTitle()),e(t).removeClass("fade show")},i.setElementContent=function(t,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=H(n,this.config.whiteList,this.config.sanitizeFn)),t.html(n)):t.text(n):this.config.html?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text())},i.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},i._getPopperConfig=function(t){var e=this;return a(a({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),this.config.popperConfig)},i._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=a(a({},e.offsets),t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},i._getContainer=function(){return!1===this.config.container?document.body:c.isElement(this.config.container)?e(this.config.container):e(document).find(this.config.container)},i._getAttachment=function(t){return K[t.toUpperCase()]},i._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==n){var i="hover"===n?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===n?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},e(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=a(a({},this.config),{},{trigger:"manual",selector:""}):this._fixTitle()},i._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},i._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},i._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},i._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},i._getConfig=function(t){var n=e(this.element).data();return Object.keys(n).forEach((function(t){-1!==V.indexOf(t)&&delete n[t]})),"number"==typeof(t=a(a(a({},this.constructor.Default),n),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),c.typeCheckConfig(U,t,this.constructor.DefaultType),t.sanitize&&(t.template=H(t.template,t.whiteList,t.sanitizeFn)),t},i._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},i._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(W);null!==n&&n.length&&t.removeClass(n.join(""))},i._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},i._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.tooltip"),o="object"==typeof n&&n;if((i||!/dispose|hide/.test(n))&&(i||(i=new t(this,o),e(this).data("bs.tooltip",i)),"string"==typeof n)){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return X}},{key:"NAME",get:function(){return U}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return Y}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return z}}]),t}();e.fn[U]=$._jQueryInterface,e.fn[U].Constructor=$,e.fn[U].noConflict=function(){return e.fn[U]=M,$._jQueryInterface};var J="popover",G=e.fn[J],Z=new RegExp("(^|\\s)bs-popover\\S+","g"),tt=a(a({},$.Default),{},{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),et=a(a({},$.DefaultType),{},{content:"(string|element|function)"}),nt={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},it=function(t){var n,i;function s(){return t.apply(this,arguments)||this}i=t,(n=s).prototype=Object.create(i.prototype),n.prototype.constructor=n,n.__proto__=i;var r=s.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},r.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},r.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(t.find(".popover-body"),n),t.removeClass("fade show")},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(Z);null!==n&&n.length>0&&t.removeClass(n.join(""))},s._jQueryInterface=function(t){return this.each((function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new s(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},o(s,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return tt}},{key:"NAME",get:function(){return J}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return nt}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return et}}]),s}($);e.fn[J]=it._jQueryInterface,e.fn[J].Constructor=it,e.fn[J].noConflict=function(){return e.fn[J]=G,it._jQueryInterface};var ot="scrollspy",st=e.fn[ot],rt={offset:10,method:"auto",target:""},at={offset:"number",method:"string",target:"(string|element)"},lt=function(){function t(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return i._process(t)})),this.refresh(),this._process()}var n=t.prototype;return n.refresh=function(){var t=this,n=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?n:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var n,s=c.getSelectorFromElement(t);if(s&&(n=document.querySelector(s)),n){var r=n.getBoundingClientRect();if(r.width||r.height)return[e(n)[i]().top+o,s]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},n.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},n._getConfig=function(t){if("string"!=typeof(t=a(a({},rt),"object"==typeof t&&t?t:{})).target&&c.isElement(t.target)){var n=e(t.target).attr("id");n||(n=c.getUID(ot),e(t.target).attr("id",n)),t.target="#"+n}return c.typeCheckConfig(ot,t,at),t},n._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},n._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},n._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},n._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},n._activate=function(t){this._activeTarget=t,this._clear();var n=this._selector.split(",").map((function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'})),i=e([].slice.call(document.querySelectorAll(n.join(","))));i.hasClass("dropdown-item")?(i.closest(".dropdown").find(".dropdown-toggle").addClass("active"),i.addClass("active")):(i.addClass("active"),i.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),i.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),e(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:t})},n._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.scrollspy");if(i||(i=new t(this,"object"==typeof n&&n),e(this).data("bs.scrollspy",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return rt}}]),t}();e(window).on("load.bs.scrollspy.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),n=t.length;n--;){var i=e(t[n]);lt._jQueryInterface.call(i,i.data())}})),e.fn[ot]=lt._jQueryInterface,e.fn[ot].Constructor=lt,e.fn[ot].noConflict=function(){return e.fn[ot]=st,lt._jQueryInterface};var ct=e.fn.tab,ht=function(){function t(t){this._element=t}var n=t.prototype;return n.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&e(this._element).hasClass("active")||e(this._element).hasClass("disabled"))){var n,i,o=e(this._element).closest(".nav, .list-group")[0],s=c.getSelectorFromElement(this._element);if(o){var r="UL"===o.nodeName||"OL"===o.nodeName?"> li > .active":".active";i=(i=e.makeArray(e(o).find(r)))[i.length-1]}var a=e.Event("hide.bs.tab",{relatedTarget:this._element}),l=e.Event("show.bs.tab",{relatedTarget:i});if(i&&e(i).trigger(a),e(this._element).trigger(l),!l.isDefaultPrevented()&&!a.isDefaultPrevented()){s&&(n=document.querySelector(s)),this._activate(this._element,o);var h=function(){var n=e.Event("hidden.bs.tab",{relatedTarget:t._element}),o=e.Event("shown.bs.tab",{relatedTarget:i});e(i).trigger(n),e(t._element).trigger(o)};n?this._activate(n,n.parentNode,h):h()}}},n.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},n._activate=function(t,n,i){var o=this,s=(!n||"UL"!==n.nodeName&&"OL"!==n.nodeName?e(n).children(".active"):e(n).find("> li > .active"))[0],r=i&&s&&e(s).hasClass("fade"),a=function(){return o._transitionComplete(t,s,i)};if(s&&r){var l=c.getTransitionDurationFromElement(s);e(s).removeClass("show").one(c.TRANSITION_END,a).emulateTransitionEnd(l)}else a()},n._transitionComplete=function(t,n,i){if(n){e(n).removeClass("active");var o=e(n.parentNode).find("> .dropdown-menu .active")[0];o&&e(o).removeClass("active"),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),c.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&e(t.parentNode).hasClass("dropdown-menu")){var s=e(t).closest(".dropdown")[0];if(s){var r=[].slice.call(s.querySelectorAll(".dropdown-toggle"));e(r).addClass("active")}t.setAttribute("aria-expanded",!0)}i&&i()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.tab");if(o||(o=new t(this),i.data("bs.tab",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}}]),t}();e(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ht._jQueryInterface.call(e(this),"show")})),e.fn.tab=ht._jQueryInterface,e.fn.tab.Constructor=ht,e.fn.tab.noConflict=function(){return e.fn.tab=ct,ht._jQueryInterface};var ut=e.fn.toast,dt={animation:"boolean",autohide:"boolean",delay:"number"},ft={animation:!0,autohide:!0,delay:500},gt=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var n=t.prototype;return n.show=function(){var t=this,n=e.Event("show.bs.toast");if(e(this._element).trigger(n),!n.isDefaultPrevented()){this._config.animation&&this._element.classList.add("fade");var i=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),e(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),c.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,i).emulateTransitionEnd(o)}else i()}},n.hide=function(){if(this._element.classList.contains("show")){var t=e.Event("hide.bs.toast");e(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},n.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains("show")&&this._element.classList.remove("show"),e(this._element).off("click.dismiss.bs.toast"),e.removeData(this._element,"bs.toast"),this._element=null,this._config=null},n._getConfig=function(t){return t=a(a(a({},ft),e(this._element).data()),"object"==typeof t&&t?t:{}),c.typeCheckConfig("toast",t,this.constructor.DefaultType),t},n._setListeners=function(){var t=this;e(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},n._close=function(){var t=this,n=function(){t._element.classList.add("hide"),e(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var i=c.getTransitionDurationFromElement(this._element);e(this._element).one(c.TRANSITION_END,n).emulateTransitionEnd(i)}else n()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.toast");if(o||(o=new t(this,"object"==typeof n&&n),i.data("bs.toast",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](this)}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.0"}},{key:"DefaultType",get:function(){return dt}},{key:"Default",get:function(){return ft}}]),t}();e.fn.toast=gt._jQueryInterface,e.fn.toast.Constructor=gt,e.fn.toast.noConflict=function(){return e.fn.toast=ut,gt._jQueryInterface},t.Alert=d,t.Button=g,t.Carousel=E,t.Collapse=D,t.Dropdown=j,t.Modal=R,t.Popover=it,t.Scrollspy=lt,t.Tab=ht,t.Toast=gt,t.Tooltip=$,t.Util=c,Object.defineProperty(t,"__esModule",{value:!0})}));
7
  //# sourceMappingURL=bootstrap.min.js.map
1
  /*!
2
+ * Bootstrap v4.5.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function o(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function s(){return(s=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t}).apply(this,arguments)}e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;function r(t){var n=this,i=!1;return e(this).one(a.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||a.triggerTransitionEnd(n)}),t),this}var a={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var n=e(t).css("transition-duration"),i=e(t).css("transition-delay"),o=parseFloat(n),s=parseFloat(i);return o||s?(n=n.split(",")[0],i=i.split(",")[0],1e3*(parseFloat(n)+parseFloat(i))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],s=e[i],r=s&&a.isElement(s)?"element":null===(l=s)||"undefined"==typeof l?""+l:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(r))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+r+'" but expected type "'+o+'".')}var l},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?a.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if("undefined"==typeof e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};a.jQueryDetection(),e.fn.emulateTransitionEnd=r,e.event.special[a.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(t){if(e(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var l="alert",c=e.fn[l],h=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=a.getSelectorFromElement(t),i=!1;return n&&(i=document.querySelector(n)),i||(i=e(t).closest(".alert")[0]),i},n._triggerCloseEvent=function(t){var n=e.Event("close.bs.alert");return e(t).trigger(n),n},n._removeElement=function(t){var n=this;if(e(t).removeClass("show"),e(t).hasClass("fade")){var i=a.getTransitionDurationFromElement(t);e(t).one(a.TRANSITION_END,(function(e){return n._destroyElement(t,e)})).emulateTransitionEnd(i)}else this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.alert");o||(o=new t(this),i.data("bs.alert",o)),"close"===n&&o[n](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}}]),t}();e(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',h._handleDismiss(new h)),e.fn[l]=h._jQueryInterface,e.fn[l].Constructor=h,e.fn[l].noConflict=function(){return e.fn[l]=c,h._jQueryInterface};var u=e.fn.button,d=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,i=e(this._element).closest('[data-toggle="buttons"]')[0];if(i){var o=this._element.querySelector('input:not([type="hidden"])');if(o){if("radio"===o.type)if(o.checked&&this._element.classList.contains("active"))t=!1;else{var s=i.querySelector(".active");s&&e(s).removeClass("active")}t&&("checkbox"!==o.type&&"radio"!==o.type||(o.checked=!this._element.classList.contains("active")),e(o).trigger("change")),o.focus(),n=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(n&&this._element.setAttribute("aria-pressed",!this._element.classList.contains("active")),t&&e(this._element).toggleClass("active"))},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}}]),t}();e(document).on("click.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=t.target,i=n;if(e(n).hasClass("btn")||(n=e(n).closest(".btn")[0]),!n||n.hasAttribute("disabled")||n.classList.contains("disabled"))t.preventDefault();else{var o=n.querySelector('input:not([type="hidden"])');if(o&&(o.hasAttribute("disabled")||o.classList.contains("disabled")))return void t.preventDefault();("LABEL"!==i.tagName||o&&"checkbox"!==o.type)&&d._jQueryInterface.call(e(n),"toggle")}})).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',(function(t){var n=e(t.target).closest(".btn")[0];e(n).toggleClass("focus",/^focus(in)?$/.test(t.type))})),e(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e<n;e++){var i=t[e],o=i.querySelector('input:not([type="hidden"])');o.checked||o.hasAttribute("checked")?i.classList.add("active"):i.classList.remove("active")}for(var s=0,r=(t=[].slice.call(document.querySelectorAll('[data-toggle="button"]'))).length;s<r;s++){var a=t[s];"true"===a.getAttribute("aria-pressed")?a.classList.add("active"):a.classList.remove("active")}})),e.fn.button=d._jQueryInterface,e.fn.button.Constructor=d,e.fn.button.noConflict=function(){return e.fn.button=u,d._jQueryInterface};var f="carousel",g=".bs.carousel",m=e.fn[f],p={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},_={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},v={TOUCH:"touch",PEN:"pen"},b=function(){function t(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(".carousel-indicators"),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var n=t.prototype;return n.next=function(){this._isSliding||this._slide("next")},n.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},n.prev=function(){this._isSliding||this._slide("prev")},n.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(a.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},n.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},n.to=function(t){var n=this;this._activeElement=this._element.querySelector(".active.carousel-item");var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one("slid.bs.carousel",(function(){return n.to(t)}));else{if(i===t)return this.pause(),void this.cycle();var o=t>i?"next":"prev";this._slide(o,this._items[t])}},n.dispose=function(){e(this._element).off(g),e.removeData(this._element,"bs.carousel"),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},n._getConfig=function(t){return t=s({},p,t),a.typeCheckConfig(f,t,_),t},n._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},n._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&e(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},n._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var n=function(e){t._pointerEvent&&v[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},i=function(e){t._pointerEvent&&v[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};e(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(e(this._element).on("pointerdown.bs.carousel",(function(t){return n(t)})),e(this._element).on("pointerup.bs.carousel",(function(t){return i(t)})),this._element.classList.add("pointer-event")):(e(this._element).on("touchstart.bs.carousel",(function(t){return n(t)})),e(this._element).on("touchmove.bs.carousel",(function(e){return function(e){e.originalEvent.touches&&e.originalEvent.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),e(this._element).on("touchend.bs.carousel",(function(t){return i(t)})))}},n._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},n._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},n._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),s=this._items.length-1;if((i&&0===o||n&&o===s)&&!this._config.wrap)return e;var r=(o+("prev"===t?-1:1))%this._items.length;return-1===r?this._items[this._items.length-1]:this._items[r]},n._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),o=this._getItemIndex(this._element.querySelector(".active.carousel-item")),s=e.Event("slide.bs.carousel",{relatedTarget:t,direction:n,from:o,to:i});return e(this._element).trigger(s),s},n._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var n=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));e(n).removeClass("active");var i=this._indicatorsElement.children[this._getItemIndex(t)];i&&e(i).addClass("active")}},n._slide=function(t,n){var i,o,s,r=this,l=this._element.querySelector(".active.carousel-item"),c=this._getItemIndex(l),h=n||l&&this._getItemByDirection(t,l),u=this._getItemIndex(h),d=Boolean(this._interval);if("next"===t?(i="carousel-item-left",o="carousel-item-next",s="left"):(i="carousel-item-right",o="carousel-item-prev",s="right"),h&&e(h).hasClass("active"))this._isSliding=!1;else if(!this._triggerSlideEvent(h,s).isDefaultPrevented()&&l&&h){this._isSliding=!0,d&&this.pause(),this._setActiveIndicatorElement(h);var f=e.Event("slid.bs.carousel",{relatedTarget:h,direction:s,from:c,to:u});if(e(this._element).hasClass("slide")){e(h).addClass(o),a.reflow(h),e(l).addClass(i),e(h).addClass(i);var g=parseInt(h.getAttribute("data-interval"),10);g?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=g):this._config.interval=this._config.defaultInterval||this._config.interval;var m=a.getTransitionDurationFromElement(l);e(l).one(a.TRANSITION_END,(function(){e(h).removeClass(i+" "+o).addClass("active"),e(l).removeClass("active "+o+" "+i),r._isSliding=!1,setTimeout((function(){return e(r._element).trigger(f)}),0)})).emulateTransitionEnd(m)}else e(l).removeClass("active"),e(h).addClass("active"),this._isSliding=!1,e(this._element).trigger(f);d&&this.cycle()}},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.carousel"),o=s({},p,e(this).data());"object"==typeof n&&(o=s({},o,n));var r="string"==typeof n?n:o.slide;if(i||(i=new t(this,o),e(this).data("bs.carousel",i)),"number"==typeof n)i.to(n);else if("string"==typeof r){if("undefined"==typeof i[r])throw new TypeError('No method named "'+r+'"');i[r]()}else o.interval&&o.ride&&(i.pause(),i.cycle())}))},t._dataApiClickHandler=function(n){var i=a.getSelectorFromElement(this);if(i){var o=e(i)[0];if(o&&e(o).hasClass("carousel")){var r=s({},e(o).data(),e(this).data()),l=this.getAttribute("data-slide-to");l&&(r.interval=!1),t._jQueryInterface.call(e(o),r),l&&e(o).data("bs.carousel").to(l),n.preventDefault()}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return p}}]),t}();e(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",b._dataApiClickHandler),e(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),n=0,i=t.length;n<i;n++){var o=e(t[n]);b._jQueryInterface.call(o,o.data())}})),e.fn[f]=b._jQueryInterface,e.fn[f].Constructor=b,e.fn[f].noConflict=function(){return e.fn[f]=m,b._jQueryInterface};var y="collapse",E=e.fn[y],w={toggle:!0,parent:""},T={toggle:"boolean",parent:"(string|element)"},C=function(){function t(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=n.length;i<o;i++){var s=n[i],r=a.getSelectorFromElement(s),l=[].slice.call(document.querySelectorAll(r)).filter((function(e){return e===t}));null!==r&&l.length>0&&(this._selector=r,this._triggerArray.push(s))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var n=t.prototype;return n.toggle=function(){e(this._element).hasClass("show")?this.hide():this.show()},n.show=function(){var n,i,o=this;if(!this._isTransitioning&&!e(this._element).hasClass("show")&&(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),!(n&&(i=e(n).not(this._selector).data("bs.collapse"))&&i._isTransitioning))){var s=e.Event("show.bs.collapse");if(e(this._element).trigger(s),!s.isDefaultPrevented()){n&&(t._jQueryInterface.call(e(n).not(this._selector),"hide"),i||e(n).data("bs.collapse",null));var r=this._getDimension();e(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[r]=0,this._triggerArray.length&&e(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(r[0].toUpperCase()+r.slice(1)),c=a.getTransitionDurationFromElement(this._element);e(this._element).one(a.TRANSITION_END,(function(){e(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[r]="",o.setTransitioning(!1),e(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(c),this._element.style[r]=this._element[l]+"px"}}},n.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass("show")){var n=e.Event("hide.bs.collapse");if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",a.reflow(this._element),e(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var s=0;s<o;s++){var r=this._triggerArray[s],l=a.getSelectorFromElement(r);if(null!==l)e([].slice.call(document.querySelectorAll(l))).hasClass("show")||e(r).addClass("collapsed").attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[i]="";var c=a.getTransitionDurationFromElement(this._element);e(this._element).one(a.TRANSITION_END,(function(){t.setTransitioning(!1),e(t._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(c)}}},n.setTransitioning=function(t){this._isTransitioning=t},n.dispose=function(){e.removeData(this._element,"bs.collapse"),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},n._getConfig=function(t){return(t=s({},w,t)).toggle=Boolean(t.toggle),a.typeCheckConfig(y,t,T),t},n._getDimension=function(){return e(this._element).hasClass("width")?"width":"height"},n._getParent=function(){var n,i=this;a.isElement(this._config.parent)?(n=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(n=this._config.parent[0])):n=document.querySelector(this._config.parent);var o='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',s=[].slice.call(n.querySelectorAll(o));return e(s).each((function(e,n){i._addAriaAndCollapsedClass(t._getTargetFromElement(n),[n])})),n},n._addAriaAndCollapsedClass=function(t,n){var i=e(t).hasClass("show");n.length&&e(n).toggleClass("collapsed",!i).attr("aria-expanded",i)},t._getTargetFromElement=function(t){var e=a.getSelectorFromElement(t);return e?document.querySelector(e):null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.collapse"),r=s({},w,i.data(),"object"==typeof n&&n?n:{});if(!o&&r.toggle&&"string"==typeof n&&/show|hide/.test(n)&&(r.toggle=!1),o||(o=new t(this,r),i.data("bs.collapse",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return w}}]),t}();e(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=e(this),i=a.getSelectorFromElement(this),o=[].slice.call(document.querySelectorAll(i));e(o).each((function(){var t=e(this),i=t.data("bs.collapse")?"toggle":n.data();C._jQueryInterface.call(t,i)}))})),e.fn[y]=C._jQueryInterface,e.fn[y].Constructor=C,e.fn[y].noConflict=function(){return e.fn[y]=E,C._jQueryInterface};var S="dropdown",k=e.fn[S],D=new RegExp("38|40|27"),N={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic",popperConfig:null},A={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string",popperConfig:"(null|object)"},I=function(){function t(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var i=t.prototype;return i.toggle=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")){var n=e(this._menu).hasClass("show");t._clearMenus(),n||this.show(!0)}},i.show=function(i){if(void 0===i&&(i=!1),!(this._element.disabled||e(this._element).hasClass("disabled")||e(this._menu).hasClass("show"))){var o={relatedTarget:this._element},s=e.Event("show.bs.dropdown",o),r=t._getParentFromElement(this._element);if(e(r).trigger(s),!s.isDefaultPrevented()){if(!this._inNavbar&&i){if("undefined"==typeof n)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var l=this._element;"parent"===this._config.reference?l=r:a.isElement(this._config.reference)&&(l=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(l=this._config.reference[0])),"scrollParent"!==this._config.boundary&&e(r).addClass("position-static"),this._popper=new n(l,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===e(r).closest(".navbar-nav").length&&e(document.body).children().on("mouseover",null,e.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),e(this._menu).toggleClass("show"),e(r).toggleClass("show").trigger(e.Event("shown.bs.dropdown",o))}}},i.hide=function(){if(!this._element.disabled&&!e(this._element).hasClass("disabled")&&e(this._menu).hasClass("show")){var n={relatedTarget:this._element},i=e.Event("hide.bs.dropdown",n),o=t._getParentFromElement(this._element);e(o).trigger(i),i.isDefaultPrevented()||(this._popper&&this._popper.destroy(),e(this._menu).toggleClass("show"),e(o).toggleClass("show").trigger(e.Event("hidden.bs.dropdown",n)))}},i.dispose=function(){e.removeData(this._element,"bs.dropdown"),e(this._element).off(".bs.dropdown"),this._element=null,this._menu=null,null!==this._popper&&(this._popper.destroy(),this._popper=null)},i.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},i._addEventListeners=function(){var t=this;e(this._element).on("click.bs.dropdown",(function(e){e.preventDefault(),e.stopPropagation(),t.toggle()}))},i._getConfig=function(t){return t=s({},this.constructor.Default,e(this._element).data(),t),a.typeCheckConfig(S,t,this.constructor.DefaultType),t},i._getMenuElement=function(){if(!this._menu){var e=t._getParentFromElement(this._element);e&&(this._menu=e.querySelector(".dropdown-menu"))}return this._menu},i._getPlacement=function(){var t=e(this._element.parentNode),n="bottom-start";return t.hasClass("dropup")?n=e(this._menu).hasClass("dropdown-menu-right")?"top-end":"top-start":t.hasClass("dropright")?n="right-start":t.hasClass("dropleft")?n="left-start":e(this._menu).hasClass("dropdown-menu-right")&&(n="bottom-end"),n},i._detectNavbar=function(){return e(this._element).closest(".navbar").length>0},i._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=s({},e.offsets,t._config.offset(e.offsets,t._element)||{}),e}:e.offset=this._config.offset,e},i._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),s({},t,this._config.popperConfig)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.dropdown");if(i||(i=new t(this,"object"==typeof n?n:null),e(this).data("bs.dropdown",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},t._clearMenus=function(n){if(!n||3!==n.which&&("keyup"!==n.type||9===n.which))for(var i=[].slice.call(document.querySelectorAll('[data-toggle="dropdown"]')),o=0,s=i.length;o<s;o++){var r=t._getParentFromElement(i[o]),a=e(i[o]).data("bs.dropdown"),l={relatedTarget:i[o]};if(n&&"click"===n.type&&(l.clickEvent=n),a){var c=a._menu;if(e(r).hasClass("show")&&!(n&&("click"===n.type&&/input|textarea/i.test(n.target.tagName)||"keyup"===n.type&&9===n.which)&&e.contains(r,n.target))){var h=e.Event("hide.bs.dropdown",l);e(r).trigger(h),h.isDefaultPrevented()||("ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),i[o].setAttribute("aria-expanded","false"),a._popper&&a._popper.destroy(),e(c).removeClass("show"),e(r).removeClass("show").trigger(e.Event("hidden.bs.dropdown",l)))}}}},t._getParentFromElement=function(t){var e,n=a.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},t._dataApiKeydownHandler=function(n){if(!(/input|textarea/i.test(n.target.tagName)?32===n.which||27!==n.which&&(40!==n.which&&38!==n.which||e(n.target).closest(".dropdown-menu").length):!D.test(n.which))&&!this.disabled&&!e(this).hasClass("disabled")){var i=t._getParentFromElement(this),o=e(i).hasClass("show");if(o||27!==n.which){if(n.preventDefault(),n.stopPropagation(),!o||o&&(27===n.which||32===n.which))return 27===n.which&&e(i.querySelector('[data-toggle="dropdown"]')).trigger("focus"),void e(this).trigger("click");var s=[].slice.call(i.querySelectorAll(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)")).filter((function(t){return e(t).is(":visible")}));if(0!==s.length){var r=s.indexOf(n.target);38===n.which&&r>0&&r--,40===n.which&&r<s.length-1&&r++,r<0&&(r=0),s[r].focus()}}}},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return N}},{key:"DefaultType",get:function(){return A}}]),t}();e(document).on("keydown.bs.dropdown.data-api",'[data-toggle="dropdown"]',I._dataApiKeydownHandler).on("keydown.bs.dropdown.data-api",".dropdown-menu",I._dataApiKeydownHandler).on("click.bs.dropdown.data-api keyup.bs.dropdown.data-api",I._clearMenus).on("click.bs.dropdown.data-api",'[data-toggle="dropdown"]',(function(t){t.preventDefault(),t.stopPropagation(),I._jQueryInterface.call(e(this),"toggle")})).on("click.bs.dropdown.data-api",".dropdown form",(function(t){t.stopPropagation()})),e.fn[S]=I._jQueryInterface,e.fn[S].Constructor=I,e.fn[S].noConflict=function(){return e.fn[S]=k,I._jQueryInterface};var O=e.fn.modal,j={backdrop:!0,keyboard:!0,focus:!0,show:!0},x={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},P=function(){function t(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(".modal-dialog"),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var n=t.prototype;return n.toggle=function(t){return this._isShown?this.hide():this.show(t)},n.show=function(t){var n=this;if(!this._isShown&&!this._isTransitioning){e(this._element).hasClass("fade")&&(this._isTransitioning=!0);var i=e.Event("show.bs.modal",{relatedTarget:t});e(this._element).trigger(i),this._isShown||i.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),e(this._element).on("click.dismiss.bs.modal",'[data-dismiss="modal"]',(function(t){return n.hide(t)})),e(this._dialog).on("mousedown.dismiss.bs.modal",(function(){e(n._element).one("mouseup.dismiss.bs.modal",(function(t){e(t.target).is(n._element)&&(n._ignoreBackdropClick=!0)}))})),this._showBackdrop((function(){return n._showElement(t)})))}},n.hide=function(t){var n=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var i=e.Event("hide.bs.modal");if(e(this._element).trigger(i),this._isShown&&!i.isDefaultPrevented()){this._isShown=!1;var o=e(this._element).hasClass("fade");if(o&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),e(document).off("focusin.bs.modal"),e(this._element).removeClass("show"),e(this._element).off("click.dismiss.bs.modal"),e(this._dialog).off("mousedown.dismiss.bs.modal"),o){var s=a.getTransitionDurationFromElement(this._element);e(this._element).one(a.TRANSITION_END,(function(t){return n._hideModal(t)})).emulateTransitionEnd(s)}else this._hideModal()}}},n.dispose=function(){[window,this._element,this._dialog].forEach((function(t){return e(t).off(".bs.modal")})),e(document).off("focusin.bs.modal"),e.removeData(this._element,"bs.modal"),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},n.handleUpdate=function(){this._adjustDialog()},n._getConfig=function(t){return t=s({},j,t),a.typeCheckConfig("modal",t,x),t},n._triggerBackdropTransition=function(){var t=this;if("static"===this._config.backdrop){var n=e.Event("hidePrevented.bs.modal");if(e(this._element).trigger(n),n.defaultPrevented)return;var i=this._element.scrollHeight>document.documentElement.clientHeight;i||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");var o=a.getTransitionDurationFromElement(this._dialog);e(this._element).off(a.TRANSITION_END),e(this._element).one(a.TRANSITION_END,(function(){t._element.classList.remove("modal-static"),i||e(t._element).one(a.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,o)})).emulateTransitionEnd(o),this._element.focus()}else this.hide()},n._showElement=function(t){var n=this,i=e(this._element).hasClass("fade"),o=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),e(this._dialog).hasClass("modal-dialog-scrollable")&&o?o.scrollTop=0:this._element.scrollTop=0,i&&a.reflow(this._element),e(this._element).addClass("show"),this._config.focus&&this._enforceFocus();var s=e.Event("shown.bs.modal",{relatedTarget:t}),r=function(){n._config.focus&&n._element.focus(),n._isTransitioning=!1,e(n._element).trigger(s)};if(i){var l=a.getTransitionDurationFromElement(this._dialog);e(this._dialog).one(a.TRANSITION_END,r).emulateTransitionEnd(l)}else r()},n._enforceFocus=function(){var t=this;e(document).off("focusin.bs.modal").on("focusin.bs.modal",(function(n){document!==n.target&&t._element!==n.target&&0===e(t._element).has(n.target).length&&t._element.focus()}))},n._setEscapeEvent=function(){var t=this;this._isShown?e(this._element).on("keydown.dismiss.bs.modal",(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||e(this._element).off("keydown.dismiss.bs.modal")},n._setResizeEvent=function(){var t=this;this._isShown?e(window).on("resize.bs.modal",(function(e){return t.handleUpdate(e)})):e(window).off("resize.bs.modal")},n._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){e(document.body).removeClass("modal-open"),t._resetAdjustments(),t._resetScrollbar(),e(t._element).trigger("hidden.bs.modal")}))},n._removeBackdrop=function(){this._backdrop&&(e(this._backdrop).remove(),this._backdrop=null)},n._showBackdrop=function(t){var n=this,i=e(this._element).hasClass("fade")?"fade":"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",i&&this._backdrop.classList.add(i),e(this._backdrop).appendTo(document.body),e(this._element).on("click.dismiss.bs.modal",(function(t){n._ignoreBackdropClick?n._ignoreBackdropClick=!1:t.target===t.currentTarget&&n._triggerBackdropTransition()})),i&&a.reflow(this._backdrop),e(this._backdrop).addClass("show"),!t)return;if(!i)return void t();var o=a.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(a.TRANSITION_END,t).emulateTransitionEnd(o)}else if(!this._isShown&&this._backdrop){e(this._backdrop).removeClass("show");var s=function(){n._removeBackdrop(),t&&t()};if(e(this._element).hasClass("fade")){var r=a.getTransitionDurationFromElement(this._backdrop);e(this._backdrop).one(a.TRANSITION_END,s).emulateTransitionEnd(r)}else s()}else t&&t()},n._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},n._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},n._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},n._setScrollbar=function(){var t=this;if(this._isBodyOverflowing){var n=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top")),i=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(n,i){var o=i.style.paddingRight,s=e(i).css("padding-right");e(i).data("padding-right",o).css("padding-right",parseFloat(s)+t._scrollbarWidth+"px")})),e(i).each((function(n,i){var o=i.style.marginRight,s=e(i).css("margin-right");e(i).data("margin-right",o).css("margin-right",parseFloat(s)-t._scrollbarWidth+"px")}));var o=document.body.style.paddingRight,s=e(document.body).css("padding-right");e(document.body).data("padding-right",o).css("padding-right",parseFloat(s)+this._scrollbarWidth+"px")}e(document.body).addClass("modal-open")},n._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(".fixed-top, .fixed-bottom, .is-fixed, .sticky-top"));e(t).each((function(t,n){var i=e(n).data("padding-right");e(n).removeData("padding-right"),n.style.paddingRight=i||""}));var n=[].slice.call(document.querySelectorAll(".sticky-top"));e(n).each((function(t,n){var i=e(n).data("margin-right");"undefined"!=typeof i&&e(n).css("margin-right",i).removeData("margin-right")}));var i=e(document.body).data("padding-right");e(document.body).removeData("padding-right"),document.body.style.paddingRight=i||""},n._getScrollbarWidth=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},t._jQueryInterface=function(n,i){return this.each((function(){var o=e(this).data("bs.modal"),r=s({},j,e(this).data(),"object"==typeof n&&n?n:{});if(o||(o=new t(this,r),e(this).data("bs.modal",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](i)}else r.show&&o.show(i)}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return j}}]),t}();e(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',(function(t){var n,i=this,o=a.getSelectorFromElement(this);o&&(n=document.querySelector(o));var r=e(n).data("bs.modal")?"toggle":s({},e(n).data(),e(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var l=e(n).one("show.bs.modal",(function(t){t.isDefaultPrevented()||l.one("hidden.bs.modal",(function(){e(i).is(":visible")&&i.focus()}))}));P._jQueryInterface.call(e(n),r,this)})),e.fn.modal=P._jQueryInterface,e.fn.modal.Constructor=P,e.fn.modal.noConflict=function(){return e.fn.modal=O,P._jQueryInterface};var R=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],L={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},q=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,F=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function Q(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var i=(new window.DOMParser).parseFromString(t,"text/html"),o=Object.keys(e),s=[].slice.call(i.body.querySelectorAll("*")),r=function(t,n){var i=s[t],r=i.nodeName.toLowerCase();if(-1===o.indexOf(i.nodeName.toLowerCase()))return i.parentNode.removeChild(i),"continue";var a=[].slice.call(i.attributes),l=[].concat(e["*"]||[],e[r]||[]);a.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===R.indexOf(n)||Boolean(t.nodeValue.match(q)||t.nodeValue.match(F));for(var i=e.filter((function(t){return t instanceof RegExp})),o=0,s=i.length;o<s;o++)if(n.match(i[o]))return!0;return!1})(t,l)||i.removeAttribute(t.nodeName)}))},a=0,l=s.length;a<l;a++)r(a);return i.body.innerHTML}var B="tooltip",H=e.fn[B],U=new RegExp("(^|\\s)bs-tooltip\\S+","g"),M=["sanitize","whiteList","sanitizeFn"],W={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},V={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},z={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:L,popperConfig:null},K={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},X=function(){function t(t,e){if("undefined"==typeof n)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var i=t.prototype;return i.enable=function(){this._isEnabled=!0},i.disable=function(){this._isEnabled=!1},i.toggleEnabled=function(){this._isEnabled=!this._isEnabled},i.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},i.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},i.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var i=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(i);var o=a.findShadowRoot(this.element),s=e.contains(null!==o?o:this.element.ownerDocument.documentElement,this.element);if(i.isDefaultPrevented()||!s)return;var r=this.getTipElement(),l=a.getUID(this.constructor.NAME);r.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&e(r).addClass("fade");var c="function"==typeof this.config.placement?this.config.placement.call(this,r,this.element):this.config.placement,h=this._getAttachment(c);this.addAttachmentClass(h);var u=this._getContainer();e(r).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(r).appendTo(u),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new n(this.element,r,this._getPopperConfig(h)),e(r).addClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().on("mouseover",null,e.noop);var d=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),"out"===n&&t._leave(null,t)};if(e(this.tip).hasClass("fade")){var f=a.getTransitionDurationFromElement(this.tip);e(this.tip).one(a.TRANSITION_END,d).emulateTransitionEnd(f)}else d()}},i.hide=function(t){var n=this,i=this.getTipElement(),o=e.Event(this.constructor.Event.HIDE),s=function(){"show"!==n._hoverState&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};if(e(this.element).trigger(o),!o.isDefaultPrevented()){if(e(i).removeClass("show"),"ontouchstart"in document.documentElement&&e(document.body).children().off("mouseover",null,e.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,e(this.tip).hasClass("fade")){var r=a.getTransitionDurationFromElement(i);e(i).one(a.TRANSITION_END,s).emulateTransitionEnd(r)}else s();this._hoverState=""}},i.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},i.isWithContent=function(){return Boolean(this.getTitle())},i.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},i.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},i.setContent=function(){var t=this.getTipElement();this.setElementContent(e(t.querySelectorAll(".tooltip-inner")),this.getTitle()),e(t).removeClass("fade show")},i.setElementContent=function(t,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=Q(n,this.config.whiteList,this.config.sanitizeFn)),t.html(n)):t.text(n):this.config.html?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text())},i.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},i._getPopperConfig=function(t){var e=this;return s({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},i._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=s({},e.offsets,t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},i._getContainer=function(){return!1===this.config.container?document.body:a.isElement(this.config.container)?e(this.config.container):e(document).find(this.config.container)},i._getAttachment=function(t){return V[t.toUpperCase()]},i._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==n){var i="hover"===n?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,o="hover"===n?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,(function(e){return t._enter(e)})).on(o,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},e(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=s({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},i._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},i._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},i._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},i._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},i._getConfig=function(t){var n=e(this.element).data();return Object.keys(n).forEach((function(t){-1!==M.indexOf(t)&&delete n[t]})),"number"==typeof(t=s({},this.constructor.Default,n,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),a.typeCheckConfig(B,t,this.constructor.DefaultType),t.sanitize&&(t.template=Q(t.template,t.whiteList,t.sanitizeFn)),t},i._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},i._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(U);null!==n&&n.length&&t.removeClass(n.join(""))},i._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},i._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.tooltip"),o="object"==typeof n&&n;if((i||!/dispose|hide/.test(n))&&(i||(i=new t(this,o),e(this).data("bs.tooltip",i)),"string"==typeof n)){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return z}},{key:"NAME",get:function(){return B}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return K}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return W}}]),t}();e.fn[B]=X._jQueryInterface,e.fn[B].Constructor=X,e.fn[B].noConflict=function(){return e.fn[B]=H,X._jQueryInterface};var Y="popover",$=e.fn[Y],J=new RegExp("(^|\\s)bs-popover\\S+","g"),G=s({},X.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),Z=s({},X.DefaultType,{content:"(string|element|function)"}),tt={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},et=function(t){var n,i;function s(){return t.apply(this,arguments)||this}i=t,(n=s).prototype=Object.create(i.prototype),n.prototype.constructor=n,n.__proto__=i;var r=s.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},r.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},r.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var n=this._getContent();"function"==typeof n&&(n=n.call(this.element)),this.setElementContent(t.find(".popover-body"),n),t.removeClass("fade show")},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(J);null!==n&&n.length>0&&t.removeClass(n.join(""))},s._jQueryInterface=function(t){return this.each((function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/dispose|hide/.test(t))&&(n||(n=new s(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new TypeError('No method named "'+t+'"');n[t]()}}))},o(s,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return G}},{key:"NAME",get:function(){return Y}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return tt}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Z}}]),s}(X);e.fn[Y]=et._jQueryInterface,e.fn[Y].Constructor=et,e.fn[Y].noConflict=function(){return e.fn[Y]=$,et._jQueryInterface};var nt="scrollspy",it=e.fn[nt],ot={offset:10,method:"auto",target:""},st={offset:"number",method:"string",target:"(string|element)"},rt=function(){function t(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return i._process(t)})),this.refresh(),this._process()}var n=t.prototype;return n.refresh=function(){var t=this,n=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?n:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var n,s=a.getSelectorFromElement(t);if(s&&(n=document.querySelector(s)),n){var r=n.getBoundingClientRect();if(r.width||r.height)return[e(n)[i]().top+o,s]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},n.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},n._getConfig=function(t){if("string"!=typeof(t=s({},ot,"object"==typeof t&&t?t:{})).target&&a.isElement(t.target)){var n=e(t.target).attr("id");n||(n=a.getUID(nt),e(t.target).attr("id",n)),t.target="#"+n}return a.typeCheckConfig(nt,t,st),t},n._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},n._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},n._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},n._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},n._activate=function(t){this._activeTarget=t,this._clear();var n=this._selector.split(",").map((function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'})),i=e([].slice.call(document.querySelectorAll(n.join(","))));i.hasClass("dropdown-item")?(i.closest(".dropdown").find(".dropdown-toggle").addClass("active"),i.addClass("active")):(i.addClass("active"),i.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),i.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),e(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:t})},n._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},t._jQueryInterface=function(n){return this.each((function(){var i=e(this).data("bs.scrollspy");if(i||(i=new t(this,"object"==typeof n&&n),e(this).data("bs.scrollspy",i)),"string"==typeof n){if("undefined"==typeof i[n])throw new TypeError('No method named "'+n+'"');i[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"Default",get:function(){return ot}}]),t}();e(window).on("load.bs.scrollspy.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),n=t.length;n--;){var i=e(t[n]);rt._jQueryInterface.call(i,i.data())}})),e.fn[nt]=rt._jQueryInterface,e.fn[nt].Constructor=rt,e.fn[nt].noConflict=function(){return e.fn[nt]=it,rt._jQueryInterface};var at=e.fn.tab,lt=function(){function t(t){this._element=t}var n=t.prototype;return n.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&e(this._element).hasClass("active")||e(this._element).hasClass("disabled"))){var n,i,o=e(this._element).closest(".nav, .list-group")[0],s=a.getSelectorFromElement(this._element);if(o){var r="UL"===o.nodeName||"OL"===o.nodeName?"> li > .active":".active";i=(i=e.makeArray(e(o).find(r)))[i.length-1]}var l=e.Event("hide.bs.tab",{relatedTarget:this._element}),c=e.Event("show.bs.tab",{relatedTarget:i});if(i&&e(i).trigger(l),e(this._element).trigger(c),!c.isDefaultPrevented()&&!l.isDefaultPrevented()){s&&(n=document.querySelector(s)),this._activate(this._element,o);var h=function(){var n=e.Event("hidden.bs.tab",{relatedTarget:t._element}),o=e.Event("shown.bs.tab",{relatedTarget:i});e(i).trigger(n),e(t._element).trigger(o)};n?this._activate(n,n.parentNode,h):h()}}},n.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},n._activate=function(t,n,i){var o=this,s=(!n||"UL"!==n.nodeName&&"OL"!==n.nodeName?e(n).children(".active"):e(n).find("> li > .active"))[0],r=i&&s&&e(s).hasClass("fade"),l=function(){return o._transitionComplete(t,s,i)};if(s&&r){var c=a.getTransitionDurationFromElement(s);e(s).removeClass("show").one(a.TRANSITION_END,l).emulateTransitionEnd(c)}else l()},n._transitionComplete=function(t,n,i){if(n){e(n).removeClass("active");var o=e(n.parentNode).find("> .dropdown-menu .active")[0];o&&e(o).removeClass("active"),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),a.reflow(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&e(t.parentNode).hasClass("dropdown-menu")){var s=e(t).closest(".dropdown")[0];if(s){var r=[].slice.call(s.querySelectorAll(".dropdown-toggle"));e(r).addClass("active")}t.setAttribute("aria-expanded",!0)}i&&i()},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.tab");if(o||(o=new t(this),i.data("bs.tab",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n]()}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}}]),t}();e(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),lt._jQueryInterface.call(e(this),"show")})),e.fn.tab=lt._jQueryInterface,e.fn.tab.Constructor=lt,e.fn.tab.noConflict=function(){return e.fn.tab=at,lt._jQueryInterface};var ct=e.fn.toast,ht={animation:"boolean",autohide:"boolean",delay:"number"},ut={animation:!0,autohide:!0,delay:500},dt=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var n=t.prototype;return n.show=function(){var t=this,n=e.Event("show.bs.toast");if(e(this._element).trigger(n),!n.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var i=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),e(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),a.reflow(this._element),this._element.classList.add("showing"),this._config.animation){var o=a.getTransitionDurationFromElement(this._element);e(this._element).one(a.TRANSITION_END,i).emulateTransitionEnd(o)}else i()}},n.hide=function(){if(this._element.classList.contains("show")){var t=e.Event("hide.bs.toast");e(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},n.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),e(this._element).off("click.dismiss.bs.toast"),e.removeData(this._element,"bs.toast"),this._element=null,this._config=null},n._getConfig=function(t){return t=s({},ut,e(this._element).data(),"object"==typeof t&&t?t:{}),a.typeCheckConfig("toast",t,this.constructor.DefaultType),t},n._setListeners=function(){var t=this;e(this._element).on("click.dismiss.bs.toast",'[data-dismiss="toast"]',(function(){return t.hide()}))},n._close=function(){var t=this,n=function(){t._element.classList.add("hide"),e(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var i=a.getTransitionDurationFromElement(this._element);e(this._element).one(a.TRANSITION_END,n).emulateTransitionEnd(i)}else n()},n._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(n){return this.each((function(){var i=e(this),o=i.data("bs.toast");if(o||(o=new t(this,"object"==typeof n&&n),i.data("bs.toast",o)),"string"==typeof n){if("undefined"==typeof o[n])throw new TypeError('No method named "'+n+'"');o[n](this)}}))},o(t,null,[{key:"VERSION",get:function(){return"4.5.2"}},{key:"DefaultType",get:function(){return ht}},{key:"Default",get:function(){return ut}}]),t}();e.fn.toast=dt._jQueryInterface,e.fn.toast.Constructor=dt,e.fn.toast.noConflict=function(){return e.fn.toast=ct,dt._jQueryInterface},t.Alert=h,t.Button=d,t.Carousel=b,t.Collapse=C,t.Dropdown=I,t.Modal=P,t.Popover=et,t.Scrollspy=rt,t.Tab=lt,t.Toast=dt,t.Tooltip=X,t.Util=a,Object.defineProperty(t,"__esModule",{value:!0})}));
7
  //# sourceMappingURL=bootstrap.min.js.map
resources/js/global-plugin.js CHANGED
@@ -38,21 +38,41 @@ var iCWP_WPSF_SecurityAdmin = new function () {
38
  };
39
  }();
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  var iCWP_WPSF_StandardAjax = new function () {
42
  this.send_ajax_req = function ( reqData ) {
43
  iCWP_WPSF_BodyOverlay.show();
44
 
45
- jQuery.post( ajaxurl, reqData,
46
- function ( oResponse ) {
 
 
 
 
 
47
 
48
  if ( typeof iCWP_WPSF_Toaster !== 'undefined' ) {
49
- iCWP_WPSF_Toaster.showMessage( oResponse.data.message, oResponse.success );
50
  }
51
  else {
52
- iCWP_WPSF_Growl.showMessage( oResponse.data.message, oResponse.success );
53
  }
54
 
55
- if ( oResponse.data.page_reload ) {
56
  setTimeout( function () {
57
  location.reload();
58
  }, 2000 );
@@ -61,9 +81,7 @@ var iCWP_WPSF_StandardAjax = new function () {
61
  iCWP_WPSF_BodyOverlay.hide();
62
  }
63
  }
64
- ).always( function () {
65
- }
66
- );
67
  };
68
  }();
69
 
@@ -305,8 +323,6 @@ var iCWP_WPSF_Growl = new function () {
305
  }, 4000 );
306
  };
307
 
308
- /**
309
- */
310
  var createDynDiv = function ( sClass ) {
311
  var $oDiv = jQuery( '<div />' ).appendTo( 'body' );
312
  $oDiv.attr( 'id', 'icwp-growl-notice' + Math.floor( (Math.random() * 100) + 1 ) );
38
  };
39
  }();
40
 
41
+ var iCWP_WPSF_ParseAjaxResponse = new function () {
42
+ this.parseIt = function ( raw ) {
43
+ let parsed = {};
44
+ try {
45
+ parsed = JSON.parse( raw );
46
+ }
47
+ catch ( e ) {
48
+ parsed = JSON.parse(
49
+ raw.substring( raw.indexOf( '{' ), raw.lastIndexOf( '}' ) + 1 )
50
+ );
51
+ }
52
+ return parsed;
53
+ };
54
+ }();
55
+
56
  var iCWP_WPSF_StandardAjax = new function () {
57
  this.send_ajax_req = function ( reqData ) {
58
  iCWP_WPSF_BodyOverlay.show();
59
 
60
+ jQuery.ajax( {
61
+ type: "POST",
62
+ url: ajaxurl,
63
+ data: reqData,
64
+ dataType: "text",
65
+ success: function ( raw ) {
66
+ let resp = iCWP_WPSF_ParseAjaxResponse.parseIt( raw );
67
 
68
  if ( typeof iCWP_WPSF_Toaster !== 'undefined' ) {
69
+ iCWP_WPSF_Toaster.showMessage( resp.data.message, resp.success );
70
  }
71
  else {
72
+ iCWP_WPSF_Growl.showMessage( resp.data.message, resp.success );
73
  }
74
 
75
+ if ( resp.data.page_reload ) {
76
  setTimeout( function () {
77
  location.reload();
78
  }, 2000 );
81
  iCWP_WPSF_BodyOverlay.hide();
82
  }
83
  }
84
+ } )
 
 
85
  };
86
  }();
87
 
323
  }, 4000 );
324
  };
325
 
 
 
326
  var createDynDiv = function ( sClass ) {
327
  var $oDiv = jQuery( '<div />' ).appendTo( 'body' );
328
  $oDiv.attr( 'id', 'icwp-growl-notice' + Math.floor( (Math.random() * 100) + 1 ) );
resources/js/plugin.js CHANGED
@@ -47,17 +47,23 @@ var iCWP_WPSF_OptionsPages = new function () {
47
  }();
48
 
49
  let iCWP_WPSF_OptsPageRender = new function () {
50
- this.renderForm = function ( aAjaxReqData ) {
51
  iCWP_WPSF_BodyOverlay.show();
52
- jQuery.post( ajaxurl, aAjaxReqData,
53
- function ( oResponse ) {
54
- jQuery( '#ColumnOptions .content-options' ).html( oResponse.data.html )
55
- .trigger( 'odp-optsrender' );
 
 
 
 
 
 
 
 
56
  }
57
- ).fail(
58
  function () {
59
- }
60
- ).always( function () {
61
  iCWP_WPSF_BodyOverlay.hide();
62
  }
63
  );
@@ -120,8 +126,6 @@ var iCWP_WPSF_OptionsFormSubmit = new function () {
120
  aAjaxReqParams = aParams;
121
  };
122
 
123
- /**
124
- */
125
  var submitOptionsForm = function ( event ) {
126
  iCWP_WPSF_BodyOverlay.show();
127
 
@@ -229,8 +233,6 @@ if ( typeof icwp_wpsf_vars_secadmin !== 'undefined' && icwp_wpsf_vars_secadmin.t
229
  var bWarningShown = false;
230
  var nIntervalTimeout = 500 * icwp_wpsf_vars_secadmin.timeleft;
231
 
232
- /**
233
- */
234
  var checkSecAdmin = function () {
235
 
236
  bCheckInPlace = false;
47
  }();
48
 
49
  let iCWP_WPSF_OptsPageRender = new function () {
50
+ this.renderForm = function ( reqData ) {
51
  iCWP_WPSF_BodyOverlay.show();
52
+ jQuery.ajax(
53
+ {
54
+ type: "POST",
55
+ url: ajaxurl,
56
+ data: reqData,
57
+ dataType: "text",
58
+ success: function ( rawResponse ) {
59
+ let response = iCWP_WPSF_ParseAjaxResponse.parseIt( rawResponse );
60
+ jQuery( '#ColumnOptions .content-options' )
61
+ .html( response.data.html )
62
+ .trigger( 'odp-optsrender' );
63
+ }
64
  }
65
+ ).always(
66
  function () {
 
 
67
  iCWP_WPSF_BodyOverlay.hide();
68
  }
69
  );
126
  aAjaxReqParams = aParams;
127
  };
128
 
 
 
129
  var submitOptionsForm = function ( event ) {
130
  iCWP_WPSF_BodyOverlay.show();
131
 
233
  var bWarningShown = false;
234
  var nIntervalTimeout = 500 * icwp_wpsf_vars_secadmin.timeleft;
235
 
 
 
236
  var checkSecAdmin = function () {
237
 
238
  bCheckInPlace = false;
src/config/feature-autoupdates.php CHANGED
@@ -150,9 +150,9 @@
150
  ],
151
  "link_info": "https://shsec.io/3x",
152
  "link_blog": "",
153
- "name": "WordPress Core Updates",
154
- "summary": "Decide how the WordPress Core will automatically update, if at all",
155
- "description": "At least automatically upgrading minor versions is recommended (and is the WordPress default)."
156
  },
157
  {
158
  "key": "enable_upgrade_notification_email",
150
  ],
151
  "link_info": "https://shsec.io/3x",
152
  "link_blog": "",
153
+ "name": "Auto Update Plugin",
154
+ "summary": "Always Automatically Update This Plugin",
155
+ "description": "Regardless of any other settings, automatically update the Shield plugin."
156
  },
157
  {
158
  "key": "enable_upgrade_notification_email",
src/config/feature-comments_filter.php CHANGED
@@ -8,7 +8,6 @@
8
  "show_module_options": true,
9
  "storage_key": "commentsfilter",
10
  "tagline": "Block comment SPAM and retain your privacy",
11
- "use_sessions": true,
12
  "show_central": true,
13
  "access_restricted": true,
14
  "premium": false,
8
  "show_module_options": true,
9
  "storage_key": "commentsfilter",
10
  "tagline": "Block comment SPAM and retain your privacy",
 
11
  "show_central": true,
12
  "access_restricted": true,
13
  "premium": false,
src/config/feature-hack_protect.php CHANGED
@@ -195,6 +195,10 @@
195
  {
196
  "value_key": "root_index",
197
  "text": "Root index.php"
 
 
 
 
198
  }
199
  ],
200
  "link_info": "https://shsec.io/h7",
195
  {
196
  "value_key": "root_index",
197
  "text": "Root index.php"
198
+ },
199
+ {
200
+ "value_key": "root_webconfig",
201
+ "text": "Root Web.Config"
202
  }
203
  ],
204
  "link_info": "https://shsec.io/h7",
src/config/feature-ips.php CHANGED
@@ -21,7 +21,7 @@
21
  "id": "visitor-whitelisted",
22
  "schedule": "conditions",
23
  "plugin_page_only": true,
24
- "per_user": true,
25
  "type": "info"
26
  }
27
  },
@@ -167,16 +167,16 @@
167
  "key": "user_auto_recover",
168
  "section": "section_auto_black_list",
169
  "premium": true,
170
- "default": "disabled",
171
- "type": "select",
172
  "value_options": [
173
- {
174
- "value_key": "disabled",
175
- "text": "Disabled"
176
- },
177
  {
178
  "value_key": "gasp",
179
  "text": "With Shield Bot Protection"
 
 
 
 
180
  }
181
  ],
182
  "link_info": "https://shsec.io/f8",
@@ -186,16 +186,16 @@
186
  "description": "Allow visitors blocked by the plugin to automatically unblock themselves."
187
  },
188
  {
189
- "key": "request_whitelist",
190
- "section": "section_auto_black_list",
191
- "premium": true,
192
- "default": [],
193
- "type": "array",
194
- "link_info": "https://shsec.io/gd",
195
- "link_blog": "",
196
- "name": "Request Path Whitelist",
197
- "summary": "Request Path Whitelist",
198
- "description": "Request Path Whitelist."
199
  },
200
  {
201
  "key": "text_loginfailed",
@@ -317,7 +317,6 @@
317
  "section": "section_logins",
318
  "default": "transgression-single",
319
  "type": "select",
320
- "default": "log",
321
  "value_options": [
322
  {
323
  "value_key": "disabled",
@@ -467,26 +466,30 @@
467
  "transferable": false,
468
  "type": "array",
469
  "default": []
 
 
 
 
 
 
 
470
  }
471
  ],
472
  "definitions": {
473
- "db_classes": {
474
  "ips": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\IPs\\Handler"
475
  },
476
  "ip_lists_table_name": "ip_lists",
477
- "ip_list_table_columns": [
478
- "id",
479
- "ip",
480
- "label",
481
- "list",
482
- "ip6",
483
- "is_range",
484
- "transgressions",
485
- "last_access_at",
486
- "blocked_at",
487
- "created_at",
488
- "deleted_at"
489
- ],
490
  "events": {
491
  "custom_offense": {
492
  "cat": 3,
21
  "id": "visitor-whitelisted",
22
  "schedule": "conditions",
23
  "plugin_page_only": true,
24
+ "per_user": true,
25
  "type": "info"
26
  }
27
  },
167
  "key": "user_auto_recover",
168
  "section": "section_auto_black_list",
169
  "premium": true,
170
+ "default": [],
171
+ "type": "multiple_select",
172
  "value_options": [
 
 
 
 
173
  {
174
  "value_key": "gasp",
175
  "text": "With Shield Bot Protection"
176
+ },
177
+ {
178
+ "value_key": "email",
179
+ "text": "Magic Email Links To Unblock Logged-In Users"
180
  }
181
  ],
182
  "link_info": "https://shsec.io/f8",
186
  "description": "Allow visitors blocked by the plugin to automatically unblock themselves."
187
  },
188
  {
189
+ "key": "request_whitelist",
190
+ "section": "section_auto_black_list",
191
+ "premium": true,
192
+ "default": [],
193
+ "type": "array",
194
+ "link_info": "https://shsec.io/gd",
195
+ "link_blog": "",
196
+ "name": "Request Path Whitelist",
197
+ "summary": "Request Path Whitelist",
198
+ "description": "Request Path Whitelist."
199
  },
200
  {
201
  "key": "text_loginfailed",
317
  "section": "section_logins",
318
  "default": "transgression-single",
319
  "type": "select",
 
320
  "value_options": [
321
  {
322
  "value_key": "disabled",
466
  "transferable": false,
467
  "type": "array",
468
  "default": []
469
+ },
470
+ {
471
+ "key": "autounblock_emailids",
472
+ "section": "section_non_ui",
473
+ "transferable": false,
474
+ "type": "array",
475
+ "default": []
476
  }
477
  ],
478
  "definitions": {
479
+ "db_classes": {
480
  "ips": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\IPs\\Handler"
481
  },
482
  "ip_lists_table_name": "ip_lists",
483
+ "ip_list_table_columns": {
484
+ "ip": "varchar(60) NOT NULL DEFAULT '' COMMENT 'Human readable IP address or range'",
485
+ "label": "varchar(255) NOT NULL DEFAULT ''",
486
+ "list": "varchar(4) NOT NULL DEFAULT ''",
487
+ "ip6": "tinyint(1) UNSIGNED NOT NULL DEFAULT 0",
488
+ "is_range": "tinyint(1) UNSIGNED NOT NULL DEFAULT 0",
489
+ "transgressions": "int(10) UNSIGNED NOT NULL DEFAULT 0",
490
+ "last_access_at": "int(15) UNSIGNED NOT NULL DEFAULT 0",
491
+ "blocked_at": "int(15) UNSIGNED NOT NULL DEFAULT 0"
492
+ },
 
 
 
493
  "events": {
494
  "custom_offense": {
495
  "cat": 3,
src/config/feature-lockdown.php CHANGED
@@ -131,26 +131,37 @@
131
  "description": "Please only enable this option if you have a valid SSL certificate installed. Equivalent to setting 'FORCE_SSL_ADMIN' to TRUE."
132
  },
133
  {
134
- "key": "hide_wordpress_generator_tag",
 
 
 
 
 
 
 
 
 
 
 
135
  "section": "section_wordpress_obscurity_options",
136
  "default": "N",
137
  "type": "checkbox",
138
  "link_info": "",
139
  "link_blog": "",
140
- "name": "WP Generator Tag",
141
- "summary": "Remove WP Generator Meta Tag",
142
- "description": "Remove a meta tag from your WordPress pages that publicly displays that your site is WordPress and its current version."
143
  },
144
  {
145
- "key": "block_author_discovery",
146
  "section": "section_wordpress_obscurity_options",
147
- "default": "Y",
148
  "type": "checkbox",
149
- "link_info": "https://shsec.io/wpsf23",
150
  "link_blog": "",
151
- "name": "Block Username Fishing",
152
- "summary": "Block the ability to discover WordPress usernames based on author IDs",
153
- "description": "When enabled, any URL requests containing 'author=' will be killed. Warning: Enabling this option may interfere with expected operations of your site."
154
  }
155
  ],
156
  "definitions": {
131
  "description": "Please only enable this option if you have a valid SSL certificate installed. Equivalent to setting 'FORCE_SSL_ADMIN' to TRUE."
132
  },
133
  {
134
+ "key": "block_author_discovery",
135
+ "section": "section_wordpress_obscurity_options",
136
+ "default": "Y",
137
+ "type": "checkbox",
138
+ "link_info": "https://shsec.io/wpsf23",
139
+ "link_blog": "",
140
+ "name": "Block Username Fishing",
141
+ "summary": "Block the ability to discover WordPress usernames based on author IDs",
142
+ "description": "When enabled, any URL requests containing 'author=' will be killed. Warning: Enabling this option may interfere with expected operations of your site."
143
+ },
144
+ {
145
+ "key": "clean_wp_rubbish",
146
  "section": "section_wordpress_obscurity_options",
147
  "default": "N",
148
  "type": "checkbox",
149
  "link_info": "",
150
  "link_blog": "",
151
+ "name": "Clean WP Files",
152
+ "summary": "Automatically Delete Unnecessary WP Files",
153
+ "description": "Automatically delete WordPress files like wp-config-sample.php."
154
  },
155
  {
156
+ "key": "hide_wordpress_generator_tag",
157
  "section": "section_wordpress_obscurity_options",
158
+ "default": "N",
159
  "type": "checkbox",
160
+ "link_info": "",
161
  "link_blog": "",
162
+ "name": "WP Generator Tag",
163
+ "summary": "Remove WP Generator Meta Tag",
164
+ "description": "Remove a meta tag from your WordPress pages that publicly displays that your site is WordPress and its current version."
165
  }
166
  ],
167
  "definitions": {
src/config/feature-login_protect.php CHANGED
@@ -370,8 +370,8 @@
370
  "premium": true,
371
  "default": "N",
372
  "type": "checkbox",
373
- "link_info": "https://shsec.io/dx",
374
- "link_blog": "https://shsec.io/dy",
375
  "name": "Allow U2F",
376
  "summary": "Allow Registration Of U2F Devices",
377
  "description": "Allow Registration Of U2F Devices."
370
  "premium": true,
371
  "default": "N",
372
  "type": "checkbox",
373
+ "link_info": "https://shsec.io/i9",
374
+ "link_blog": "",
375
  "name": "Allow U2F",
376
  "summary": "Allow Registration Of U2F Devices",
377
  "description": "Allow Registration Of U2F Devices."
src/config/feature-plugin.php CHANGED
@@ -34,6 +34,14 @@
34
  "can_dismiss": false,
35
  "type": "error"
36
  },
 
 
 
 
 
 
 
 
37
  "php7": {
38
  "id": "php7",
39
  "schedule": "conditions",
@@ -62,10 +70,6 @@
62
  "type": "promo",
63
  "drip_form_id": "250437573"
64
  },
65
- "plugin-update-available": {
66
- "id": "plugin-update-available",
67
- "type": "warning"
68
- },
69
  "allow-tracking": {
70
  "id": "allow-tracking",
71
  "plugin_admin": true,
34
  "can_dismiss": false,
35
  "type": "error"
36
  },
37
+ "update-available": {
38
+ "id": "update-available",
39
+ "schedule": "conditions",
40
+ "valid_admin": true,
41
+ "plugin_page_only": true,
42
+ "can_dismiss": false,
43
+ "type": "error"
44
+ },
45
  "php7": {
46
  "id": "php7",
47
  "schedule": "conditions",
70
  "type": "promo",
71
  "drip_form_id": "250437573"
72
  },
 
 
 
 
73
  "allow-tracking": {
74
  "id": "allow-tracking",
75
  "plugin_admin": true,
src/features/admin_access_restriction.php CHANGED
@@ -13,8 +13,6 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
13
  */
14
  private $bValidSecAdminRequest;
15
 
16
- /**
17
- */
18
  protected function setupCustomHooks() {
19
  parent::setupCustomHooks();
20
  add_action( $this->prefix( 'pre_deactivate_plugin' ), [ $this, 'preDeactivatePlugin' ] );
@@ -30,32 +28,29 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
30
 
31
  /**
32
  * @return array
33
- * @deprecated 9.1.0
34
  */
35
  public function getSecurityAdminUsers() {
36
  $aU = $this->getOpt( 'sec_admin_users', [] );
37
  return ( is_array( $aU ) && $this->isPremium() ) ? $aU : [];
38
  }
39
 
40
- /**
41
- * @return bool
42
- * @deprecated 9.1.0
43
- */
44
- public function hasSecAdminUsers() {
45
- return count( $this->getSecurityAdminUsers() ) > 0;
46
- }
47
-
48
  /**
49
  * No checking of admin capabilities in-case of infinite loop with
50
  * admin access caps check
51
  * @return bool
52
  */
53
  public function isRegisteredSecAdminUser() {
 
 
54
  $sUser = Services::WpUsers()->getCurrentWpUsername();
55
- return !empty( $sUser ) && in_array( $sUser, $this->getSecurityAdminUsers() );
56
  }
57
 
58
  protected function preProcessOptions() {
 
 
 
59
  if ( $this->isValidSecAdminRequest() ) {
60
  $this->setSecurityAdminStatusOnOff( true );
61
  }
@@ -75,7 +70,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
75
  }
76
  }
77
 
78
- $this->setOpt( 'sec_admin_users', $this->verifySecAdminUsers( $this->getSecurityAdminUsers() ) );
79
  }
80
 
81
  /**
@@ -86,8 +81,8 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
86
  private function verifySecAdminUsers( $aSecUsers ) {
87
  $oDP = Services::Data();
88
  $oWpUsers = Services::WpUsers();
89
- /** @var SecurityAdmin\Options $oOpts */
90
- $oOpts = $this->getOptions();
91
 
92
  $aFiltered = [];
93
  foreach ( $aSecUsers as $nCurrentKey => $sUsernameOrEmail ) {
@@ -109,7 +104,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
109
  // We now run a bit of a sanity check to ensure that the current user is
110
  // not adding users here that aren't themselves without a key to still gain access
111
  $oCurrent = $oWpUsers->getCurrentWpUser();
112
- if ( !empty( $aFiltered ) && !$oOpts->hasAccessKey() && !in_array( $oCurrent->user_login, $aFiltered ) ) {
113
  $aFiltered[] = $oCurrent->user_login;
114
  }
115
 
@@ -169,11 +164,11 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
169
  * @return bool
170
  */
171
  public function isEnabledSecurityAdmin() {
172
- /** @var SecurityAdmin\Options $oOpts */
173
- $oOpts = $this->getOptions();
174
  return $this->isModOptEnabled() &&
175
- ( count( $oOpts->getSecurityAdminUsers() ) > 0 ||
176
- ( $oOpts->hasAccessKey() && $this->getSecAdminTimeout() > 0 )
177
  );
178
  }
179
 
@@ -204,14 +199,14 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
204
  $bValid = false;
205
  $sReqKey = Services::Request()->post( 'sec_admin_key' );
206
  if ( !empty( $sReqKey ) ) {
207
- /** @var SecurityAdmin\Options $oOpts */
208
- $oOpts = $this->getOptions();
209
- $bValid = hash_equals( $oOpts->getAccessKeyHash(), md5( $sReqKey ) );
210
  if ( !$bValid ) {
211
  $sEscaped = isset( $_POST[ 'sec_admin_key' ] ) ? $_POST[ 'sec_admin_key' ] : '';
212
  if ( !empty( $sEscaped ) ) {
213
  // Workaround for escaping of passwords
214
- $bValid = hash_equals( $oOpts->getAccessKeyHash(), md5( $sEscaped ) );
215
  if ( $bValid ) {
216
  $this->setOpt( 'admin_access_key', md5( $sReqKey ) );
217
  }
@@ -234,13 +229,13 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
234
  }
235
 
236
  /**
237
- * @param string $sKey
238
  * @return bool
239
  */
240
- public function verifyAccessKey( $sKey ) {
241
- /** @var SecurityAdmin\Options $oOpts */
242
- $oOpts = $this->getOptions();
243
- return !empty( $sKey ) && hash_equals( $oOpts->getAccessKeyHash(), md5( $sKey ) );
244
  }
245
 
246
  /**
@@ -292,31 +287,13 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
292
  return $sLogoUrl;
293
  }
294
 
295
- /**
296
- * @param string $sSection
297
- * @return array
298
- */
299
- protected function getSectionWarnings( $sSection ) {
300
- $aWarnings = [];
301
-
302
- switch ( $sSection ) {
303
- case 'section_whitelabel':
304
- if ( !$this->isEnabledSecurityAdmin() ) {
305
- $aWarnings[] = __( 'Please also supply a Security Admin PIN, as whitelabel settings are only applied when the Security Admin feature is active.', 'wp-simple-firewall' );
306
- }
307
- break;
308
- }
309
-
310
- return $aWarnings;
311
- }
312
-
313
  /**
314
  * @return bool
315
  */
316
  public function isWlEnabled() {
317
- /** @var SecurityAdmin\Options $oOpts */
318
- $oOpts = $this->getOptions();
319
- return $oOpts->isEnabledWhitelabel() && $this->isPremium();
320
  }
321
 
322
  /**
@@ -381,120 +358,22 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
381
  }
382
  }
383
 
384
- /**
385
- * @param array $aAllData
386
- * @return array
387
- */
388
- public function addInsightsConfigData( $aAllData ) {
389
- /** @var SecurityAdmin\Options $oOpts */
390
- $oOpts = $this->getOptions();
391
-
392
- $aThis = [
393
- 'strings' => [
394
- 'title' => __( 'Security Admin', 'wp-simple-firewall' ),
395
- 'sub' => sprintf( __( 'Prevent Tampering With %s Settings', 'wp-simple-firewall' ), $this->getCon()
396
- ->getHumanName() ),
397
- ],
398
- 'key_opts' => [],
399
- 'href_options' => $this->getUrl_AdminPage()
400
- ];
401
-
402
- if ( !$this->isEnabledForUiSummary() ) {
403
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
404
- }
405
- else {
406
- $aThis[ 'key_opts' ][ 'mod' ] = [
407
- 'name' => __( 'Security Admin', 'wp-simple-firewall' ),
408
- 'enabled' => $this->isEnabledForUiSummary(),
409
- 'summary' => $this->isEnabledForUiSummary() ?
410
- __( 'Security plugin is protected against tampering', 'wp-simple-firewall' )
411
- : __( 'Security plugin is vulnerable to tampering', 'wp-simple-firewall' ),
412
- 'weight' => 2,
413
- 'href' => $this->getUrl_DirectLinkToOption( 'admin_access_key' ),
414
- ];
415
-
416
- $bWpOpts = $oOpts->getAdminAccessArea_Options();
417
- $aThis[ 'key_opts' ][ 'wpopts' ] = [
418
- 'name' => __( 'Important Options', 'wp-simple-firewall' ),
419
- 'enabled' => $bWpOpts,
420
- 'summary' => $bWpOpts ?
421
- __( 'Important WP options are protected against tampering', 'wp-simple-firewall' )
422
- : __( "Important WP options aren't protected against tampering", 'wp-simple-firewall' ),
423
- 'weight' => 2,
424
- 'href' => $this->getUrl_DirectLinkToOption( 'admin_access_restrict_options' ),
425
- ];
426
-
427
- $bUsers = $oOpts->isSecAdminRestrictUsersEnabled();
428
- $aThis[ 'key_opts' ][ 'adminusers' ] = [
429
- 'name' => __( 'WP Admins', 'wp-simple-firewall' ),
430
- 'enabled' => $bUsers,
431
- 'summary' => $bUsers ?
432
- __( 'Admin users are protected against tampering', 'wp-simple-firewall' )
433
- : __( "Admin users aren't protected against tampering", 'wp-simple-firewall' ),
434
- 'weight' => 1,
435
- 'href' => $this->getUrl_DirectLinkToOption( 'admin_access_restrict_admin_users' ),
436
- ];
437
- }
438
-
439
- $aAllData[ $this->getSlug() ] = $aThis;
440
- return $aAllData;
441
- }
442
-
443
- /**
444
- * @param array $aAllNotices
445
- * @return array
446
- */
447
- public function addInsightsNoticeData( $aAllNotices ) {
448
-
449
- $aNotices = [
450
- 'title' => __( 'Security Admin Protection', 'wp-simple-firewall' ),
451
- 'messages' => []
452
- ];
453
-
454
- {//sec admin
455
- if ( !$this->isEnabledSecurityAdmin() ) {
456
- $aNotices[ 'messages' ][ 'sec_admin' ] = [
457
- 'title' => __( 'Security Plugin Unprotected', 'wp-simple-firewall' ),
458
- 'message' => sprintf(
459
- __( "The Security Admin protection is not active.", 'wp-simple-firewall' ),
460
- $this->getCon()->getHumanName()
461
- ),
462
- 'href' => $this->getUrl_AdminPage(),
463
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options' ) ),
464
- 'rec' => __( 'Security Admin should be turned-on to protect your security settings.', 'wp-simple-firewall' )
465
- ];
466
- }
467
- }
468
-
469
- $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
470
- $aAllNotices[ 'sec_admin' ] = $aNotices;
471
-
472
- return $aAllNotices;
473
- }
474
-
475
- /**
476
- * @return bool
477
- */
478
- protected function isEnabledForUiSummary() {
479
- return parent::isEnabledForUiSummary() && $this->isEnabledSecurityAdmin();
480
- }
481
-
482
  /**
483
  * This is the point where you would want to do any options verification
484
  */
485
  protected function doPrePluginOptionsSave() {
486
- /** @var SecurityAdmin\Options $oOpts */
487
- $oOpts = $this->getOptions();
488
 
489
- if ( hash_equals( $oOpts->getAccessKeyHash(), self::HASH_DELETE ) ) {
490
- $oOpts->clearSecurityAdminKey();
491
  $this->setSecurityAdminStatusOnOff( false );
492
  }
493
 
494
  // Restricting Activate Plugins also means restricting the rest.
495
- $aPluginsRestrictions = $oOpts->getAdminAccessArea_Plugins();
496
  if ( in_array( 'activate_plugins', $aPluginsRestrictions ) ) {
497
- $oOpts->setOpt(
498
  'admin_access_restrict_plugins',
499
  array_unique( array_merge( $aPluginsRestrictions, [
500
  'install_plugins',
@@ -505,9 +384,9 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
505
  }
506
 
507
  // Restricting Switch (Activate) Themes also means restricting the rest.
508
- $aThemesRestrictions = $oOpts->getAdminAccessArea_Themes();
509
  if ( in_array( 'switch_themes', $aThemesRestrictions ) && in_array( 'edit_theme_options', $aThemesRestrictions ) ) {
510
- $oOpts->setOpt(
511
  'admin_access_restrict_themes',
512
  array_unique( array_merge( $aThemesRestrictions, [
513
  'install_themes',
@@ -517,17 +396,15 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
517
  );
518
  }
519
 
520
- $aPostRestrictions = $oOpts->getAdminAccessArea_Posts();
521
  if ( in_array( 'edit', $aPostRestrictions ) ) {
522
- $oOpts->setOpt(
523
  'admin_access_restrict_posts',
524
  array_unique( array_merge( $aPostRestrictions, [ 'create', 'publish', 'delete' ] ) )
525
  );
526
  }
527
  }
528
 
529
- /**
530
- */
531
  public function preDeactivatePlugin() {
532
  if ( !$this->getCon()->isPluginAdmin() ) {
533
  Services::WpGeneral()->wpDie(
13
  */
14
  private $bValidSecAdminRequest;
15
 
 
 
16
  protected function setupCustomHooks() {
17
  parent::setupCustomHooks();
18
  add_action( $this->prefix( 'pre_deactivate_plugin' ), [ $this, 'preDeactivatePlugin' ] );
28
 
29
  /**
30
  * @return array
31
+ * @deprecated 9.2.0
32
  */
33
  public function getSecurityAdminUsers() {
34
  $aU = $this->getOpt( 'sec_admin_users', [] );
35
  return ( is_array( $aU ) && $this->isPremium() ) ? $aU : [];
36
  }
37
 
 
 
 
 
 
 
 
 
38
  /**
39
  * No checking of admin capabilities in-case of infinite loop with
40
  * admin access caps check
41
  * @return bool
42
  */
43
  public function isRegisteredSecAdminUser() {
44
+ /** @var SecurityAdmin\Options $opts */
45
+ $opts = $this->getOptions();
46
  $sUser = Services::WpUsers()->getCurrentWpUsername();
47
+ return !empty( $sUser ) && in_array( $sUser, $opts->getSecurityAdminUsers() );
48
  }
49
 
50
  protected function preProcessOptions() {
51
+ /** @var SecurityAdmin\Options $opts */
52
+ $opts = $this->getOptions();
53
+
54
  if ( $this->isValidSecAdminRequest() ) {
55
  $this->setSecurityAdminStatusOnOff( true );
56
  }
70
  }
71
  }
72
 
73
+ $this->setOpt( 'sec_admin_users', $this->verifySecAdminUsers( $opts->getSecurityAdminUsers() ) );
74
  }
75
 
76
  /**
81
  private function verifySecAdminUsers( $aSecUsers ) {
82
  $oDP = Services::Data();
83
  $oWpUsers = Services::WpUsers();
84
+ /** @var SecurityAdmin\Options $opts */
85
+ $opts = $this->getOptions();
86
 
87
  $aFiltered = [];
88
  foreach ( $aSecUsers as $nCurrentKey => $sUsernameOrEmail ) {
104
  // We now run a bit of a sanity check to ensure that the current user is
105
  // not adding users here that aren't themselves without a key to still gain access
106
  $oCurrent = $oWpUsers->getCurrentWpUser();
107
+ if ( !empty( $aFiltered ) && !$opts->hasSecurityPIN() && !in_array( $oCurrent->user_login, $aFiltered ) ) {
108
  $aFiltered[] = $oCurrent->user_login;
109
  }
110
 
164
  * @return bool
165
  */
166
  public function isEnabledSecurityAdmin() {
167
+ /** @var SecurityAdmin\Options $opts */
168
+ $opts = $this->getOptions();
169
  return $this->isModOptEnabled() &&
170
+ ( count( $opts->getSecurityAdminUsers() ) > 0 ||
171
+ ( $opts->hasSecurityPIN() && $this->getSecAdminTimeout() > 0 )
172
  );
173
  }
174
 
199
  $bValid = false;
200
  $sReqKey = Services::Request()->post( 'sec_admin_key' );
201
  if ( !empty( $sReqKey ) ) {
202
+ /** @var SecurityAdmin\Options $opts */
203
+ $opts = $this->getOptions();
204
+ $bValid = hash_equals( $opts->getSecurityPIN(), md5( $sReqKey ) );
205
  if ( !$bValid ) {
206
  $sEscaped = isset( $_POST[ 'sec_admin_key' ] ) ? $_POST[ 'sec_admin_key' ] : '';
207
  if ( !empty( $sEscaped ) ) {
208
  // Workaround for escaping of passwords
209
+ $bValid = hash_equals( $opts->getSecurityPIN(), md5( $sEscaped ) );
210
  if ( $bValid ) {
211
  $this->setOpt( 'admin_access_key', md5( $sReqKey ) );
212
  }
229
  }
230
 
231
  /**
232
+ * @param string $key
233
  * @return bool
234
  */
235
+ public function verifyAccessKey( $key ) {
236
+ /** @var SecurityAdmin\Options $opts */
237
+ $opts = $this->getOptions();
238
+ return !empty( $key ) && hash_equals( $opts->getSecurityPIN(), md5( $key ) );
239
  }
240
 
241
  /**
287
  return $sLogoUrl;
288
  }
289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  /**
291
  * @return bool
292
  */
293
  public function isWlEnabled() {
294
+ /** @var SecurityAdmin\Options $opts */
295
+ $opts = $this->getOptions();
296
+ return $opts->isEnabledWhitelabel() && $this->isPremium();
297
  }
298
 
299
  /**
358
  }
359
  }
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  /**
362
  * This is the point where you would want to do any options verification
363
  */
364
  protected function doPrePluginOptionsSave() {
365
+ /** @var SecurityAdmin\Options $opts */
366
+ $opts = $this->getOptions();
367
 
368
+ if ( hash_equals( $opts->getSecurityPIN(), self::HASH_DELETE ) ) {
369
+ $opts->clearSecurityAdminKey();
370
  $this->setSecurityAdminStatusOnOff( false );
371
  }
372
 
373
  // Restricting Activate Plugins also means restricting the rest.
374
+ $aPluginsRestrictions = $opts->getAdminAccessArea_Plugins();
375
  if ( in_array( 'activate_plugins', $aPluginsRestrictions ) ) {
376
+ $opts->setOpt(
377
  'admin_access_restrict_plugins',
378
  array_unique( array_merge( $aPluginsRestrictions, [
379
  'install_plugins',
384
  }
385
 
386
  // Restricting Switch (Activate) Themes also means restricting the rest.
387
+ $aThemesRestrictions = $opts->getAdminAccessArea_Themes();
388
  if ( in_array( 'switch_themes', $aThemesRestrictions ) && in_array( 'edit_theme_options', $aThemesRestrictions ) ) {
389
+ $opts->setOpt(
390
  'admin_access_restrict_themes',
391
  array_unique( array_merge( $aThemesRestrictions, [
392
  'install_themes',
396
  );
397
  }
398
 
399
+ $aPostRestrictions = $opts->getAdminAccessArea_Posts();
400
  if ( in_array( 'edit', $aPostRestrictions ) ) {
401
+ $opts->setOpt(
402
  'admin_access_restrict_posts',
403
  array_unique( array_merge( $aPostRestrictions, [ 'create', 'publish', 'delete' ] ) )
404
  );
405
  }
406
  }
407
 
 
 
408
  public function preDeactivatePlugin() {
409
  if ( !$this->getCon()->isPluginAdmin() ) {
410
  Services::WpGeneral()->wpDie(
src/features/audit_trail.php CHANGED
@@ -1,7 +1,6 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
4
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail;
5
  use FernleafSystems\Wordpress\Services\Services;
6
 
7
  class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseWpsf {
@@ -107,78 +106,6 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
107
  return $aData;
108
  }
109
 
110
- /**
111
- * @param array $aAllData
112
- * @return array
113
- */
114
- public function addInsightsConfigData( $aAllData ) {
115
- /** @var AuditTrail\Options $oOpts */
116
- $oOpts = $this->getOptions();
117
-
118
- $aThis = [
119
- 'strings' => [
120
- 'title' => __( 'Activity Audit Log', 'wp-simple-firewall' ),
121
- 'sub' => __( 'Track Activity: What, Who, When, Where', 'wp-simple-firewall' ),
122
- ],
123
- 'key_opts' => [],
124
- 'href_options' => $this->getUrl_AdminPage()
125
- ];
126
-
127
- if ( !$this->isModOptEnabled() ) {
128
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
129
- }
130
- else {
131
- $aAudit = [];
132
- $aNonAudit = [];
133
- $oOpts->isAuditShield() ? $aAudit[] = 'Shield' : $aNonAudit[] = 'Shield';
134
- $oOpts->isAuditUsers() ? $aAudit[] = __( 'users', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'users', 'wp-simple-firewall' );
135
- $oOpts->isAuditPlugins() ? $aAudit[] = __( 'plugins', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'plugins', 'wp-simple-firewall' );
136
- $oOpts->isAuditThemes() ? $aAudit[] = __( 'themes', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'themes', 'wp-simple-firewall' );
137
- $oOpts->isAuditPosts() ? $aAudit[] = __( 'posts', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'posts', 'wp-simple-firewall' );
138
- $oOpts->isAuditEmails() ? $aAudit[] = __( 'emails', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'emails', 'wp-simple-firewall' );
139
- $oOpts->isAuditWp() ? $aAudit[] = 'WP' : $aNonAudit[] = 'WP';
140
-
141
- if ( empty( $aNonAudit ) ) {
142
- $aThis[ 'key_opts' ][ 'audit' ] = [
143
- 'name' => __( 'Audit Areas', 'wp-simple-firewall' ),
144
- 'enabled' => true,
145
- 'summary' => __( 'All important events on your site are being logged', 'wp-simple-firewall' ),
146
- 'weight' => 2,
147
- 'href' => $this->getUrl_DirectLinkToSection( 'section_enable_audit_contexts' ),
148
- ];
149
- }
150
- elseif ( empty( $aAudit ) ) {
151
- $aThis[ 'key_opts' ][ 'audit' ] = [
152
- 'name' => __( 'Audit Areas', 'wp-simple-firewall' ),
153
- 'enabled' => false,
154
- 'summary' => sprintf( __( 'No areas are set to be audited: %s', 'wp-simple-firewall' ), implode( ', ', $aAudit ) ),
155
- 'weight' => 2,
156
- 'href' => $this->getUrl_DirectLinkToSection( 'section_enable_audit_contexts' ),
157
- ];
158
- }
159
- else {
160
- $aThis[ 'key_opts' ][ 'nonaudit' ] = [
161
- 'name' => __( 'Audit Events', 'wp-simple-firewall' ),
162
- 'enabled' => false,
163
- 'summary' => sprintf( __( "Important events aren't being audited: %s", 'wp-simple-firewall' ), implode( ', ', $aNonAudit ) ),
164
- 'weight' => 2,
165
- 'href' => $this->getUrl_DirectLinkToSection( 'section_enable_audit_contexts' ),
166
- ];
167
- }
168
-
169
- $aThis[ 'key_opts' ][ 'length' ] = [
170
- 'name' => __( 'Audit Trail', 'wp-simple-firewall' ),
171
- 'enabled' => true,
172
- 'summary' => sprintf( __( 'Maximum Audit Trail entries limited to %s', 'wp-simple-firewall' ), $oOpts->getMaxEntries() ),
173
- 'weight' => 0,
174
- 'href' => $this->getUrl_DirectLinkToOption( 'audit_trail_max_entries' ),
175
- ];
176
- }
177
-
178
- $aAllData[ $this->getSlug() ] = $aThis;
179
- return $aAllData;
180
- }
181
-
182
  /**
183
  * @return string
184
  */
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
 
4
  use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseWpsf {
106
  return $aData;
107
  }
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  /**
110
  * @return string
111
  */
src/features/autoupdates.php CHANGED
@@ -1,121 +1,9 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
4
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Autoupdates;
5
- use FernleafSystems\Wordpress\Services\Services;
6
 
7
  class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_BaseWpsf {
8
 
9
- /**
10
- * @param array $aAllNotices
11
- * @return array
12
- */
13
- public function addInsightsNoticeData( $aAllNotices ) {
14
- /** @var Autoupdates\Options $oOpts */
15
- $oOpts = $this->getOptions();
16
-
17
- $aNotices = [
18
- 'title' => __( 'Automatic Updates', 'wp-simple-firewall' ),
19
- 'messages' => []
20
- ];
21
- { //really disabled?
22
- $oWp = Services::WpGeneral();
23
- if ( $this->isModOptEnabled() ) {
24
- if ( $oOpts->isDisableAllAutoUpdates() && !$oWp->getWpAutomaticUpdater()->is_disabled() ) {
25
- $aNotices[ 'messages' ][ 'disabled_auto' ] = [
26
- 'title' => 'Auto Updates Not Really Disabled',
27
- 'message' => __( 'Automatic Updates Are Not Disabled As Expected.', 'wp-simple-firewall' ),
28
- 'href' => $this->getUrl_DirectLinkToOption( 'enable_autoupdate_disable_all' ),
29
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
30
- 'rec' => sprintf( __( 'A plugin/theme other than %s is affecting your automatic update settings.', 'wp-simple-firewall' ), $this->getCon()
31
- ->getHumanName() )
32
- ];
33
- }
34
- }
35
- }
36
-
37
- $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
38
-
39
- $aAllNotices[ 'autoupdates' ] = $aNotices;
40
- return $aAllNotices;
41
- }
42
-
43
- /**
44
- * @param array $aAllData
45
- * @return array
46
- */
47
- public function addInsightsConfigData( $aAllData ) {
48
- /** @var Autoupdates\Options $oOpts */
49
- $oOpts = $this->getOptions();
50
-
51
- $aThis = [
52
- 'strings' => [
53
- 'title' => __( 'Automatic Updates', 'wp-simple-firewall' ),
54
- 'sub' => __( 'Control WordPress Automatic Updates', 'wp-simple-firewall' ),
55
- ],
56
- 'key_opts' => [],
57
- 'href_options' => $this->getUrl_AdminPage()
58
- ];
59
-
60
- if ( !$this->isModOptEnabled() ) {
61
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
62
- }
63
- else {
64
-
65
- $bAllDisabled = $oOpts->isDisableAllAutoUpdates();
66
- if ( $bAllDisabled ) {
67
- $aThis[ 'key_opts' ][ 'disabled' ] = [
68
- 'name' => __( 'Disabled All', 'wp-simple-firewall' ),
69
- 'enabled' => !$bAllDisabled,
70
- 'summary' => $bAllDisabled ?
71
- __( 'All automatic updates on this site are disabled', 'wp-simple-firewall' )
72
- : __( 'The automatic updates system is enabled', 'wp-simple-firewall' ),
73
- 'weight' => 2,
74
- 'href' => $this->getUrl_DirectLinkToOption( 'enable_autoupdate_disable_all' ),
75
- ];
76
- }
77
- else {
78
- $bCanCore = Services::WpGeneral()->canCoreUpdateAutomatically();
79
- $aThis[ 'key_opts' ][ 'core_minor' ] = [
80
- 'name' => __( 'Core Updates', 'wp-simple-firewall' ),
81
- 'enabled' => $bCanCore,
82
- 'summary' => $bCanCore ?
83
- __( 'Minor WP Core updates will be installed automatically', 'wp-simple-firewall' )
84
- : __( 'Minor WP Core updates will not be installed automatically', 'wp-simple-firewall' ),
85
- 'weight' => 2,
86
- 'href' => $this->getUrl_DirectLinkToOption( 'autoupdate_core' ),
87
- ];
88
-
89
- $bHasDelay = $this->isModOptEnabled() && $oOpts->getDelayUpdatesPeriod();
90
- $aThis[ 'key_opts' ][ 'delay' ] = [
91
- 'name' => __( 'Update Delay', 'wp-simple-firewall' ),
92
- 'enabled' => $bHasDelay,
93
- 'summary' => $bHasDelay ?
94
- __( 'Automatic updates are applied after a short delay', 'wp-simple-firewall' )
95
- : __( 'Automatic updates are applied immediately', 'wp-simple-firewall' ),
96
- 'weight' => 1,
97
- 'href' => $this->getUrl_DirectLinkToOption( 'update_delay' ),
98
- ];
99
-
100
- $sName = $this->getCon()->getHumanName();
101
- $bSelfAuto = $this->isModOptEnabled()
102
- && in_array( $oOpts->getSelfAutoUpdateOpt(), [ 'auto', 'immediate' ] );
103
- $aThis[ 'key_opts' ][ 'self' ] = [
104
- 'name' => __( 'Self Auto-Update', 'wp-simple-firewall' ),
105
- 'enabled' => $bSelfAuto,
106
- 'summary' => $bSelfAuto ?
107
- sprintf( __( '%s is automatically updated', 'wp-simple-firewall' ), $sName )
108
- : sprintf( __( "%s isn't automatically updated", 'wp-simple-firewall' ), $sName ),
109
- 'weight' => 1,
110
- 'href' => $this->getUrl_DirectLinkToOption( 'autoupdate_plugin_self' ),
111
- ];
112
- }
113
- }
114
-
115
- $aAllData[ $this->getSlug() ] = $aThis;
116
- return $aAllData;
117
- }
118
-
119
  /**
120
  * @return string
121
  */
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
 
 
4
 
5
  class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_BaseWpsf {
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  /**
8
  * @return string
9
  */
src/features/base.php CHANGED
@@ -50,6 +50,11 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
50
  */
51
  private $oStrings;
52
 
 
 
 
 
 
53
  /**
54
  * @var Shield\Modules\Base\Options
55
  */
@@ -96,33 +101,29 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
96
  * @param array $aModProps
97
  */
98
  protected function setupHooks( $aModProps ) {
99
- $oCon = $this->getCon();
100
  $nRunPriority = isset( $aModProps[ 'load_priority' ] ) ? $aModProps[ 'load_priority' ] : 100;
101
 
102
- add_action( $oCon->prefix( 'modules_loaded' ), function () {
103
  $this->onModulesLoaded();
104
  }, $nRunPriority );
105
- add_action( $oCon->prefix( 'run_processors' ), [ $this, 'onRunProcessors' ], $nRunPriority );
106
  add_action( 'init', [ $this, 'onWpInit' ], 1 );
107
 
108
  $nMenuPri = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
109
- add_filter( $oCon->prefix( 'submenu_items' ), [ $this, 'supplySubMenuItem' ], $nMenuPri );
110
- add_filter( $oCon->prefix( 'admin_bar_menu_items' ), [ $this, 'addAdminMenuBarItems' ], $nMenuPri );
111
- add_filter( $oCon->prefix( 'collect_mod_summary' ), [ $this, 'addModuleSummaryData' ], $nMenuPri );
112
- add_filter( $oCon->prefix( 'collect_notices' ), [ $this, 'addInsightsNoticeData' ] );
113
- add_filter( $oCon->prefix( 'collect_summary' ), [ $this, 'addInsightsConfigData' ], $nRunPriority );
114
- add_action( $oCon->prefix( 'plugin_shutdown' ), [ $this, 'onPluginShutdown' ] );
115
- add_action( $oCon->prefix( 'deactivate_plugin' ), [ $this, 'onPluginDeactivate' ] );
116
- add_action( $oCon->prefix( 'delete_plugin' ), [ $this, 'onPluginDelete' ] );
117
- add_filter( $oCon->prefix( 'aggregate_all_plugin_options' ), [ $this, 'aggregateOptionsValues' ] );
118
 
119
- add_filter( $oCon->prefix( 'register_admin_notices' ), [ $this, 'fRegisterAdminNotices' ] );
120
 
121
- add_action( $oCon->prefix( 'daily_cron' ), [ $this, 'runDailyCron' ] );
122
- add_action( $oCon->prefix( 'hourly_cron' ), [ $this, 'runHourlyCron' ] );
123
 
124
  // supply supported events for this module
125
- add_filter( $oCon->prefix( 'get_all_events' ), function ( $aEvents ) {
126
  return array_merge(
127
  is_array( $aEvents ) ? $aEvents : [],
128
  array_map(
@@ -217,8 +218,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
217
  * @return string[]
218
  */
219
  private function getAllDbClasses() {
220
- $aCls = $this->getOptions()->getDef( 'db_classes' );
221
- return is_array( $aCls ) ? $aCls : [];
222
  }
223
 
224
  /**
@@ -331,11 +332,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
331
  $this->getProcessor()->execute();
332
  }
333
 
334
- /**
335
- * A action added to WordPress 'init' hook
336
- */
337
  public function onWpInit() {
338
- $oReq = Services::Request();
339
 
340
  $sShieldAction = $this->getCon()->getShieldAction();
341
  if ( !empty( $sShieldAction ) ) {
@@ -360,7 +357,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
360
  else {
361
  try {
362
  if ( $this->verifyModActionRequest() ) {
363
- $this->handleModAction( $oReq->request( 'exec' ) );
364
  }
365
  }
366
  catch ( \Exception $oE ) {
@@ -496,14 +493,14 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
496
  * @return array
497
  */
498
  protected function getModActionParams( $sAction ) {
499
- $oCon = $this->getCon();
500
  return [
501
- 'action' => $oCon->prefix(),
502
  'exec' => $sAction,
503
  'mod_slug' => $this->getModSlug(),
504
  'ts' => Services::Request()->ts(),
505
  'exec_nonce' => substr(
506
- hash_hmac( 'md5', $sAction.Services::Request()->ts(), $oCon->getSiteInstallationId() )
507
  , 0, 6 )
508
  ];
509
  }
@@ -593,7 +590,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
593
  * @return bool
594
  */
595
  public function isModuleEnabled() {
596
- $oOpts = $this->getOptions();
597
  /** @var Shield\Modules\Plugin\Options $oPluginOpts */
598
  $oPluginOpts = $this->getCon()->getModule_Plugin()->getOptions();
599
 
@@ -607,7 +603,8 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
607
  elseif ( $this->getCon()->getIfForceOffActive() ) {
608
  $bEnabled = false;
609
  }
610
- elseif ( $oOpts->getFeatureProperty( 'premium' ) === true && !$this->isPremium() ) {
 
611
  $bEnabled = false;
612
  }
613
  else {
@@ -628,7 +625,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
628
  /**
629
  * @return string
630
  */
631
- protected function getEnableModOptKey() {
632
  return 'enable_'.$this->getSlug();
633
  }
634
 
@@ -660,7 +657,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
660
  /**
661
  * @param array $aItems
662
  * @return array
663
- * @deprecated 9.0.4
664
  */
665
  public function addAdminMenuBarItems( array $aItems ) {
666
  return $aItems;
@@ -740,38 +737,33 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
740
  /**
741
  * @param array $aSummaryData
742
  * @return array
 
743
  */
744
  public function addModuleSummaryData( $aSummaryData ) {
745
- if ( $this->getIfShowModuleLink() ) {
746
- $aSummaryData[ $this->getModSlug( false ) ] = $this->buildSummaryData();
747
- }
748
  return $aSummaryData;
749
  }
750
 
751
  /**
752
- * @param array $aAllNotices
753
- * @return array
754
- */
755
- public function addInsightsNoticeData( $aAllNotices ) {
756
- return $aAllNotices;
757
- }
758
-
759
- /**
760
- * @param array $aAllData
761
- * @return array
762
  */
763
- public function addInsightsConfigData( $aAllData ) {
764
- return $aAllData;
 
 
 
 
 
765
  }
766
 
767
  /**
768
  * @return array
769
  */
770
- protected function buildSummaryData() {
771
- $oOpts = $this->getOptions();
772
- $sMenuTitle = $oOpts->getFeatureProperty( 'menu_title' );
773
 
774
- $aSections = $oOpts->getSections();
775
  foreach ( $aSections as $sSlug => $aSection ) {
776
  try {
777
  $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
@@ -780,29 +772,30 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
780
  $aSection[ $sKey ] = $sVal;
781
  }
782
  }
783
- catch ( \Exception $oE ) {
784
  }
785
  }
786
 
787
  $aSum = [
788
- 'enabled' => $this->isEnabledForUiSummary(),
789
- 'active' => $this->isThisModulePage() || $this->isPage_InsightsThisModule(),
790
- 'slug' => $this->getSlug(),
791
- 'name' => $this->getMainFeatureName(),
792
- 'sidebar_name' => $oOpts->getFeatureProperty( 'sidebar_name' ),
793
- 'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : __( $sMenuTitle, 'wp-simple-firewall' ),
794
- 'href' => network_admin_url( 'admin.php?page='.$this->getModSlug() ),
795
- 'sections' => $aSections,
796
- 'options' => [],
 
797
  ];
798
 
799
- foreach ( $oOpts->getVisibleOptionsKeys() as $sOptKey ) {
800
  try {
801
  $aOptData = $this->getStrings()->getOptionStrings( $sOptKey );
802
  $aOptData[ 'href' ] = $this->getUrl_DirectLinkToOption( $sOptKey );
803
  $aSum[ 'options' ][ $sOptKey ] = $aOptData;
804
  }
805
- catch ( \Exception $oE ) {
806
  }
807
  }
808
 
@@ -814,31 +807,43 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
814
  }
815
 
816
  /**
817
- * @return bool
 
 
818
  */
819
- protected function isEnabledForUiSummary() {
820
- return $this->isModuleEnabled();
 
 
 
 
 
 
 
 
 
821
  }
822
 
823
  /**
824
  * @return bool
 
825
  */
826
- public function getIfShowModuleMenuItem() {
827
- return (bool)$this->getOptions()->getFeatureProperty( 'show_module_menu_item' );
828
  }
829
 
830
  /**
831
  * @return bool
832
  */
833
- public function getIfShowModuleLink() {
834
- return (bool)$this->getOptions()->getFeatureProperty( 'show_module_options' );
835
  }
836
 
837
  /**
838
  * @return bool
839
  */
840
- public function getIfUseSessions() {
841
- return $this->getOptions()->getFeatureProperty( 'use_sessions' );
842
  }
843
 
844
  /**
@@ -936,7 +941,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
936
 
937
  /**
938
  * Sets the value for the given option key
939
- * Note: We also set the ability to bypass admin access since setOpt() is a protected function
940
  * @param string $sOptionKey
941
  * @param mixed $mValue
942
  * @return $this
@@ -1076,154 +1080,19 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1076
  * It doesn't set any values, just populates the array created in buildOptions()
1077
  * with values stored.
1078
  * It has to handle the conversion of stored values to data to be displayed to the user.
 
1079
  */
1080
  public function buildOptions() {
1081
-
1082
- $bPremiumEnabled = $this->getCon()->isPremiumExtensionsEnabled();
1083
-
1084
- $oOptsVo = $this->getOptions();
1085
- $aOptions = $oOptsVo->getOptionsForPluginUse();
1086
-
1087
- foreach ( $aOptions as $nSectionKey => $aSection ) {
1088
-
1089
- if ( !empty( $aSection[ 'options' ] ) ) {
1090
-
1091
- foreach ( $aSection[ 'options' ] as $nKey => $aOption ) {
1092
- $aOption[ 'is_value_default' ] = ( $aOption[ 'value' ] === $aOption[ 'default' ] );
1093
- $bIsPrem = isset( $aOption[ 'premium' ] ) && $aOption[ 'premium' ];
1094
- if ( !$bIsPrem || $bPremiumEnabled ) {
1095
- $aSection[ 'options' ][ $nKey ] = $this->buildOptionForUi( $aOption );
1096
- }
1097
- else {
1098
- unset( $aSection[ 'options' ][ $nKey ] );
1099
- }
1100
- }
1101
-
1102
- if ( empty( $aSection[ 'options' ] ) ) {
1103
- unset( $aOptions[ $nSectionKey ] );
1104
- }
1105
- else {
1106
- try {
1107
- $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
1108
- foreach ( $aStrings as $sKey => $sVal ) {
1109
- unset( $aSection[ $sKey ] );
1110
- $aSection[ $sKey ] = $sVal;
1111
- }
1112
- }
1113
- catch ( \Exception $oE ) {
1114
- }
1115
- $aOptions[ $nSectionKey ] = $aSection;
1116
- }
1117
-
1118
- $aWarnings = [];
1119
- if ( !$oOptsVo->isSectionReqsMet( $aSection[ 'slug' ] ) ) {
1120
- $aWarnings[] = __( 'Unfortunately your WordPress and/or PHP versions are too old to support this feature.', 'wp-simple-firewall' );
1121
- }
1122
- $aOptions[ $nSectionKey ][ 'warnings' ] = array_merge(
1123
- $aWarnings,
1124
- $this->getSectionWarnings( $aSection[ 'slug' ] )
1125
- );
1126
- $aOptions[ $nSectionKey ][ 'notices' ] = $this->getSectionNotices( $aSection[ 'slug' ] );
1127
-
1128
- if ( !empty( $aSection[ 'help_video_id' ] ) ) {
1129
- $sHelpVideoUrl = $this->getHelpVideoUrl( $aSection[ 'help_video_id' ] );
1130
- }
1131
- else {
1132
- $sHelpVideoUrl = '';
1133
- }
1134
- $aOptions[ $nSectionKey ][ 'help_video_url' ] = ''; /* Remove on Shield 9.0 */
1135
- }
1136
- }
1137
-
1138
- return $aOptions;
1139
- }
1140
-
1141
- /**
1142
- * @param string $sSectionSlug
1143
- * @return array
1144
- */
1145
- protected function getSectionNotices( $sSectionSlug ) {
1146
- return [];
1147
- }
1148
-
1149
- /**
1150
- * @param string $sSection
1151
- * @return array
1152
- */
1153
- protected function getSectionWarnings( $sSection ) {
1154
- return [];
1155
  }
1156
 
1157
  /**
1158
  * @param array $aOptParams
1159
  * @return array
 
1160
  */
1161
  protected function buildOptionForUi( $aOptParams ) {
1162
-
1163
- $mCurrent = $aOptParams[ 'value' ];
1164
-
1165
- switch ( $aOptParams[ 'type' ] ) {
1166
-
1167
- case 'password':
1168
- if ( !empty( $mCurrent ) ) {
1169
- $mCurrent = '';
1170
- }
1171
- break;
1172
-
1173
- case 'array':
1174
-
1175
- if ( empty( $mCurrent ) || !is_array( $mCurrent ) ) {
1176
- $mCurrent = [];
1177
- }
1178
-
1179
- $aOptParams[ 'rows' ] = count( $mCurrent ) + 2;
1180
- $mCurrent = stripslashes( implode( "\n", $mCurrent ) );
1181
-
1182
- break;
1183
-
1184
- case 'comma_separated_lists':
1185
-
1186
- $aNewValues = [];
1187
- if ( !empty( $mCurrent ) && is_array( $mCurrent ) ) {
1188
-
1189
- foreach ( $mCurrent as $sPage => $aParams ) {
1190
- $aNewValues[] = $sPage.', '.implode( ", ", $aParams );
1191
- }
1192
- }
1193
- $aOptParams[ 'rows' ] = count( $aNewValues ) + 1;
1194
- $mCurrent = implode( "\n", $aNewValues );
1195
-
1196
- break;
1197
-
1198
- case 'multiple_select':
1199
- if ( !is_array( $mCurrent ) ) {
1200
- $mCurrent = [];
1201
- }
1202
- break;
1203
-
1204
- case 'text':
1205
- $mCurrent = stripslashes( $this->getTextOpt( $aOptParams[ 'key' ] ) );
1206
- break;
1207
- }
1208
-
1209
- $aParams = [
1210
- 'value' => is_scalar( $mCurrent ) ? esc_attr( $mCurrent ) : $mCurrent,
1211
- 'disabled' => !$this->isPremium() && ( isset( $aOptParams[ 'premium' ] ) && $aOptParams[ 'premium' ] ),
1212
- ];
1213
- $aParams[ 'enabled' ] = !$aParams[ 'disabled' ];
1214
- $aOptParams = array_merge( [ 'rows' => 2 ], $aOptParams, $aParams );
1215
-
1216
- // add strings
1217
- try {
1218
- $aOptStrings = $this->getStrings()->getOptionStrings( $aOptParams[ 'key' ] );
1219
- if ( is_array( $aOptStrings[ 'description' ] ) ) {
1220
- $aOptStrings[ 'description' ] = implode( "<br/>", $aOptStrings[ 'description' ] );
1221
- }
1222
- $aOptParams = Services::DataManipulation()->mergeArraysRecursive( $aOptParams, $aOptStrings );
1223
- }
1224
- catch ( \Exception $oE ) {
1225
- }
1226
- return $aOptParams;
1227
  }
1228
 
1229
  /**
@@ -1250,7 +1119,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1250
  protected function getAllFormOptionsAndTypes() {
1251
  $aOpts = [];
1252
 
1253
- foreach ( $this->buildOptions() as $aOptionsSection ) {
1254
  if ( !empty( $aOptionsSection ) ) {
1255
  foreach ( $aOptionsSection[ 'options' ] as $aOption ) {
1256
  $aOpts[ $aOption[ 'key' ] ] = $aOption[ 'type' ];
@@ -1463,118 +1332,25 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1463
  * @return string
1464
  */
1465
  protected function renderModulePage( $aData = [] ) {
1466
- // Get Base Data
1467
- $aData = Services::DataManipulation()
1468
- ->mergeArraysRecursive( $this->getBaseDisplayData(), $aData );
1469
- $aData[ 'content' ][ 'options_form' ] = $this->renderOptionsForm();
1470
-
1471
- return $this->renderTemplate( 'index.php', $aData );
1472
  }
1473
 
1474
  /**
1475
  * @return array
 
1476
  */
1477
  public function getBaseDisplayData() {
1478
- $oCon = $this->getCon();
1479
-
1480
- /** @var Shield\Modules\Plugin\Options $oPluginOptions */
1481
- $oPluginOptions = $oCon->getModule_Plugin()
1482
- ->getOptions();
1483
-
1484
- return [
1485
- 'sPluginName' => $oCon->getHumanName(),
1486
- 'sTagline' => $this->getOptions()->getFeatureTagline(),
1487
- 'nonce_field' => wp_nonce_field( $oCon->getPluginPrefix(), '_wpnonce', true, false ), //don't echo!
1488
- 'form_action' => 'admin.php?page='.$this->getModSlug(),
1489
- 'aPluginLabels' => $oCon->getLabels(),
1490
- 'help_video' => [
1491
- 'auto_show' => $this->getIfAutoShowHelpVideo(),
1492
- 'iframe_url' => $this->getHelpVideoUrl( $this->getHelpVideoId() ),
1493
- 'display_id' => 'ShieldHelpVideo'.$this->getSlug(),
1494
- 'options' => $this->getHelpVideoOptions(),
1495
- 'displayable' => $this->isHelpVideoDisplayable(),
1496
- 'show' => $this->isHelpVideoDisplayable() && !$this->getHelpVideoHasBeenClosed(),
1497
- 'width' => 772,
1498
- 'height' => 454,
1499
- ],
1500
- 'aSummaryData' => $this->getModulesSummaryData(),
1501
-
1502
- // 'sPageTitle' => sprintf( '%s: %s', $oCon->getHumanName(), $this->getMainFeatureName() ),
1503
- 'sPageTitle' => $this->getMainFeatureName(),
1504
- 'data' => [
1505
- 'mod_slug' => $this->getModSlug( true ),
1506
- 'mod_slug_short' => $this->getModSlug( false ),
1507
- 'all_options' => $this->buildOptions(),
1508
- 'xferable_opts' => ( new Shield\Modules\Plugin\Lib\ImportExport\Options\BuildTransferableOptions() )
1509
- ->setMod( $this )
1510
- ->build(),
1511
- 'hidden_options' => $this->getOptions()->getHiddenOptions()
1512
- ],
1513
- 'ajax' => [
1514
- 'mod_options' => $this->getAjaxActionData( 'mod_options' ),
1515
- ],
1516
- 'vendors' => [
1517
- 'widget_freshdesk' => '3000000081' /* TODO: plugin spec config */
1518
- ],
1519
- 'strings' => $this->getStrings()->getDisplayStrings(),
1520
- 'flags' => [
1521
- 'access_restricted' => !$this->canDisplayOptionsForm(),
1522
- 'show_ads' => $this->getIsShowMarketing(),
1523
- 'wrap_page_content' => true,
1524
- 'show_standard_options' => true,
1525
- 'show_content_help' => true,
1526
- 'show_alt_content' => false,
1527
- 'has_wizard' => $this->hasWizard(),
1528
- 'is_premium' => $this->isPremium(),
1529
- 'show_transfer_switch' => $this->isPremium(),
1530
- 'is_wpcli' => $oPluginOptions->isEnabledWpcli()
1531
- ],
1532
- 'hrefs' => [
1533
- 'go_pro' => 'https://shsec.io/shieldgoprofeature',
1534
- 'goprofooter' => 'https://shsec.io/goprofooter',
1535
- 'wizard_link' => $this->getUrl_WizardLanding(),
1536
- 'wizard_landing' => $this->getUrl_WizardLanding(),
1537
-
1538
- 'form_action' => Services::Request()->getUri(),
1539
- 'css_bootstrap' => $oCon->getPluginUrl_Css( 'bootstrap4.min' ),
1540
- 'css_pages' => $oCon->getPluginUrl_Css( 'pages' ),
1541
- 'css_steps' => $oCon->getPluginUrl_Css( 'jquery.steps' ),
1542
- 'css_fancybox' => $oCon->getPluginUrl_Css( 'jquery.fancybox.min' ),
1543
- 'css_globalplugin' => $oCon->getPluginUrl_Css( 'global-plugin' ),
1544
- 'css_wizard' => $oCon->getPluginUrl_Css( 'wizard' ),
1545
- 'js_jquery' => Services::Includes()->getUrl_Jquery(),
1546
- 'js_bootstrap' => $oCon->getPluginUrl_Js( 'bootstrap4.bundle.min' ),
1547
- 'js_fancybox' => $oCon->getPluginUrl_Js( 'jquery.fancybox.min' ),
1548
- 'js_globalplugin' => $oCon->getPluginUrl_Js( 'global-plugin' ),
1549
- 'js_steps' => $oCon->getPluginUrl_Js( 'jquery.steps.min' ),
1550
- 'js_wizard' => $oCon->getPluginUrl_Js( 'wizard' ),
1551
- ],
1552
- 'imgs' => [
1553
- 'favicon' => $oCon->getPluginUrl_Image( 'pluginlogo_24x24.png' ),
1554
- 'plugin_banner' => $oCon->getPluginUrl_Image( 'banner-1500x500-transparent.png' ),
1555
- ],
1556
- 'content' => [
1557
- 'options_form' => '',
1558
- 'alt' => '',
1559
- 'actions' => '',
1560
- 'help' => '',
1561
- 'wizard_landing' => ''
1562
- ]
1563
- ];
1564
- }
1565
-
1566
- /**
1567
- * @return string
1568
- */
1569
- protected function getContentHelp() {
1570
- return $this->renderTemplate( 'snippets/module-help-template.php', $this->getBaseDisplayData() );
1571
  }
1572
 
1573
  /**
1574
  * @return string
1575
  */
1576
  protected function getContentWizardLanding() {
1577
- $aData = $this->getBaseDisplayData();
1578
  if ( $this->hasWizard() ) {
1579
  $aData[ 'content' ][ 'wizard_landing' ] = $this->getWizardHandler()->renderWizardLandingSnippet();
1580
  }
@@ -1601,13 +1377,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1601
  );
1602
  }
1603
 
1604
- /**
1605
- * @return array[]
1606
- */
1607
- protected function getModulesSummaryData() {
1608
- return apply_filters( $this->prefix( 'collect_mod_summary' ), [] );
1609
- }
1610
-
1611
  /**
1612
  * @param string $sWizardSlug
1613
  * @return string
@@ -1636,7 +1405,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1636
  /**
1637
  * @return string
1638
  */
1639
- protected function getUrl_WizardLanding() {
1640
  return $this->getUrl_Wizard( 'landing' );
1641
  }
1642
 
@@ -1680,7 +1449,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1680
  /**
1681
  * @return bool
1682
  */
1683
- protected function getIsShowMarketing() {
1684
  return apply_filters( $this->prefix( 'show_marketing' ), !$this->isPremium() );
1685
  }
1686
 
@@ -1700,7 +1469,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1700
  return $this->getCon()
1701
  ->getRenderer()
1702
  ->setTemplate( $sTemplate )
1703
- ->setRenderVars( $this->getBaseDisplayData() )
1704
  ->setTemplateEngineTwig()
1705
  ->render();
1706
  }
@@ -1712,7 +1481,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1712
  /**
1713
  * @return bool
1714
  */
1715
- protected function canDisplayOptionsForm() {
1716
  return $this->getOptions()->isAccessRestricted() ? $this->getCon()->isPluginAdmin() : true;
1717
  }
1718
 
@@ -1865,80 +1634,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1865
  return $aData;
1866
  }
1867
 
1868
- protected function getHelpVideoOptions() {
1869
- $aOptions = $this->getOpt( 'help_video_options', [] );
1870
- if ( is_null( $aOptions ) || !is_array( $aOptions ) ) {
1871
- $aOptions = [
1872
- 'closed' => false,
1873
- 'displayed' => false,
1874
- 'played' => false,
1875
- ];
1876
- $this->setOpt( 'help_video_options', $aOptions );
1877
- }
1878
- return $aOptions;
1879
- }
1880
-
1881
- /**
1882
- * @return bool
1883
- */
1884
- protected function getHelpVideoHasBeenClosed() {
1885
- return (bool)$this->getHelpVideoOption( 'closed' );
1886
- }
1887
-
1888
- /**
1889
- * @return bool
1890
- */
1891
- protected function getHelpVideoHasBeenDisplayed() {
1892
- return (bool)$this->getHelpVideoOption( 'displayed' );
1893
- }
1894
-
1895
- /**
1896
- * @return bool
1897
- */
1898
- protected function getVideoHasBeenPlayed() {
1899
- return (bool)$this->getHelpVideoOption( 'played' );
1900
- }
1901
-
1902
- /**
1903
- * @param string $sKey
1904
- * @return mixed|null
1905
- */
1906
- protected function getHelpVideoOption( $sKey ) {
1907
- $aOpts = $this->getHelpVideoOptions();
1908
- return isset( $aOpts[ $sKey ] ) ? $aOpts[ $sKey ] : null;
1909
- }
1910
-
1911
- /**
1912
- * @return bool
1913
- */
1914
- protected function getIfAutoShowHelpVideo() {
1915
- return !$this->getHelpVideoHasBeenClosed();
1916
- }
1917
-
1918
- /**
1919
- * @return string
1920
- */
1921
- protected function getHelpVideoId() {
1922
- return $this->getDef( 'help_video_id' );
1923
- }
1924
-
1925
- /**
1926
- * @param string $sId
1927
- * @return string
1928
- */
1929
- protected function getHelpVideoUrl( $sId ) {
1930
- return sprintf( 'https://player.vimeo.com/video/%s', $sId );
1931
- }
1932
-
1933
- /**
1934
- * @return bool
1935
- */
1936
- protected function isHelpVideoDisplayable() {
1937
- $sId = $this->getHelpVideoId();
1938
- return false;
1939
- return !empty( $sId );
1940
- }
1941
-
1942
  /**
1943
  * @return null|Shield\Modules\Base\ShieldOptions|mixed
1944
  */
@@ -1972,15 +1667,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1972
  return $this->oWpCli;
1973
  }
1974
 
1975
- /**
1976
- * The primary DB for the
1977
- * @return null|Shield\Databases\Base\Handler|mixed
1978
- */
1979
- public function getPrimaryDbHandler() {
1980
- $aDBs = $this->getAllDbClasses();
1981
- return empty( $aDBs ) ? null : $this->getDbH( key( $aDBs ) );
1982
- }
1983
-
1984
  /**
1985
  * @return null|Shield\Modules\Base\Strings
1986
  */
@@ -1991,6 +1677,21 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
1991
  return $this->oStrings;
1992
  }
1993
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1994
  /**
1995
  * @return Shield\Modules\Base\BaseReporting|mixed|false
1996
  */
@@ -2095,14 +1796,4 @@ abstract class ICWP_WPSF_FeatureHandler_Base {
2095
  protected function doExtraSubmitProcessing() {
2096
  $this->preProcessOptions();
2097
  }
2098
-
2099
- /**
2100
- * @deprecated 9.0.5
2101
- */
2102
- protected function updateHandler() {
2103
- $oH = $this->getUpgradeHandler();
2104
- if ( $oH instanceof Shield\Modules\Base\Upgrade ) {
2105
- $oH->setMod( $this )->execute();
2106
- }
2107
- }
2108
  }
50
  */
51
  private $oStrings;
52
 
53
+ /**
54
+ * @var Shield\Modules\Base\UI
55
+ */
56
+ private $oUI;
57
+
58
  /**
59
  * @var Shield\Modules\Base\Options
60
  */
101
  * @param array $aModProps
102
  */
103
  protected function setupHooks( $aModProps ) {
104
+ $con = $this->getCon();
105
  $nRunPriority = isset( $aModProps[ 'load_priority' ] ) ? $aModProps[ 'load_priority' ] : 100;
106
 
107
+ add_action( $con->prefix( 'modules_loaded' ), function () {
108
  $this->onModulesLoaded();
109
  }, $nRunPriority );
110
+ add_action( $con->prefix( 'run_processors' ), [ $this, 'onRunProcessors' ], $nRunPriority );
111
  add_action( 'init', [ $this, 'onWpInit' ], 1 );
112
 
113
  $nMenuPri = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
114
+ add_filter( $con->prefix( 'submenu_items' ), [ $this, 'supplySubMenuItem' ], $nMenuPri );
115
+ add_action( $con->prefix( 'plugin_shutdown' ), [ $this, 'onPluginShutdown' ] );
116
+ add_action( $con->prefix( 'deactivate_plugin' ), [ $this, 'onPluginDeactivate' ] );
117
+ add_action( $con->prefix( 'delete_plugin' ), [ $this, 'onPluginDelete' ] );
118
+ add_filter( $con->prefix( 'aggregate_all_plugin_options' ), [ $this, 'aggregateOptionsValues' ] );
 
 
 
 
119
 
120
+ add_filter( $con->prefix( 'register_admin_notices' ), [ $this, 'fRegisterAdminNotices' ] );
121
 
122
+ add_action( $con->prefix( 'daily_cron' ), [ $this, 'runDailyCron' ] );
123
+ add_action( $con->prefix( 'hourly_cron' ), [ $this, 'runHourlyCron' ] );
124
 
125
  // supply supported events for this module
126
+ add_filter( $con->prefix( 'get_all_events' ), function ( $aEvents ) {
127
  return array_merge(
128
  is_array( $aEvents ) ? $aEvents : [],
129
  array_map(
218
  * @return string[]
219
  */
220
  private function getAllDbClasses() {
221
+ $classes = $this->getOptions()->getDef( 'db_classes' );
222
+ return is_array( $classes ) ? $classes : [];
223
  }
224
 
225
  /**
332
  $this->getProcessor()->execute();
333
  }
334
 
 
 
 
335
  public function onWpInit() {
 
336
 
337
  $sShieldAction = $this->getCon()->getShieldAction();
338
  if ( !empty( $sShieldAction ) ) {
357
  else {
358
  try {
359
  if ( $this->verifyModActionRequest() ) {
360
+ $this->handleModAction( Services::Request()->request( 'exec' ) );
361
  }
362
  }
363
  catch ( \Exception $oE ) {
493
  * @return array
494
  */
495
  protected function getModActionParams( $sAction ) {
496
+ $con = $this->getCon();
497
  return [
498
+ 'action' => $con->prefix(),
499
  'exec' => $sAction,
500
  'mod_slug' => $this->getModSlug(),
501
  'ts' => Services::Request()->ts(),
502
  'exec_nonce' => substr(
503
+ hash_hmac( 'md5', $sAction.Services::Request()->ts(), $con->getSiteInstallationId() )
504
  , 0, 6 )
505
  ];
506
  }
590
  * @return bool
591
  */
592
  public function isModuleEnabled() {
 
593
  /** @var Shield\Modules\Plugin\Options $oPluginOpts */
594
  $oPluginOpts = $this->getCon()->getModule_Plugin()->getOptions();
595
 
603
  elseif ( $this->getCon()->getIfForceOffActive() ) {
604
  $bEnabled = false;
605
  }
606
+ elseif ( $this->getOptions()->getFeatureProperty( 'premium' ) === true
607
+ && !$this->isPremium() ) {
608
  $bEnabled = false;
609
  }
610
  else {
625
  /**
626
  * @return string
627
  */
628
+ public function getEnableModOptKey() {
629
  return 'enable_'.$this->getSlug();
630
  }
631
 
657
  /**
658
  * @param array $aItems
659
  * @return array
660
+ * @deprecated 9.2.0
661
  */
662
  public function addAdminMenuBarItems( array $aItems ) {
663
  return $aItems;
737
  /**
738
  * @param array $aSummaryData
739
  * @return array
740
+ * @deprecated 9.2.0
741
  */
742
  public function addModuleSummaryData( $aSummaryData ) {
 
 
 
743
  return $aSummaryData;
744
  }
745
 
746
  /**
747
+ * TODO: not the place for this method.
748
+ * @return array[]
 
 
 
 
 
 
 
 
749
  */
750
+ public function getModulesSummaryData() {
751
+ return array_map(
752
+ function ( $mod ) {
753
+ return $mod->buildSummaryData();
754
+ },
755
+ $this->getCon()->modules
756
+ );
757
  }
758
 
759
  /**
760
  * @return array
761
  */
762
+ public function buildSummaryData() {
763
+ $opts = $this->getOptions();
764
+ $sMenuTitle = $opts->getFeatureProperty( 'menu_title' );
765
 
766
+ $aSections = $opts->getSections();
767
  foreach ( $aSections as $sSlug => $aSection ) {
768
  try {
769
  $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
772
  $aSection[ $sKey ] = $sVal;
773
  }
774
  }
775
+ catch ( \Exception $e ) {
776
  }
777
  }
778
 
779
  $aSum = [
780
+ 'slug' => $this->getSlug(),
781
+ 'enabled' => $this->getUIHandler()->isEnabledForUiSummary(),
782
+ 'active' => $this->isThisModulePage() || $this->isPage_InsightsThisModule(),
783
+ 'name' => $this->getMainFeatureName(),
784
+ 'sidebar_name' => $opts->getFeatureProperty( 'sidebar_name' ),
785
+ 'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : __( $sMenuTitle, 'wp-simple-firewall' ),
786
+ 'href' => network_admin_url( 'admin.php?page='.$this->getModSlug() ),
787
+ 'sections' => $aSections,
788
+ 'options' => [],
789
+ 'show_mod_opts' => $this->getIfShowModuleOpts(),
790
  ];
791
 
792
+ foreach ( $opts->getVisibleOptionsKeys() as $sOptKey ) {
793
  try {
794
  $aOptData = $this->getStrings()->getOptionStrings( $sOptKey );
795
  $aOptData[ 'href' ] = $this->getUrl_DirectLinkToOption( $sOptKey );
796
  $aSum[ 'options' ][ $sOptKey ] = $aOptData;
797
  }
798
+ catch ( \Exception $e ) {
799
  }
800
  }
801
 
807
  }
808
 
809
  /**
810
+ * @param array $aAllNotices
811
+ * @return array
812
+ * @deprecated 9.2.0
813
  */
814
+ public function addInsightsNoticeData( $aAllNotices ) {
815
+ return $aAllNotices;
816
+ }
817
+
818
+ /**
819
+ * @param array $aAllData
820
+ * @return array
821
+ * @deprecated 9.2.0
822
+ */
823
+ public function addInsightsConfigData( $aAllData ) {
824
+ return $aAllData;
825
  }
826
 
827
  /**
828
  * @return bool
829
+ * @deprecated 9.2.0
830
  */
831
+ public function isEnabledForUiSummary() {
832
+ return $this->isModuleEnabled();
833
  }
834
 
835
  /**
836
  * @return bool
837
  */
838
+ public function getIfShowModuleMenuItem() {
839
+ return (bool)$this->getOptions()->getFeatureProperty( 'show_module_menu_item' );
840
  }
841
 
842
  /**
843
  * @return bool
844
  */
845
+ public function getIfShowModuleOpts() {
846
+ return (bool)$this->getOptions()->getFeatureProperty( 'show_module_options' );
847
  }
848
 
849
  /**
941
 
942
  /**
943
  * Sets the value for the given option key
 
944
  * @param string $sOptionKey
945
  * @param mixed $mValue
946
  * @return $this
1080
  * It doesn't set any values, just populates the array created in buildOptions()
1081
  * with values stored.
1082
  * It has to handle the conversion of stored values to data to be displayed to the user.
1083
+ * @deprecated 9.2.0
1084
  */
1085
  public function buildOptions() {
1086
+ return $this->getUIHandler()->buildOptions();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1087
  }
1088
 
1089
  /**
1090
  * @param array $aOptParams
1091
  * @return array
1092
+ * @deprecated 9.2.0
1093
  */
1094
  protected function buildOptionForUi( $aOptParams ) {
1095
+ return [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1096
  }
1097
 
1098
  /**
1119
  protected function getAllFormOptionsAndTypes() {
1120
  $aOpts = [];
1121
 
1122
+ foreach ( $this->getUIHandler()->buildOptions() as $aOptionsSection ) {
1123
  if ( !empty( $aOptionsSection ) ) {
1124
  foreach ( $aOptionsSection[ 'options' ] as $aOption ) {
1125
  $aOpts[ $aOption[ 'key' ] ] = $aOption[ 'type' ];
1332
  * @return string
1333
  */
1334
  protected function renderModulePage( $aData = [] ) {
1335
+ return $this->renderTemplate(
1336
+ 'index.php',
1337
+ Services::DataManipulation()->mergeArraysRecursive( $this->getUIHandler()->getBaseDisplayData(), $aData )
1338
+ );
 
 
1339
  }
1340
 
1341
  /**
1342
  * @return array
1343
+ * @deprecated 9.2.0
1344
  */
1345
  public function getBaseDisplayData() {
1346
+ return $this->getUIHandler()->getBaseDisplayData();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1347
  }
1348
 
1349
  /**
1350
  * @return string
1351
  */
1352
  protected function getContentWizardLanding() {
1353
+ $aData = $this->getUIHandler()->getBaseDisplayData();
1354
  if ( $this->hasWizard() ) {
1355
  $aData[ 'content' ][ 'wizard_landing' ] = $this->getWizardHandler()->renderWizardLandingSnippet();
1356
  }
1377
  );
1378
  }
1379
 
 
 
 
 
 
 
 
1380
  /**
1381
  * @param string $sWizardSlug
1382
  * @return string
1405
  /**
1406
  * @return string
1407
  */
1408
+ public function getUrl_WizardLanding() {
1409
  return $this->getUrl_Wizard( 'landing' );
1410
  }
1411
 
1449
  /**
1450
  * @return bool
1451
  */
1452
+ public function getIsShowMarketing() {
1453
  return apply_filters( $this->prefix( 'show_marketing' ), !$this->isPremium() );
1454
  }
1455
 
1469
  return $this->getCon()
1470
  ->getRenderer()
1471
  ->setTemplate( $sTemplate )
1472
+ ->setRenderVars( $this->getUIHandler()->getBaseDisplayData() )
1473
  ->setTemplateEngineTwig()
1474
  ->render();
1475
  }
1481
  /**
1482
  * @return bool
1483
  */
1484
+ public function canDisplayOptionsForm() {
1485
  return $this->getOptions()->isAccessRestricted() ? $this->getCon()->isPluginAdmin() : true;
1486
  }
1487
 
1634
  return $aData;
1635
  }
1636
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1637
  /**
1638
  * @return null|Shield\Modules\Base\ShieldOptions|mixed
1639
  */
1667
  return $this->oWpCli;
1668
  }
1669
 
 
 
 
 
 
 
 
 
 
1670
  /**
1671
  * @return null|Shield\Modules\Base\Strings
1672
  */
1677
  return $this->oStrings;
1678
  }
1679
 
1680
+ /**
1681
+ * @return Shield\Modules\Base\UI
1682
+ */
1683
+ public function getUIHandler() {
1684
+ if ( !isset( $this->oUI ) ) {
1685
+ $this->oUI = $this->loadClass( 'UI' );
1686
+ if ( !$this->oUI instanceof Shield\Modules\Base\UI ) {
1687
+ // TODO: autoloader for base classes
1688
+ $this->oUI = $this->loadClassFromBase( 'ShieldUI' );
1689
+ }
1690
+ $this->oUI->setMod( $this );
1691
+ }
1692
+ return $this->oUI;
1693
+ }
1694
+
1695
  /**
1696
  * @return Shield\Modules\Base\BaseReporting|mixed|false
1697
  */
1796
  protected function doExtraSubmitProcessing() {
1797
  $this->preProcessOptions();
1798
  }
 
 
 
 
 
 
 
 
 
 
1799
  }
src/features/base_wpsf.php CHANGED
@@ -56,7 +56,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
56
  * @return bool
57
  */
58
  public function hasSession() {
59
- return ( $this->getSession() instanceof \FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO );
60
  }
61
 
62
  /**
@@ -157,55 +157,6 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
157
  }
158
  }
159
 
160
- /**
161
- * @return array
162
- */
163
- public function getBaseDisplayData() {
164
- return Services::DataManipulation()->mergeArraysRecursive(
165
- parent::getBaseDisplayData(),
166
- [
167
- 'head' => [
168
- 'html' => [
169
- 'lang' => Services::WpGeneral()->getLocale( '-' ),
170
- 'dir' => is_rtl() ? 'rtl' : 'ltr',
171
- ],
172
- 'meta' => [
173
- [
174
- 'type' => 'http-equiv',
175
- 'type_type' => 'Cache-Control',
176
- 'content' => 'no-store, no-cache',
177
- ],
178
- [
179
- 'type' => 'http-equiv',
180
- 'type_type' => 'Expires',
181
- 'content' => '0',
182
- ],
183
- ],
184
- 'scripts' => []
185
- ],
186
- 'ajax' => [
187
- 'sec_admin_login' => $this->getSecAdminLoginAjaxData(),
188
- ],
189
- 'flags' => [
190
- 'show_promo' => !$this->isPremium(),
191
- 'has_session' => $this->hasSession()
192
- ],
193
- 'hrefs' => [
194
- 'aar_forget_key' => $this->isWlEnabled() ?
195
- $this->getCon()->getLabels()[ 'AuthorURI' ] : 'https://shsec.io/gc'
196
- ],
197
- 'classes' => [
198
- 'top_container' => implode( ' ', array_filter( [
199
- 'odp-outercontainer',
200
- $this->isPremium() ? 'is-pro' : 'is-not-pro',
201
- $this->getModSlug(),
202
- Services::Request()->query( 'inav', '' )
203
- ] ) )
204
- ],
205
- ]
206
- );
207
- }
208
-
209
  /**
210
  * @return string
211
  */
@@ -216,7 +167,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
216
  ->getOptions();
217
  $aData = Services::DataManipulation()
218
  ->mergeArraysRecursive(
219
- $this->getBaseDisplayData(),
220
  [
221
  'ajax' => [
222
  'restricted_access' => $this->getAjaxActionData( 'restricted_access' ),
@@ -329,17 +280,4 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
329
  }
330
  return array_unique( array_filter( $aCleaned ) );
331
  }
332
-
333
- /**
334
- * @return array
335
- */
336
- protected function getModDisabledInsight() {
337
- return [
338
- 'name' => __( 'Module Disabled', 'wp-simple-firewall' ),
339
- 'enabled' => false,
340
- 'summary' => __( 'All features of this module are completely disabled', 'wp-simple-firewall' ),
341
- 'weight' => 2,
342
- 'href' => $this->getUrl_DirectLinkToOption( $this->getEnableModOptKey() ),
343
- ];
344
- }
345
  }
56
  * @return bool
57
  */
58
  public function hasSession() {
59
+ return $this->getSession() instanceof Shield\Databases\Session\EntryVO;
60
  }
61
 
62
  /**
157
  }
158
  }
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  /**
161
  * @return string
162
  */
167
  ->getOptions();
168
  $aData = Services::DataManipulation()
169
  ->mergeArraysRecursive(
170
+ $this->getUIHandler()->getBaseDisplayData(),
171
  [
172
  'ajax' => [
173
  'restricted_access' => $this->getAjaxActionData( 'restricted_access' ),
280
  }
281
  return array_unique( array_filter( $aCleaned ) );
282
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  }
src/features/comments_filter.php CHANGED
@@ -19,25 +19,26 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
19
  }
20
 
21
  public function ensureCorrectCaptchaConfig() {
22
- /** @var CommentsFilter\Options $oOpts */
23
- $oOpts = $this->getOptions();
24
 
25
- $sStyle = $oOpts->getOpt( 'google_recaptcha_style_comments' );
26
  if ( $this->isPremium() ) {
27
  $oCfg = $this->getCaptchaCfg();
28
  if ( $oCfg->provider == $oCfg::PROV_GOOGLE_RECAP2 ) {
29
  if ( !$oCfg->invisible && $sStyle == 'invisible' ) {
30
- $oOpts->setOpt( 'google_recaptcha_style_comments', 'default' );
31
  }
32
  }
33
  }
34
  elseif ( !in_array( $sStyle, [ 'disabled', 'default' ] ) ) {
35
- $oOpts->setOpt( 'google_recaptcha_style_comments', 'default' );
36
  }
37
  }
38
 
39
  /**
40
  * @return bool
 
41
  */
42
  public function getApprovedMinimum() {
43
  return $this->getOpt( 'trusted_commenter_minimum', 1 );
@@ -45,6 +46,7 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
45
 
46
  /**
47
  * @return string[]
 
48
  */
49
  public function getTrustedRoles() {
50
  $aRoles = [];
@@ -81,90 +83,52 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
81
  }
82
 
83
  protected function preProcessOptions() {
84
- /** @var Shield\Modules\CommentsFilter\Options $oOpts */
85
- $oOpts = $this->getOptions();
86
 
87
  // clean roles
88
- $oOpts->setOpt( 'trusted_user_roles',
89
  array_unique( array_filter( array_map(
90
  function ( $sRole ) {
91
  return sanitize_key( strtolower( $sRole ) );
92
  },
93
- $this->getTrustedRoles()
94
  ) ) )
95
  );
96
 
97
  $this->ensureCorrectCaptchaConfig();
98
  }
99
 
100
- /**
101
- * @param array $aAllData
102
- * @return array
103
- */
104
- public function addInsightsConfigData( $aAllData ) {
105
- $aThis = [
106
- 'strings' => [
107
- 'title' => __( 'SPAM Blocking', 'wp-simple-firewall' ),
108
- 'sub' => __( 'Block Bot & Human Comment SPAM', 'wp-simple-firewall' ),
109
- ],
110
- 'key_opts' => [],
111
- 'href_options' => $this->getUrl_AdminPage()
112
- ];
113
-
114
- if ( !$this->isModOptEnabled() ) {
115
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
116
- }
117
- else {
118
- $aThis[ 'key_opts' ][ 'bot' ] = [
119
- 'name' => __( 'Bot SPAM', 'wp-simple-firewall' ),
120
- 'enabled' => $this->isEnabledGaspCheck() || $this->isEnabledCaptcha(),
121
- 'summary' => ( $this->isEnabledGaspCheck() || $this->isEnabledCaptcha() ) ?
122
- __( 'Bot SPAM comments are blocked', 'wp-simple-firewall' )
123
- : __( 'There is no protection against Bot SPAM comments', 'wp-simple-firewall' ),
124
- 'weight' => 2,
125
- 'href' => $this->getUrl_DirectLinkToSection( 'section_bot_comment_spam_protection_filter' ),
126
- ];
127
- $aThis[ 'key_opts' ][ 'human' ] = [
128
- 'name' => __( 'Human SPAM', 'wp-simple-firewall' ),
129
- 'enabled' => $this->isEnabledHumanCheck(),
130
- 'summary' => $this->isEnabledHumanCheck() ?
131
- __( 'Comments posted by humans are checked for SPAM', 'wp-simple-firewall' )
132
- : __( "Comments posted by humans aren't checked for SPAM", 'wp-simple-firewall' ),
133
- 'weight' => 1,
134
- 'href' => $this->getUrl_DirectLinkToSection( 'section_human_spam_filter' ),
135
- ];
136
- }
137
-
138
- $aAllData[ $this->getSlug() ] = $aThis;
139
- return $aAllData;
140
- }
141
-
142
  /**
143
  * @return bool
144
  */
145
  public function isEnabledCaptcha() {
146
- return $this->isModOptEnabled() && !$this->isOpt( 'google_recaptcha_style_comments', 'disabled' )
 
 
147
  && $this->getCaptchaCfg()->ready;
148
  }
149
 
150
  /**
151
  * @return bool
 
152
  */
153
  public function isEnabledGaspCheck() {
154
- /** @var CommentsFilter\Options $oOpts */
155
- $oOpts = $this->getOptions();
156
  return $this->isModOptEnabled() && $this->isOpt( 'enable_comments_gasp_protection', 'Y' )
157
- && ( $oOpts->getTokenExpireInterval() > $oOpts->getTokenCooldown() );
158
  }
159
 
160
  /**
161
  * @return bool
 
162
  */
163
  public function isEnabledHumanCheck() {
164
- /** @var CommentsFilter\Options $oOpts */
165
- $oOpts = $this->getOptions();
166
- return $this->isModOptEnabled() && $oOpts->isOpt( 'enable_comments_human_spam_filter', 'Y' )
167
- && count( $oOpts->getHumanSpamFilterItems() ) > 0;
168
  }
169
 
170
  /**
19
  }
20
 
21
  public function ensureCorrectCaptchaConfig() {
22
+ /** @var CommentsFilter\Options $opts */
23
+ $opts = $this->getOptions();
24
 
25
+ $sStyle = $opts->getOpt( 'google_recaptcha_style_comments' );
26
  if ( $this->isPremium() ) {
27
  $oCfg = $this->getCaptchaCfg();
28
  if ( $oCfg->provider == $oCfg::PROV_GOOGLE_RECAP2 ) {
29
  if ( !$oCfg->invisible && $sStyle == 'invisible' ) {
30
+ $opts->setOpt( 'google_recaptcha_style_comments', 'default' );
31
  }
32
  }
33
  }
34
  elseif ( !in_array( $sStyle, [ 'disabled', 'default' ] ) ) {
35
+ $opts->setOpt( 'google_recaptcha_style_comments', 'default' );
36
  }
37
  }
38
 
39
  /**
40
  * @return bool
41
+ * @deprecated 9.2.0
42
  */
43
  public function getApprovedMinimum() {
44
  return $this->getOpt( 'trusted_commenter_minimum', 1 );
46
 
47
  /**
48
  * @return string[]
49
+ * @deprecated 9.2.0
50
  */
51
  public function getTrustedRoles() {
52
  $aRoles = [];
83
  }
84
 
85
  protected function preProcessOptions() {
86
+ /** @var CommentsFilter\Options $opts */
87
+ $opts = $this->getOptions();
88
 
89
  // clean roles
90
+ $opts->setOpt( 'trusted_user_roles',
91
  array_unique( array_filter( array_map(
92
  function ( $sRole ) {
93
  return sanitize_key( strtolower( $sRole ) );
94
  },
95
+ $opts->getTrustedRoles()
96
  ) ) )
97
  );
98
 
99
  $this->ensureCorrectCaptchaConfig();
100
  }
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  /**
103
  * @return bool
104
  */
105
  public function isEnabledCaptcha() {
106
+ /** @var CommentsFilter\Options $opts */
107
+ $opts = $this->getOptions();
108
+ return $this->isModOptEnabled() && !$opts->isEnabledCaptcha()
109
  && $this->getCaptchaCfg()->ready;
110
  }
111
 
112
  /**
113
  * @return bool
114
+ * @deprecated 9.2
115
  */
116
  public function isEnabledGaspCheck() {
117
+ /** @var CommentsFilter\Options $opts */
118
+ $opts = $this->getOptions();
119
  return $this->isModOptEnabled() && $this->isOpt( 'enable_comments_gasp_protection', 'Y' )
120
+ && ( $opts->getTokenExpireInterval() > $opts->getTokenCooldown() );
121
  }
122
 
123
  /**
124
  * @return bool
125
+ * @deprecated 9.2
126
  */
127
  public function isEnabledHumanCheck() {
128
+ /** @var CommentsFilter\Options $opts */
129
+ $opts = $this->getOptions();
130
+ return $opts->isOpt( 'enable_comments_human_spam_filter', 'Y' )
131
+ && count( $opts->getHumanSpamFilterItems() ) > 0;
132
  }
133
 
134
  /**
src/features/firewall.php CHANGED
@@ -56,54 +56,6 @@ class ICWP_WPSF_FeatureHandler_Firewall extends ICWP_WPSF_FeatureHandler_BaseWps
56
  return $sText;
57
  }
58
 
59
- /**
60
- * @param array $aAllData
61
- * @return array
62
- */
63
- public function addInsightsConfigData( $aAllData ) {
64
- /** @var Firewall\Options $oOpts */
65
- $oOpts = $this->getOptions();
66
-
67
- $aThis = [
68
- 'strings' => [
69
- 'title' => __( 'Firewall', 'wp-simple-firewall' ),
70
- 'sub' => __( 'Block Malicious Requests', 'wp-simple-firewall' ),
71
- ],
72
- 'key_opts' => [],
73
- 'href_options' => $this->getUrl_AdminPage()
74
- ];
75
-
76
- if ( !$this->isModOptEnabled() ) {
77
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
78
- }
79
- else {
80
- $aThis[ 'key_opts' ][ 'mod' ] = [
81
- 'name' => __( 'Firewall', 'wp-simple-firewall' ),
82
- 'enabled' => $this->isModOptEnabled(),
83
- 'summary' => $this->isModOptEnabled() ?
84
- __( 'Your site is protected against malicious requests', 'wp-simple-firewall' )
85
- : __( 'Your site is not protected against malicious requests', 'wp-simple-firewall' ),
86
- 'weight' => 2,
87
- 'href' => $this->getUrl_DirectLinkToOption( $this->getEnableModOptKey() ),
88
- ];
89
-
90
- //ignoring admin isn't a good idea
91
- $bAdminIncluded = !$oOpts->isIgnoreAdmin();
92
- $aThis[ 'key_opts' ][ 'admin' ] = [
93
- 'name' => __( 'Ignore Admins', 'wp-simple-firewall' ),
94
- 'enabled' => $bAdminIncluded,
95
- 'summary' => $bAdminIncluded ?
96
- __( "Firewall rules are also applied to admins", 'wp-simple-firewall' )
97
- : __( "Firewall rules aren't applied to admins", 'wp-simple-firewall' ),
98
- 'weight' => 1,
99
- 'href' => $this->getUrl_DirectLinkToOption( 'whitelist_admins' ),
100
- ];
101
- }
102
-
103
- $aAllData[ $this->getSlug() ] = $aThis;
104
- return $aAllData;
105
- }
106
-
107
  /**
108
  * @return string
109
  */
56
  return $sText;
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  * @return string
61
  */
src/features/hack_protect.php CHANGED
@@ -56,34 +56,34 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
56
  * @return HackGuard\Scan\Controller\Base[]
57
  */
58
  public function getAllScanCons() {
59
- /** @var HackGuard\Options $oOpts */
60
- $oOpts = $this->getOptions();
61
- foreach ( $oOpts->getScanSlugs() as $scanSlug ) {
62
  $this->getScanCon( $scanSlug );
63
  }
64
  return $this->aScanCons;
65
  }
66
 
67
  /**
68
- * @param string $sSlug
69
  * @return HackGuard\Scan\Controller\Base|mixed
70
  */
71
- public function getScanCon( $sSlug ) {
72
  if ( !is_array( $this->aScanCons ) ) {
73
  $this->aScanCons = [];
74
  }
75
- if ( !isset( $this->aScanCons[ $sSlug ] ) ) {
76
- $sClass = '\FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\\'.ucwords( $sSlug );
77
- if ( @class_exists( $sClass ) ) {
78
  /** @var HackGuard\Scan\Controller\Base $oObj */
79
- $oObj = new $sClass();
80
- $this->aScanCons[ $sSlug ] = $oObj->setMod( $this );
81
  }
82
  else {
83
- $this->aScanCons[ $sSlug ] = false;
84
  }
85
  }
86
- return $this->aScanCons[ $sSlug ];
87
  }
88
 
89
  /**
@@ -106,28 +106,34 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
106
  }
107
 
108
  protected function preProcessOptions() {
109
- /** @var HackGuard\Options $oOpts */
110
- $oOpts = $this->getOptions();
111
 
112
  $this->cleanFileExclusions();
113
 
114
- if ( $oOpts->isOptChanged( 'scan_frequency' ) ) {
115
  /** @var \ICWP_WPSF_Processor_HackProtect $oPro */
116
  $oPro = $this->getProcessor();
117
  $oPro->getSubProScanner()->deleteCron();
118
  }
119
 
120
- if ( count( $oOpts->getFilesToLock() ) === 0 || !$this->getCon()
121
- ->getModule_Plugin()
122
- ->getShieldNetApiController()
123
- ->canHandshake() ) {
124
- $oOpts->setOpt( 'file_locker', [] );
125
  $this->getFileLocker()->purge();
126
  }
127
 
128
- foreach ( $this->getAllScanCons() as $oCon ) {
129
- if ( !$oCon->isEnabled() ) {
130
- $oCon->purge();
 
 
 
 
 
 
131
  }
132
  }
133
  }
@@ -171,9 +177,9 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
171
  * @return $this
172
  */
173
  protected function setCustomCronSchedules() {
174
- /** @var HackGuard\Options $oOpts */
175
- $oOpts = $this->getOptions();
176
- $nFreq = $oOpts->getScanFrequency();
177
  Services::WpCron()
178
  ->addNewSchedule(
179
  $this->prefix( sprintf( 'per-day-%s', $nFreq ) ),
@@ -248,10 +254,10 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
248
  public function insertCustomJsVars_Admin() {
249
  parent::insertCustomJsVars_Admin();
250
 
251
- /** @var HackGuard\Options $oOpts */
252
- $oOpts = $this->getOptions();
253
  if ( Services::WpPost()->isCurrentPage( 'plugins.php' )
254
- && $oOpts->isPtgReinstallLinks() && $this->getScanCon( 'ptg' )->isReady() ) {
255
  wp_localize_script(
256
  $this->prefix( 'global-plugin' ),
257
  'icwp_wpsf_vars_hp',
@@ -273,35 +279,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
273
  }
274
  }
275
 
276
- /**
277
- * @param string $sSection
278
- * @return array
279
- */
280
- protected function getSectionWarnings( $sSection ) {
281
- $aWarnings = [];
282
-
283
- switch ( $sSection ) {
284
-
285
- case 'section_realtime':
286
- $bCanHandshake = $this->getCon()
287
- ->getModule_Plugin()
288
- ->getShieldNetApiController()
289
- ->canHandshake();
290
- if ( !$bCanHandshake ) {
291
- $aWarnings[] = sprintf( __( 'Not available as your site cannot handshake with ShieldNET API.', 'wp-simple-firewall' ), 'OpenSSL' );
292
- }
293
- // if ( !Services::Encrypt()->isSupportedOpenSslDataEncryption() ) {
294
- // $aWarnings[] = sprintf( __( 'Not available because the %s extension is not available.', 'wp-simple-firewall' ), 'OpenSSL' );
295
- // }
296
- // if ( !Services::WpFs()->isFilesystemAccessDirect() ) {
297
- // $aWarnings[] = sprintf( __( "Not available because PHP/WordPress doesn't have direct filesystem access.", 'wp-simple-firewall' ), 'OpenSSL' );
298
- // }
299
- break;
300
- }
301
-
302
- return $aWarnings;
303
- }
304
-
305
  /**
306
  * @return string|false
307
  */
@@ -325,298 +302,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
325
  return Services::WpFs()->mkdir( $sDir ) ? $sDir : false;
326
  }
327
 
328
- /**
329
- * @param array $aAllNotices
330
- * @return array
331
- */
332
- public function addInsightsNoticeData( $aAllNotices ) {
333
- /** @var HackGuard\Strings $oStrings */
334
- $oStrings = $this->getStrings();
335
- $aScanNames = $oStrings->getScanNames();
336
-
337
- $aNotices = [
338
- 'title' => __( 'Scans', 'wp-simple-firewall' ),
339
- 'messages' => []
340
- ];
341
-
342
- $sScansUrl = $this->getCon()->getModule_Insights()->getUrl_SubInsightsPage( 'scans' );
343
-
344
- {// Core files
345
- if ( !$this->isScanEnabled( 'wcf' ) ) {
346
- $aNotices[ 'messages' ][ 'wcf' ] = [
347
- 'title' => $aScanNames[ 'wcf' ],
348
- 'message' => __( 'Core File scanner is not enabled.', 'wp-simple-firewall' ),
349
- 'href' => $this->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
350
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
351
- 'rec' => __( 'Automatic WordPress Core File scanner should be turned-on.', 'wp-simple-firewall' )
352
- ];
353
- }
354
- elseif ( $this->getScanCon( 'wcf' )->getScanHasProblem() ) {
355
- $aNotices[ 'messages' ][ 'wcf' ] = [
356
- 'title' => $aScanNames[ 'wcf' ],
357
- 'message' => __( 'Modified WordPress core files found.', 'wp-simple-firewall' ),
358
- 'href' => $sScansUrl,
359
- 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
360
- 'rec' => __( 'Scan WP core files and repair any files that are flagged as modified.', 'wp-simple-firewall' )
361
- ];
362
- }
363
- }
364
-
365
- {// Unrecognised
366
- if ( !$this->isScanEnabled( 'ufc' ) ) {
367
- $aNotices[ 'messages' ][ 'ufc' ] = [
368
- 'title' => $aScanNames[ 'ufc' ],
369
- 'message' => __( 'Unrecognised File scanner is not enabled.', 'wp-simple-firewall' ),
370
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
371
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
372
- 'rec' => __( 'Automatic scanning for non-WordPress core files is recommended.', 'wp-simple-firewall' )
373
- ];
374
- }
375
- elseif ( $this->getScanCon( 'ufc' )->getScanHasProblem() ) {
376
- $aNotices[ 'messages' ][ 'ufc' ] = [
377
- 'title' => $aScanNames[ 'ufc' ],
378
- 'message' => __( 'Unrecognised files found in WordPress Core directory.', 'wp-simple-firewall' ),
379
- 'href' => $sScansUrl,
380
- 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
381
- 'rec' => __( 'Scan and remove any files that are not meant to be in the WP core directories.', 'wp-simple-firewall' )
382
- ];
383
- }
384
- }
385
-
386
- {// Plugin/Theme Guard
387
- $oPTG = $this->getScanCon( 'ptg' );
388
- if ( !$oPTG->isEnabled() ) {
389
- $aNotices[ 'messages' ][ 'ptg' ] = [
390
- 'title' => $aScanNames[ 'ptg' ],
391
- 'message' => __( 'Automatic Plugin/Themes Guard is not enabled.', 'wp-simple-firewall' ),
392
- 'href' => $this->getUrl_DirectLinkToOption( 'ptg_enable' ),
393
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
394
- 'rec' => __( 'Automatic detection of plugin/theme modifications is recommended.', 'wp-simple-firewall' )
395
- ];
396
- }
397
- elseif ( $oPTG->getScanHasProblem() ) {
398
- $aNotices[ 'messages' ][ 'ptg' ] = [
399
- 'title' => $aScanNames[ 'ptg' ],
400
- 'message' => __( 'A plugin/theme was found to have been modified.', 'wp-simple-firewall' ),
401
- 'href' => $sScansUrl,
402
- 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
403
- 'rec' => __( 'Reviewing modifications to your plugins/themes is recommended.', 'wp-simple-firewall' )
404
- ];
405
- }
406
- }
407
-
408
- {// Vulnerability Scanner
409
- if ( !$this->isScanEnabled( 'wpv' ) ) {
410
- $aNotices[ 'messages' ][ 'wpv' ] = [
411
- 'title' => $aScanNames[ 'wpv' ],
412
- 'message' => __( 'Vulnerability Scanner is not enabled.', 'wp-simple-firewall' ),
413
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
414
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
415
- 'rec' => __( 'Automatic detection of vulnerabilities is recommended.', 'wp-simple-firewall' )
416
- ];
417
- }
418
- elseif ( $this->getScanCon( 'wpv' )->getScanHasProblem() ) {
419
- $aNotices[ 'messages' ][ 'wpv' ] = [
420
- 'title' => $aScanNames[ 'wpv' ],
421
- 'message' => __( 'At least 1 item has known vulnerabilities.', 'wp-simple-firewall' ),
422
- 'href' => $sScansUrl,
423
- 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
424
- 'rec' => __( 'Items with known vulnerabilities should be updated, removed, or replaced.', 'wp-simple-firewall' )
425
- ];
426
- }
427
- }
428
-
429
- {// Abandoned Plugins
430
- if ( !$this->isScanEnabled( 'apc' ) ) {
431
- $aNotices[ 'messages' ][ 'apc' ] = [
432
- 'title' => $aScanNames[ 'apc' ],
433
- 'message' => __( 'Abandoned Plugins Scanner is not enabled.', 'wp-simple-firewall' ),
434
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_apc' ),
435
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
436
- 'rec' => __( 'Automatic detection of abandoned plugins is recommended.', 'wp-simple-firewall' )
437
- ];
438
- }
439
- elseif ( $this->getScanCon( 'apc' )->getScanHasProblem() ) {
440
- $aNotices[ 'messages' ][ 'apc' ] = [
441
- 'title' => $aScanNames[ 'apc' ],
442
- 'message' => __( 'At least 1 plugin on your site is abandoned.', 'wp-simple-firewall' ),
443
- 'href' => $sScansUrl,
444
- 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
445
- 'rec' => __( 'Plugins that have been abandoned represent a potential risk to your site.', 'wp-simple-firewall' )
446
- ];
447
- }
448
- }
449
-
450
- {// Malware
451
- if ( !$this->isScanEnabled( 'mal' ) ) {
452
- $aNotices[ 'messages' ][ 'mal' ] = [
453
- 'title' => $aScanNames[ 'mal' ],
454
- 'message' => sprintf( __( '%s Scanner is not enabled.' ), $aScanNames[ 'mal' ] ),
455
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_mal' ),
456
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
457
- 'rec' => __( 'Automatic detection of Malware is recommended.', 'wp-simple-firewall' )
458
- ];
459
- }
460
- elseif ( $this->getScanCon( 'mal' )->getScanHasProblem() ) {
461
- $aNotices[ 'messages' ][ 'mal' ] = [
462
- 'title' => $aScanNames[ 'mal' ],
463
- 'message' => __( 'At least 1 file with potential Malware has been discovered.', 'wp-simple-firewall' ),
464
- 'href' => $sScansUrl,
465
- 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
466
- 'rec' => __( 'Files identified as potential malware should be examined as soon as possible.', 'wp-simple-firewall' )
467
- ];
468
- }
469
- }
470
-
471
- $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
472
-
473
- $aAllNotices[ 'scans' ] = $aNotices;
474
- return $aAllNotices;
475
- }
476
-
477
- /**
478
- * @param array $aAllData
479
- * @return array
480
- */
481
- public function addInsightsConfigData( $aAllData ) {
482
- /** @var HackGuard\Strings $oStrings */
483
- $oStrings = $this->getStrings();
484
- /** @var HackGuard\Options $oOpts */
485
- $oOpts = $this->getOptions();
486
- $aScanNames = $oStrings->getScanNames();
487
-
488
- $aThis = [
489
- 'strings' => [
490
- 'title' => __( 'Hack Guard', 'wp-simple-firewall' ),
491
- 'sub' => __( 'Threats/Intrusions Detection & Repair', 'wp-simple-firewall' ),
492
- ],
493
- 'key_opts' => [],
494
- 'href_options' => $this->getUrl_AdminPage()
495
- ];
496
-
497
- if ( !$this->isModOptEnabled() ) {
498
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
499
- }
500
- else {
501
- $bGoodFrequency = $oOpts->getScanFrequency() > 1;
502
- $aThis[ 'key_opts' ][ 'frequency' ] = [
503
- 'name' => __( 'Scan Frequency', 'wp-simple-firewall' ),
504
- 'enabled' => $bGoodFrequency,
505
- 'summary' => $bGoodFrequency ?
506
- __( 'Automatic scanners run more than once per day', 'wp-simple-firewall' )
507
- : __( "Automatic scanners only run once per day", 'wp-simple-firewall' ),
508
- 'weight' => 1,
509
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_options' ),
510
- ];
511
-
512
- $bCore = $this->isScanEnabled( 'wcf' );
513
- $aThis[ 'key_opts' ][ 'wcf' ] = [
514
- 'name' => __( 'WP Core File Scan', 'wp-simple-firewall' ),
515
- 'enabled' => $bCore,
516
- 'summary' => $bCore ?
517
- __( 'Core files scanned regularly for hacks', 'wp-simple-firewall' )
518
- : __( "Core files are never scanned for hacks!", 'wp-simple-firewall' ),
519
- 'weight' => 2,
520
- 'href' => $this->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
521
- ];
522
- if ( $bCore && !$oOpts->isRepairFileWP() ) {
523
- $aThis[ 'key_opts' ][ 'wcf_repair' ] = [
524
- 'name' => __( 'WP Core File Repair', 'wp-simple-firewall' ),
525
- 'enabled' => $oOpts->isRepairFileWP(),
526
- 'summary' => $oOpts->isRepairFileWP() ?
527
- __( 'Core files are automatically repaired', 'wp-simple-firewall' )
528
- : __( "Core files aren't automatically repaired!", 'wp-simple-firewall' ),
529
- 'weight' => 1,
530
- 'href' => $this->getUrl_DirectLinkToOption( 'file_repair_areas' ),
531
- ];
532
- }
533
-
534
- $bUcf = $this->isScanEnabled( 'ufc' );
535
- $aThis[ 'key_opts' ][ 'ufc' ] = [
536
- 'name' => __( 'Unrecognised Files', 'wp-simple-firewall' ),
537
- 'enabled' => $bUcf,
538
- 'summary' => $bUcf ?
539
- __( 'Core directories scanned regularly for unrecognised files', 'wp-simple-firewall' )
540
- : __( "WP Core is never scanned for unrecognised files!", 'wp-simple-firewall' ),
541
- 'weight' => 2,
542
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
543
- ];
544
- if ( $bUcf && !$oOpts->isUfsDeleteFiles() ) {
545
- $aThis[ 'key_opts' ][ 'ufc_repair' ] = [
546
- 'name' => __( 'Unrecognised Files Removal', 'wp-simple-firewall' ),
547
- 'enabled' => $oOpts->isUfsDeleteFiles(),
548
- 'summary' => $oOpts->isUfsDeleteFiles() ?
549
- __( 'Unrecognised files are automatically removed', 'wp-simple-firewall' )
550
- : __( "Unrecognised files aren't automatically removed!", 'wp-simple-firewall' ),
551
- 'weight' => 1,
552
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
553
- ];
554
- }
555
-
556
- $bWpv = $this->isScanEnabled( 'wpv' );
557
- $aThis[ 'key_opts' ][ 'wpv' ] = [
558
- 'name' => __( 'Vulnerability Scan', 'wp-simple-firewall' ),
559
- 'enabled' => $bWpv,
560
- 'summary' => $bWpv ?
561
- __( 'Regularly scanning for known vulnerabilities', 'wp-simple-firewall' )
562
- : __( "Plugins/Themes never scanned for vulnerabilities!", 'wp-simple-firewall' ),
563
- 'weight' => 2,
564
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
565
- ];
566
- $bWpvAutoUpdates = $oOpts->isWpvulnAutoupdatesEnabled();
567
- if ( $bWpv && !$bWpvAutoUpdates ) {
568
- $aThis[ 'key_opts' ][ 'wpv_repair' ] = [
569
- 'name' => __( 'Auto Update', 'wp-simple-firewall' ),
570
- 'enabled' => $bWpvAutoUpdates,
571
- 'summary' => $bWpvAutoUpdates ?
572
- __( 'Vulnerable items are automatically updated', 'wp-simple-firewall' )
573
- : __( "Vulnerable items aren't automatically updated!", 'wp-simple-firewall' ),
574
- 'weight' => 1,
575
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
576
- ];
577
- }
578
-
579
- $bPtg = $this->isScanEnabled( 'ptg' );
580
- $aThis[ 'key_opts' ][ 'ptg' ] = [
581
- 'title' => $aScanNames[ 'ptg' ],
582
- 'name' => __( 'Plugin/Theme Guard', 'wp-simple-firewall' ),
583
- 'enabled' => $bPtg,
584
- 'summary' => $bPtg ?
585
- __( 'Plugins and Themes are guarded against tampering', 'wp-simple-firewall' )
586
- : __( "Plugins and Themes are never scanned for tampering!", 'wp-simple-firewall' ),
587
- 'weight' => 2,
588
- 'href' => $this->getUrl_DirectLinkToOption( 'ptg_enable' ),
589
- ];
590
-
591
- $bMal = $this->isScanEnabled( 'mal' );
592
- $aThis[ 'key_opts' ][ 'mal' ] = [
593
- 'title' => $aScanNames[ 'mal' ],
594
- 'name' => $aScanNames[ 'mal' ],
595
- 'enabled' => $bMal,
596
- 'summary' => $bMal ?
597
- sprintf( __( '%s Scanner is enabled.' ), $aScanNames[ 'mal' ] )
598
- : sprintf( __( '%s Scanner is not enabled.' ), $aScanNames[ 'mal' ] ),
599
- 'weight' => 2,
600
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_mal' ),
601
- ];
602
-
603
- $bApc = $this->isScanEnabled( 'apc' );
604
- $aThis[ 'key_opts' ][ 'apc' ] = [
605
- 'title' => $aScanNames[ 'apc' ],
606
- 'name' => $aScanNames[ 'apc' ],
607
- 'enabled' => $bApc,
608
- 'summary' => $bApc ?
609
- sprintf( __( '%s Scanner is enabled.' ), $aScanNames[ 'apc' ] )
610
- : sprintf( __( '%s Scanner is not enabled.' ), $aScanNames[ 'apc' ] ),
611
- 'weight' => 2,
612
- 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_apc' ),
613
- ];
614
- }
615
-
616
- $aAllData[ $this->getSlug() ] = $aThis;
617
- return $aAllData;
618
- }
619
-
620
  /**
621
  * @return Shield\Databases\FileLocker\Handler
622
  */
@@ -657,8 +342,8 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
657
  foreach ( $oOpts->getScanSlugs() as $sSlug ) {
658
  $this->getScanCon( $sSlug )->purge();
659
  }
660
- $this->getDbHandler_ScanQueue()->deleteTable();
661
- $this->getDbHandler_ScanResults()->deleteTable();
662
  // 2. Clean out the file locker
663
  $this->getFileLocker()->purge();
664
  }
56
  * @return HackGuard\Scan\Controller\Base[]
57
  */
58
  public function getAllScanCons() {
59
+ /** @var HackGuard\Options $opts */
60
+ $opts = $this->getOptions();
61
+ foreach ( $opts->getScanSlugs() as $scanSlug ) {
62
  $this->getScanCon( $scanSlug );
63
  }
64
  return $this->aScanCons;
65
  }
66
 
67
  /**
68
+ * @param string $slug
69
  * @return HackGuard\Scan\Controller\Base|mixed
70
  */
71
+ public function getScanCon( $slug ) {
72
  if ( !is_array( $this->aScanCons ) ) {
73
  $this->aScanCons = [];
74
  }
75
+ if ( !isset( $this->aScanCons[ $slug ] ) ) {
76
+ $class = '\FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\\'.ucwords( $slug );
77
+ if ( @class_exists( $class ) ) {
78
  /** @var HackGuard\Scan\Controller\Base $oObj */
79
+ $oObj = new $class();
80
+ $this->aScanCons[ $slug ] = $oObj->setMod( $this );
81
  }
82
  else {
83
+ $this->aScanCons[ $slug ] = false;
84
  }
85
  }
86
+ return $this->aScanCons[ $slug ];
87
  }
88
 
89
  /**
106
  }
107
 
108
  protected function preProcessOptions() {
109
+ /** @var HackGuard\Options $opts */
110
+ $opts = $this->getOptions();
111
 
112
  $this->cleanFileExclusions();
113
 
114
+ if ( $opts->isOptChanged( 'scan_frequency' ) ) {
115
  /** @var \ICWP_WPSF_Processor_HackProtect $oPro */
116
  $oPro = $this->getProcessor();
117
  $oPro->getSubProScanner()->deleteCron();
118
  }
119
 
120
+ if ( count( $opts->getFilesToLock() ) === 0 || !$this->getCon()
121
+ ->getModule_Plugin()
122
+ ->getShieldNetApiController()
123
+ ->canHandshake() ) {
124
+ $opts->setOpt( 'file_locker', [] );
125
  $this->getFileLocker()->purge();
126
  }
127
 
128
+ $lockFiles = $opts->getFilesToLock();
129
+ if ( in_array( 'root_webconfig', $lockFiles ) && !Services::Data()->isWindows() ) {
130
+ unset( $lockFiles[ array_search( 'root_webconfig', $lockFiles ) ] );
131
+ $opts->setOpt( 'file_locker', $lockFiles );
132
+ }
133
+
134
+ foreach ( $this->getAllScanCons() as $con ) {
135
+ if ( !$con->isEnabled() ) {
136
+ $con->purge();
137
  }
138
  }
139
  }
177
  * @return $this
178
  */
179
  protected function setCustomCronSchedules() {
180
+ /** @var HackGuard\Options $opts */
181
+ $opts = $this->getOptions();
182
+ $nFreq = $opts->getScanFrequency();
183
  Services::WpCron()
184
  ->addNewSchedule(
185
  $this->prefix( sprintf( 'per-day-%s', $nFreq ) ),
254
  public function insertCustomJsVars_Admin() {
255
  parent::insertCustomJsVars_Admin();
256
 
257
+ /** @var HackGuard\Options $opts */
258
+ $opts = $this->getOptions();
259
  if ( Services::WpPost()->isCurrentPage( 'plugins.php' )
260
+ && $opts->isPtgReinstallLinks() && $this->getScanCon( 'ptg' )->isReady() ) {
261
  wp_localize_script(
262
  $this->prefix( 'global-plugin' ),
263
  'icwp_wpsf_vars_hp',
279
  }
280
  }
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  /**
283
  * @return string|false
284
  */
302
  return Services::WpFs()->mkdir( $sDir ) ? $sDir : false;
303
  }
304
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  /**
306
  * @return Shield\Databases\FileLocker\Handler
307
  */
342
  foreach ( $oOpts->getScanSlugs() as $sSlug ) {
343
  $this->getScanCon( $sSlug )->purge();
344
  }
345
+ $this->getDbHandler_ScanQueue()->tableDelete();
346
+ $this->getDbHandler_ScanResults()->tableDelete();
347
  // 2. Clean out the file locker
348
  $this->getFileLocker()->purge();
349
  }
src/features/headers.php CHANGED
@@ -86,54 +86,6 @@ class ICWP_WPSF_FeatureHandler_Headers extends ICWP_WPSF_FeatureHandler_BaseWpsf
86
  $oOpts->setOpt( 'xcsp_hosts', array_unique( $aValidDomains ) );
87
  }
88
 
89
- /**
90
- * @param array $aAllData
91
- * @return array
92
- */
93
- public function addInsightsConfigData( $aAllData ) {
94
- /** @var Headers\Options $oOpts */
95
- $oOpts = $this->getOptions();
96
-
97
- $aThis = [
98
- 'strings' => [
99
- 'title' => __( 'HTTP Security Headers', 'wp-simple-firewall' ),
100
- 'sub' => __( 'Protect Visitors With Powerful HTTP Headers', 'wp-simple-firewall' ),
101
- ],
102
- 'key_opts' => [],
103
- 'href_options' => $this->getUrl_AdminPage()
104
- ];
105
-
106
- if ( !$this->isModOptEnabled() ) {
107
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
108
- }
109
- else {
110
- $bAllEnabled = $oOpts->isEnabledXFrame() && $oOpts->isEnabledXssProtection()
111
- && $oOpts->isEnabledContentTypeHeader() && $oOpts->isReferrerPolicyEnabled();
112
- $aThis[ 'key_opts' ][ 'all' ] = [
113
- 'name' => __( 'HTTP Headers', 'wp-simple-firewall' ),
114
- 'enabled' => $bAllEnabled,
115
- 'summary' => $bAllEnabled ?
116
- __( 'All important security Headers have been set', 'wp-simple-firewall' )
117
- : __( "At least one of the HTTP Headers hasn't been set", 'wp-simple-firewall' ),
118
- 'weight' => 2,
119
- 'href' => $this->getUrl_DirectLinkToSection( 'section_security_headers' ),
120
- ];
121
- $bCsp = $oOpts->isEnabledContentSecurityPolicy();
122
- $aThis[ 'key_opts' ][ 'csp' ] = [
123
- 'name' => __( 'Content Security Policies', 'wp-simple-firewall' ),
124
- 'enabled' => $bCsp,
125
- 'summary' => $bCsp ?
126
- __( 'Content Security Policy is turned on', 'wp-simple-firewall' )
127
- : __( "Content Security Policies aren't active", 'wp-simple-firewall' ),
128
- 'weight' => 1,
129
- 'href' => $this->getUrl_DirectLinkToSection( 'section_content_security_policy' ),
130
- ];
131
- }
132
-
133
- $aAllData[ $this->getSlug() ] = $aThis;
134
- return $aAllData;
135
- }
136
-
137
  /**
138
  * @return string
139
  */
86
  $oOpts->setOpt( 'xcsp_hosts', array_unique( $aValidDomains ) );
87
  }
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  /**
90
  * @return string
91
  */
src/features/insights.php CHANGED
@@ -70,10 +70,10 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
70
 
71
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oModUsers */
72
  $oModUsers = $oCon->getModule( 'user_management' );
73
- /** @var ICWP_WPSF_Processor_HackProtect $oProHp */
74
- $oProHp = $oCon->getModule( 'hack_protect' )->getProcessor();
75
- /** @var ICWP_WPSF_FeatureHandler_License $oModLicense */
76
- $oModLicense = $oCon->getModule( 'license' );
77
 
78
  $oModPlugin = $oCon->getModule_Plugin();
79
  $oTourManager = $oModPlugin->getTourManager();
@@ -97,6 +97,8 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
97
  'flags' => [],
98
  'strings' => [
99
  'table_title' => __( 'Audit Trail', 'wp-simple-firewall' ),
 
 
100
  'title_filter_form' => __( 'Audit Trail Filters', 'wp-simple-firewall' ),
101
  'username_ignores' => __( "Providing a username will cause the 'logged-in' filter to be ignored.", 'wp-simple-firewall' ),
102
  'exclude_your_ip' => __( 'Exclude Your Current IP', 'wp-simple-firewall' ),
@@ -111,6 +113,9 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
111
  'unique_ips' => $oAuditSelect->getDistinctIps(),
112
  'unique_users' => $oAuditSelect->getDistinctUsernames(),
113
  ],
 
 
 
114
  ];
115
  break;
116
 
@@ -223,11 +228,11 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
223
  break;
224
 
225
  case 'license':
226
- $aData = $oModLicense->buildInsightsVars();
227
  break;
228
 
229
  case 'scans':
230
- $aData = $oProHp->buildInsightsVars();
231
  break;
232
 
233
  case 'importexport':
@@ -279,7 +284,6 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
279
  $aData = [
280
  'vars' => [
281
  'config_cards' => $this->getConfigCardsData(),
282
- 'summary' => $this->getInsightsModsSummary(),
283
  'insight_events' => $this->getRecentEvents(),
284
  'insight_notices' => $aSecNotices,
285
  'insight_notices_count' => $nNoticesCount,
@@ -331,7 +335,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
331
  'notes' => __( 'Notes', 'wp-simple-firewall' ),
332
  // 'reports' => __( 'Reports', 'wp-simple-firewall' ),
333
  'importexport' => sprintf( '%s/%s', __( 'Import', 'wp-simple-firewall' ), __( 'Export', 'wp-simple-firewall' ) ),
334
- // 'debug' => __( 'Debug', 'wp-simple-firewall' ),
335
  ];
336
  if ( $bIsPro ) {
337
  unset( $aTopNav[ 'license' ] );
@@ -350,27 +354,29 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
350
 
351
  $aSearchSelect = [];
352
  $aSettingsSubNav = [];
353
- foreach ( $this->getModulesSummaryData() as $sSlug => $aSubMod ) {
354
- $aSettingsSubNav[ $sSlug ] = [
355
- 'href' => add_query_arg( [ 'subnav' => $sSlug ], $aTopNav[ 'settings' ][ 'href' ] ),
356
- 'name' => $aSubMod[ 'name' ],
357
- 'active' => $sSlug === $sSubNavSection,
358
- 'slug' => $sSlug
359
- ];
 
360
 
361
- $aSearchSelect[ $aSubMod[ 'name' ] ] = $aSubMod[ 'options' ];
 
362
  }
363
- $aTopNav[ 'settings' ][ 'subnavs' ] = $aSettingsSubNav;
364
 
365
- // $aTopNav[ 'full_options' ] = [
366
- // 'href' => $this->getCon()->getModule_Plugin( )->getUrl_AdminPage(),
367
- // 'name' => __( 'Settings', 'wp-simple-firewall' ),
368
- // 'active' => false
369
- // ];
 
370
 
371
- $oDp = Services::DataManipulation();
372
- $aData = $oDp->mergeArraysRecursive(
373
- $this->getBaseDisplayData(),
374
  [
375
  'classes' => [
376
  'page_container' => 'page-insights page-'.$sNavSection
@@ -404,23 +410,23 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
404
 
405
  if ( $this->isThisModulePage() ) {
406
 
407
- $oCon = $this->getCon();
408
- $aStdDepsJs = [ $this->prefix( 'plugin' ) ];
409
  $sNav = Services::Request()->query( 'inav', 'overview' );
410
 
411
- $oModPlugin = $oCon->getModule_Plugin();
412
  $oTourManager = $oModPlugin->getTourManager();
413
  switch ( $sNav ) {
414
 
415
  case 'importexport':
416
 
417
  $sAsset = 'shield-import';
418
- $sUnique = $oCon->prefix( $sAsset );
419
  wp_register_script(
420
  $sUnique,
421
- $oCon->getPluginUrl_Js( $sAsset ),
422
  $aStdDepsJs,
423
- $oCon->getVersion(),
424
  false
425
  );
426
  wp_enqueue_script( $sUnique );
@@ -436,12 +442,12 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
436
  array_unshift( $aJsAssets, 'introjs.min.js' );
437
  }
438
  foreach ( $aJsAssets as $sAsset ) {
439
- $sUnique = $oCon->prefix( $sAsset );
440
  wp_register_script(
441
  $sUnique,
442
- $oCon->getPluginUrl_Js( $sAsset ),
443
  $aDeps,
444
- $oCon->getVersion(),
445
  false
446
  );
447
  wp_enqueue_script( $sUnique );
@@ -454,12 +460,12 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
454
  array_unshift( $aCssAssets, 'introjs.min.css' );
455
  }
456
  foreach ( $aCssAssets as $sAsset ) {
457
- $sUnique = $oCon->prefix( $sAsset );
458
  wp_register_style(
459
  $sUnique,
460
- $oCon->getPluginUrl_Css( $sAsset ),
461
  $aDeps,
462
- $oCon->getVersion(),
463
  false
464
  );
465
  wp_enqueue_style( $sUnique );
@@ -477,12 +483,12 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
477
  case 'users':
478
 
479
  $sAsset = 'shield-tables';
480
- $sUnique = $oCon->prefix( $sAsset );
481
  wp_register_script(
482
  $sUnique,
483
- $oCon->getPluginUrl_Js( $sAsset ),
484
  $aStdDepsJs,
485
- $oCon->getVersion(),
486
  false
487
  );
488
  wp_enqueue_script( $sUnique );
@@ -490,24 +496,24 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
490
  $aStdDepsJs[] = $sUnique;
491
  if ( $sNav == 'scans' ) {
492
  $sAsset = 'shield-scans';
493
- $sUnique = $oCon->prefix( $sAsset );
494
  wp_register_script(
495
  $sUnique,
496
- $oCon->getPluginUrl_Js( $sAsset ),
497
  array_unique( $aStdDepsJs ),
498
- $oCon->getVersion(),
499
  false
500
  );
501
  wp_enqueue_script( $sUnique );
502
  }
503
 
504
  if ( $sNav == 'audit' ) {
505
- $sUnique = $this->prefix( 'datepicker' );
506
  wp_register_script(
507
  $sUnique, //TODO: use an includes services for CNDJS
508
  'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js',
509
  array_unique( $aStdDepsJs ),
510
- $oCon->getVersion(),
511
  false
512
  );
513
  wp_enqueue_script( $sUnique );
@@ -516,7 +522,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
516
  $sUnique,
517
  'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css',
518
  [],
519
- $oCon->getVersion(),
520
  false
521
  );
522
  wp_enqueue_style( $sUnique );
@@ -526,7 +532,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
526
  }
527
 
528
  wp_localize_script(
529
- $this->prefix( 'plugin' ),
530
  'icwp_wpsf_vars_insights',
531
  [
532
  'strings' => [
@@ -568,7 +574,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
568
  $oStrs = $oEvtsMod->getStrings();
569
  $aEvtNames = $oStrs->getEventNames();
570
 
571
- $aData = [
572
  'ajax' => [
573
  'render_chart' => $oEvtsMod->getAjaxActionData( 'render_chart', true ),
574
  ],
@@ -588,61 +594,57 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
588
  )
589
  ],
590
  ];
591
- return $aData;
592
- }
593
-
594
- /**
595
- * @return array[]
596
- */
597
- protected function getInsightsModsSummary() {
598
- $aMods = [];
599
- foreach ( $this->getModulesSummaryData() as $aMod ) {
600
- if ( !in_array( $aMod[ 'slug' ], [ 'insights' ] ) ) {
601
- $aMods[] = $aMod;
602
- }
603
- }
604
- return $aMods;
605
  }
606
 
607
  /**
608
  * @return array[]
609
  */
610
  protected function getConfigCardsData() {
611
- return apply_filters( $this->prefix( 'collect_summary' ), [] );
 
 
 
 
612
  }
613
 
614
  /**
615
  * @return array[]
616
  */
617
  protected function getNotices() {
618
- $aAll = apply_filters(
619
- $this->prefix( 'collect_notices' ),
620
- [
621
- 'plugins' => $this->getNoticesPlugins(),
622
- 'themes' => $this->getNoticesThemes(),
623
- 'core' => $this->getNoticesCore(),
624
- ]
625
- );
626
 
627
- // order and then remove empties
628
- return array_filter(
629
- array_merge(
630
- [
631
- 'site' => [],
632
- 'sec_admin' => [],
633
- 'scans' => [],
634
- 'core' => [],
635
- 'plugins' => [],
636
- 'themes' => [],
637
- 'users' => [],
638
- 'lockdown' => [],
639
- ],
640
- $aAll
641
- ),
642
- function ( $aSection ) {
643
- return !empty( $aSection[ 'count' ] );
644
- }
645
- );
 
 
 
 
 
 
646
  }
647
 
648
  protected function getNoticesSite() {
70
 
71
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oModUsers */
72
  $oModUsers = $oCon->getModule( 'user_management' );
73
+ /** @var Shield\Modules\HackGuard\UI $UIHackGuard */
74
+ $UIHackGuard = $oCon->getModule_HackGuard()->getUIHandler();
75
+ /** @var Shield\Modules\License\UI $UILicense */
76
+ $UILicense = $oCon->getModule_License()->getUIHandler();
77
 
78
  $oModPlugin = $oCon->getModule_Plugin();
79
  $oTourManager = $oModPlugin->getTourManager();
97
  'flags' => [],
98
  'strings' => [
99
  'table_title' => __( 'Audit Trail', 'wp-simple-firewall' ),
100
+ 'sub_title' => __( 'Use the Audit Trail Glossary for help interpreting log entries.', 'wp-simple-firewall' ),
101
+ 'audit_trail_glossary' => __( 'Audit Trail Glossary', 'wp-simple-firewall' ),
102
  'title_filter_form' => __( 'Audit Trail Filters', 'wp-simple-firewall' ),
103
  'username_ignores' => __( "Providing a username will cause the 'logged-in' filter to be ignored.", 'wp-simple-firewall' ),
104
  'exclude_your_ip' => __( 'Exclude Your Current IP', 'wp-simple-firewall' ),
113
  'unique_ips' => $oAuditSelect->getDistinctIps(),
114
  'unique_users' => $oAuditSelect->getDistinctUsernames(),
115
  ],
116
+ 'hrefs' => [
117
+ 'audit_trail_glossary' => 'https://shsec.io/audittrailglossary',
118
+ ],
119
  ];
120
  break;
121
 
228
  break;
229
 
230
  case 'license':
231
+ $aData = $UILicense->buildInsightsVars();
232
  break;
233
 
234
  case 'scans':
235
+ $aData = $UIHackGuard->buildInsightsVars();
236
  break;
237
 
238
  case 'importexport':
284
  $aData = [
285
  'vars' => [
286
  'config_cards' => $this->getConfigCardsData(),
 
287
  'insight_events' => $this->getRecentEvents(),
288
  'insight_notices' => $aSecNotices,
289
  'insight_notices_count' => $nNoticesCount,
335
  'notes' => __( 'Notes', 'wp-simple-firewall' ),
336
  // 'reports' => __( 'Reports', 'wp-simple-firewall' ),
337
  'importexport' => sprintf( '%s/%s', __( 'Import', 'wp-simple-firewall' ), __( 'Export', 'wp-simple-firewall' ) ),
338
+ // 'debug' => __( 'Debug', 'wp-simple-firewall' ),
339
  ];
340
  if ( $bIsPro ) {
341
  unset( $aTopNav[ 'license' ] );
354
 
355
  $aSearchSelect = [];
356
  $aSettingsSubNav = [];
357
+ foreach ( $this->getModulesSummaryData() as $slug => $summary ) {
358
+ if ( $summary[ 'show_mod_opts' ] ) {
359
+ $aSettingsSubNav[ $slug ] = [
360
+ 'href' => add_query_arg( [ 'subnav' => $slug ], $aTopNav[ 'settings' ][ 'href' ] ),
361
+ 'name' => $summary[ 'name' ],
362
+ 'active' => $slug === $sSubNavSection,
363
+ 'slug' => $slug
364
+ ];
365
 
366
+ $aSearchSelect[ $summary[ 'name' ] ] = $summary[ 'options' ];
367
+ }
368
  }
 
369
 
370
+ if ( empty( $aSettingsSubNav ) ) {
371
+ unset( $aTopNav[ 'settings' ] );
372
+ }
373
+ else {
374
+ $aTopNav[ 'settings' ][ 'subnavs' ] = $aSettingsSubNav;
375
+ }
376
 
377
+ $DP = Services::DataManipulation();
378
+ $aData = $DP->mergeArraysRecursive(
379
+ $this->getUIHandler()->getBaseDisplayData(),
380
  [
381
  'classes' => [
382
  'page_container' => 'page-insights page-'.$sNavSection
410
 
411
  if ( $this->isThisModulePage() ) {
412
 
413
+ $con = $this->getCon();
414
+ $aStdDepsJs = [ $con->prefix( 'plugin' ) ];
415
  $sNav = Services::Request()->query( 'inav', 'overview' );
416
 
417
+ $oModPlugin = $con->getModule_Plugin();
418
  $oTourManager = $oModPlugin->getTourManager();
419
  switch ( $sNav ) {
420
 
421
  case 'importexport':
422
 
423
  $sAsset = 'shield-import';
424
+ $sUnique = $con->prefix( $sAsset );
425
  wp_register_script(
426
  $sUnique,
427
+ $con->getPluginUrl_Js( $sAsset ),
428
  $aStdDepsJs,
429
+ $con->getVersion(),
430
  false
431
  );
432
  wp_enqueue_script( $sUnique );
442
  array_unshift( $aJsAssets, 'introjs.min.js' );
443
  }
444
  foreach ( $aJsAssets as $sAsset ) {
445
+ $sUnique = $con->prefix( $sAsset );
446
  wp_register_script(
447
  $sUnique,
448
+ $con->getPluginUrl_Js( $sAsset ),
449
  $aDeps,
450
+ $con->getVersion(),
451
  false
452
  );
453
  wp_enqueue_script( $sUnique );
460
  array_unshift( $aCssAssets, 'introjs.min.css' );
461
  }
462
  foreach ( $aCssAssets as $sAsset ) {
463
+ $sUnique = $con->prefix( $sAsset );
464
  wp_register_style(
465
  $sUnique,
466
+ $con->getPluginUrl_Css( $sAsset ),
467
  $aDeps,
468
+ $con->getVersion(),
469
  false
470
  );
471
  wp_enqueue_style( $sUnique );
483
  case 'users':
484
 
485
  $sAsset = 'shield-tables';
486
+ $sUnique = $con->prefix( $sAsset );
487
  wp_register_script(
488
  $sUnique,
489
+ $con->getPluginUrl_Js( $sAsset ),
490
  $aStdDepsJs,
491
+ $con->getVersion(),
492
  false
493
  );
494
  wp_enqueue_script( $sUnique );
496
  $aStdDepsJs[] = $sUnique;
497
  if ( $sNav == 'scans' ) {
498
  $sAsset = 'shield-scans';
499
+ $sUnique = $con->prefix( $sAsset );
500
  wp_register_script(
501
  $sUnique,
502
+ $con->getPluginUrl_Js( $sAsset ),
503
  array_unique( $aStdDepsJs ),
504
+ $con->getVersion(),
505
  false
506
  );
507
  wp_enqueue_script( $sUnique );
508
  }
509
 
510
  if ( $sNav == 'audit' ) {
511
+ $sUnique = $con->prefix( 'datepicker' );
512
  wp_register_script(
513
  $sUnique, //TODO: use an includes services for CNDJS
514
  'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js',
515
  array_unique( $aStdDepsJs ),
516
+ $con->getVersion(),
517
  false
518
  );
519
  wp_enqueue_script( $sUnique );
522
  $sUnique,
523
  'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css',
524
  [],
525
+ $con->getVersion(),
526
  false
527
  );
528
  wp_enqueue_style( $sUnique );
532
  }
533
 
534
  wp_localize_script(
535
+ $con->prefix( 'plugin' ),
536
  'icwp_wpsf_vars_insights',
537
  [
538
  'strings' => [
574
  $oStrs = $oEvtsMod->getStrings();
575
  $aEvtNames = $oStrs->getEventNames();
576
 
577
+ return [
578
  'ajax' => [
579
  'render_chart' => $oEvtsMod->getAjaxActionData( 'render_chart', true ),
580
  ],
594
  )
595
  ],
596
  ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  }
598
 
599
  /**
600
  * @return array[]
601
  */
602
  protected function getConfigCardsData() {
603
+ $data = [];
604
+ foreach ( $this->getCon()->modules as $mod ) {
605
+ $data[ $mod->getSlug() ] = $mod->getUIHandler()->getInsightsConfigCardData();
606
+ }
607
+ return array_filter( $data );
608
  }
609
 
610
  /**
611
  * @return array[]
612
  */
613
  protected function getNotices() {
614
+ $aAll = [
615
+ 'plugins' => $this->getNoticesPlugins(),
616
+ 'themes' => $this->getNoticesThemes(),
617
+ 'core' => $this->getNoticesCore(),
618
+ ];
619
+ foreach ( $this->getCon()->modules as $module ) {
620
+ $aAll[ $module->getSlug() ] = $module->getUIHandler()->getInsightsNoticesData();
621
+ }
622
 
623
+ // remove empties, add a count, then order.
624
+ return array_filter( array_merge(
625
+ [
626
+ 'plugin' => [],
627
+ 'admin_access_restriction' => [],
628
+ 'hack_protect' => [],
629
+ 'core' => [],
630
+ 'plugins' => [],
631
+ 'themes' => [],
632
+ 'user_management' => [],
633
+ 'lockdown' => [],
634
+ ],
635
+ array_map(
636
+ function ( $notices ) {
637
+ $notices[ 'count' ] = count( $notices[ 'messages' ] );
638
+ return $notices;
639
+ },
640
+ array_filter(
641
+ $aAll,
642
+ function ( $notices ) {
643
+ return !empty( $notices[ 'messages' ] );
644
+ }
645
+ )
646
+ )
647
+ ) );
648
  }
649
 
650
  protected function getNoticesSite() {
src/features/ips.php CHANGED
@@ -107,40 +107,6 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
107
  return $this->oOffenseTracker;
108
  }
109
 
110
- /**
111
- * @param string $sSection
112
- * @return array
113
- */
114
- protected function getSectionWarnings( $sSection ) {
115
- $aWarnings = [];
116
-
117
- /** @var IPs\Options $oOpts */
118
- $oOpts = $this->getOptions();
119
-
120
- switch ( $sSection ) {
121
-
122
- case 'section_auto_black_list':
123
- if ( !$oOpts->isEnabledAutoBlackList() ) {
124
- $aWarnings[] = sprintf( '%s: %s', __( 'Note', 'wp-simple-firewall' ), __( "IP blocking is turned-off because the offenses limit is set to 0.", 'wp-simple-firewall' ) );
125
- }
126
- break;
127
-
128
- case 'section_behaviours':
129
- case 'section_probes':
130
- case 'section_logins':
131
- if ( !$oOpts->isEnabledAutoBlackList() ) {
132
- $aWarnings[] = __( "Since the offenses limit is set to 0, these options have no effect.", 'wp-simple-firewall' );
133
- }
134
-
135
- if ( $sSection == 'section_behaviours' && strlen( Services::Request()->getUserAgent() ) == 0 ) {
136
- $aWarnings[] = __( "Your User Agent appears to be empty. We recommend not turning on this option.", 'wp-simple-firewall' );
137
- }
138
- break;
139
- }
140
-
141
- return $aWarnings;
142
- }
143
-
144
  /**
145
  * @param string $sOptKey
146
  * @return string
@@ -181,8 +147,6 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
181
  parent::onPluginShutdown();
182
  }
183
 
184
- /**
185
- */
186
  protected function addFilterIpsToWhiteList() {
187
  $aIps = [];
188
  $oSp = Services::ServiceProviders();
107
  return $this->oOffenseTracker;
108
  }
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  /**
111
  * @param string $sOptKey
112
  * @return string
147
  parent::onPluginShutdown();
148
  }
149
 
 
 
150
  protected function addFilterIpsToWhiteList() {
151
  $aIps = [];
152
  $oSp = Services::ServiceProviders();
src/features/license.php CHANGED
@@ -43,85 +43,6 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
43
  return $this->oWpHashesTokenManager;
44
  }
45
 
46
- /**
47
- * @return bool
48
- */
49
- protected function isEnabledForUiSummary() {
50
- return $this->getLicenseHandler()->hasValidWorkingLicense();
51
- }
52
-
53
- public function buildInsightsVars() {
54
- $oWp = Services::WpGeneral();
55
- $oCon = $this->getCon();
56
- $oCarbon = Services::Request()->carbon();
57
-
58
- $oCurrent = $this->getLicenseHandler()->getLicense();
59
-
60
- $nExpiresAt = $oCurrent->getExpiresAt();
61
- if ( $nExpiresAt > 0 && $nExpiresAt != PHP_INT_MAX ) {
62
- $sExpiresAt = $oCarbon->setTimestamp( $nExpiresAt )->diffForHumans()
63
- .sprintf( '<br/><small>%s</small>', $oWp->getTimeStampForDisplay( $nExpiresAt ) );
64
- }
65
- else {
66
- $sExpiresAt = 'n/a';
67
- }
68
-
69
- $nLastReqAt = $oCurrent->last_request_at;
70
- if ( empty( $nLastReqAt ) ) {
71
- $sChecked = __( 'Never', 'wp-simple-firewall' );
72
- }
73
- else {
74
- $sChecked = $oCarbon->setTimestamp( $nLastReqAt )->diffForHumans()
75
- .sprintf( '<br/><small>%s</small>', $oWp->getTimeStampForDisplay( $nLastReqAt ) );
76
- }
77
- $aLicenseTableVars = [
78
- 'product_name' => $oCurrent->is_central ?
79
- $this->getDef( 'license_item_name_sc' ) :
80
- $this->getDef( 'license_item_name' ),
81
- 'license_active' => $this->getLicenseHandler()->hasValidWorkingLicense() ?
82
- __( '&#10004;', 'wp-simple-firewall' ) : __( '&#10006;', 'wp-simple-firewall' ),
83
- 'license_expires' => $sExpiresAt,
84
- 'license_email' => $oCurrent->customer_email,
85
- 'last_checked' => $sChecked,
86
- 'last_errors' => $this->hasLastErrors() ? $this->getLastErrors( true ) : '',
87
- 'wphashes_token' => $this->getWpHashesTokenManager()->hasToken() ?
88
- __( '&#10004;', 'wp-simple-firewall' ) : __( '&#10006;', 'wp-simple-firewall' ),
89
- 'installation_id' => $oCon->getSiteInstallationId(),
90
- ];
91
- return [
92
- 'vars' => [
93
- 'license_table' => $aLicenseTableVars,
94
- 'activation_url' => $oWp->getHomeUrl(),
95
- 'error' => $this->getLastErrors( true )
96
- ],
97
- 'inputs' => [
98
- 'license_key' => [
99
- 'name' => $oCon->prefixOption( 'license_key' ),
100
- 'maxlength' => $this->getDef( 'license_key_length' ),
101
- ]
102
- ],
103
- 'ajax' => [
104
- 'license_handling' => $this->getAjaxActionData( 'license_handling' ),
105
- 'connection_debug' => $this->getAjaxActionData( 'connection_debug' )
106
- ],
107
- 'aHrefs' => [
108
- 'shield_pro_url' => 'https://shsec.io/shieldpro',
109
- 'shield_pro_more_info_url' => 'https://shsec.io/shld1',
110
- 'iframe_url' => $this->getDef( 'landing_page_url' ),
111
- 'keyless_cp' => $this->getDef( 'keyless_cp' ),
112
- ],
113
- 'flags' => [
114
- 'show_ads' => false,
115
- 'button_enabled_check' => true,
116
- 'show_standard_options' => false,
117
- 'show_alt_content' => true,
118
- 'is_pro' => $this->isPremium(),
119
- 'has_error' => $this->hasLastErrors()
120
- ],
121
- 'strings' => $this->getStrings()->getDisplayStrings(),
122
- ];
123
- }
124
-
125
  protected function redirectToInsightsSubPage() {
126
  Services::Response()->redirect(
127
  $this->getCon()->getModule_Insights()->getUrl_AdminPage(),
43
  return $this->oWpHashesTokenManager;
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  protected function redirectToInsightsSubPage() {
47
  Services::Response()->redirect(
48
  $this->getCon()->getModule_Insights()->getUrl_AdminPage(),
src/features/lockdown.php CHANGED
@@ -1,12 +1,12 @@
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
4
- use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWpsf {
7
 
8
  /**
9
  * @return string[]
 
10
  */
11
  private function getRestApiAnonymousExclusions() {
12
  $aExcl = $this->getOpt( 'api_namespace_exclusions' );
@@ -17,15 +17,18 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
17
  }
18
 
19
  /**
20
- * @param string $sNamespace
21
  * @return bool
22
  */
23
- public function isPermittedAnonRestApiNamespace( $sNamespace ) {
24
- return in_array( $sNamespace, $this->getRestApiAnonymousExclusions() );
 
 
25
  }
26
 
27
  /**
28
  * @return bool
 
29
  */
30
  public function isOptFileEditingDisabled() {
31
  return $this->isOpt( 'disable_file_editing', 'Y' );
@@ -33,6 +36,7 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
33
 
34
  /**
35
  * @return bool
 
36
  */
37
  public function isRestApiAnonymousAccessDisabled() {
38
  return $this->isOpt( 'disable_anonymous_restapi', 'Y' );
@@ -40,6 +44,7 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
40
 
41
  /**
42
  * @return bool
 
43
  */
44
  public function isXmlrpcDisabled() {
45
  return $this->isOpt( 'disable_xmlrpc', 'Y' );
@@ -53,95 +58,12 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
53
  * @return $this
54
  */
55
  private function cleanApiExclusions() {
56
- $aExt = $this->cleanStringArray( $this->getRestApiAnonymousExclusions(), '#[^a-z0-9_-]#i' );
 
 
57
  return $this->setOpt( 'api_namespace_exclusions', $aExt );
58
  }
59
 
60
- /**
61
- * @param array $aAllNotices
62
- * @return array
63
- */
64
- public function addInsightsNoticeData( $aAllNotices ) {
65
- $aNotices = [
66
- 'title' => __( 'WP Lockdown', 'wp-simple-firewall' ),
67
- 'messages' => []
68
- ];
69
-
70
- { //edit plugins
71
- $bEditingDisabled = $this->isOptFileEditingDisabled() || !current_user_can( 'edit_plugins' );
72
- if ( !$bEditingDisabled ) { //assumes current user is admin
73
- $aNotices[ 'messages' ][ 'disallow_file_edit' ] = [
74
- 'title' => __( 'File Editing via WP', 'wp-simple-firewall' ),
75
- 'message' => __( 'Direct editing of plugin/theme files is permitted.', 'wp-simple-firewall' ),
76
- 'href' => $this->getUrl_DirectLinkToOption( 'disable_file_editing' ),
77
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
78
- 'rec' => __( 'WP Plugin file editing should be disabled.', 'wp-simple-firewall' )
79
- ];
80
- }
81
- }
82
-
83
- $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
84
-
85
- $aAllNotices[ 'lockdown' ] = $aNotices;
86
- return $aAllNotices;
87
- }
88
-
89
- /**
90
- * @param array $aAllData
91
- * @return array
92
- */
93
- public function addInsightsConfigData( $aAllData ) {
94
- $aThis = [
95
- 'strings' => [
96
- 'title' => __( 'WordPress Lockdown', 'wp-simple-firewall' ),
97
- 'sub' => __( 'Restrict WP Functionality e.g. XMLRPC & REST API', 'wp-simple-firewall' ),
98
- ],
99
- 'key_opts' => [],
100
- 'href_options' => $this->getUrl_AdminPage()
101
- ];
102
-
103
- if ( !$this->isModOptEnabled() ) {
104
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
105
- }
106
- else {
107
- $bEditingDisabled = $this->isOptFileEditingDisabled() || !current_user_can( 'edit_plugins' );
108
- $aThis[ 'key_opts' ][ 'editing' ] = [
109
- 'name' => __( 'File Editing via WP', 'wp-simple-firewall' ),
110
- 'enabled' => $bEditingDisabled,
111
- 'summary' => $bEditingDisabled ?
112
- __( 'File editing is disabled', 'wp-simple-firewall' )
113
- : __( "File editing is permitted through WP admin", 'wp-simple-firewall' ),
114
- 'weight' => 2,
115
- 'href' => $this->getUrl_DirectLinkToOption( 'disable_file_editing' ),
116
- ];
117
-
118
- $bXml = $this->isXmlrpcDisabled();
119
- $aThis[ 'key_opts' ][ 'xml' ] = [
120
- 'name' => __( 'XML-RPC', 'wp-simple-firewall' ),
121
- 'enabled' => $bXml,
122
- 'summary' => $bXml ?
123
- __( 'XML-RPC is disabled', 'wp-simple-firewall' )
124
- : __( "XML-RPC is not blocked", 'wp-simple-firewall' ),
125
- 'weight' => 1,
126
- 'href' => $this->getUrl_DirectLinkToOption( 'disable_xmlrpc' ),
127
- ];
128
-
129
- $bApi = $this->isRestApiAnonymousAccessDisabled();
130
- $aThis[ 'key_opts' ][ 'api' ] = [
131
- 'name' => __( 'REST API', 'wp-simple-firewall' ),
132
- 'enabled' => $bApi,
133
- 'summary' => $bApi ?
134
- __( 'Anonymous REST API is disabled', 'wp-simple-firewall' )
135
- : __( "Anonymous REST API is allowed", 'wp-simple-firewall' ),
136
- 'weight' => 1,
137
- 'href' => $this->getUrl_DirectLinkToOption( 'disable_anonymous_restapi' ),
138
- ];
139
- }
140
-
141
- $aAllData[ $this->getSlug() ] = $aThis;
142
- return $aAllData;
143
- }
144
-
145
  /**
146
  * @return string
147
  */
1
  <?php
2
 
3
  use FernleafSystems\Wordpress\Plugin\Shield;
 
4
 
5
  class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWpsf {
6
 
7
  /**
8
  * @return string[]
9
+ * @deprecated 9.2.0
10
  */
11
  private function getRestApiAnonymousExclusions() {
12
  $aExcl = $this->getOpt( 'api_namespace_exclusions' );
17
  }
18
 
19
  /**
20
+ * @param string $namespace
21
  * @return bool
22
  */
23
+ public function isPermittedAnonRestApiNamespace( $namespace ) {
24
+ /** @var Shield\Modules\Lockdown\Options $opts */
25
+ $opts = $this->getOptions();
26
+ return in_array( $namespace, $opts->getRestApiAnonymousExclusions() );
27
  }
28
 
29
  /**
30
  * @return bool
31
+ * @deprecated 9.2.0
32
  */
33
  public function isOptFileEditingDisabled() {
34
  return $this->isOpt( 'disable_file_editing', 'Y' );
36
 
37
  /**
38
  * @return bool
39
+ * @deprecated 9.2.0
40
  */
41
  public function isRestApiAnonymousAccessDisabled() {
42
  return $this->isOpt( 'disable_anonymous_restapi', 'Y' );
44
 
45
  /**
46
  * @return bool
47
+ * @deprecated 9.2.0
48
  */
49
  public function isXmlrpcDisabled() {
50
  return $this->isOpt( 'disable_xmlrpc', 'Y' );
58
  * @return $this
59
  */
60
  private function cleanApiExclusions() {
61
+ /** @var Shield\Modules\Lockdown\Options $opts */
62
+ $opts = $this->getOptions();
63
+ $aExt = $this->cleanStringArray( $opts->getRestApiAnonymousExclusions(), '#[^a-z0-9_-]#i' );
64
  return $this->setOpt( 'api_namespace_exclusions', $aExt );
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  /**
68
  * @return string
69
  */
src/features/login_protect.php CHANGED
@@ -128,8 +128,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
128
  ->sendEmailWithWrap( $sEmail, $sEmailSubject, $aMessage );
129
  }
130
 
131
- /**
132
- */
133
  private function cleanLoginUrlPath() {
134
  $sCustomLoginPath = $this->getCustomLoginPath();
135
  if ( !empty( $sCustomLoginPath ) ) {
@@ -274,7 +272,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
274
  * @return string
275
  */
276
  public function getLoginIntentRequestFlag() {
277
- return $this->prefix( 'login-intent-request' );
278
  }
279
 
280
  /**
@@ -307,55 +305,11 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
307
  return $this->setOpt( 'enable_login_gasp_check', $bEnabled ? 'Y' : 'N' );
308
  }
309
 
310
- /**
311
- * @param string $sSection
312
- * @return array
313
- */
314
- protected function getSectionWarnings( $sSection ) {
315
- $aWarnings = [];
316
-
317
- if ( $sSection == 'section_brute_force_login_protection' && !$this->isPremium() ) {
318
- $sIntegration = $this->getPremiumOnlyIntegration();
319
- if ( !empty( $sIntegration ) ) {
320
- $aWarnings[] = sprintf( __( 'Support for login protection with %s is a Pro-only feature.', 'wp-simple-firewall' ), $sIntegration );
321
- }
322
- }
323
-
324
- if ( $sSection == 'section_2fa_email' ) {
325
- $aWarnings[] =
326
- __( '2FA by email demands that your WP site is properly configured to send email.', 'wp-simple-firewall' )
327
- .'<br/>'.__( 'This is a common problem and you may get locked out in the future if you ignore this.', 'wp-simple-firewall' )
328
- .' '.sprintf( '<a href="%s" target="_blank" class="alert-link">%s</a>', 'https://shsec.io/dd', __( 'Learn More.', 'wp-simple-firewall' ) );
329
- }
330
-
331
- return $aWarnings;
332
- }
333
-
334
- /**
335
- * @return string
336
- */
337
- protected function getPremiumOnlyIntegration() {
338
- $aIntegrations = [
339
- 'WooCommerce' => 'WooCommerce',
340
- 'Easy_Digital_Downloads' => 'Easy Digital Downloads',
341
- 'BuddyPress' => 'BuddyPress',
342
- ];
343
-
344
- $sIntegration = '';
345
- foreach ( $aIntegrations as $sInt => $sName ) {
346
- if ( class_exists( $sInt ) ) {
347
- $sIntegration = $sName;
348
- break;
349
- }
350
- }
351
- return $sIntegration;
352
- }
353
-
354
  public function insertCustomJsVars_Admin() {
355
  parent::insertCustomJsVars_Admin();
356
 
357
  wp_localize_script(
358
- $this->prefix( 'global-plugin' ),
359
  'icwp_wpsf_vars_lg',
360
  [
361
  'ajax_gen_backup_codes' => $this->getAjaxActionData( 'gen_backup_codes' ),
@@ -366,76 +320,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
366
  wp_enqueue_style( 'wp-jquery-ui-dialog' );
367
  }
368
 
369
- /**
370
- * @param array $aAllData
371
- * @return array
372
- */
373
- public function addInsightsConfigData( $aAllData ) {
374
- /** @var LoginGuard\Options $oOpts */
375
- $oOpts = $this->getOptions();
376
- $aThis = [
377
- 'strings' => [
378
- 'title' => __( 'Login Guard', 'wp-simple-firewall' ),
379
- 'sub' => __( 'Brute Force Protection & Identity Verification', 'wp-simple-firewall' ),
380
- ],
381
- 'key_opts' => [],
382
- 'href_options' => $this->getUrl_AdminPage()
383
- ];
384
-
385
- if ( !$this->isModOptEnabled() ) {
386
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
387
- }
388
- else {
389
- $bHasBotCheck = $oOpts->isEnabledGaspCheck() || $this->isEnabledCaptcha();
390
-
391
- $bBotLogin = $bHasBotCheck && $oOpts->isProtectLogin();
392
- $bBotRegister = $bHasBotCheck && $oOpts->isProtectRegister();
393
- $bBotPassword = $bHasBotCheck && $oOpts->isProtectLostPassword();
394
- $aThis[ 'key_opts' ][ 'bot_login' ] = [
395
- 'name' => __( 'Brute Force Login', 'wp-simple-firewall' ),
396
- 'enabled' => $bBotLogin,
397
- 'summary' => $bBotLogin ?
398
- __( 'Login forms are protected against bot attacks', 'wp-simple-firewall' )
399
- : __( 'Login forms are not protected against brute force bot attacks', 'wp-simple-firewall' ),
400
- 'weight' => 2,
401
- 'href' => $this->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
402
- ];
403
- $aThis[ 'key_opts' ][ 'bot_register' ] = [
404
- 'name' => __( 'Bot User Register', 'wp-simple-firewall' ),
405
- 'enabled' => $bBotRegister,
406
- 'summary' => $bBotRegister ?
407
- __( 'Registration forms are protected against bot attacks', 'wp-simple-firewall' )
408
- : __( 'Registration forms are not protected against automated bots', 'wp-simple-firewall' ),
409
- 'weight' => 2,
410
- 'href' => $this->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
411
- ];
412
- $aThis[ 'key_opts' ][ 'bot_password' ] = [
413
- 'name' => __( 'Brute Force Lost Password', 'wp-simple-firewall' ),
414
- 'enabled' => $bBotPassword,
415
- 'summary' => $bBotPassword ?
416
- __( 'Lost Password forms are protected against bot attacks', 'wp-simple-firewall' )
417
- : __( 'Lost Password forms are not protected against automated bots', 'wp-simple-firewall' ),
418
- 'weight' => 2,
419
- 'href' => $this->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
420
- ];
421
-
422
- $bHas2Fa = $oOpts->isEmailAuthenticationActive()
423
- || $oOpts->isEnabledGoogleAuthenticator() || $oOpts->isEnabledYubikey();
424
- $aThis[ 'key_opts' ][ '2fa' ] = [
425
- 'name' => __( 'Identity Verification', 'wp-simple-firewall' ),
426
- 'enabled' => $bHas2Fa,
427
- 'summary' => $bHas2Fa ?
428
- __( 'At least 1 2FA option is enabled', 'wp-simple-firewall' )
429
- : __( 'No 2FA options, such as Google Authenticator, are active', 'wp-simple-firewall' ),
430
- 'weight' => 2,
431
- 'href' => $this->getUrl_DirectLinkToSection( 'section_2fa_email' ),
432
- ];
433
- }
434
-
435
- $aAllData[ $this->getSlug() ] = $aThis;
436
- return $aAllData;
437
- }
438
-
439
  /**
440
  * @return string
441
  */
128
  ->sendEmailWithWrap( $sEmail, $sEmailSubject, $aMessage );
129
  }
130
 
 
 
131
  private function cleanLoginUrlPath() {
132
  $sCustomLoginPath = $this->getCustomLoginPath();
133
  if ( !empty( $sCustomLoginPath ) ) {
272
  * @return string
273
  */
274
  public function getLoginIntentRequestFlag() {
275
+ return $this->getCon()->prefix( 'login-intent-request' );
276
  }
277
 
278
  /**
305
  return $this->setOpt( 'enable_login_gasp_check', $bEnabled ? 'Y' : 'N' );
306
  }
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  public function insertCustomJsVars_Admin() {
309
  parent::insertCustomJsVars_Admin();
310
 
311
  wp_localize_script(
312
+ $this->getCon()->prefix( 'global-plugin' ),
313
  'icwp_wpsf_vars_lg',
314
  [
315
  'ajax_gen_backup_codes' => $this->getAjaxActionData( 'gen_backup_codes' ),
320
  wp_enqueue_style( 'wp-jquery-ui-dialog' );
321
  }
322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  /**
324
  * @return string
325
  */
src/features/plugin.php CHANGED
@@ -70,44 +70,14 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
70
  ->checkAll();
71
  }
72
 
73
- /**
74
- * @param string $sSection
75
- * @return array
76
- */
77
- protected function getSectionWarnings( $sSection ) {
78
- $aWarnings = [];
79
-
80
- switch ( $sSection ) {
81
- case 'section_third_party_captcha':
82
- /** @var Plugin\Options $oOpts */
83
- $oOpts = $this->getOptions();
84
- if ( $this->getCaptchaCfg()->ready ) {
85
- if ( $oOpts->getOpt( 'captcha_checked_at' ) < 0 ) {
86
- ( new Plugin\Lib\Captcha\CheckCaptchaSettings() )
87
- ->setMod( $this )
88
- ->checkAll();
89
- }
90
- if ( $oOpts->getOpt( 'captcha_checked_at' ) == 0 ) {
91
- $aWarnings[] = sprintf(
92
- __( "Your captcha key and secret haven't been verified.", 'wp-simple-firewall' ).' '
93
- .__( "Please double-check and make sure you haven't mixed them about, and then re-save.", 'wp-simple-firewall' )
94
- );
95
- }
96
- }
97
- break;
98
- }
99
-
100
- return $aWarnings;
101
- }
102
-
103
  public function deleteAllPluginCrons() {
104
- $oCon = $this->getCon();
105
  $oWpCron = Services::WpCron();
106
 
107
  foreach ( $oWpCron->getCrons() as $nKey => $aCronArgs ) {
108
  foreach ( $aCronArgs as $sHook => $aCron ) {
109
- if ( strpos( $sHook, $this->prefix() ) === 0
110
- || strpos( $sHook, $oCon->prefixOption() ) === 0 ) {
111
  $oWpCron->deleteCronJob( $sHook );
112
  }
113
  }
@@ -225,7 +195,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
225
  public function getPluginReportEmail() {
226
  $sE = (string)$this->getOpt( 'block_send_email_address' );
227
  if ( $this->isPremium() ) {
228
- $sE = apply_filters( $this->prefix( 'report_email' ), $sE );
229
  }
230
  $sE = trim( $sE );
231
  return Services::Data()->validEmail( $sE ) ? $sE : Services::WpGeneral()->getSiteAdminEmail();
@@ -576,11 +546,11 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
576
  public function insertCustomJsVars_Admin() {
577
  parent::insertCustomJsVars_Admin();
578
 
579
- $oCon = $this->getCon();
580
  if ( Services::WpPost()->isCurrentPage( 'plugins.php' ) ) {
581
- $sFile = $oCon->getPluginBaseFile();
582
  wp_localize_script(
583
- $this->prefix( 'global-plugin' ),
584
  'icwp_wpsf_vars_plugin',
585
  [
586
  'file' => $sFile,
@@ -597,12 +567,12 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
597
  }
598
 
599
  wp_localize_script(
600
- $oCon->prefix( 'plugin' ),
601
  'icwp_wpsf_vars_tourmanager',
602
  [ 'ajax' => $this->getAjaxActionData( 'mark_tour_finished' ) ]
603
  );
604
  wp_localize_script(
605
- $this->prefix( 'plugin' ),
606
  'icwp_wpsf_vars_plugin',
607
  [
608
  'strings' => [
@@ -613,62 +583,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
613
  );
614
  }
615
 
616
- /**
617
- * @param array $aAllData
618
- * @return array
619
- */
620
- public function addInsightsConfigData( $aAllData ) {
621
- $aThis = [
622
- 'strings' => [
623
- 'title' => __( 'General Settings', 'wp-simple-firewall' ),
624
- 'sub' => sprintf( __( 'General %s Settings', 'wp-simple-firewall' ), $this->getCon()
625
- ->getHumanName() ),
626
- ],
627
- 'key_opts' => [],
628
- 'href_options' => $this->getUrl_AdminPage()
629
- ];
630
-
631
- $oOpts = $this->getOptions();
632
- if ( $this->isModOptEnabled() ) {
633
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
634
- }
635
- else {
636
- $aThis[ 'key_opts' ][ 'editing' ] = [
637
- 'name' => __( 'Visitor IP', 'wp-simple-firewall' ),
638
- 'enabled' => true,
639
- 'summary' => sprintf( __( 'Visitor IP address source is: %s', 'wp-simple-firewall' ),
640
- __( $oOpts->getSelectOptionValueText( 'visitor_address_source' ), 'wp-simple-firewall' ) ),
641
- 'weight' => 0,
642
- 'href' => $this->getUrl_DirectLinkToOption( 'visitor_address_source' ),
643
- ];
644
-
645
- $bHasSupportEmail = Services::Data()->validEmail( $this->getOpt( 'block_send_email_address' ) );
646
- $aThis[ 'key_opts' ][ 'reports' ] = [
647
- 'name' => __( 'Reporting Email', 'wp-simple-firewall' ),
648
- 'enabled' => $bHasSupportEmail,
649
- 'summary' => $bHasSupportEmail ?
650
- sprintf( __( 'Email address for reports set to: %s', 'wp-simple-firewall' ), $this->getPluginReportEmail() )
651
- : sprintf( __( 'No address provided - defaulting to: %s', 'wp-simple-firewall' ), $this->getPluginReportEmail() ),
652
- 'weight' => 0,
653
- 'href' => $this->getUrl_DirectLinkToOption( 'block_send_email_address' ),
654
- ];
655
-
656
- $bRecap = $this->getCaptchaCfg()->ready;
657
- $aThis[ 'key_opts' ][ 'recap' ] = [
658
- 'name' => __( 'CAPTCHA', 'wp-simple-firewall' ),
659
- 'enabled' => $bRecap,
660
- 'summary' => $bRecap ?
661
- __( 'CAPTCHA keys have been provided', 'wp-simple-firewall' )
662
- : __( "CAPTCHA keys haven't been provided", 'wp-simple-firewall' ),
663
- 'weight' => 1,
664
- 'href' => $this->getUrl_DirectLinkToSection( 'section_third_party_captcha' ),
665
- ];
666
- }
667
-
668
- $aAllData[ $this->getSlug() ] = $aThis;
669
- return $aAllData;
670
- }
671
-
672
  /**
673
  * @return Shield\Databases\GeoIp\Handler
674
  */
@@ -693,30 +607,6 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
693
  return $this->oCaptchaEnqueue;
694
  }
695
 
696
- /**
697
- * @param array $aOptParams
698
- * @return array
699
- */
700
- protected function buildOptionForUi( $aOptParams ) {
701
- $aOptParams = parent::buildOptionForUi( $aOptParams );
702
- if ( $aOptParams[ 'key' ] === 'visitor_address_source' ) {
703
- $aNewOptions = [];
704
- $oIPDet = Services::IP()->getIpDetector();
705
- foreach ( $aOptParams[ 'value_options' ] as $sValKey => $sSource ) {
706
- if ( $sValKey == 'AUTO_DETECT_IP' ) {
707
- $aNewOptions[ $sValKey ] = $sSource;
708
- }
709
- else {
710
- $sIPs = implode( ', ', $oIPDet->getIpsFromSource( $sSource ) );
711
- $aNewOptions[ $sValKey ] = sprintf( '%s (%s)',
712
- $sSource, empty( $sIPs ) ? '-' : $sIPs );
713
- }
714
- }
715
- $aOptParams[ 'value_options' ] = $aNewOptions;
716
- }
717
- return $aOptParams;
718
- }
719
-
720
  /**
721
  * @return string
722
  */
70
  ->checkAll();
71
  }
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  public function deleteAllPluginCrons() {
74
+ $con = $this->getCon();
75
  $oWpCron = Services::WpCron();
76
 
77
  foreach ( $oWpCron->getCrons() as $nKey => $aCronArgs ) {
78
  foreach ( $aCronArgs as $sHook => $aCron ) {
79
+ if ( strpos( $sHook, $con->prefix() ) === 0
80
+ || strpos( $sHook, $con->prefixOption() ) === 0 ) {
81
  $oWpCron->deleteCronJob( $sHook );
82
  }
83
  }
195
  public function getPluginReportEmail() {
196
  $sE = (string)$this->getOpt( 'block_send_email_address' );
197
  if ( $this->isPremium() ) {
198
+ $sE = apply_filters( $this->getCon()->prefix( 'report_email' ), $sE );
199
  }
200
  $sE = trim( $sE );
201
  return Services::Data()->validEmail( $sE ) ? $sE : Services::WpGeneral()->getSiteAdminEmail();
546
  public function insertCustomJsVars_Admin() {
547
  parent::insertCustomJsVars_Admin();
548
 
549
+ $con = $this->getCon();
550
  if ( Services::WpPost()->isCurrentPage( 'plugins.php' ) ) {
551
+ $sFile = $con->getPluginBaseFile();
552
  wp_localize_script(
553
+ $con->prefix( 'global-plugin' ),
554
  'icwp_wpsf_vars_plugin',
555
  [
556
  'file' => $sFile,
567
  }
568
 
569
  wp_localize_script(
570
+ $con->prefix( 'plugin' ),
571
  'icwp_wpsf_vars_tourmanager',
572
  [ 'ajax' => $this->getAjaxActionData( 'mark_tour_finished' ) ]
573
  );
574
  wp_localize_script(
575
+ $con->prefix( 'plugin' ),
576
  'icwp_wpsf_vars_plugin',
577
  [
578
  'strings' => [
583
  );
584
  }
585
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
  /**
587
  * @return Shield\Databases\GeoIp\Handler
588
  */
607
  return $this->oCaptchaEnqueue;
608
  }
609
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  /**
611
  * @return string
612
  */
src/features/traffic.php CHANGED
@@ -39,37 +39,6 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
39
  && parent::isReadyToExecute();
40
  }
41
 
42
- /**
43
- * @param string $sSection
44
- * @return array
45
- */
46
- protected function getSectionWarnings( $sSection ) {
47
- /** @var Traffic\Options $oOpts */
48
- $oOpts = $this->getOptions();
49
-
50
- $aWarnings = [];
51
-
52
- $oIp = Services::IP();
53
- if ( !$oIp->isValidIp_PublicRange( $oIp->getRequestIp() ) ) {
54
- $aWarnings[] = __( 'Traffic Watcher will not run because visitor IP address detection is not correctly configured.', 'wp-simple-firewall' );
55
- }
56
-
57
- switch ( $sSection ) {
58
- case 'section_traffic_limiter':
59
- if ( $this->isPremium() ) {
60
- if ( !$oOpts->isTrafficLoggerEnabled() ) {
61
- $aWarnings[] = sprintf( __( '%s may only be enabled if the Traffic Logger feature is also turned on.', 'wp-simple-firewall' ), __( 'Traffic Rate Limiter', 'wp-simple-firewall' ) );
62
- }
63
- }
64
- else {
65
- $aWarnings[] = sprintf( __( '%s is a Pro-only feature.', 'wp-simple-firewall' ), __( 'Traffic Rate Limiter', 'wp-simple-firewall' ) );
66
- }
67
- break;
68
- }
69
-
70
- return $aWarnings;
71
- }
72
-
73
  /**
74
  * @return string
75
  */
39
  && parent::isReadyToExecute();
40
  }
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  /**
43
  * @return string
44
  */
src/features/user_management.php CHANGED
@@ -35,31 +35,29 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends \ICWP_WPSF_FeatureHandler_
35
  }
36
 
37
  protected function preProcessOptions() {
38
- /** @var UserManagement\Options $oOpts */
39
- $oOpts = $this->getOptions();
40
 
41
- $oOpts->setOpt( 'enable_admin_login_email_notification', implode( ', ', $this->getAdminLoginNotificationEmails() ) );
42
 
43
- if ( $oOpts->getIdleTimeoutInterval() > $oOpts->getMaxSessionTime() ) {
44
- $oOpts->setOpt( 'session_idle_timeout_interval', $oOpts->getOpt( 'session_timeout_interval' )*24 );
45
  }
46
 
47
- $oOpts->setOpt( 'auto_idle_roles',
48
  array_unique( array_filter( array_map(
49
  function ( $sRole ) {
50
  return preg_replace( '#[^\sa-z0-9_-]#i', '', trim( strtolower( $sRole ) ) );
51
  },
52
- $oOpts->getSuspendAutoIdleUserRoles()
53
  ) ) )
54
  );
55
 
56
- {
57
- $aChecks = $oOpts->getEmailValidationChecks();
58
- if ( !empty( $aChecks ) ) {
59
- $aChecks[] = 'syntax';
60
- }
61
- $oOpts->setOpt( 'email_checks', array_unique( $aChecks ) );
62
  }
 
63
  }
64
 
65
  /**
@@ -137,121 +135,6 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends \ICWP_WPSF_FeatureHandler_
137
  return $this->setOpt( 'hard_suspended_userids', $aIds );
138
  }
139
 
140
- /**
141
- * @param array $aAllNotices
142
- * @return array
143
- */
144
- public function addInsightsNoticeData( $aAllNotices ) {
145
- /** @var UserManagement\Options $oOpts */
146
- $oOpts = $this->getOptions();
147
-
148
- $aNotices = [
149
- 'title' => __( 'Users', 'wp-simple-firewall' ),
150
- 'messages' => []
151
- ];
152
-
153
- { //admin user
154
- $oAdmin = Services::WpUsers()->getUserByUsername( 'admin' );
155
- if ( !empty( $oAdmin ) && user_can( $oAdmin, 'manage_options' ) ) {
156
- $aNotices[ 'messages' ][ 'admin' ] = [
157
- 'title' => 'Admin User',
158
- 'message' => sprintf( __( "Default 'admin' user still available.", 'wp-simple-firewall' ) ),
159
- 'href' => '',
160
- 'rec' => __( "Default 'admin' user should be disabled or removed.", 'wp-simple-firewall' )
161
- ];
162
- }
163
- }
164
-
165
- {//password policies
166
- if ( !$oOpts->isPasswordPoliciesEnabled() ) {
167
- $aNotices[ 'messages' ][ 'password' ] = [
168
- 'title' => __( 'Password Policies', 'wp-simple-firewall' ),
169
- 'message' => __( "Strong password policies are not enforced.", 'wp-simple-firewall' ),
170
- 'href' => $this->getUrl_DirectLinkToSection( 'section_passwords' ),
171
- 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
172
- 'rec' => __( 'Password policies should be turned-on.', 'wp-simple-firewall' )
173
- ];
174
- }
175
- }
176
-
177
- $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
178
-
179
- $aAllNotices[ 'users' ] = $aNotices;
180
- return $aAllNotices;
181
- }
182
-
183
- /**
184
- * @param array $aAllData
185
- * @return array
186
- */
187
- public function addInsightsConfigData( $aAllData ) {
188
- /** @var UserManagement\Options $oOpts */
189
- $oOpts = $this->getOptions();
190
-
191
- $aThis = [
192
- 'strings' => [
193
- 'title' => __( 'User Management', 'wp-simple-firewall' ),
194
- 'sub' => __( 'Sessions Control & Password Policies', 'wp-simple-firewall' ),
195
- ],
196
- 'key_opts' => [],
197
- 'href_options' => $this->getUrl_AdminPage()
198
- ];
199
-
200
- if ( !$this->isModOptEnabled() ) {
201
- $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
202
- }
203
- else {
204
- $bHasIdle = $oOpts->hasSessionIdleTimeout();
205
- $aThis[ 'key_opts' ][ 'idle' ] = [
206
- 'name' => __( 'Idle Users', 'wp-simple-firewall' ),
207
- 'enabled' => $bHasIdle,
208
- 'summary' => $bHasIdle ?
209
- sprintf( __( 'Idle sessions are terminated after %s hours', 'wp-simple-firewall' ), $this->getOpt( 'session_idle_timeout_interval' ) )
210
- : __( 'Idle sessions wont be terminated', 'wp-simple-firewall' ),
211
- 'weight' => 2,
212
- 'href' => $this->getUrl_DirectLinkToOption( 'session_idle_timeout_interval' ),
213
- ];
214
-
215
- $bLocked = $oOpts->isLockToIp();
216
- $aThis[ 'key_opts' ][ 'lock' ] = [
217
- 'name' => __( 'Lock To IP', 'wp-simple-firewall' ),
218
- 'enabled' => $bLocked,
219
- 'summary' => $bLocked ?
220
- __( 'Sessions are locked to IP address', 'wp-simple-firewall' )
221
- : __( "Sessions aren't locked to IP address", 'wp-simple-firewall' ),
222
- 'weight' => 1,
223
- 'href' => $this->getUrl_DirectLinkToOption( 'session_lock_location' ),
224
- ];
225
-
226
- $bPolicies = $oOpts->isPasswordPoliciesEnabled();
227
-
228
- $bPwned = $bPolicies && $oOpts->isPassPreventPwned();
229
- $aThis[ 'key_opts' ][ 'pwned' ] = [
230
- 'name' => __( 'Pwned Passwords', 'wp-simple-firewall' ),
231
- 'enabled' => $bPwned,
232
- 'summary' => $bPwned ?
233
- __( 'Pwned passwords are blocked on this site', 'wp-simple-firewall' )
234
- : __( 'Pwned passwords are allowed on this site', 'wp-simple-firewall' ),
235
- 'weight' => 2,
236
- 'href' => $this->getUrl_DirectLinkToOption( 'pass_prevent_pwned' ),
237
- ];
238
-
239
- $bIndepthPolices = $bPolicies && $this->isPremium();
240
- $aThis[ 'key_opts' ][ 'policies' ] = [
241
- 'name' => __( 'Password Policies', 'wp-simple-firewall' ),
242
- 'enabled' => $bIndepthPolices,
243
- 'summary' => $bIndepthPolices ?
244
- __( 'Several password policies are active', 'wp-simple-firewall' )
245
- : __( 'Limited or no password polices are active', 'wp-simple-firewall' ),
246
- 'weight' => 2,
247
- 'href' => $this->getUrl_DirectLinkToSection( 'section_passwords' ),
248
- ];
249
- }
250
-
251
- $aAllData[ $this->getSlug() ] = $aThis;
252
- return $aAllData;
253
- }
254
-
255
  /**
256
  * @return string
257
  */
35
  }
36
 
37
  protected function preProcessOptions() {
38
+ /** @var UserManagement\Options $opts */
39
+ $opts = $this->getOptions();
40
 
41
+ $opts->setOpt( 'enable_admin_login_email_notification', implode( ', ', $this->getAdminLoginNotificationEmails() ) );
42
 
43
+ if ( $opts->getIdleTimeoutInterval() > $opts->getMaxSessionTime() ) {
44
+ $opts->setOpt( 'session_idle_timeout_interval', $opts->getOpt( 'session_timeout_interval' )*24 );
45
  }
46
 
47
+ $opts->setOpt( 'auto_idle_roles',
48
  array_unique( array_filter( array_map(
49
  function ( $sRole ) {
50
  return preg_replace( '#[^\sa-z0-9_-]#i', '', trim( strtolower( $sRole ) ) );
51
  },
52
+ $opts->getSuspendAutoIdleUserRoles()
53
  ) ) )
54
  );
55
 
56
+ $aChecks = $opts->getEmailValidationChecks();
57
+ if ( !empty( $aChecks ) ) {
58
+ $aChecks[] = 'syntax';
 
 
 
59
  }
60
+ $opts->setOpt( 'email_checks', array_unique( $aChecks ) );
61
  }
62
 
63
  /**
135
  return $this->setOpt( 'hard_suspended_userids', $aIds );
136
  }
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  /**
139
  * @return string
140
  */
src/lib/src/Controller/Controller.php CHANGED
@@ -15,7 +15,7 @@ use FernleafSystems\Wordpress\Services\Services;
15
  * @property bool $plugin_deactivating
16
  * @property bool $plugin_deleting
17
  * @property bool $plugin_reset
18
- * @property string $file_forceoff
19
  * @property string $base_file
20
  * @property string $root_file
21
  * @property bool $user_can_base_permissions
@@ -46,11 +46,6 @@ class Controller {
46
  */
47
  protected $bRebuildOptions;
48
 
49
- /**
50
- * @var string
51
- */
52
- protected $sForceOffFile;
53
-
54
  /**
55
  * @var string
56
  */
@@ -218,8 +213,6 @@ class Controller {
218
  }
219
  }
220
 
221
- /**
222
- */
223
  public function adminNoticeDoesNotMeetRequirements() {
224
  $aMessages = $this->getRequirementsMessages();
225
  if ( !empty( $aMessages ) && is_array( $aMessages ) ) {
@@ -241,8 +234,6 @@ class Controller {
241
  }
242
  }
243
 
244
- /**
245
- */
246
  public function adminNoticePluginFailedToLoad() {
247
  $aDisplayData = [
248
  'strings' => [
@@ -332,8 +323,6 @@ class Controller {
332
  return $bSuccess;
333
  }
334
 
335
- /**
336
- */
337
  protected function doRegisterHooks() {
338
  register_deactivation_hook( $this->getRootFile(), [ $this, 'onWpDeactivatePlugin' ] );
339
 
@@ -397,8 +386,6 @@ class Controller {
397
  );
398
  }
399
 
400
- /**
401
- */
402
  public function onWpAdminInit() {
403
  add_action( 'admin_bar_menu', [ $this, 'onWpAdminBarMenu' ], 100 );
404
  add_action( 'wp_dashboard_setup', [ $this, 'onWpDashboardSetup' ] );
@@ -429,8 +416,6 @@ class Controller {
429
  return $aHeaders;
430
  }
431
 
432
- /**
433
- */
434
  public function onWpInit() {
435
  $this->getMeetsBasePermissions();
436
  add_action( 'wp_enqueue_scripts', [ $this, 'onWpEnqueueFrontendCss' ], 99 );
@@ -504,8 +489,6 @@ class Controller {
504
  ->run();
505
  }
506
 
507
- /**
508
- */
509
  public function onWpAdminMenu() {
510
  if ( $this->isValidAdminArea() ) {
511
  $this->createPluginMenu();
@@ -517,7 +500,8 @@ class Controller {
517
  */
518
  public function onWpAdminBarMenu( $oAdminBar ) {
519
  $bShow = apply_filters( $this->prefix( 'show_admin_bar_menu' ),
520
- $this->isValidAdminArea() && (bool)$this->getPluginSpec_Property( 'show_admin_bar_menu' )
 
521
  );
522
  if ( $bShow ) {
523
  $aMenuItems = apply_filters( $this->prefix( 'admin_bar_menu_items' ), [] );
@@ -1612,8 +1596,7 @@ class Controller {
1612
  public function getPreviousVersion() {
1613
  $oOpts = $this->getPluginControllerOptions();
1614
  if ( empty( $oOpts->previous_version ) ) {
1615
- $oOpts->previous_version = '9.0.4'; //@deprecated 9.0.4
1616
- // $oOpts->previous_version = $this->getVersion();
1617
  }
1618
  return $oOpts->previous_version;
1619
  }
@@ -1657,14 +1640,6 @@ class Controller {
1657
  return self::$oControllerOptions;
1658
  }
1659
 
1660
- /**
1661
- * @deprecated 9.0.4
1662
- */
1663
- protected function deletePluginControllerOptions() {
1664
- $this->setPluginControllerOptions( false );
1665
- $this->saveCurrentPluginControllerOptions();
1666
- }
1667
-
1668
  protected function deleteCronJobs() {
1669
  $oWpCron = Services::WpCron();
1670
  $aCrons = $oWpCron->getCrons();
@@ -1734,24 +1709,12 @@ class Controller {
1734
  return strtolower( get_class() );
1735
  }
1736
 
1737
- /**
1738
- * @param string $sPathToLib
1739
- * @return mixed
1740
- */
1741
- public function loadLib( $sPathToLib ) {
1742
- return include( $this->getPath_LibFile( $sPathToLib ) );
1743
- }
1744
-
1745
- /**
1746
- */
1747
  public function deactivateSelf() {
1748
  if ( $this->isPluginAdmin() && function_exists( 'deactivate_plugins' ) ) {
1749
  deactivate_plugins( $this->getPluginBaseFile() );
1750
  }
1751
  }
1752
 
1753
- /**
1754
- */
1755
  public function clearSession() {
1756
  Services::Response()->cookieDelete( $this->getPluginPrefix() );
1757
  self::$sSessionId = null;
@@ -1763,7 +1726,6 @@ class Controller {
1763
  public function deleteForceOffFile() {
1764
  if ( $this->getIfForceOffActive() ) {
1765
  Services::WpFs()->deleteFile( $this->getForceOffFilePath() );
1766
- $this->sForceOffFile = null;
1767
  unset( $this->file_forceoff );
1768
  clearstatcache();
1769
  }
@@ -1771,23 +1733,22 @@ class Controller {
1771
  }
1772
 
1773
  /**
1774
- * Returns true if you're overriding OFF. We don't do override ON any more (as of 3.5.1)
1775
  */
1776
  public function getIfForceOffActive() {
1777
- return ( $this->getForceOffFilePath() !== false );
1778
  }
1779
 
1780
  /**
1781
- * @return null|string
1782
  */
1783
  protected function getForceOffFilePath() {
1784
- if ( !isset( $this->sForceOffFile ) ) {
1785
- $oFs = Services::WpFs();
1786
- $sFile = $oFs->findFileInDir( 'forceOff', $this->getRootDir(), false, false );
1787
- $this->sForceOffFile = ( !empty( $sFile ) && $oFs->isFile( $sFile ) ) ? $sFile : false;
1788
- $this->file_forceoff = $this->sForceOffFile;
1789
  }
1790
- return $this->sForceOffFile;
1791
  }
1792
 
1793
  /**
@@ -1796,7 +1757,11 @@ class Controller {
1796
  */
1797
  public function getSessionId( $bSetIfNeeded = true ) {
1798
  if ( empty( self::$sSessionId ) ) {
1799
- self::$sSessionId = Services::Request()->cookie( $this->getPluginPrefix(), '' );
 
 
 
 
1800
  if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1801
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1802
  $this->setSessionCookie();
@@ -1833,11 +1798,9 @@ class Controller {
1833
  return !empty( $sSessionId );
1834
  }
1835
 
1836
- /**
1837
- */
1838
  protected function setSessionCookie() {
1839
  Services::Response()->cookieSet(
1840
- $this->getPluginPrefix(),
1841
  $this->getSessionId(),
1842
  Services::Request()->ts() + DAY_IN_SECONDS*30,
1843
  Services::WpGeneral()->getCookiePath(),
15
  * @property bool $plugin_deactivating
16
  * @property bool $plugin_deleting
17
  * @property bool $plugin_reset
18
+ * @property false|string $file_forceoff
19
  * @property string $base_file
20
  * @property string $root_file
21
  * @property bool $user_can_base_permissions
46
  */
47
  protected $bRebuildOptions;
48
 
 
 
 
 
 
49
  /**
50
  * @var string
51
  */
213
  }
214
  }
215
 
 
 
216
  public function adminNoticeDoesNotMeetRequirements() {
217
  $aMessages = $this->getRequirementsMessages();
218
  if ( !empty( $aMessages ) && is_array( $aMessages ) ) {
234
  }
235
  }
236
 
 
 
237
  public function adminNoticePluginFailedToLoad() {
238
  $aDisplayData = [
239
  'strings' => [
323
  return $bSuccess;
324
  }
325
 
 
 
326
  protected function doRegisterHooks() {
327
  register_deactivation_hook( $this->getRootFile(), [ $this, 'onWpDeactivatePlugin' ] );
328
 
386
  );
387
  }
388
 
 
 
389
  public function onWpAdminInit() {
390
  add_action( 'admin_bar_menu', [ $this, 'onWpAdminBarMenu' ], 100 );
391
  add_action( 'wp_dashboard_setup', [ $this, 'onWpDashboardSetup' ] );
416
  return $aHeaders;
417
  }
418
 
 
 
419
  public function onWpInit() {
420
  $this->getMeetsBasePermissions();
421
  add_action( 'wp_enqueue_scripts', [ $this, 'onWpEnqueueFrontendCss' ], 99 );
489
  ->run();
490
  }
491
 
 
 
492
  public function onWpAdminMenu() {
493
  if ( $this->isValidAdminArea() ) {
494
  $this->createPluginMenu();
500
  */
501
  public function onWpAdminBarMenu( $oAdminBar ) {
502
  $bShow = apply_filters( $this->prefix( 'show_admin_bar_menu' ),
503
+ $this->isValidAdminArea( true )
504
+ && (bool)$this->getPluginSpec_Property( 'show_admin_bar_menu' )
505
  );
506
  if ( $bShow ) {
507
  $aMenuItems = apply_filters( $this->prefix( 'admin_bar_menu_items' ), [] );
1596
  public function getPreviousVersion() {
1597
  $oOpts = $this->getPluginControllerOptions();
1598
  if ( empty( $oOpts->previous_version ) ) {
1599
+ $oOpts->previous_version = $this->getVersion();
 
1600
  }
1601
  return $oOpts->previous_version;
1602
  }
1640
  return self::$oControllerOptions;
1641
  }
1642
 
 
 
 
 
 
 
 
 
1643
  protected function deleteCronJobs() {
1644
  $oWpCron = Services::WpCron();
1645
  $aCrons = $oWpCron->getCrons();
1709
  return strtolower( get_class() );
1710
  }
1711
 
 
 
 
 
 
 
 
 
 
 
1712
  public function deactivateSelf() {
1713
  if ( $this->isPluginAdmin() && function_exists( 'deactivate_plugins' ) ) {
1714
  deactivate_plugins( $this->getPluginBaseFile() );
1715
  }
1716
  }
1717
 
 
 
1718
  public function clearSession() {
1719
  Services::Response()->cookieDelete( $this->getPluginPrefix() );
1720
  self::$sSessionId = null;
1726
  public function deleteForceOffFile() {
1727
  if ( $this->getIfForceOffActive() ) {
1728
  Services::WpFs()->deleteFile( $this->getForceOffFilePath() );
 
1729
  unset( $this->file_forceoff );
1730
  clearstatcache();
1731
  }
1733
  }
1734
 
1735
  /**
1736
+ * @return bool
1737
  */
1738
  public function getIfForceOffActive() {
1739
+ return $this->getForceOffFilePath() !== false;
1740
  }
1741
 
1742
  /**
1743
+ * @return false|string
1744
  */
1745
  protected function getForceOffFilePath() {
1746
+ if ( !isset( $this->file_forceoff ) ) {
1747
+ $FS = Services::WpFs();
1748
+ $file = $FS->findFileInDir( 'forceoff', $this->getRootDir(), false, false );
1749
+ $this->file_forceoff = empty( $file ) ? false : $file;
 
1750
  }
1751
+ return $this->file_forceoff;
1752
  }
1753
 
1754
  /**
1757
  */
1758
  public function getSessionId( $bSetIfNeeded = true ) {
1759
  if ( empty( self::$sSessionId ) ) {
1760
+ $req = Services::Request();
1761
+ self::$sSessionId = $req->cookie( 'wp-'.$this->getPluginPrefix(), '' );
1762
+ if ( empty( self::$sSessionId ) ) { /* the old cookie name */
1763
+ self::$sSessionId = $req->cookie( $this->getPluginPrefix(), '' );
1764
+ }
1765
  if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1766
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1767
  $this->setSessionCookie();
1798
  return !empty( $sSessionId );
1799
  }
1800
 
 
 
1801
  protected function setSessionCookie() {
1802
  Services::Response()->cookieSet(
1803
+ 'wp-'.$this->getPluginPrefix(),
1804
  $this->getSessionId(),
1805
  Services::Request()->ts() + DAY_IN_SECONDS*30,
1806
  Services::WpGeneral()->getCookiePath(),
src/lib/src/Controller/Utilities/Upgrade.php CHANGED
@@ -13,10 +13,10 @@ class Upgrade {
13
  $oCon = $this->getCon();
14
 
15
  if ( $oCon->getPreviousVersion() !== $oCon->getVersion() ) {
16
- foreach ( $oCon->modules as $oMod ) {
17
- $oH = $oMod->getUpgradeHandler();
18
- if ( $oH instanceof Shield\Modules\Base\Upgrade ) {
19
- $oH->setMod( $oMod )->execute();
20
  }
21
  }
22
  }
13
  $oCon = $this->getCon();
14
 
15
  if ( $oCon->getPreviousVersion() !== $oCon->getVersion() ) {
16
+ foreach ( $oCon->modules as $mod ) {
17
+ $H = $mod->getUpgradeHandler();
18
+ if ( $H instanceof Shield\Modules\Base\Upgrade ) {
19
+ $H->setMod( $mod )->execute();
20
  }
21
  }
22
  }
src/lib/src/Databases/AdminNotes/Handler.php CHANGED
@@ -10,19 +10,17 @@ class Handler extends Base\Handler {
10
  /**
11
  * @return string[]
12
  */
13
- protected function getDefaultColumnsDefinition() {
14
- /** @var Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- return $oOpts->getDbColumns_Notes();
17
  }
18
 
19
  /**
20
  * @return string
21
  */
22
  protected function getDefaultTableName() {
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- return $oOpts->getDbTable_Notes();
26
  }
27
 
28
  /**
@@ -38,4 +36,12 @@ class Handler extends Base\Handler {
38
  PRIMARY KEY (id)
39
  ) %s;";
40
  }
 
 
 
 
 
 
 
 
41
  }
10
  /**
11
  * @return string[]
12
  */
13
+ public function getColumns() {
14
+ return $this->getOptions()->getDef( 'db_notes_table_columns' );
 
 
15
  }
16
 
17
  /**
18
  * @return string
19
  */
20
  protected function getDefaultTableName() {
21
+ /** @var Options $opts */
22
+ $opts = $this->getOptions();
23
+ return $opts->getDbTable_Notes();
24
  }
25
 
26
  /**
36
  PRIMARY KEY (id)
37
  ) %s;";
38
  }
39
+
40
+ /**
41
+ * @return string[]
42
+ * @deprecated 9.2.0
43
+ */
44
+ protected function getDefaultColumnsDefinition() {
45
+ return $this->getOptions()->getDef( 'db_notes_table_columns' );
46
+ }
47
  }
src/lib/src/Databases/AuditTrail/Handler.php CHANGED
@@ -8,28 +8,26 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Options;
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
- /** @var Options $oOpts */
12
- $oOpts = $this->getMod()->getOptions();
13
- $this->cleanDb( $oOpts->getAutoCleanDays() );
14
- $this->tableTrimExcess( $oOpts->getMaxEntries() );
15
  }
16
 
17
  /**
18
  * @return array
19
  */
20
- protected function getDefaultColumnsDefinition() {
21
- /** @var Options $oOpts */
22
- $oOpts = $this->getOptions();
23
- return $oOpts->getDbColumns_AuditTrail();
24
  }
25
 
26
  /**
27
  * @return string
28
  */
29
  protected function getDefaultTableName() {
30
- /** @var Options $oOpts */
31
- $oOpts = $this->getOptions();
32
- return $oOpts->getDbTable_AuditTrail();
33
  }
34
 
35
  /**
@@ -54,4 +52,12 @@ class Handler extends Base\Handler {
54
  PRIMARY KEY (id)
55
  ) %s;";
56
  }
 
 
 
 
 
 
 
 
57
  }
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
+ /** @var Options $opts */
12
+ $opts = $this->getOptions();
13
+ $this->tableCleanExpired( $opts->getAutoCleanDays() );
14
+ $this->tableTrimExcess( $opts->getMaxEntries() );
15
  }
16
 
17
  /**
18
  * @return array
19
  */
20
+ public function getColumns() {
21
+ return $this->getOptions()->getDef( 'audit_trail_table_columns' );
 
 
22
  }
23
 
24
  /**
25
  * @return string
26
  */
27
  protected function getDefaultTableName() {
28
+ /** @var Options $opts */
29
+ $opts = $this->getOptions();
30
+ return $opts->getDbTable_AuditTrail();
31
  }
32
 
33
  /**
52
  PRIMARY KEY (id)
53
  ) %s;";
54
  }
55
+
56
+ /**
57
+ * @return string[]
58
+ * @deprecated 9.2.0
59
+ */
60
+ protected function getDefaultColumnsDefinition() {
61
+ return $this->getOptions()->getDef( 'audit_trail_table_columns' );
62
+ }
63
  }
src/lib/src/Databases/Base/Handler.php CHANGED
@@ -30,22 +30,11 @@ class Handler {
30
  */
31
  protected $sTable;
32
 
33
- /**
34
- * @var bool
35
- * @deprecated 9.0.4
36
- */
37
- private $bTableExist;
38
-
39
  /**
40
  * @var bool
41
  */
42
  private $bIsReady;
43
 
44
- /**
45
- * @var string
46
- */
47
- private $sSqlCreate;
48
-
49
  public function __construct() {
50
  }
51
 
@@ -54,9 +43,9 @@ class Handler {
54
 
55
  /**
56
  * @param int $nAutoExpireDays
57
- * @return $this;
58
  */
59
- public function cleanDb( $nAutoExpireDays ) {
60
  $nAutoExpire = $nAutoExpireDays*DAY_IN_SECONDS;
61
  if ( $nAutoExpire > 0 ) {
62
  $this->deleteRowsOlderThan( Services::Request()->ts() - $nAutoExpire );
@@ -84,11 +73,26 @@ class Handler {
84
  return is_array( $this->aColActual ) ? $this->aColActual : [];
85
  }
86
 
 
 
 
 
 
 
 
 
87
  /**
88
  * @return string[]
89
  */
90
  public function getColumnsDefinition() {
91
- return is_array( $this->aColDef ) ? $this->aColDef : $this->getDefaultColumnsDefinition();
 
 
 
 
 
 
 
92
  }
93
 
94
  /**
@@ -158,7 +162,7 @@ class Handler {
158
  * @return string
159
  */
160
  public function getSqlCreate() {
161
- return empty( $this->sSqlCreate ) ? $this->getDefaultCreateTableSql() : $this->sSqlCreate;
162
  }
163
 
164
  /**
@@ -180,7 +184,7 @@ class Handler {
180
  }
181
  $oDB = Services::WpDb();
182
  $sSql = sprintf( $sSql, $this->getTable(), $oDB->getCharCollate() );
183
- $this->isTable() ? $oDB->dbDelta( $sSql ) : $oDB->doSql( $sSql );
184
  return $this;
185
  }
186
 
@@ -191,7 +195,7 @@ class Handler {
191
  public function tableDelete( $bTruncate = false ) {
192
  $table = $this->getTable();
193
  $oDB = Services::WpDb();
194
- $mResult = !$this->isTable() ||
195
  ( $bTruncate ? $oDB->doTruncateTable( $table ) : $oDB->doDropTable( $table ) );
196
  $this->reset();
197
  return $mResult !== false;
@@ -214,7 +218,7 @@ class Handler {
214
  $this->tableCreate();
215
 
216
  if ( !$this->isReady( true ) ) {
217
- $this->deleteTable();
218
  $this->tableCreate();
219
  }
220
  }
@@ -246,7 +250,7 @@ class Handler {
246
 
247
  if ( !isset( $this->bIsReady ) ) {
248
  try {
249
- $this->bIsReady = $this->isTable() && $this->verifyTableStructure();
250
  }
251
  catch ( \Exception $e ) {
252
  $this->bIsReady = false;
@@ -265,15 +269,6 @@ class Handler {
265
  return $this;
266
  }
267
 
268
- /**
269
- * @param string $sSqlCreate
270
- * @return $this
271
- */
272
- public function setSqlCreate( $sSqlCreate ) {
273
- $this->sSqlCreate = $sSqlCreate;
274
- return $this;
275
- }
276
-
277
  /**
278
  * @param string $sTable
279
  * @return $this
@@ -286,7 +281,7 @@ class Handler {
286
  /**
287
  * @return string[]
288
  */
289
- protected function getDefaultColumnsDefinition() {
290
  return [];
291
  }
292
 
@@ -335,7 +330,7 @@ class Handler {
335
  * @throws \Exception
336
  */
337
  protected function verifyTableStructure() {
338
- $aColDef = array_map( 'strtolower', $this->getColumnsDefinition() );
339
  if ( empty( $aColDef ) ) {
340
  throw new \Exception( 'Could not verify table structure as no columns definition provided' );
341
  }
@@ -367,28 +362,6 @@ class Handler {
367
  return $this;
368
  }
369
 
370
- /**
371
- * @return bool
372
- * @deprecated 9.0.4
373
- */
374
- public function isTable() {
375
- return Services::WpDb()->getIfTableExists( $this->getTable() );
376
- }
377
-
378
- /**
379
- * @param bool $bTruncate
380
- * @return bool
381
- * @deprecated 9.0.4
382
- */
383
- public function deleteTable( $bTruncate = false ) {
384
- $table = $this->getTable();
385
- $oDB = Services::WpDb();
386
- $mResult = !$this->isTable() ||
387
- ( $bTruncate ? $oDB->doTruncateTable( $table ) : $oDB->doDropTable( $table ) );
388
- $this->reset();
389
- return $mResult !== false;
390
- }
391
-
392
  /**
393
  * @return string[]
394
  */
@@ -414,4 +387,30 @@ class Handler {
414
  protected function getPrimaryKeySpec() {
415
  return 'PRIMARY KEY (id)';
416
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  }
30
  */
31
  protected $sTable;
32
 
 
 
 
 
 
 
33
  /**
34
  * @var bool
35
  */
36
  private $bIsReady;
37
 
 
 
 
 
 
38
  public function __construct() {
39
  }
40
 
43
 
44
  /**
45
  * @param int $nAutoExpireDays
46
+ * @return $this
47
  */
48
+ public function tableCleanExpired( $nAutoExpireDays ) {
49
  $nAutoExpire = $nAutoExpireDays*DAY_IN_SECONDS;
50
  if ( $nAutoExpire > 0 ) {
51
  $this->deleteRowsOlderThan( Services::Request()->ts() - $nAutoExpire );
73
  return is_array( $this->aColActual ) ? $this->aColActual : [];
74
  }
75
 
76
+ /**
77
+ * @return string[]
78
+ * @deprecated 9.2.0
79
+ */
80
+ protected function getDefaultColumnsDefinition() {
81
+ return $this->getColumns();
82
+ }
83
+
84
  /**
85
  * @return string[]
86
  */
87
  public function getColumnsDefinition() {
88
+ return $this->enumerateColumns();
89
+ }
90
+
91
+ /**
92
+ * @return string[]
93
+ */
94
+ public function getColumnas() {
95
+ return $this->getColumns();
96
  }
97
 
98
  /**
162
  * @return string
163
  */
164
  public function getSqlCreate() {
165
+ return $this->getDefaultCreateTableSql();
166
  }
167
 
168
  /**
184
  }
185
  $oDB = Services::WpDb();
186
  $sSql = sprintf( $sSql, $this->getTable(), $oDB->getCharCollate() );
187
+ $this->tableExists() ? $oDB->dbDelta( $sSql ) : $oDB->doSql( $sSql );
188
  return $this;
189
  }
190
 
195
  public function tableDelete( $bTruncate = false ) {
196
  $table = $this->getTable();
197
  $oDB = Services::WpDb();
198
+ $mResult = !$this->tableExists() ||
199
  ( $bTruncate ? $oDB->doTruncateTable( $table ) : $oDB->doDropTable( $table ) );
200
  $this->reset();
201
  return $mResult !== false;
218
  $this->tableCreate();
219
 
220
  if ( !$this->isReady( true ) ) {
221
+ $this->tableDelete();
222
  $this->tableCreate();
223
  }
224
  }
250
 
251
  if ( !isset( $this->bIsReady ) ) {
252
  try {
253
+ $this->bIsReady = $this->tableExists() && $this->verifyTableStructure();
254
  }
255
  catch ( \Exception $e ) {
256
  $this->bIsReady = false;
269
  return $this;
270
  }
271
 
 
 
 
 
 
 
 
 
 
272
  /**
273
  * @param string $sTable
274
  * @return $this
281
  /**
282
  * @return string[]
283
  */
284
+ public function getColumns() {
285
  return [];
286
  }
287
 
330
  * @throws \Exception
331
  */
332
  protected function verifyTableStructure() {
333
+ $aColDef = array_map( 'strtolower', $this->getColumns() );
334
  if ( empty( $aColDef ) ) {
335
  throw new \Exception( 'Could not verify table structure as no columns definition provided' );
336
  }
362
  return $this;
363
  }
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  /**
366
  * @return string[]
367
  */
387
  protected function getPrimaryKeySpec() {
388
  return 'PRIMARY KEY (id)';
389
  }
390
+
391
+ /**
392
+ * @param bool $bTruncate
393
+ * @return bool
394
+ * @deprecated 9.0.4
395
+ */
396
+ public function deleteTable( $bTruncate = false ) {
397
+ return $this->tableDelete( $bTruncate );
398
+ }
399
+
400
+ /**
401
+ * @return bool
402
+ * @deprecated 9.0.4
403
+ */
404
+ public function isTable() {
405
+ return $this->tableExists();
406
+ }
407
+
408
+ /**
409
+ * @param int $nAutoExpireDays
410
+ * @return $this
411
+ * @deprecated 9.2.0
412
+ */
413
+ public function cleanDb( $nAutoExpireDays ) {
414
+ return $this->tableCleanExpired( $nAutoExpireDays );
415
+ }
416
  }
src/lib/src/Databases/ChangeTracking/Handler.php CHANGED
@@ -10,19 +10,17 @@ class Handler extends Base\Handler {
10
  /**
11
  * @return string[]
12
  */
13
- protected function getDefaultColumnsDefinition() {
14
- /** @var Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- return $oOpts->getDbColumns_ChangeTracking();
17
  }
18
 
19
  /**
20
  * @return string
21
  */
22
  protected function getDefaultTableName() {
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- return $oOpts->getDbTable_ChangeTracking();
26
  }
27
 
28
  /**
@@ -38,4 +36,12 @@ class Handler extends Base\Handler {
38
  PRIMARY KEY (id)
39
  ) %s;";
40
  }
 
 
 
 
 
 
 
 
41
  }
10
  /**
11
  * @return string[]
12
  */
13
+ public function getColumns() {
14
+ return $this->getOptions()->getDef( 'table_columns_changetracking' );
 
 
15
  }
16
 
17
  /**
18
  * @return string
19
  */
20
  protected function getDefaultTableName() {
21
+ /** @var Options $opts */
22
+ $opts = $this->getOptions();
23
+ return $opts->getDbTable_ChangeTracking();
24
  }
25
 
26
  /**
36
  PRIMARY KEY (id)
37
  ) %s;";
38
  }
39
+
40
+ /**
41
+ * @return string[]
42
+ * @deprecated 9.2.0
43
+ */
44
+ protected function getDefaultColumnsDefinition() {
45
+ return $this->getOptions()->getDef( 'table_columns_changetracking' );
46
+ }
47
  }
src/lib/src/Databases/Events/Handler.php CHANGED
@@ -33,27 +33,25 @@ class Handler extends Base\Handler {
33
  $oEvt->event = $sEvent;
34
  $oEvt->count = max( 1, (int)$nCount );
35
  $oEvt->created_at = max( 1, $nTs );
36
- /** @var Insert $oQI */
37
- $oQI = $this->getQueryInserter();
38
- return $oQI->insert( $oEvt );
39
  }
40
 
41
  /**
42
  * @return string[]
43
  */
44
- protected function getDefaultColumnsDefinition() {
45
- /** @var Options $oOpts */
46
- $oOpts = $this->getOptions();
47
- return $oOpts->getDbColumns_Events();
48
  }
49
 
50
  /**
51
  * @return string
52
  */
53
  protected function getDefaultTableName() {
54
- /** @var Options $oOpts */
55
- $oOpts = $this->getOptions();
56
- return $oOpts->getDbTable_Events();
57
  }
58
 
59
  /**
@@ -69,4 +67,12 @@ class Handler extends Base\Handler {
69
  PRIMARY KEY (id)
70
  ) %s;";
71
  }
 
 
 
 
 
 
 
 
72
  }
33
  $oEvt->event = $sEvent;
34
  $oEvt->count = max( 1, (int)$nCount );
35
  $oEvt->created_at = max( 1, $nTs );
36
+ /** @var Insert $QI */
37
+ $QI = $this->getQueryInserter();
38
+ return $QI->insert( $oEvt );
39
  }
40
 
41
  /**
42
  * @return string[]
43
  */
44
+ public function getColumns() {
45
+ return $this->getOptions()->getDef( 'events_table_columns' );
 
 
46
  }
47
 
48
  /**
49
  * @return string
50
  */
51
  protected function getDefaultTableName() {
52
+ /** @var Options $opts */
53
+ $opts = $this->getOptions();
54
+ return $opts->getDbTable_Events();
55
  }
56
 
57
  /**
67
  PRIMARY KEY (id)
68
  ) %s;";
69
  }
70
+
71
+ /**
72
+ * @return string[]
73
+ * @deprecated 9.2.0
74
+ */
75
+ protected function getDefaultColumnsDefinition() {
76
+ return $this->getOptions()->getDef( 'events_table_columns' );
77
+ }
78
  }
src/lib/src/Databases/FileLocker/Handler.php CHANGED
@@ -10,19 +10,17 @@ class Handler extends Base\Handler {
10
  /**
11
  * @return string[]
12
  */
13
- protected function getDefaultColumnsDefinition() {
14
- /** @var Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- return $oOpts->getDbColumns_FileLocker();
17
  }
18
 
19
  /**
20
  * @return string
21
  */
22
  protected function getDefaultTableName() {
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- return $oOpts->getDbTable_FileLocker();
26
  }
27
 
28
  /**
@@ -45,4 +43,12 @@ class Handler extends Base\Handler {
45
  PRIMARY KEY (id)
46
  ) %s;";
47
  }
 
 
 
 
 
 
 
 
48
  }
10
  /**
11
  * @return string[]
12
  */
13
+ public function getColumns() {
14
+ return $this->getOptions()->getDef( 'table_columns_filelocker' );
 
 
15
  }
16
 
17
  /**
18
  * @return string
19
  */
20
  protected function getDefaultTableName() {
21
+ /** @var Options $opts */
22
+ $opts = $this->getOptions();
23
+ return $opts->getDbTable_FileLocker();
24
  }
25
 
26
  /**
43
  PRIMARY KEY (id)
44
  ) %s;";
45
  }
46
+
47
+ /**
48
+ * @return string[]
49
+ * @deprecated 9.2.0
50
+ */
51
+ protected function getDefaultColumnsDefinition() {
52
+ return $this->getOptions()->getDef( 'table_columns_filelocker' );
53
+ }
54
  }
src/lib/src/Databases/GeoIp/Handler.php CHANGED
@@ -8,27 +8,23 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Options;
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
- /** @var Options $oOpts */
12
- $oOpts = $this->getOptions();
13
- $this->cleanDb( $oOpts->getDef( 'db_autoexpire_geoip' ) );
14
  }
15
 
16
  /**
17
  * @return string[]
18
  */
19
- protected function getDefaultColumnsDefinition() {
20
- /** @var Options $oOpts */
21
- $oOpts = $this->getOptions();
22
- return $oOpts->getDbColumns_GeoIp();
23
  }
24
 
25
  /**
26
  * @return string
27
  */
28
  protected function getDefaultTableName() {
29
- /** @var Options $oOpts */
30
- $oOpts = $this->getOptions();
31
- return $oOpts->getDbTable_GeoIp();
32
  }
33
 
34
  /**
@@ -44,4 +40,12 @@ class Handler extends Base\Handler {
44
  PRIMARY KEY (id)
45
  ) %s;";
46
  }
 
 
 
 
 
 
 
 
47
  }
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
+ $this->tableCleanExpired( $this->getOptions()->getDef( 'db_autoexpire_geoip' ) );
 
 
12
  }
13
 
14
  /**
15
  * @return string[]
16
  */
17
+ public function getColumns() {
18
+ return $this->getOptions()->getDef( 'geoip_table_columns' );
 
 
19
  }
20
 
21
  /**
22
  * @return string
23
  */
24
  protected function getDefaultTableName() {
25
+ /** @var Options $opts */
26
+ $opts = $this->getOptions();
27
+ return $opts->getDbTable_GeoIp();
28
  }
29
 
30
  /**
40
  PRIMARY KEY (id)
41
  ) %s;";
42
  }
43
+
44
+ /**
45
+ * @return string[]
46
+ * @deprecated 9.2.0
47
+ */
48
+ protected function getDefaultColumnsDefinition() {
49
+ return $this->getOptions()->getDef( 'geoip_table_columns' );
50
+ }
51
  }
src/lib/src/Databases/IPs/Handler.php CHANGED
@@ -9,14 +9,12 @@ use FernleafSystems\Wordpress\Services\Services;
9
  class Handler extends Base\Handler {
10
 
11
  public function autoCleanDb() {
12
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
13
- $oMod = $this->getMod();
14
- /** @var Options $oOpts */
15
- $oOpts = $oMod->getOptions();
16
- /** @var Delete $oDel */
17
- $oDel = $this->getQueryDeleter();
18
- $oDel->filterByBlacklist()
19
- ->filterByLastAccessBefore( Services::Request()->ts() - $oOpts->getAutoExpireTime() )
20
  ->query();
21
  }
22
 
@@ -34,34 +32,31 @@ class Handler extends Base\Handler {
34
  /**
35
  * @return string[]
36
  */
37
- protected function getDefaultColumnsDefinition() {
38
- /** @var Options $oOpts */
39
- $oOpts = $this->getOptions();
40
- return $oOpts->getDbColumns_IPs();
41
  }
42
 
43
  /**
44
  * @return string
45
  */
46
  protected function getDefaultTableName() {
47
- /** @var Options $oOpts */
48
- $oOpts = $this->getOptions();
49
- return $oOpts->getDbTable_IPs();
50
  }
51
 
52
  /**
53
  * @return string[]
54
  */
55
  protected function getColumnsAsArray() {
56
- return [
57
- 'ip' => "varchar(60) NOT NULL DEFAULT '' COMMENT 'Human readable IP address or range'",
58
- 'label' => "varchar(255) NOT NULL DEFAULT ''",
59
- 'transgressions' => "smallint(1) UNSIGNED NOT NULL DEFAULT 0",
60
- 'list' => "varchar(4) NOT NULL DEFAULT ''",
61
- 'ip6' => "tinyint(1) UNSIGNED NOT NULL DEFAULT 0",
62
- 'is_range' => "tinyint(1) UNSIGNED NOT NULL DEFAULT 0",
63
- 'last_access_at' => "int(15) UNSIGNED NOT NULL DEFAULT 0",
64
- 'blocked_at' => "int(15) UNSIGNED NOT NULL DEFAULT 0",
65
- ];
66
  }
67
  }
9
  class Handler extends Base\Handler {
10
 
11
  public function autoCleanDb() {
12
+ /** @var Options $opts */
13
+ $opts = $this->getOptions();
14
+ /** @var Delete $del */
15
+ $del = $this->getQueryDeleter();
16
+ $del->filterByBlacklist()
17
+ ->filterByLastAccessBefore( Services::Request()->ts() - $opts->getAutoExpireTime() )
 
 
18
  ->query();
19
  }
20
 
32
  /**
33
  * @return string[]
34
  */
35
+ public function getColumns() {
36
+ return array_keys( $this->getColumnsDefinition() );
 
 
37
  }
38
 
39
  /**
40
  * @return string
41
  */
42
  protected function getDefaultTableName() {
43
+ /** @var Options $opts */
44
+ $opts = $this->getOptions();
45
+ return $opts->getDbTable_IPs();
46
  }
47
 
48
  /**
49
  * @return string[]
50
  */
51
  protected function getColumnsAsArray() {
52
+ return $this->getOptions()->getDef( 'ip_list_table_columns' );
53
+ }
54
+
55
+ /**
56
+ * @return string[]
57
+ * @deprecated 9.2.0
58
+ */
59
+ protected function getDefaultColumnsDefinition() {
60
+ return $this->getOptions()->getDef( 'ip_list_table_columns' );
 
61
  }
62
  }
src/lib/src/Databases/Reports/Handler.php CHANGED
@@ -11,25 +11,23 @@ class Handler extends Base\Handler {
11
  const TYPE_INFO = 'nfo';
12
 
13
  public function autoCleanDb() {
14
- $this->cleanDb( 30 );
15
  }
16
 
17
  /**
18
  * @return string[]
19
  */
20
- protected function getDefaultColumnsDefinition() {
21
- /** @var Options $oOpts */
22
- $oOpts = $this->getOptions();
23
- return $oOpts->getDbColumns_Reports();
24
  }
25
 
26
  /**
27
  * @return string
28
  */
29
  protected function getDefaultTableName() {
30
- /** @var Options $oOpts */
31
- $oOpts = $this->getOptions();
32
- return $oOpts->getDbTable_Reports();
33
  }
34
 
35
  /**
@@ -48,4 +46,12 @@ class Handler extends Base\Handler {
48
  PRIMARY KEY (id)
49
  ) %s;";
50
  }
 
 
 
 
 
 
 
 
51
  }
11
  const TYPE_INFO = 'nfo';
12
 
13
  public function autoCleanDb() {
14
+ $this->tableCleanExpired( 30 );
15
  }
16
 
17
  /**
18
  * @return string[]
19
  */
20
+ public function getColumns() {
21
+ return $this->getOptions()->getDef( 'reports_table_columns' );
 
 
22
  }
23
 
24
  /**
25
  * @return string
26
  */
27
  protected function getDefaultTableName() {
28
+ /** @var Options $opts */
29
+ $opts = $this->getOptions();
30
+ return $opts->getDbTable_Reports();
31
  }
32
 
33
  /**
46
  PRIMARY KEY (id)
47
  ) %s;";
48
  }
49
+
50
+ /**
51
+ * @return string[]
52
+ * @deprecated 9.2.0
53
+ */
54
+ protected function getDefaultColumnsDefinition() {
55
+ return $this->getOptions()->getDef( 'reports_table_columns' );
56
+ }
57
  }
src/lib/src/Databases/ScanQueue/Handler.php CHANGED
@@ -10,19 +10,17 @@ class Handler extends Base\Handler {
10
  /**
11
  * @return string[]
12
  */
13
- protected function getDefaultColumnsDefinition() {
14
- /** @var Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- return $oOpts->getDbColumns_ScanQueue();
17
  }
18
 
19
  /**
20
  * @return string
21
  */
22
  protected function getDefaultTableName() {
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- return $oOpts->getDbTable_ScanQueue();
26
  }
27
 
28
  /**
@@ -42,4 +40,12 @@ class Handler extends Base\Handler {
42
  PRIMARY KEY (id)
43
  ) %s;";
44
  }
 
 
 
 
 
 
 
 
45
  }
10
  /**
11
  * @return string[]
12
  */
13
+ public function getColumns() {
14
+ return $this->getOptions()->getDef( 'table_columns_scanqueue' );
 
 
15
  }
16
 
17
  /**
18
  * @return string
19
  */
20
  protected function getDefaultTableName() {
21
+ /** @var Options $opts */
22
+ $opts = $this->getOptions();
23
+ return $opts->getDbTable_ScanQueue();
24
  }
25
 
26
  /**
40
  PRIMARY KEY (id)
41
  ) %s;";
42
  }
43
+
44
+ /**
45
+ * @return string[]
46
+ * @deprecated 9.2.0
47
+ */
48
+ protected function getDefaultColumnsDefinition() {
49
+ return $this->getOptions()->getDef( 'table_columns_scanqueue' );
50
+ }
51
  }
src/lib/src/Databases/Scanner/Handler.php CHANGED
@@ -10,19 +10,17 @@ class Handler extends Base\Handler {
10
  /**
11
  * @return string[]
12
  */
13
- protected function getDefaultColumnsDefinition() {
14
- /** @var Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- return $oOpts->getDbColumns_Scanner();
17
  }
18
 
19
  /**
20
  * @return string
21
  */
22
  protected function getDefaultTableName() {
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- return $oOpts->getDbTable_Scanner();
26
  }
27
 
28
  /**
@@ -42,4 +40,12 @@ class Handler extends Base\Handler {
42
  PRIMARY KEY (id)
43
  ) %s;";
44
  }
 
 
 
 
 
 
 
 
45
  }
10
  /**
11
  * @return string[]
12
  */
13
+ public function getColumns() {
14
+ return $this->getOptions()->getDef( 'table_columns_scanner' );
 
 
15
  }
16
 
17
  /**
18
  * @return string
19
  */
20
  protected function getDefaultTableName() {
21
+ /** @var Options $opts */
22
+ $opts = $this->getOptions();
23
+ return $opts->getDbTable_Scanner();
24
  }
25
 
26
  /**
40
  PRIMARY KEY (id)
41
  ) %s;";
42
  }
43
+
44
+ /**
45
+ * @return string[]
46
+ * @deprecated 9.2.0
47
+ */
48
+ protected function getDefaultColumnsDefinition() {
49
+ return $this->getOptions()->getDef( 'table_columns_scanner' );
50
+ }
51
  }
src/lib/src/Databases/Session/Handler.php CHANGED
@@ -8,25 +8,23 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Options;
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
- $this->cleanDb( 30 );
12
  }
13
 
14
  /**
15
  * @return string[]
16
  */
17
- protected function getDefaultColumnsDefinition() {
18
- /** @var Options $oOpts */
19
- $oOpts = $this->getOptions();
20
- return $oOpts->getDbColumns_Sessions();
21
  }
22
 
23
  /**
24
  * @return string
25
  */
26
  protected function getDefaultTableName() {
27
- /** @var Options $oOpts */
28
- $oOpts = $this->getOptions();
29
- return $oOpts->getDbTable_Sessions();
30
  }
31
 
32
  /**
@@ -50,4 +48,12 @@ class Handler extends Base\Handler {
50
  PRIMARY KEY (id)
51
  ) %s;";
52
  }
 
 
 
 
 
 
 
 
53
  }
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
+ $this->tableCleanExpired( 30 );
12
  }
13
 
14
  /**
15
  * @return string[]
16
  */
17
+ public function getColumns() {
18
+ return $this->getOptions()->getDef( 'sessions_table_columns' );
 
 
19
  }
20
 
21
  /**
22
  * @return string
23
  */
24
  protected function getDefaultTableName() {
25
+ /** @var Options $opts */
26
+ $opts = $this->getOptions();
27
+ return $opts->getDbTable_Sessions();
28
  }
29
 
30
  /**
48
  PRIMARY KEY (id)
49
  ) %s;";
50
  }
51
+
52
+ /**
53
+ * @return string[]
54
+ * @deprecated 9.2.0
55
+ */
56
+ protected function getDefaultColumnsDefinition() {
57
+ return $this->getOptions()->getDef( 'sessions_table_columns' );
58
+ }
59
  }
src/lib/src/Databases/Tally/Handler.php CHANGED
@@ -10,19 +10,17 @@ class Handler extends Base\Handler {
10
  /**
11
  * @return string[]
12
  */
13
- protected function getDefaultColumnsDefinition() {
14
- /** @var Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- return $oOpts->getDbColumns_Tallys();
17
  }
18
 
19
  /**
20
  * @return string
21
  */
22
  protected function getDefaultTableName() {
23
- /** @var Options $oOpts */
24
- $oOpts = $this->getOptions();
25
- return $oOpts->getDbTable_Tallys();
26
  }
27
 
28
  /**
@@ -40,4 +38,12 @@ class Handler extends Base\Handler {
40
  PRIMARY KEY (id)
41
  ) %s;";
42
  }
 
 
 
 
 
 
 
 
43
  }
10
  /**
11
  * @return string[]
12
  */
13
+ public function getColumns() {
14
+ return $this->getOptions()->getDef( 'statistics_table_columns' );
 
 
15
  }
16
 
17
  /**
18
  * @return string
19
  */
20
  protected function getDefaultTableName() {
21
+ /** @var Options $opts */
22
+ $opts = $this->getOptions();
23
+ return $opts->getDbTable_Tallys();
24
  }
25
 
26
  /**
38
  PRIMARY KEY (id)
39
  ) %s;";
40
  }
41
+
42
+ /**
43
+ * @return string[]
44
+ * @deprecated 9.2.0
45
+ */
46
+ protected function getDefaultColumnsDefinition() {
47
+ return $this->getOptions()->getDef( 'statistics_table_columns' );
48
+ }
49
  }
src/lib/src/Databases/Traffic/Handler.php CHANGED
@@ -8,28 +8,26 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Traffic\Options;
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
- /** @var Options $oOpts */
12
- $oOpts = $this->getOptions();
13
- $this->cleanDb( $oOpts->getAutoCleanDays() );
14
- $this->tableTrimExcess( $oOpts->getMaxEntries() );
15
  }
16
 
17
  /**
18
  * @return string[]
19
  */
20
- protected function getDefaultColumnsDefinition() {
21
- /** @var Options $oOpts */
22
- $oOpts = $this->getOptions();
23
- return $oOpts->getDbColumns_TrafficLog();
24
  }
25
 
26
  /**
27
  * @return string
28
  */
29
  protected function getDefaultTableName() {
30
- /** @var Options $oOpts */
31
- $oOpts = $this->getOptions();
32
- return $oOpts->getDbTable_TrafficLog();
33
  }
34
 
35
  /**
@@ -51,4 +49,12 @@ class Handler extends Base\Handler {
51
  PRIMARY KEY (id)
52
  ) %s;";
53
  }
 
 
 
 
 
 
 
 
54
  }
8
  class Handler extends Base\Handler {
9
 
10
  public function autoCleanDb() {
11
+ /** @var Options $opts */
12
+ $opts = $this->getOptions();
13
+ $this->tableCleanExpired( $opts->getAutoCleanDays() );
14
+ $this->tableTrimExcess( $opts->getMaxEntries() );
15
  }
16
 
17
  /**
18
  * @return string[]
19
  */
20
+ public function getColumns() {
21
+ return $this->getOptions()->getDef( 'traffic_table_columns' );
 
 
22
  }
23
 
24
  /**
25
  * @return string
26
  */
27
  protected function getDefaultTableName() {
28
+ /** @var Options $opts */
29
+ $opts = $this->getOptions();
30
+ return $opts->getDbTable_TrafficLog();
31
  }
32
 
33
  /**
49
  PRIMARY KEY (id)
50
  ) %s;";
51
  }
52
+
53
+ /**
54
+ * @return string[]
55
+ * @deprecated 9.2.0
56
+ */
57
+ protected function getDefaultColumnsDefinition() {
58
+ return $this->getOptions()->getDef( 'traffic_table_columns' );
59
+ }
60
  }
src/lib/src/Helpers/QuickAccess.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Helpers;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Controller\Controller;
6
+
7
+ class QuickAccess {
8
+
9
+ public static function IsRequestWhiteListed() {
10
+ try {
11
+ return Controller::GetInstance()
12
+ ->getModule_IPs()
13
+ ->isVisitorWhitelisted();
14
+ }
15
+ catch ( \Exception $e ) {
16
+ return false;
17
+ }
18
+ }
19
+ }
src/lib/src/Modules/AuditTrail/AjaxHandler.php CHANGED
@@ -8,12 +8,12 @@ use FernleafSystems\Wordpress\Services\Services;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
- * @param string $sAction
12
  * @return array
13
  */
14
- protected function processAjaxAction( $sAction ) {
15
 
16
- switch ( $sAction ) {
17
  case 'render_table_audittrail':
18
  $aResponse = $this->ajaxExec_BuildTableAuditTrail();
19
  break;
@@ -23,7 +23,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
23
  break;
24
 
25
  default:
26
- $aResponse = parent::processAjaxAction( $sAction );
27
  }
28
 
29
  return $aResponse;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
+ * @param string $action
12
  * @return array
13
  */
14
+ protected function processAjaxAction( $action ) {
15
 
16
+ switch ( $action ) {
17
  case 'render_table_audittrail':
18
  $aResponse = $this->ajaxExec_BuildTableAuditTrail();
19
  break;
23
  break;
24
 
25
  default:
26
+ $aResponse = parent::processAjaxAction( $action );
27
  }
28
 
29
  return $aResponse;
src/lib/src/Modules/AuditTrail/Options.php CHANGED
@@ -9,6 +9,7 @@ class Options extends Base\ShieldOptions {
9
 
10
  /**
11
  * @return array
 
12
  */
13
  public function getDbColumns_AuditTrail() {
14
  return $this->getDef( 'audit_trail_table_columns' );
@@ -16,6 +17,7 @@ class Options extends Base\ShieldOptions {
16
 
17
  /**
18
  * @return array
 
19
  */
20
  public function getDbColumns_ChangeTracking() {
21
  return $this->getDef( 'table_columns_changetracking' );
9
 
10
  /**
11
  * @return array
12
+ * @deprecated 9.2.0
13
  */
14
  public function getDbColumns_AuditTrail() {
15
  return $this->getDef( 'audit_trail_table_columns' );
17
 
18
  /**
19
  * @return array
20
+ * @deprecated 9.2.0
21
  */
22
  public function getDbColumns_ChangeTracking() {
23
  return $this->getDef( 'table_columns_changetracking' );
src/lib/src/Modules/AuditTrail/Strings.php CHANGED
@@ -105,13 +105,13 @@ class Strings extends Base\Strings {
105
  }
106
 
107
  /**
108
- * @param string $sSectionSlug
109
  * @return array
110
  * @throws \Exception
111
  */
112
- public function getSectionStrings( $sSectionSlug ) {
113
 
114
- switch ( $sSectionSlug ) {
115
 
116
  case 'section_enable_plugin_feature_audit_trail' :
117
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -159,7 +159,7 @@ class Strings extends Base\Strings {
159
  */
160
 
161
  default:
162
- return parent::getSectionStrings( $sSectionSlug );
163
  }
164
 
165
  return [
@@ -170,19 +170,17 @@ class Strings extends Base\Strings {
170
  }
171
 
172
  /**
173
- * @param string $sOptKey
174
  * @return array
175
  * @throws \Exception
176
  */
177
- public function getOptionStrings( $sOptKey ) {
178
- /** @var \ICWP_WPSF_FeatureHandler_AuditTrail $oMod */
179
- $oMod = $this->getMod();
180
- $oCon = $this->getCon();
181
- /** @var Options $oOpts */
182
- $oOpts = $oMod->getOptions();
183
- $sModName = $oMod->getMainFeatureName();
184
 
185
- switch ( $sOptKey ) {
186
 
187
  case 'enable_audit_trail' :
188
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -196,9 +194,9 @@ class Strings extends Base\Strings {
196
  $sDescription = [
197
  __( 'Automatically remove any audit trail entries when this limit is exceeded.', 'wp-simple-firewall' ),
198
  ];
199
- if ( !$oCon->isPremiumActive() ) {
200
  $sDescription[] = sprintf( __( 'Upgrade to PRO to increase limit above %s.', 'wp-simple-firewall' ),
201
- '<code>'.$oOpts->getDef( 'audit_trail_free_max_entries' ).'</code>' );
202
  }
203
 
204
  break;
@@ -246,9 +244,9 @@ class Strings extends Base\Strings {
246
  break;
247
 
248
  case 'enable_audit_context_wpsf' :
249
- $sName = $oCon->getHumanName();
250
- $sSummary = sprintf( __( 'Enable Audit Context - %s', 'wp-simple-firewall' ), $oCon->getHumanName() );
251
- $sDescription = sprintf( __( 'When this context is enabled, the audit trail will track activity relating to: %s', 'wp-simple-firewall' ), $oCon->getHumanName() );
252
  break;
253
 
254
  case 'enable_change_tracking' :
@@ -273,7 +271,7 @@ class Strings extends Base\Strings {
273
  break;
274
 
275
  default:
276
- return parent::getOptionStrings( $sOptKey );
277
  }
278
 
279
  return [
105
  }
106
 
107
  /**
108
+ * @param string $section
109
  * @return array
110
  * @throws \Exception
111
  */
112
+ public function getSectionStrings( $section ) {
113
 
114
+ switch ( $section ) {
115
 
116
  case 'section_enable_plugin_feature_audit_trail' :
117
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
159
  */
160
 
161
  default:
162
+ return parent::getSectionStrings( $section );
163
  }
164
 
165
  return [
170
  }
171
 
172
  /**
173
+ * @param string $key
174
  * @return array
175
  * @throws \Exception
176
  */
177
+ public function getOptionStrings( $key ) {
178
+ $con = $this->getCon();
179
+ /** @var Options $opts */
180
+ $opts = $this->getOptions();
181
+ $sModName = $this->getMod()->getMainFeatureName();
 
 
182
 
183
+ switch ( $key ) {
184
 
185
  case 'enable_audit_trail' :
186
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
194
  $sDescription = [
195
  __( 'Automatically remove any audit trail entries when this limit is exceeded.', 'wp-simple-firewall' ),
196
  ];
197
+ if ( !$con->isPremiumActive() ) {
198
  $sDescription[] = sprintf( __( 'Upgrade to PRO to increase limit above %s.', 'wp-simple-firewall' ),
199
+ '<code>'.$opts->getDef( 'audit_trail_free_max_entries' ).'</code>' );
200
  }
201
 
202
  break;
244
  break;
245
 
246
  case 'enable_audit_context_wpsf' :
247
+ $sName = $con->getHumanName();
248
+ $sSummary = sprintf( __( 'Enable Audit Context - %s', 'wp-simple-firewall' ), $con->getHumanName() );
249
+ $sDescription = sprintf( __( 'When this context is enabled, the audit trail will track activity relating to: %s', 'wp-simple-firewall' ), $con->getHumanName() );
250
  break;
251
 
252
  case 'enable_change_tracking' :
271
  break;
272
 
273
  default:
274
+ return parent::getOptionStrings( $key );
275
  }
276
 
277
  return [
src/lib/src/Modules/AuditTrail/UI.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class UI extends Base\ShieldUI {
8
+
9
+ /**
10
+ * @return array
11
+ */
12
+ public function getInsightsConfigCardData() {
13
+ /** @var \ICWP_WPSF_FeatureHandler_AuditTrail $mod */
14
+ $mod = $this->getMod();
15
+ /** @var Options $opts */
16
+ $opts = $this->getOptions();
17
+
18
+ $data = [
19
+ 'strings' => [
20
+ 'title' => __( 'Activity Audit Log', 'wp-simple-firewall' ),
21
+ 'sub' => __( 'Track Activity: What, Who, When, Where', 'wp-simple-firewall' ),
22
+ ],
23
+ 'key_opts' => [],
24
+ 'href_options' => $mod->getUrl_AdminPage()
25
+ ];
26
+
27
+ if ( !$mod->isModOptEnabled() ) {
28
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
29
+ }
30
+ else {
31
+ $aAudit = [];
32
+ $aNonAudit = [];
33
+ $opts->isAuditShield() ? $aAudit[] = 'Shield' : $aNonAudit[] = 'Shield';
34
+ $opts->isAuditUsers() ? $aAudit[] = __( 'users', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'users', 'wp-simple-firewall' );
35
+ $opts->isAuditPlugins() ? $aAudit[] = __( 'plugins', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'plugins', 'wp-simple-firewall' );
36
+ $opts->isAuditThemes() ? $aAudit[] = __( 'themes', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'themes', 'wp-simple-firewall' );
37
+ $opts->isAuditPosts() ? $aAudit[] = __( 'posts', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'posts', 'wp-simple-firewall' );
38
+ $opts->isAuditEmails() ? $aAudit[] = __( 'emails', 'wp-simple-firewall' ) : $aNonAudit[] = __( 'emails', 'wp-simple-firewall' );
39
+ $opts->isAuditWp() ? $aAudit[] = 'WP' : $aNonAudit[] = 'WP';
40
+
41
+ if ( empty( $aNonAudit ) ) {
42
+ $data[ 'key_opts' ][ 'audit' ] = [
43
+ 'name' => __( 'Audit Areas', 'wp-simple-firewall' ),
44
+ 'enabled' => true,
45
+ 'summary' => __( 'All important events on your site are being logged', 'wp-simple-firewall' ),
46
+ 'weight' => 2,
47
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_enable_audit_contexts' ),
48
+ ];
49
+ }
50
+ elseif ( empty( $aAudit ) ) {
51
+ $data[ 'key_opts' ][ 'audit' ] = [
52
+ 'name' => __( 'Audit Areas', 'wp-simple-firewall' ),
53
+ 'enabled' => false,
54
+ 'summary' => sprintf( __( 'No areas are set to be audited: %s', 'wp-simple-firewall' ), implode( ', ', $aAudit ) ),
55
+ 'weight' => 2,
56
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_enable_audit_contexts' ),
57
+ ];
58
+ }
59
+ else {
60
+ $data[ 'key_opts' ][ 'nonaudit' ] = [
61
+ 'name' => __( 'Audit Events', 'wp-simple-firewall' ),
62
+ 'enabled' => false,
63
+ 'summary' => sprintf( __( "Important events aren't being audited: %s", 'wp-simple-firewall' ), implode( ', ', $aNonAudit ) ),
64
+ 'weight' => 2,
65
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_enable_audit_contexts' ),
66
+ ];
67
+ }
68
+
69
+ $data[ 'key_opts' ][ 'length' ] = [
70
+ 'name' => __( 'Audit Trail', 'wp-simple-firewall' ),
71
+ 'enabled' => true,
72
+ 'summary' => sprintf( __( 'Maximum Audit Trail entries limited to %s', 'wp-simple-firewall' ), $opts->getMaxEntries() ),
73
+ 'weight' => 0,
74
+ 'href' => $mod->getUrl_DirectLinkToOption( 'audit_trail_max_entries' ),
75
+ ];
76
+ }
77
+
78
+ return $data;
79
+ }
80
+ }
src/lib/src/Modules/Autoupdates/Strings.php CHANGED
@@ -7,15 +7,15 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
  class Strings extends Base\Strings {
8
 
9
  /**
10
- * @param string $sSectionSlug
11
  * @return array
12
  * @throws \Exception
13
  */
14
- public function getSectionStrings( $sSectionSlug ) {
15
  $sModName = $this->getMod()->getMainFeatureName();
16
  $sPlugName = $this->getCon()->getHumanName();
17
 
18
- switch ( $sSectionSlug ) {
19
 
20
  case 'section_enable_plugin_feature_automatic_updates_control' :
21
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -65,7 +65,7 @@ class Strings extends Base\Strings {
65
  break;
66
 
67
  default:
68
- return parent::getSectionStrings( $sSectionSlug );
69
  }
70
 
71
  return [
@@ -76,15 +76,15 @@ class Strings extends Base\Strings {
76
  }
77
 
78
  /**
79
- * @param string $sOptKey
80
  * @return array
81
  * @throws \Exception
82
  */
83
- public function getOptionStrings( $sOptKey ) {
84
  $sModName = $this->getMod()->getMainFeatureName();
85
  $sPlugName = $this->getCon()->getHumanName();
86
 
87
- switch ( $sOptKey ) {
88
 
89
  case 'enable_autoupdates' :
90
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -160,7 +160,7 @@ class Strings extends Base\Strings {
160
  break;
161
 
162
  default:
163
- return parent::getOptionStrings( $sOptKey );
164
  }
165
 
166
  return [
7
  class Strings extends Base\Strings {
8
 
9
  /**
10
+ * @param string $section
11
  * @return array
12
  * @throws \Exception
13
  */
14
+ public function getSectionStrings( $section ) {
15
  $sModName = $this->getMod()->getMainFeatureName();
16
  $sPlugName = $this->getCon()->getHumanName();
17
 
18
+ switch ( $section ) {
19
 
20
  case 'section_enable_plugin_feature_automatic_updates_control' :
21
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
65
  break;
66
 
67
  default:
68
+ return parent::getSectionStrings( $section );
69
  }
70
 
71
  return [
76
  }
77
 
78
  /**
79
+ * @param string $key
80
  * @return array
81
  * @throws \Exception
82
  */
83
+ public function getOptionStrings( $key ) {
84
  $sModName = $this->getMod()->getMainFeatureName();
85
  $sPlugName = $this->getCon()->getHumanName();
86
 
87
+ switch ( $key ) {
88
 
89
  case 'enable_autoupdates' :
90
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
160
  break;
161
 
162
  default:
163
+ return parent::getOptionStrings( $key );
164
  }
165
 
166
  return [
src/lib/src/Modules/Autoupdates/UI.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Autoupdates;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class UI extends Base\ShieldUI {
9
+
10
+ /**
11
+ * @return array
12
+ */
13
+ public function getInsightsConfigCardData() {
14
+ /** @var \ICWP_WPSF_FeatureHandler_Autoupdates $mod */
15
+ $mod = $this->getMod();
16
+ /** @var Options $opts */
17
+ $opts = $this->getOptions();
18
+
19
+ $data = [
20
+ 'strings' => [
21
+ 'title' => __( 'Automatic Updates', 'wp-simple-firewall' ),
22
+ 'sub' => __( 'Control WordPress Automatic Updates', 'wp-simple-firewall' ),
23
+ ],
24
+ 'key_opts' => [],
25
+ 'href_options' => $mod->getUrl_AdminPage()
26
+ ];
27
+
28
+ if ( !$mod->isModOptEnabled() ) {
29
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
30
+ }
31
+ elseif ( $opts->isDisableAllAutoUpdates() ) {
32
+ $data[ 'key_opts' ][ 'disabled' ] = [
33
+ 'name' => __( 'Disabled All', 'wp-simple-firewall' ),
34
+ 'enabled' => false,
35
+ 'summary' => __( 'All automatic updates on this site are disabled', 'wp-simple-firewall' ),
36
+ 'weight' => 2,
37
+ 'href' => $mod->getUrl_DirectLinkToOption( 'enable_autoupdate_disable_all' ),
38
+ ];
39
+ }
40
+ else {
41
+ $bCanCore = Services::WpGeneral()->canCoreUpdateAutomatically();
42
+ $data[ 'key_opts' ][ 'core_minor' ] = [
43
+ 'name' => __( 'Core Updates', 'wp-simple-firewall' ),
44
+ 'enabled' => $bCanCore,
45
+ 'summary' => $bCanCore ?
46
+ __( 'Minor WP Core updates will be installed automatically', 'wp-simple-firewall' )
47
+ : __( 'Minor WP Core updates will not be installed automatically', 'wp-simple-firewall' ),
48
+ 'weight' => 2,
49
+ 'href' => $mod->getUrl_DirectLinkToOption( 'autoupdate_core' ),
50
+ ];
51
+
52
+ $bHasDelay = $mod->isModOptEnabled() && $opts->getDelayUpdatesPeriod();
53
+ $data[ 'key_opts' ][ 'delay' ] = [
54
+ 'name' => __( 'Update Delay', 'wp-simple-firewall' ),
55
+ 'enabled' => $bHasDelay,
56
+ 'summary' => $bHasDelay ?
57
+ __( 'Automatic updates are applied after a short delay', 'wp-simple-firewall' )
58
+ : __( 'Automatic updates are applied immediately', 'wp-simple-firewall' ),
59
+ 'weight' => 1,
60
+ 'href' => $mod->getUrl_DirectLinkToOption( 'update_delay' ),
61
+ ];
62
+
63
+ $sName = $this->getCon()->getHumanName();
64
+ $bSelfAuto = $mod->isModOptEnabled()
65
+ && in_array( $opts->getSelfAutoUpdateOpt(), [ 'auto', 'immediate' ] );
66
+ $data[ 'key_opts' ][ 'self' ] = [
67
+ 'name' => __( 'Self Auto-Update', 'wp-simple-firewall' ),
68
+ 'enabled' => $bSelfAuto,
69
+ 'summary' => $bSelfAuto ?
70
+ sprintf( __( '%s is automatically updated', 'wp-simple-firewall' ), $sName )
71
+ : sprintf( __( "%s isn't automatically updated", 'wp-simple-firewall' ), $sName ),
72
+ 'weight' => 1,
73
+ 'href' => $mod->getUrl_DirectLinkToOption( 'autoupdate_plugin_self' ),
74
+ ];
75
+ }
76
+
77
+ return $data;
78
+ }
79
+
80
+ /**
81
+ * @return array
82
+ */
83
+ public function getInsightsNoticesData() {
84
+ /** @var \ICWP_WPSF_FeatureHandler_Autoupdates $mod */
85
+ $mod = $this->getMod();
86
+ /** @var Options $opts */
87
+ $opts = $this->getOptions();
88
+
89
+ $notices = [
90
+ 'title' => __( 'Automatic Updates', 'wp-simple-firewall' ),
91
+ 'messages' => []
92
+ ];
93
+
94
+ { //really disabled?
95
+ $WP = Services::WpGeneral();
96
+ if ( $mod->isModOptEnabled() ) {
97
+ if ( $opts->isDisableAllAutoUpdates() && !$WP->getWpAutomaticUpdater()->is_disabled() ) {
98
+ $notices[ 'messages' ][ 'disabled_auto' ] = [
99
+ 'title' => 'Auto Updates Not Really Disabled',
100
+ 'message' => __( 'Automatic Updates Are Not Disabled As Expected.', 'wp-simple-firewall' ),
101
+ 'href' => $mod->getUrl_DirectLinkToOption( 'enable_autoupdate_disable_all' ),
102
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
103
+ 'rec' => sprintf( __( 'A plugin/theme other than %s is affecting your automatic update settings.', 'wp-simple-firewall' ), $this->getCon()
104
+ ->getHumanName() )
105
+ ];
106
+ }
107
+ }
108
+ }
109
+
110
+ return $notices;
111
+ }
112
+ }
src/lib/src/Modules/Base/AdminNotices.php CHANGED
@@ -10,15 +10,11 @@ class AdminNotices {
10
 
11
  use Shield\Modules\ModConsumer;
12
 
13
- /**
14
- * @var
15
- */
16
  protected static $nCount = 0;
17
 
18
  public function run() {
19
- $oMod = $this->getMod();
20
- add_filter( $oMod->prefix( 'collectNotices' ), [ $this, 'addNotices' ] );
21
- add_filter( $oMod->prefix( 'ajaxAuthAction' ), [ $this, 'handleAuthAjax' ] );
22
  }
23
 
24
  /**
@@ -70,13 +66,13 @@ class AdminNotices {
70
  protected function buildNotices() {
71
  $aNotices = [];
72
 
73
- foreach ( $this->getAdminNotices() as $oNtc ) {
74
- $this->preProcessNotice( $oNtc );
75
- if ( $oNtc->display ) {
76
  try {
77
- $this->processNotice( $oNtc );
78
- if ( $oNtc->display ) {
79
- $aNotices[] = $oNtc;
80
  }
81
  }
82
  catch ( \Exception $oE ) {
@@ -116,61 +112,60 @@ class AdminNotices {
116
  }
117
 
118
  /**
119
- * @param Shield\Utilities\AdminNotices\NoticeVO $oNtc
120
  */
121
- protected function preProcessNotice( $oNtc ) {
122
- $oCon = $this->getCon();
123
- $oMod = $this->getMod();
124
- $oOpts = $oMod->getOptions();
125
 
126
- if ( $oNtc->plugin_page_only && !$oCon->isModulePage() ) {
127
- $oNtc->non_display_reason = 'plugin_page_only';
128
  }
129
- elseif ( $oNtc->type == 'promo' && !$this->getOptions()->isShowPromoAdminNotices() ) {
130
- $oNtc->non_display_reason = 'promo_hidden';
131
  }
132
- elseif ( $oNtc->valid_admin && !$oCon->isValidAdminArea() ) {
133
- $oNtc->non_display_reason = 'not_admin_area';
134
  }
135
- elseif ( $oNtc->plugin_admin == 'yes' && !$oCon->isPluginAdmin() ) {
136
- $oNtc->non_display_reason = 'not_plugin_admin';
137
  }
138
- elseif ( $oNtc->plugin_admin == 'no' && $oCon->isPluginAdmin() ) {
139
- $oNtc->non_display_reason = 'is_plugin_admin';
140
  }
141
- elseif ( $oNtc->min_install_days > 0 && $oNtc->min_install_days > $oOpts->getInstallationDays() ) {
142
- $oNtc->non_display_reason = 'min_install_days';
143
  }
144
- elseif ( static::$nCount > 0 && $oNtc->type !== 'error' ) {
145
- $oNtc->non_display_reason = 'max_nonerror_count';
146
  }
147
- elseif ( $oNtc->can_dismiss && $this->isNoticeDismissed( $oNtc ) ) {
148
- $oNtc->non_display_reason = 'dismissed';
149
  }
150
- elseif ( !$this->isDisplayNeeded( $oNtc ) ) {
151
- $oNtc->non_display_reason = 'not_needed';
152
  }
153
  else {
154
  static::$nCount++;
155
- $oNtc->display = true;
156
- $oNtc->non_display_reason = 'n/a';
157
  }
158
 
159
- $oNtc->template = '/notices/'.$oNtc->id;
160
  }
161
 
162
  /**
163
- * @param Shield\Utilities\AdminNotices\NoticeVO $oNotice
164
  * @return bool
165
  */
166
- protected function isNoticeDismissed( $oNotice ) {
167
- $bDismissedUser = $this->isNoticeDismissedForCurrentUser( $oNotice );
168
 
169
  $aDisd = $this->getMod()->getDismissedNotices();
170
- $bDismissedMod = isset( $aDisd[ $oNotice->id ] ) && $aDisd[ $oNotice->id ] > 0;
171
 
172
- if ( !$oNotice->per_user && $bDismissedUser && !$bDismissedMod ) {
173
- $this->setNoticeDismissed( $oNotice );
174
  }
175
 
176
  return $bDismissedUser || $bDismissedMod;
@@ -185,22 +180,22 @@ class AdminNotices {
185
  }
186
 
187
  /**
188
- * @param Shield\Utilities\AdminNotices\NoticeVO $oNotice
189
  * @return bool
190
  */
191
- protected function isNoticeDismissedForCurrentUser( $oNotice ) {
192
  $bDismissed = false;
193
 
194
- $oMeta = $this->getCon()->getCurrentUserMeta();
195
- if ( $oMeta instanceof PluginUserMeta ) {
196
- $sNoticeMetaKey = $this->getNoticeMetaKey( $oNotice );
197
 
198
- if ( isset( $oMeta->{$sNoticeMetaKey} ) ) {
199
  $bDismissed = true;
200
 
201
  // migrate from old-style array storage to plain Timestamp
202
- if ( is_array( $oMeta->{$sNoticeMetaKey} ) ) {
203
- $oMeta->{$sNoticeMetaKey} = $oMeta->{$sNoticeMetaKey}[ 'time' ];
204
  }
205
  }
206
  }
@@ -217,39 +212,39 @@ class AdminNotices {
217
  }
218
 
219
  /**
220
- * @param Shield\Utilities\AdminNotices\NoticeVO $oNotice
221
  * @return $this
222
  */
223
- protected function setNoticeDismissed( $oNotice ) {
224
  $nTs = Services::Request()->ts();
225
 
226
- $oMeta = $this->getCon()->getCurrentUserMeta();
227
- $sNoticeMetaKey = $this->getNoticeMetaKey( $oNotice );
228
 
229
- if ( $oNotice->per_user ) {
230
- if ( $oMeta instanceof PluginUserMeta ) {
231
- $oMeta->{$sNoticeMetaKey} = $nTs;
232
  }
233
  }
234
  else {
235
- $oMod = $this->getMod();
236
- $aDismissed = $oMod->getDismissedNotices();
237
- $aDismissed[ $oNotice->id ] = $nTs;
238
- $oMod->setDismissedNotices( $aDismissed );
239
 
240
  // Clear out any old
241
- if ( $oMeta instanceof PluginUserMeta ) {
242
- unset( $oMeta->{$sNoticeMetaKey} );
243
  }
244
  }
245
  return $this;
246
  }
247
 
248
  /**
249
- * @param Shield\Utilities\AdminNotices\NoticeVO $oNotice
250
  * @return string
251
  */
252
- private function getNoticeMetaKey( $oNotice ) {
253
- return 'notice_'.str_replace( [ '-', '_' ], '', $oNotice->id );
254
  }
255
  }
10
 
11
  use Shield\Modules\ModConsumer;
12
 
 
 
 
13
  protected static $nCount = 0;
14
 
15
  public function run() {
16
+ add_filter( $this->getCon()->prefix( 'collectNotices' ), [ $this, 'addNotices' ] );
17
+ add_filter( $this->getCon()->prefix( 'ajaxAuthAction' ), [ $this, 'handleAuthAjax' ] );
 
18
  }
19
 
20
  /**
66
  protected function buildNotices() {
67
  $aNotices = [];
68
 
69
+ foreach ( $this->getAdminNotices() as $notice ) {
70
+ $this->preProcessNotice( $notice );
71
+ if ( $notice->display ) {
72
  try {
73
+ $this->processNotice( $notice );
74
+ if ( $notice->display ) {
75
+ $aNotices[] = $notice;
76
  }
77
  }
78
  catch ( \Exception $oE ) {
112
  }
113
 
114
  /**
115
+ * @param Shield\Utilities\AdminNotices\NoticeVO $notice
116
  */
117
+ protected function preProcessNotice( $notice ) {
118
+ $con = $this->getCon();
119
+ $opts = $this->getOptions();
 
120
 
121
+ if ( $notice->plugin_page_only && !$con->isModulePage() ) {
122
+ $notice->non_display_reason = 'plugin_page_only';
123
  }
124
+ elseif ( $notice->type == 'promo' && !$opts->isShowPromoAdminNotices() ) {
125
+ $notice->non_display_reason = 'promo_hidden';
126
  }
127
+ elseif ( $notice->valid_admin && !$con->isValidAdminArea() ) {
128
+ $notice->non_display_reason = 'not_admin_area';
129
  }
130
+ elseif ( $notice->plugin_admin == 'yes' && !$con->isPluginAdmin() ) {
131
+ $notice->non_display_reason = 'not_plugin_admin';
132
  }
133
+ elseif ( $notice->plugin_admin == 'no' && $con->isPluginAdmin() ) {
134
+ $notice->non_display_reason = 'is_plugin_admin';
135
  }
136
+ elseif ( $notice->min_install_days > 0 && $notice->min_install_days > $opts->getInstallationDays() ) {
137
+ $notice->non_display_reason = 'min_install_days';
138
  }
139
+ elseif ( static::$nCount > 0 && $notice->type !== 'error' ) {
140
+ $notice->non_display_reason = 'max_nonerror_count';
141
  }
142
+ elseif ( $notice->can_dismiss && $this->isNoticeDismissed( $notice ) ) {
143
+ $notice->non_display_reason = 'dismissed';
144
  }
145
+ elseif ( !$this->isDisplayNeeded( $notice ) ) {
146
+ $notice->non_display_reason = 'not_needed';
147
  }
148
  else {
149
  static::$nCount++;
150
+ $notice->display = true;
151
+ $notice->non_display_reason = 'n/a';
152
  }
153
 
154
+ $notice->template = '/notices/'.$notice->id;
155
  }
156
 
157
  /**
158
+ * @param Shield\Utilities\AdminNotices\NoticeVO $notice
159
  * @return bool
160
  */
161
+ protected function isNoticeDismissed( $notice ) {
162
+ $bDismissedUser = $this->isNoticeDismissedForCurrentUser( $notice );
163
 
164
  $aDisd = $this->getMod()->getDismissedNotices();
165
+ $bDismissedMod = isset( $aDisd[ $notice->id ] ) && $aDisd[ $notice->id ] > 0;
166
 
167
+ if ( !$notice->per_user && $bDismissedUser && !$bDismissedMod ) {
168
+ $this->setNoticeDismissed( $notice );
169
  }
170
 
171
  return $bDismissedUser || $bDismissedMod;
180
  }
181
 
182
  /**
183
+ * @param Shield\Utilities\AdminNotices\NoticeVO $notice
184
  * @return bool
185
  */
186
+ protected function isNoticeDismissedForCurrentUser( $notice ) {
187
  $bDismissed = false;
188
 
189
+ $meta = $this->getCon()->getCurrentUserMeta();
190
+ if ( $meta instanceof PluginUserMeta ) {
191
+ $sNoticeMetaKey = $this->getNoticeMetaKey( $notice );
192
 
193
+ if ( isset( $meta->{$sNoticeMetaKey} ) ) {
194
  $bDismissed = true;
195
 
196
  // migrate from old-style array storage to plain Timestamp
197
+ if ( is_array( $meta->{$sNoticeMetaKey} ) ) {
198
+ $meta->{$sNoticeMetaKey} = $meta->{$sNoticeMetaKey}[ 'time' ];
199
  }
200
  }
201
  }
212
  }
213
 
214
  /**
215
+ * @param Shield\Utilities\AdminNotices\NoticeVO $notice
216
  * @return $this
217
  */
218
+ protected function setNoticeDismissed( $notice ) {
219
  $nTs = Services::Request()->ts();
220
 
221
+ $meta = $this->getCon()->getCurrentUserMeta();
222
+ $sNoticeMetaKey = $this->getNoticeMetaKey( $notice );
223
 
224
+ if ( $notice->per_user ) {
225
+ if ( $meta instanceof PluginUserMeta ) {
226
+ $meta->{$sNoticeMetaKey} = $nTs;
227
  }
228
  }
229
  else {
230
+ $mod = $this->getMod();
231
+ $aDismissed = $mod->getDismissedNotices();
232
+ $aDismissed[ $notice->id ] = $nTs;
233
+ $mod->setDismissedNotices( $aDismissed );
234
 
235
  // Clear out any old
236
+ if ( $meta instanceof PluginUserMeta ) {
237
+ unset( $meta->{$sNoticeMetaKey} );
238
  }
239
  }
240
  return $this;
241
  }
242
 
243
  /**
244
+ * @param Shield\Utilities\AdminNotices\NoticeVO $notice
245
  * @return string
246
  */
247
+ private function getNoticeMetaKey( $notice ) {
248
+ return 'notice_'.str_replace( [ '-', '_' ], '', $notice->id );
249
  }
250
  }
src/lib/src/Modules/Base/AjaxHandlerBase.php CHANGED
@@ -13,8 +13,6 @@ class AjaxHandlerBase {
13
  add_action( 'wp_loaded', [ $this, 'init' ] );
14
  }
15
 
16
- /**
17
- */
18
  public function init() {
19
  add_filter( $this->getCon()->prefix( 'ajaxAuthAction' ), [ $this, 'handleAjaxAuth' ], 10, 2 );
20
  add_filter( $this->getCon()->prefix( 'ajaxNonAuthAction' ), [ $this, 'handleAjaxNonAuth' ], 10, 2 );
@@ -80,10 +78,10 @@ class AjaxHandlerBase {
80
  }
81
 
82
  /**
83
- * @param string $sAjaxAction
84
  * @return array
85
  */
86
- protected function processAjaxAction( $sAjaxAction ) {
87
  return [];
88
  }
89
 
13
  add_action( 'wp_loaded', [ $this, 'init' ] );
14
  }
15
 
 
 
16
  public function init() {
17
  add_filter( $this->getCon()->prefix( 'ajaxAuthAction' ), [ $this, 'handleAjaxAuth' ], 10, 2 );
18
  add_filter( $this->getCon()->prefix( 'ajaxNonAuthAction' ), [ $this, 'handleAjaxNonAuth' ], 10, 2 );
78
  }
79
 
80
  /**
81
+ * @param string $action
82
  * @return array
83
  */
84
+ protected function processAjaxAction( $action ) {
85
  return [];
86
  }
87
 
src/lib/src/Modules/Base/AjaxHandlerShield.php CHANGED
@@ -5,14 +5,14 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
5
  class AjaxHandlerShield extends AjaxHandlerBase {
6
 
7
  /**
8
- * @param string $sAction
9
  * @return array
10
  */
11
- protected function processAjaxAction( $sAction ) {
12
  $aResponse = [];
13
- $oMod = $this->getMod();
14
 
15
- switch ( $sAction ) {
16
 
17
  case 'mod_opts_form_render':
18
  $aResponse = $this->ajaxExec_ModOptionsFormRender();
@@ -23,21 +23,21 @@ class AjaxHandlerShield extends AjaxHandlerBase {
23
  break;
24
 
25
  case 'wiz_process_step':
26
- if ( $oMod->hasWizard() ) {
27
- $aResponse = $oMod->getWizardHandler()
28
  ->ajaxExec_WizProcessStep();
29
  }
30
  break;
31
 
32
  case 'wiz_render_step':
33
- if ( $oMod->hasWizard() ) {
34
- $aResponse = $oMod->getWizardHandler()
35
  ->ajaxExec_WizRenderStep();
36
  }
37
  break;
38
 
39
  default:
40
- $aResponse = parent::processAjaxAction( $sAction );
41
  }
42
 
43
  return $aResponse;
5
  class AjaxHandlerShield extends AjaxHandlerBase {
6
 
7
  /**
8
+ * @param string $action
9
  * @return array
10
  */
11
+ protected function processAjaxAction( $action ) {
12
  $aResponse = [];
13
+ $mod = $this->getMod();
14
 
15
+ switch ( $action ) {
16
 
17
  case 'mod_opts_form_render':
18
  $aResponse = $this->ajaxExec_ModOptionsFormRender();
23
  break;
24
 
25
  case 'wiz_process_step':
26
+ if ( $mod->hasWizard() ) {
27
+ $aResponse = $mod->getWizardHandler()
28
  ->ajaxExec_WizProcessStep();
29
  }
30
  break;
31
 
32
  case 'wiz_render_step':
33
+ if ( $mod->hasWizard() ) {
34
+ $aResponse = $mod->getWizardHandler()
35
  ->ajaxExec_WizRenderStep();
36
  }
37
  break;
38
 
39
  default:
40
+ $aResponse = parent::processAjaxAction( $action );
41
  }
42
 
43
  return $aResponse;
src/lib/src/Modules/Base/BaseModCon.php CHANGED
@@ -112,9 +112,6 @@ class BaseModCon {
112
 
113
  $nMenuPri = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
114
  add_filter( $this->prefix( 'submenu_items' ), [ $this, 'supplySubMenuItem' ], $nMenuPri );
115
- add_filter( $this->prefix( 'collect_mod_summary' ), [ $this, 'addModuleSummaryData' ], $nMenuPri );
116
- add_filter( $this->prefix( 'collect_notices' ), [ $this, 'addInsightsNoticeData' ] );
117
- add_filter( $this->prefix( 'collect_summary' ), [ $this, 'addInsightsConfigData' ], $nRunPriority );
118
  add_action( $this->prefix( 'plugin_shutdown' ), [ $this, 'onPluginShutdown' ] );
119
  add_action( $this->prefix( 'deactivate_plugin' ), [ $this, 'onPluginDeactivate' ] );
120
  add_action( $this->prefix( 'delete_plugin' ), [ $this, 'onPluginDelete' ] );
@@ -305,8 +302,6 @@ class BaseModCon {
305
  return $bMeetsReqs;
306
  }
307
 
308
- /**
309
- */
310
  public function onRunProcessors() {
311
  if ( $this->isUpgrading() ) {
312
  $this->updateHandler();
@@ -354,8 +349,6 @@ class BaseModCon {
354
  add_action( 'load-'.$page_hook, [ $this, 'onLoadOptionsScreen' ] );
355
  }
356
 
357
- /**
358
- */
359
  public function onLoadOptionsScreen() {
360
  if ( $this->getCon()->isValidAdminArea() ) {
361
  $this->buildContextualHelp();
@@ -651,55 +644,6 @@ class BaseModCon {
651
  return $aAllData;
652
  }
653
 
654
- /**
655
- * @return array
656
- */
657
- protected function buildSummaryData() {
658
- $oOptsVo = $this->getOptions();
659
- $sMenuTitle = $oOptsVo->getFeatureProperty( 'menu_title' );
660
-
661
- $aSections = $oOptsVo->getSections();
662
- foreach ( $aSections as $sSlug => $aSection ) {
663
- try {
664
- $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
665
- foreach ( $aStrings as $sKey => $sVal ) {
666
- unset( $aSection[ $sKey ] );
667
- $aSection[ $sKey ] = $sVal;
668
- }
669
- }
670
- catch ( \Exception $oE ) {
671
- }
672
- }
673
-
674
- $aSum = [
675
- 'enabled' => $this->isEnabledForUiSummary(),
676
- 'active' => $this->isThisModulePage() || $this->isPage_InsightsThisModule(),
677
- 'slug' => $this->getSlug(),
678
- 'name' => $this->getMainFeatureName(),
679
- 'menu_title' => empty( $sMenuTitle ) ? $this->getMainFeatureName() : __( $sMenuTitle, 'wp-simple-firewall' ),
680
- 'href' => network_admin_url( 'admin.php?page='.$this->getModSlug() ),
681
- 'sections' => $aSections,
682
- 'options' => [],
683
- ];
684
-
685
- foreach ( $oOptsVo->getVisibleOptionsKeys() as $sOptKey ) {
686
- try {
687
- $aOptData = $this->getStrings()->getOptionStrings( $sOptKey );
688
- $aOptData[ 'href' ] = $this->getUrl_DirectLinkToOption( $sOptKey );
689
- $aSum[ 'options' ][ $sOptKey ] = $aOptData;
690
- }
691
- catch ( \Exception $oE ) {
692
- }
693
- }
694
-
695
- $aSum[ 'tooltip' ] = sprintf(
696
- '%s%s',
697
- $aSum[ 'name' ],
698
- ( $aSum[ 'enabled' ] ? '' : ' ('.strtolower( __( 'Disabled', 'wp-simple-firewall' ) ).')' )
699
- );
700
- return $aSum;
701
- }
702
-
703
  /**
704
  * @return bool
705
  */
@@ -949,168 +893,12 @@ class BaseModCon {
949
  return array_merge( $aAggregatedOptions, $this->getOptions()->getAllOptionsValues() );
950
  }
951
 
952
- /**
953
- * Will initiate the plugin options structure for use by the UI builder.
954
- * It doesn't set any values, just populates the array created in buildOptions()
955
- * with values stored.
956
- * It has to handle the conversion of stored values to data to be displayed to the user.
957
- */
958
- public function buildOptions() {
959
-
960
- $bPremiumEnabled = $this->getCon()->isPremiumExtensionsEnabled();
961
-
962
- $oOptsVo = $this->getOptions();
963
- $aOptions = $oOptsVo->getOptionsForPluginUse();
964
-
965
- foreach ( $aOptions as $nSectionKey => $aSection ) {
966
-
967
- if ( !empty( $aSection[ 'options' ] ) ) {
968
-
969
- foreach ( $aSection[ 'options' ] as $nKey => $aOption ) {
970
- $aOption[ 'is_value_default' ] = ( $aOption[ 'value' ] === $aOption[ 'default' ] );
971
- $bIsPrem = isset( $aOption[ 'premium' ] ) && $aOption[ 'premium' ];
972
- if ( !$bIsPrem || $bPremiumEnabled ) {
973
- $aSection[ 'options' ][ $nKey ] = $this->buildOptionForUi( $aOption );
974
- }
975
- else {
976
- unset( $aSection[ 'options' ][ $nKey ] );
977
- }
978
- }
979
-
980
- if ( empty( $aSection[ 'options' ] ) ) {
981
- unset( $aOptions[ $nSectionKey ] );
982
- }
983
- else {
984
- try {
985
- $aStrings = $this->getStrings()->getSectionStrings( $aSection[ 'slug' ] );
986
- foreach ( $aStrings as $sKey => $sVal ) {
987
- unset( $aSection[ $sKey ] );
988
- $aSection[ $sKey ] = $sVal;
989
- }
990
- }
991
- catch ( \Exception $oE ) {
992
- }
993
- $aOptions[ $nSectionKey ] = $aSection;
994
- }
995
-
996
- $aWarnings = [];
997
- if ( !$oOptsVo->isSectionReqsMet( $aSection[ 'slug' ] ) ) {
998
- $aWarnings[] = __( 'Unfortunately your WordPress and/or PHP versions are too old to support this feature.', 'wp-simple-firewall' );
999
- }
1000
- $aOptions[ $nSectionKey ][ 'warnings' ] = array_merge(
1001
- $aWarnings,
1002
- $this->getSectionWarnings( $aSection[ 'slug' ] )
1003
- );
1004
- $aOptions[ $nSectionKey ][ 'notices' ] = $this->getSectionNotices( $aSection[ 'slug' ] );
1005
-
1006
- if ( !empty( $aSection[ 'help_video_id' ] ) ) {
1007
- $sHelpVideoUrl = $this->getHelpVideoUrl( $aSection[ 'help_video_id' ] );
1008
- }
1009
- else {
1010
- $sHelpVideoUrl = '';
1011
- }
1012
- $aOptions[ $nSectionKey ][ 'help_video_url' ] = $sHelpVideoUrl;
1013
- }
1014
- }
1015
-
1016
- return $aOptions;
1017
- }
1018
-
1019
- /**
1020
- * @param string $sSectionSlug
1021
- * @return array
1022
- */
1023
- protected function getSectionNotices( $sSectionSlug ) {
1024
- return [];
1025
- }
1026
-
1027
- /**
1028
- * @param string $sSection
1029
- * @return array
1030
- */
1031
- protected function getSectionWarnings( $sSection ) {
1032
- return [];
1033
- }
1034
-
1035
- /**
1036
- * @param array $aOptParams
1037
- * @return array
1038
- */
1039
- protected function buildOptionForUi( $aOptParams ) {
1040
-
1041
- $mCurrent = $aOptParams[ 'value' ];
1042
-
1043
- switch ( $aOptParams[ 'type' ] ) {
1044
-
1045
- case 'password':
1046
- if ( !empty( $mCurrent ) ) {
1047
- $mCurrent = '';
1048
- }
1049
- break;
1050
-
1051
- case 'array':
1052
-
1053
- if ( empty( $mCurrent ) || !is_array( $mCurrent ) ) {
1054
- $mCurrent = [];
1055
- }
1056
-
1057
- $aOptParams[ 'rows' ] = count( $mCurrent ) + 2;
1058
- $mCurrent = stripslashes( implode( "\n", $mCurrent ) );
1059
-
1060
- break;
1061
-
1062
- case 'comma_separated_lists':
1063
-
1064
- $aNewValues = [];
1065
- if ( !empty( $mCurrent ) && is_array( $mCurrent ) ) {
1066
-
1067
- foreach ( $mCurrent as $sPage => $aParams ) {
1068
- $aNewValues[] = $sPage.', '.implode( ", ", $aParams );
1069
- }
1070
- }
1071
- $aOptParams[ 'rows' ] = count( $aNewValues ) + 1;
1072
- $mCurrent = implode( "\n", $aNewValues );
1073
-
1074
- break;
1075
-
1076
- case 'multiple_select':
1077
- if ( !is_array( $mCurrent ) ) {
1078
- $mCurrent = [];
1079
- }
1080
- break;
1081
-
1082
- case 'text':
1083
- $mCurrent = stripslashes( $this->getTextOpt( $aOptParams[ 'key' ] ) );
1084
- break;
1085
- }
1086
-
1087
- $aParams = [
1088
- 'value' => is_scalar( $mCurrent ) ? esc_attr( $mCurrent ) : $mCurrent,
1089
- 'disabled' => !$this->isPremium() && ( isset( $aOptParams[ 'premium' ] ) && $aOptParams[ 'premium' ] ),
1090
- ];
1091
- $aParams[ 'enabled' ] = !$aParams[ 'disabled' ];
1092
- $aOptParams = array_merge( [ 'rows' => 2 ], $aOptParams, $aParams );
1093
-
1094
- // add strings
1095
- try {
1096
- $aOptParams = Services::DataManipulation()->mergeArraysRecursive(
1097
- $aOptParams,
1098
- $this->getStrings()->getOptionStrings( $aOptParams[ 'key' ] )
1099
- );
1100
- }
1101
- catch ( \Exception $oE ) {
1102
- }
1103
- return $aOptParams;
1104
- }
1105
-
1106
  /**
1107
  * This is the point where you would want to do any options verification
1108
  */
1109
  protected function doPrePluginOptionsSave() {
1110
  }
1111
 
1112
- /**
1113
- */
1114
  public function onPluginDeactivate() {
1115
  }
1116
 
@@ -1135,8 +923,6 @@ class BaseModCon {
1135
  return $aOpts;
1136
  }
1137
 
1138
- /**
1139
- */
1140
  public function handleModRequest() {
1141
  }
1142
 
@@ -1256,8 +1042,6 @@ class BaseModCon {
1256
  }
1257
  }
1258
 
1259
- /**
1260
- */
1261
  protected function runWizards() {
1262
  if ( $this->isWizardPage() && $this->hasWizard() ) {
1263
  $oWiz = $this->getWizardHandler();
@@ -1386,7 +1170,6 @@ class BaseModCon {
1386
  'width' => 772,
1387
  'height' => 454,
1388
  ],
1389
- 'aSummaryData' => $this->getModulesSummaryData(),
1390
 
1391
  // 'sPageTitle' => sprintf( '%s: %s', $oCon->getHumanName(), $this->getMainFeatureName() ),
1392
  'sPageTitle' => $this->getMainFeatureName(),
@@ -1463,13 +1246,6 @@ class BaseModCon {
1463
  );
1464
  }
1465
 
1466
- /**
1467
- * @return array[]
1468
- */
1469
- protected function getModulesSummaryData() {
1470
- return apply_filters( $this->prefix( 'collect_mod_summary' ), [] );
1471
- }
1472
-
1473
  /**
1474
  * @param string $sWizardSlug
1475
  * @return string
112
 
113
  $nMenuPri = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
114
  add_filter( $this->prefix( 'submenu_items' ), [ $this, 'supplySubMenuItem' ], $nMenuPri );
 
 
 
115
  add_action( $this->prefix( 'plugin_shutdown' ), [ $this, 'onPluginShutdown' ] );
116
  add_action( $this->prefix( 'deactivate_plugin' ), [ $this, 'onPluginDeactivate' ] );
117
  add_action( $this->prefix( 'delete_plugin' ), [ $this, 'onPluginDelete' ] );
302
  return $bMeetsReqs;
303
  }
304
 
 
 
305
  public function onRunProcessors() {
306
  if ( $this->isUpgrading() ) {
307
  $this->updateHandler();
349
  add_action( 'load-'.$page_hook, [ $this, 'onLoadOptionsScreen' ] );
350
  }
351
 
 
 
352
  public function onLoadOptionsScreen() {
353
  if ( $this->getCon()->isValidAdminArea() ) {
354
  $this->buildContextualHelp();
644
  return $aAllData;
645
  }
646
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
647
  /**
648
  * @return bool
649
  */
893
  return array_merge( $aAggregatedOptions, $this->getOptions()->getAllOptionsValues() );
894
  }
895
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
896
  /**
897
  * This is the point where you would want to do any options verification
898
  */
899
  protected function doPrePluginOptionsSave() {
900
  }
901
 
 
 
902
  public function onPluginDeactivate() {
903
  }
904
 
923
  return $aOpts;
924
  }
925
 
 
 
926
  public function handleModRequest() {
927
  }
928
 
1042
  }
1043
  }
1044
 
 
 
1045
  protected function runWizards() {
1046
  if ( $this->isWizardPage() && $this->hasWizard() ) {
1047
  $oWiz = $this->getWizardHandler();
1170
  'width' => 772,
1171
  'height' => 454,
1172
  ],
 
1173
 
1174
  // 'sPageTitle' => sprintf( '%s: %s', $oCon->getHumanName(), $this->getMainFeatureName() ),
1175
  'sPageTitle' => $this->getMainFeatureName(),
1246
  );
1247
  }
1248
 
 
 
 
 
 
 
 
1249
  /**
1250
  * @param string $sWizardSlug
1251
  * @return string
src/lib/src/Modules/Base/BaseProcessor.php CHANGED
@@ -108,8 +108,6 @@ class BaseProcessor {
108
  public function onModuleShutdown() {
109
  }
110
 
111
- /**
112
- */
113
  public function init() {
114
  }
115
 
@@ -175,8 +173,6 @@ class BaseProcessor {
175
  return [];
176
  }
177
 
178
- /**
179
- */
180
  public function deactivatePlugin() {
181
  }
182
 
@@ -198,6 +194,6 @@ class BaseProcessor {
198
  * @deprecated
199
  */
200
  protected function prefix( $sSuffix = '', $sGlue = '-' ) {
201
- return $this->getMod()->prefix( $sSuffix, $sGlue );
202
  }
203
  }
108
  public function onModuleShutdown() {
109
  }
110
 
 
 
111
  public function init() {
112
  }
113
 
173
  return [];
174
  }
175
 
 
 
176
  public function deactivatePlugin() {
177
  }
178
 
194
  * @deprecated
195
  */
196
  protected function prefix( $sSuffix = '', $sGlue = '-' ) {
197
+ return $this->getCon()->prefix( $sSuffix, $sGlue );
198
  }
199
  }
src/lib/src/Modules/Base/Options.php CHANGED
@@ -56,8 +56,6 @@ class Options {
56
  */
57
  protected $sPathToConfig;
58
 
59
- /**
60
- */
61
  public function __construct() {
62
  }
63
 
@@ -146,8 +144,9 @@ class Options {
146
  return array_filter(
147
  $this->getOptionsKeys(),
148
  function ( $sKey ) {
149
- return $this->getRawData_SingleOption( $sKey )[ 'section' ]
150
- !== 'section_non_ui';
 
151
  }
152
  );
153
  }
@@ -873,17 +872,6 @@ class Options {
873
  return $this;
874
  }
875
 
876
- /**
877
- * @param $sOptKey
878
- * @param $mValue
879
- * @return array|int|mixed|string
880
- * @throws \Exception
881
- * @deprecated 9.1.0
882
- */
883
- private function ensureOptValueState( $sOptKey, $mValue ) {
884
- return $mValue;
885
- }
886
-
887
  /**
888
  * @param string $sOptKey
889
  * @param mixed $mPotentialValue
56
  */
57
  protected $sPathToConfig;
58
 
 
 
59
  public function __construct() {
60
  }
61
 
144
  return array_filter(
145
  $this->getOptionsKeys(),
146
  function ( $sKey ) {
147
+ $opt = $this->getRawData_SingleOption( $sKey );
148
+ return !empty( $opt[ 'section' ] )
149
+ && $opt[ 'section' ] !== 'section_non_ui';
150
  }
151
  );
152
  }
872
  return $this;
873
  }
874
 
 
 
 
 
 
 
 
 
 
 
 
875
  /**
876
  * @param string $sOptKey
877
  * @param mixed $mPotentialValue
src/lib/src/Modules/Base/ShieldUI.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class ShieldUI extends UI {
9
+
10
+ /**
11
+ * @return array
12
+ */
13
+ public function getBaseDisplayData() {
14
+ /** @var \ICWP_WPSF_FeatureHandler_BaseWpsf $mod */
15
+ $mod = $this->getMod();
16
+
17
+ return Services::DataManipulation()->mergeArraysRecursive(
18
+ parent::getBaseDisplayData(),
19
+ [
20
+ 'head' => [
21
+ 'html' => [
22
+ 'lang' => Services::WpGeneral()->getLocale( '-' ),
23
+ 'dir' => is_rtl() ? 'rtl' : 'ltr',
24
+ ],
25
+ 'meta' => [
26
+ [
27
+ 'type' => 'http-equiv',
28
+ 'type_type' => 'Cache-Control',
29
+ 'content' => 'no-store, no-cache',
30
+ ],
31
+ [
32
+ 'type' => 'http-equiv',
33
+ 'type_type' => 'Expires',
34
+ 'content' => '0',
35
+ ],
36
+ ],
37
+ 'scripts' => []
38
+ ],
39
+ 'ajax' => [
40
+ 'sec_admin_login' => $mod->getSecAdminLoginAjaxData(),
41
+ ],
42
+ 'flags' => [
43
+ 'show_promo' => !$this->getCon()->isPremiumActive(),
44
+ 'has_session' => $mod->hasSession()
45
+ ],
46
+ 'hrefs' => [
47
+ 'aar_forget_key' => $mod->isWlEnabled() ?
48
+ $this->getCon()->getLabels()[ 'AuthorURI' ] : 'https://shsec.io/gc'
49
+ ],
50
+ 'classes' => [
51
+ 'top_container' => implode( ' ', array_filter( [
52
+ 'odp-outercontainer',
53
+ $this->getCon()->isPremiumActive() ? 'is-pro' : 'is-not-pro',
54
+ $mod->getModSlug(),
55
+ Services::Request()->query( 'inav', '' )
56
+ ] ) )
57
+ ],
58
+ ]
59
+ );
60
+ }
61
+ }
src/lib/src/Modules/Base/Strings.php CHANGED
@@ -13,7 +13,7 @@ class Strings {
13
  * @return string[]
14
  */
15
  public function getDisplayStrings() {
16
- $oCon = $this->getCon();
17
 
18
  $aProFeatures = [
19
  __( 'Customer Support', 'wp-simple-firewall' ),
@@ -50,8 +50,8 @@ class Strings {
50
  'logged_in' => __( 'Logged-In', 'wp-simple-firewall' ),
51
  'username' => __( 'Username' ),
52
  'blog' => __( 'Blog', 'wp-simple-firewall' ),
53
- 'save_all_settings' => sprintf( __( 'Save %s Settings', 'wp-simple-firewall' ), $oCon->getHumanName() ),
54
- 'plugin_name' => $oCon->getHumanName(),
55
  'options_title' => __( 'Options', 'wp-simple-firewall' ),
56
  'options_summary' => __( 'Configure Module', 'wp-simple-firewall' ),
57
  'actions_title' => __( 'Actions and Info', 'wp-simple-firewall' ),
@@ -135,12 +135,12 @@ class Strings {
135
  }
136
 
137
  /**
138
- * @param string $sOptKey
139
  * @return array
140
  * @throws \Exception
141
  */
142
- public function getOptionStrings( $sOptKey ) {
143
- $aOpt = $this->getOptions()->getOptDefinition( $sOptKey );
144
  if ( is_array( $aOpt ) && !empty( $aOpt[ 'name' ] ) && !empty( $aOpt[ 'summary' ] ) && !empty( $aOpt[ 'description' ] ) ) {
145
  return [
146
  'name' => __( $aOpt[ 'name' ], 'wp-simple-firewall' ),
@@ -148,17 +148,17 @@ class Strings {
148
  'description' => __( $aOpt[ 'description' ], 'wp-simple-firewall' ),
149
  ];
150
  }
151
- throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sOptKey ) );
152
  }
153
 
154
  /**
155
- * @param string $sSectionSlug
156
  * @return array
157
  * @throws \Exception
158
  */
159
- public function getSectionStrings( $sSectionSlug ) {
160
 
161
- switch ( $sSectionSlug ) {
162
 
163
  case 'section_user_messages' :
164
  $sTitle = __( 'User Messages', 'wp-simple-firewall' );
@@ -171,14 +171,14 @@ class Strings {
171
  break;
172
 
173
  default:
174
- $aSect = $this->getOptions()->getSection( $sSectionSlug );
175
  if ( is_array( $aSect ) && !empty( $aSect[ 'title' ] ) && !empty( $aSect[ 'title_short' ] ) ) {
176
  $sTitle = __( $aSect[ 'title' ], 'wp-simple-firewall' );
177
  $sTitleShort = __( $aSect[ 'title_short' ], 'wp-simple-firewall' );
178
  $aSummary = empty( $aSect[ 'summary' ] ) ? [] : $aSect[ 'summary' ];
179
  }
180
  else {
181
- throw new \Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
182
  }
183
  }
184
 
13
  * @return string[]
14
  */
15
  public function getDisplayStrings() {
16
+ $con = $this->getCon();
17
 
18
  $aProFeatures = [
19
  __( 'Customer Support', 'wp-simple-firewall' ),
50
  'logged_in' => __( 'Logged-In', 'wp-simple-firewall' ),
51
  'username' => __( 'Username' ),
52
  'blog' => __( 'Blog', 'wp-simple-firewall' ),
53
+ 'save_all_settings' => sprintf( __( 'Save %s Settings', 'wp-simple-firewall' ), $con->getHumanName() ),
54
+ 'plugin_name' => $con->getHumanName(),
55
  'options_title' => __( 'Options', 'wp-simple-firewall' ),
56
  'options_summary' => __( 'Configure Module', 'wp-simple-firewall' ),
57
  'actions_title' => __( 'Actions and Info', 'wp-simple-firewall' ),
135
  }
136
 
137
  /**
138
+ * @param string $key
139
  * @return array
140
  * @throws \Exception
141
  */
142
+ public function getOptionStrings( $key ) {
143
+ $aOpt = $this->getOptions()->getOptDefinition( $key );
144
  if ( is_array( $aOpt ) && !empty( $aOpt[ 'name' ] ) && !empty( $aOpt[ 'summary' ] ) && !empty( $aOpt[ 'description' ] ) ) {
145
  return [
146
  'name' => __( $aOpt[ 'name' ], 'wp-simple-firewall' ),
148
  'description' => __( $aOpt[ 'description' ], 'wp-simple-firewall' ),
149
  ];
150
  }
151
+ throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $key ) );
152
  }
153
 
154
  /**
155
+ * @param string $section
156
  * @return array
157
  * @throws \Exception
158
  */
159
+ public function getSectionStrings( $section ) {
160
 
161
+ switch ( $section ) {
162
 
163
  case 'section_user_messages' :
164
  $sTitle = __( 'User Messages', 'wp-simple-firewall' );
171
  break;
172
 
173
  default:
174
+ $aSect = $this->getOptions()->getSection( $section );
175
  if ( is_array( $aSect ) && !empty( $aSect[ 'title' ] ) && !empty( $aSect[ 'title_short' ] ) ) {
176
  $sTitle = __( $aSect[ 'title' ], 'wp-simple-firewall' );
177
  $sTitleShort = __( $aSect[ 'title_short' ], 'wp-simple-firewall' );
178
  $aSummary = empty( $aSect[ 'summary' ] ) ? [] : $aSect[ 'summary' ];
179
  }
180
  else {
181
+ throw new \Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $section ) );
182
  }
183
  }
184
 
src/lib/src/Modules/Base/UI.php ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class UI {
10
+
11
+ use ModConsumer;
12
+
13
+ /**
14
+ * Will initiate the plugin options structure for use by the UI builder.
15
+ * It doesn't set any values, just populates the array created in buildOptions()
16
+ * with values stored.
17
+ * It has to handle the conversion of stored values to data to be displayed to the user.
18
+ */
19
+ public function buildOptions() {
20
+
21
+ $bPremiumEnabled = $this->getCon()->isPremiumExtensionsEnabled();
22
+
23
+ $opts = $this->getOptions();
24
+ $aOptions = $opts->getOptionsForPluginUse();
25
+
26
+ foreach ( $aOptions as $nSectionKey => $aSection ) {
27
+
28
+ if ( !empty( $aSection[ 'options' ] ) ) {
29
+
30
+ foreach ( $aSection[ 'options' ] as $nKey => $aOption ) {
31
+ $aOption[ 'is_value_default' ] = ( $aOption[ 'value' ] === $aOption[ 'default' ] );
32
+ $bIsPrem = isset( $aOption[ 'premium' ] ) && $aOption[ 'premium' ];
33
+ if ( !$bIsPrem || $bPremiumEnabled ) {
34
+ $aSection[ 'options' ][ $nKey ] = $this->buildOptionForUi( $aOption );
35
+ }
36
+ else {
37
+ unset( $aSection[ 'options' ][ $nKey ] );
38
+ }
39
+ }
40
+
41
+ if ( empty( $aSection[ 'options' ] ) ) {
42
+ unset( $aOptions[ $nSectionKey ] );
43
+ }
44
+ else {
45
+ try {
46
+ $aSection = array_merge(
47
+ $aSection,
48
+ $this->getMod()
49
+ ->getStrings()
50
+ ->getSectionStrings( $aSection[ 'slug' ] )
51
+ );
52
+ }
53
+ catch ( \Exception $oE ) {
54
+ }
55
+ $aOptions[ $nSectionKey ] = $aSection;
56
+ }
57
+
58
+ $aWarnings = [];
59
+ if ( !$opts->isSectionReqsMet( $aSection[ 'slug' ] ) ) {
60
+ $aWarnings[] = __( 'Unfortunately your WordPress and/or PHP versions are too old to support this feature.', 'wp-simple-firewall' );
61
+ }
62
+ $aOptions[ $nSectionKey ][ 'warnings' ] = array_merge(
63
+ $aWarnings,
64
+ $this->getSectionWarnings( $aSection[ 'slug' ] )
65
+ );
66
+ $aOptions[ $nSectionKey ][ 'notices' ] = $this->getSectionNotices( $aSection[ 'slug' ] );
67
+ }
68
+ }
69
+
70
+ return $aOptions;
71
+ }
72
+
73
+ /**
74
+ * @param array $aOptParams
75
+ * @return array
76
+ */
77
+ protected function buildOptionForUi( $aOptParams ) {
78
+
79
+ $mCurrent = $aOptParams[ 'value' ];
80
+
81
+ switch ( $aOptParams[ 'type' ] ) {
82
+
83
+ case 'password':
84
+ if ( !empty( $mCurrent ) ) {
85
+ $mCurrent = '';
86
+ }
87
+ break;
88
+
89
+ case 'array':
90
+
91
+ if ( empty( $mCurrent ) || !is_array( $mCurrent ) ) {
92
+ $mCurrent = [];
93
+ }
94
+
95
+ $aOptParams[ 'rows' ] = count( $mCurrent ) + 2;
96
+ $mCurrent = stripslashes( implode( "\n", $mCurrent ) );
97
+
98
+ break;
99
+
100
+ case 'comma_separated_lists':
101
+
102
+ $aNewValues = [];
103
+ if ( !empty( $mCurrent ) && is_array( $mCurrent ) ) {
104
+
105
+ foreach ( $mCurrent as $sPage => $aParams ) {
106
+ $aNewValues[] = $sPage.', '.implode( ", ", $aParams );
107
+ }
108
+ }
109
+ $aOptParams[ 'rows' ] = count( $aNewValues ) + 1;
110
+ $mCurrent = implode( "\n", $aNewValues );
111
+
112
+ break;
113
+
114
+ case 'multiple_select':
115
+ if ( !is_array( $mCurrent ) ) {
116
+ $mCurrent = [];
117
+ }
118
+ break;
119
+
120
+ case 'text':
121
+ $mCurrent = stripslashes( $this->getMod()->getTextOpt( $aOptParams[ 'key' ] ) );
122
+ break;
123
+ }
124
+
125
+ $aParams = [
126
+ 'value' => is_scalar( $mCurrent ) ? esc_attr( $mCurrent ) : $mCurrent,
127
+ 'disabled' => !$this->getCon()
128
+ ->isPremiumActive() && ( isset( $aOptParams[ 'premium' ] ) && $aOptParams[ 'premium' ] ),
129
+ ];
130
+ $aParams[ 'enabled' ] = !$aParams[ 'disabled' ];
131
+ $aOptParams = array_merge( [ 'rows' => 2 ], $aOptParams, $aParams );
132
+
133
+ // add strings
134
+ try {
135
+ $aOptStrings = $this->getMod()->getStrings()->getOptionStrings( $aOptParams[ 'key' ] );
136
+ if ( !is_array( $aOptStrings[ 'description' ] ) ) {
137
+ $aOptStrings[ 'description' ] = [ $aOptStrings[ 'description' ] ];
138
+ }
139
+ $aOptParams = Services::DataManipulation()->mergeArraysRecursive( $aOptParams, $aOptStrings );
140
+ }
141
+ catch ( \Exception $oE ) {
142
+ }
143
+ return $aOptParams;
144
+ }
145
+
146
+ /**
147
+ * @return array
148
+ */
149
+ public function getBaseDisplayData() {
150
+ $mod = $this->getMod();
151
+ $con = $this->getCon();
152
+
153
+ /** @var Shield\Modules\Plugin\Options $oPluginOptions */
154
+ $oPluginOptions = $con->getModule_Plugin()->getOptions();
155
+
156
+ return [
157
+ 'sPluginName' => $con->getHumanName(),
158
+ 'sTagline' => $this->getOptions()->getFeatureTagline(),
159
+ 'nonce_field' => wp_nonce_field( $con->getPluginPrefix(), '_wpnonce', true, false ), //don't echo!
160
+ 'form_action' => 'admin.php?page='.$mod->getModSlug(),
161
+ 'aPluginLabels' => $con->getLabels(),
162
+ 'help_video' => [
163
+ 'auto_show' => $this->getIfAutoShowHelpVideo(),
164
+ 'display_id' => 'ShieldHelpVideo'.$mod->getSlug(),
165
+ 'options' => $this->getHelpVideoOptions(),
166
+ 'displayable' => $this->isHelpVideoDisplayable(),
167
+ 'show' => $this->isHelpVideoDisplayable() && !$this->getHelpVideoHasBeenClosed(),
168
+ 'width' => 772,
169
+ 'height' => 454,
170
+ ],
171
+
172
+ 'aSummaryData' => array_filter(
173
+ $mod->getModulesSummaryData(),
174
+ function ( $summary ) {
175
+ return $summary[ 'show_mod_opts' ];
176
+ }
177
+ ),
178
+
179
+ 'sPageTitle' => $mod->getMainFeatureName(),
180
+ 'data' => [
181
+ 'mod_slug' => $mod->getModSlug( true ),
182
+ 'mod_slug_short' => $mod->getModSlug( false ),
183
+ 'all_options' => $this->buildOptions(),
184
+ 'xferable_opts' => ( new Shield\Modules\Plugin\Lib\ImportExport\Options\BuildTransferableOptions() )
185
+ ->setMod( $mod )
186
+ ->build(),
187
+ 'hidden_options' => $this->getOptions()->getHiddenOptions()
188
+ ],
189
+ 'ajax' => [
190
+ 'mod_options' => $mod->getAjaxActionData( 'mod_options' ),
191
+ ],
192
+ 'vendors' => [
193
+ 'widget_freshdesk' => '3000000081' /* TODO: plugin spec config */
194
+ ],
195
+ 'strings' => $mod->getStrings()->getDisplayStrings(),
196
+ 'flags' => [
197
+ 'access_restricted' => !$mod->canDisplayOptionsForm(),
198
+ 'show_ads' => $mod->getIsShowMarketing(),
199
+ 'wrap_page_content' => true,
200
+ 'show_standard_options' => true,
201
+ 'show_content_help' => true,
202
+ 'show_alt_content' => false,
203
+ 'has_wizard' => $mod->hasWizard(),
204
+ 'is_premium' => $con->isPremiumActive(),
205
+ 'show_transfer_switch' => $con->isPremiumActive(),
206
+ 'is_wpcli' => $oPluginOptions->isEnabledWpcli()
207
+ ],
208
+ 'hrefs' => [
209
+ 'go_pro' => 'https://shsec.io/shieldgoprofeature',
210
+ 'goprofooter' => 'https://shsec.io/goprofooter',
211
+ 'wizard_link' => $mod->getUrl_WizardLanding(),
212
+ 'wizard_landing' => $mod->getUrl_WizardLanding(),
213
+
214
+ 'form_action' => Services::Request()->getUri(),
215
+ 'css_bootstrap' => $con->getPluginUrl_Css( 'bootstrap4.min' ),
216
+ 'css_pages' => $con->getPluginUrl_Css( 'pages' ),
217
+ 'css_steps' => $con->getPluginUrl_Css( 'jquery.steps' ),
218
+ 'css_fancybox' => $con->getPluginUrl_Css( 'jquery.fancybox.min' ),
219
+ 'css_globalplugin' => $con->getPluginUrl_Css( 'global-plugin' ),
220
+ 'css_wizard' => $con->getPluginUrl_Css( 'wizard' ),
221
+ 'js_jquery' => Services::Includes()->getUrl_Jquery(),
222
+ 'js_bootstrap' => $con->getPluginUrl_Js( 'bootstrap4.bundle.min' ),
223
+ 'js_fancybox' => $con->getPluginUrl_Js( 'jquery.fancybox.min' ),
224
+ 'js_globalplugin' => $con->getPluginUrl_Js( 'global-plugin' ),
225
+ 'js_steps' => $con->getPluginUrl_Js( 'jquery.steps.min' ),
226
+ 'js_wizard' => $con->getPluginUrl_Js( 'wizard' ),
227
+ ],
228
+ 'imgs' => [
229
+ 'favicon' => $con->getPluginUrl_Image( 'pluginlogo_24x24.png' ),
230
+ 'plugin_banner' => $con->getPluginUrl_Image( 'banner-1500x500-transparent.png' ),
231
+ ],
232
+ 'content' => [
233
+ 'options_form' => '',
234
+ 'alt' => '',
235
+ 'actions' => '',
236
+ 'help' => '',
237
+ 'wizard_landing' => ''
238
+ ]
239
+ ];
240
+ }
241
+
242
+ /**
243
+ * @return array
244
+ */
245
+ public function getInsightsConfigCardData() {
246
+ return [];
247
+ }
248
+
249
+ /**
250
+ * @return array
251
+ */
252
+ public function getInsightsNoticesData() {
253
+ return [];
254
+ }
255
+
256
+ /**
257
+ * @return array
258
+ */
259
+ protected function getModDisabledInsight() {
260
+ $mod = $this->getMod();
261
+ return [
262
+ 'name' => __( 'Module Disabled', 'wp-simple-firewall' ),
263
+ 'enabled' => false,
264
+ 'summary' => __( 'All features of this module are completely disabled', 'wp-simple-firewall' ),
265
+ 'weight' => 2,
266
+ 'href' => $mod->getUrl_DirectLinkToOption( $mod->getEnableModOptKey() ),
267
+ ];
268
+ }
269
+
270
+ protected function getHelpVideoOptions() {
271
+ $aOptions = $this->getOptions()->getOpt( 'help_video_options', [] );
272
+ if ( is_null( $aOptions ) || !is_array( $aOptions ) ) {
273
+ $aOptions = [
274
+ 'closed' => false,
275
+ 'displayed' => false,
276
+ 'played' => false,
277
+ ];
278
+ $this->getOptions()->setOpt( 'help_video_options', $aOptions );
279
+ }
280
+ return $aOptions;
281
+ }
282
+
283
+ /**
284
+ * @param string $sId
285
+ * @return string
286
+ */
287
+ protected function getHelpVideoUrl( $sId ) {
288
+ return sprintf( 'https://player.vimeo.com/video/%s', $sId );
289
+ }
290
+
291
+ /**
292
+ * @return bool
293
+ */
294
+ protected function getIfAutoShowHelpVideo() {
295
+ return !$this->getHelpVideoHasBeenClosed();
296
+ }
297
+
298
+ /**
299
+ * @return bool
300
+ */
301
+ protected function getHelpVideoHasBeenDisplayed() {
302
+ return (bool)$this->getHelpVideoOption( 'displayed' );
303
+ }
304
+
305
+ /**
306
+ * @return bool
307
+ */
308
+ protected function getVideoHasBeenPlayed() {
309
+ return (bool)$this->getHelpVideoOption( 'played' );
310
+ }
311
+
312
+ /**
313
+ * @param string $sKey
314
+ * @return mixed|null
315
+ */
316
+ protected function getHelpVideoOption( $sKey ) {
317
+ $aOpts = $this->getHelpVideoOptions();
318
+ return isset( $aOpts[ $sKey ] ) ? $aOpts[ $sKey ] : null;
319
+ }
320
+
321
+ /**
322
+ * @return bool
323
+ */
324
+ protected function getHelpVideoHasBeenClosed() {
325
+ return (bool)$this->getHelpVideoOption( 'closed' );
326
+ }
327
+
328
+ /**
329
+ * @return bool
330
+ */
331
+ protected function isHelpVideoDisplayable() {
332
+ return false;
333
+ }
334
+
335
+ /**
336
+ * @return string
337
+ */
338
+ protected function getHelpVideoId() {
339
+ return $this->getOptions()->getDef( 'help_video_id' );
340
+ }
341
+
342
+ /**
343
+ * @param string $section
344
+ * @return array
345
+ */
346
+ protected function getSectionNotices( $section ) {
347
+ return [];
348
+ }
349
+
350
+ /**
351
+ * @param string $section
352
+ * @return array
353
+ */
354
+ protected function getSectionWarnings( $section ) {
355
+ return [];
356
+ }
357
+
358
+ /**
359
+ * @return bool
360
+ */
361
+ public function isEnabledForUiSummary() {
362
+ return $this->getMod()->isModuleEnabled();
363
+ }
364
+ }
src/lib/src/Modules/BaseShield/ShieldProcessor.php CHANGED
@@ -19,8 +19,8 @@ class ShieldProcessor extends Base\BaseProcessor {
19
  */
20
  public function init() {
21
  parent::init();
22
- $oFO = $this->getMod();
23
- add_filter( $oFO->prefix( 'collect_tracking_data' ), [ $this, 'tracking_DataCollect' ] );
24
  }
25
 
26
  /**
19
  */
20
  public function init() {
21
  parent::init();
22
+ $con = $this->getCon();
23
+ add_filter( $con->prefix( 'collect_tracking_data' ), [ $this, 'tracking_DataCollect' ] );
24
  }
25
 
26
  /**
src/lib/src/Modules/CommentsFilter/AdminNotices.php CHANGED
@@ -50,16 +50,18 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
50
  * @return bool
51
  */
52
  protected function isDisplayNeeded( $oNotice ) {
53
- /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $oMod */
54
- $oMod = $this->getMod();
55
 
56
  switch ( $oNotice->id ) {
57
 
58
  case 'akismet-running':
59
  $oWpPlugins = Services::WpPlugins();
60
  $sPluginFile = $oWpPlugins->findPluginFileFromDirName( 'akismet' );
61
- $bNeeded = $oMod->isEnabledHumanCheck()
62
- && !empty( $sPluginFile ) && $oWpPlugins->isActive( $sPluginFile );
 
 
63
  break;
64
 
65
  default:
50
  * @return bool
51
  */
52
  protected function isDisplayNeeded( $oNotice ) {
53
+ /** @var Options $opts */
54
+ $opts = $this->getOptions();
55
 
56
  switch ( $oNotice->id ) {
57
 
58
  case 'akismet-running':
59
  $oWpPlugins = Services::WpPlugins();
60
  $sPluginFile = $oWpPlugins->findPluginFileFromDirName( 'akismet' );
61
+ $bNeeded = $this->getMod()->isModuleEnabled()
62
+ && !empty( $sPluginFile )
63
+ && $oWpPlugins->isActive( $sPluginFile )
64
+ && $opts->isEnabledHumanCheck();
65
  break;
66
 
67
  default:
src/lib/src/Modules/CommentsFilter/AjaxHandler.php CHANGED
@@ -8,18 +8,18 @@ use FernleafSystems\Wordpress\Services\Services;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
- * @param string $sAction
12
  * @return array
13
  */
14
- protected function processAjaxAction( $sAction ) {
15
 
16
- switch ( $sAction ) {
17
  case 'comment_token'.Services::IP()->getRequestIp():
18
  $aResponse = $this->ajaxExec_GenCommentToken();
19
  break;
20
 
21
  default:
22
- $aResponse = parent::processAjaxAction( $sAction );
23
  }
24
 
25
  return $aResponse;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
+ * @param string $action
12
  * @return array
13
  */
14
+ protected function processAjaxAction( $action ) {
15
 
16
+ switch ( $action ) {
17
  case 'comment_token'.Services::IP()->getRequestIp():
18
  $aResponse = $this->ajaxExec_GenCommentToken();
19
  break;
20
 
21
  default:
22
+ $aResponse = parent::processAjaxAction( $action );
23
  }
24
 
25
  return $aResponse;
src/lib/src/Modules/CommentsFilter/Options.php CHANGED
@@ -6,6 +6,13 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
 
7
  class Options extends Base\ShieldOptions {
8
 
 
 
 
 
 
 
 
9
  /**
10
  * @return string[]
11
  */
@@ -44,4 +51,38 @@ class Options extends Base\ShieldOptions {
44
  )
45
  );
46
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }
6
 
7
  class Options extends Base\ShieldOptions {
8
 
9
+ /**
10
+ * @return int
11
+ */
12
+ public function getApprovedMinimum() {
13
+ return (int)$this->getOpt( 'trusted_commenter_minimum', 1 );
14
+ }
15
+
16
  /**
17
  * @return string[]
18
  */
51
  )
52
  );
53
  }
54
+
55
+ /**
56
+ * @return string[]
57
+ */
58
+ public function getTrustedRoles() {
59
+ $aRoles = [];
60
+ if ( $this->isPremium() ) {
61
+ $aRoles = $this->getOpt( 'trusted_user_roles', [] );
62
+ }
63
+ return is_array( $aRoles ) ? $aRoles : [];
64
+ }
65
+
66
+ /**
67
+ * @return bool
68
+ */
69
+ public function isEnabledGaspCheck() {
70
+ return $this->isOpt( 'enable_comments_gasp_protection', 'Y' )
71
+ && ( $this->getTokenExpireInterval() > $this->getTokenCooldown() );
72
+ }
73
+
74
+ /**
75
+ * @return bool
76
+ */
77
+ public function isEnabledCaptcha() {
78
+ return !$this->isOpt( 'google_recaptcha_style_comments', 'disabled' );
79
+ }
80
+
81
+ /**
82
+ * @return bool
83
+ */
84
+ public function isEnabledHumanCheck() {
85
+ return $this->isOpt( 'enable_comments_human_spam_filter', 'Y' )
86
+ && count( $this->getHumanSpamFilterItems() ) > 0;
87
+ }
88
  }
src/lib/src/Modules/CommentsFilter/Scan/Bot.php CHANGED
@@ -64,12 +64,12 @@ class Bot {
64
  * @return bool
65
  */
66
  private function checkTokenHash( $sToken, $nTs, $nPostId ) {
67
- $oWp = Services::WpGeneral();
68
- $sKey = $this->getMod()->prefix(
69
  'comtok-'.md5( sprintf( '%s-%s-%s', $nPostId, $nTs, Services::IP()->getRequestIp() ) )
70
  );
71
- $sStoredToken = Services::WpGeneral()->getTransient( $sKey );
72
- $oWp->deleteTransient( $sKey ); // single use hashes & clean as we go
73
  return hash_equals(
74
  (string)$sStoredToken,
75
  $sToken
64
  * @return bool
65
  */
66
  private function checkTokenHash( $sToken, $nTs, $nPostId ) {
67
+ $WP = Services::WpGeneral();
68
+ $key = $this->getCon()->prefix(
69
  'comtok-'.md5( sprintf( '%s-%s-%s', $nPostId, $nTs, Services::IP()->getRequestIp() ) )
70
  );
71
+ $sStoredToken = Services::WpGeneral()->getTransient( $key );
72
+ $WP->deleteTransient( $key ); // single use hashes & clean as we go
73
  return hash_equals(
74
  (string)$sStoredToken,
75
  $sToken
src/lib/src/Modules/CommentsFilter/Scan/Scanner.php CHANGED
@@ -2,6 +2,7 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan;
4
 
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Utilities;
7
  use FernleafSystems\Wordpress\Services\Services;
@@ -113,31 +114,33 @@ class Scanner {
113
  }
114
 
115
  /**
116
- * @param $aCommData
117
  * @return true|\WP_Error|null
118
  */
119
  private function runScans( $aCommData ) {
120
- /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $oMod */
121
- $oMod = $this->getMod();
 
 
122
 
123
  $mResult = true;
124
 
125
- if ( !is_wp_error( $mResult ) && $oMod->isEnabledGaspCheck() ) {
126
  $mResult = ( new Bot() )
127
- ->setMod( $oMod )
128
  ->scan( $aCommData[ 'comment_post_ID' ] );
129
  }
130
 
131
- if ( !is_wp_error( $mResult ) && $oMod->isEnabledCaptcha() ) {
132
  try {
133
- if ( $oMod->getCaptchaCfg()->provider === 'hcaptcha' ) {
134
  ( new Utilities\HCaptcha\TestRequest() )
135
- ->setMod( $oMod )
136
  ->test();
137
  }
138
  else {
139
  ( new Utilities\ReCaptcha\TestRequest() )
140
- ->setMod( $oMod )
141
  ->test();
142
  }
143
  }
@@ -146,9 +149,9 @@ class Scanner {
146
  }
147
  }
148
 
149
- if ( !is_wp_error( $mResult ) && $oMod->isEnabledHumanCheck() ) {
150
  $mResult = ( new Human() )
151
- ->setMod( $oMod )
152
  ->scan( $aCommData );
153
  }
154
 
@@ -161,10 +164,11 @@ class Scanner {
161
  * @return bool
162
  */
163
  public function getIfDoCommentsCheck( $nPostId, $sCommentEmail ) {
164
- /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $oMod */
165
- $oMod = $this->getMod();
166
- $oPost = Services::WpPost()->getById( $nPostId );
167
- return ( $oPost instanceof \WP_Post ) && Services::WpComments()->isCommentsOpen( $oPost )
168
- && !( new IsEmailTrusted() )->trusted( $sCommentEmail, $oMod->getApprovedMinimum(), $oMod->getTrustedRoles() );
 
169
  }
170
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan;
4
 
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Options;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Utilities;
8
  use FernleafSystems\Wordpress\Services\Services;
114
  }
115
 
116
  /**
117
+ * @param array $aCommData
118
  * @return true|\WP_Error|null
119
  */
120
  private function runScans( $aCommData ) {
121
+ /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $mod */
122
+ $mod = $this->getMod();
123
+ /** @var Options $opts */
124
+ $opts = $this->getOptions();
125
 
126
  $mResult = true;
127
 
128
+ if ( !is_wp_error( $mResult ) && $opts->isEnabledGaspCheck() ) {
129
  $mResult = ( new Bot() )
130
+ ->setMod( $this->getMod() )
131
  ->scan( $aCommData[ 'comment_post_ID' ] );
132
  }
133
 
134
+ if ( !is_wp_error( $mResult ) && $opts->isEnabledCaptcha() && $mod->getCaptchaCfg()->ready ) {
135
  try {
136
+ if ( $mod->getCaptchaCfg()->provider === 'hcaptcha' ) {
137
  ( new Utilities\HCaptcha\TestRequest() )
138
+ ->setMod( $this->getMod() )
139
  ->test();
140
  }
141
  else {
142
  ( new Utilities\ReCaptcha\TestRequest() )
143
+ ->setMod( $this->getMod() )
144
  ->test();
145
  }
146
  }
149
  }
150
  }
151
 
152
+ if ( !is_wp_error( $mResult ) && $opts->isEnabledHumanCheck() ) {
153
  $mResult = ( new Human() )
154
+ ->setMod( $this->getMod() )
155
  ->scan( $aCommData );
156
  }
157
 
164
  * @return bool
165
  */
166
  public function getIfDoCommentsCheck( $nPostId, $sCommentEmail ) {
167
+ /** @var Options $opts */
168
+ $opts = $this->getOptions();
169
+ $post = Services::WpPost()->getById( $nPostId );
170
+ return $post instanceof \WP_Post
171
+ && Services::WpComments()->isCommentsOpen( $post )
172
+ && !( new IsEmailTrusted() )->trusted( $sCommentEmail, $opts->getApprovedMinimum(), $opts->getTrustedRoles() );
173
  }
174
  }
src/lib/src/Modules/CommentsFilter/Strings.php CHANGED
@@ -26,13 +26,13 @@ class Strings extends Base\Strings {
26
  }
27
 
28
  /**
29
- * @param string $sSectionSlug
30
  * @return array
31
  * @throws \Exception
32
  */
33
- public function getSectionStrings( $sSectionSlug ) {
34
 
35
- switch ( $sSectionSlug ) {
36
 
37
  case 'section_enable_plugin_feature_spam_comments_protection_filter' :
38
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -71,7 +71,7 @@ class Strings extends Base\Strings {
71
  break;
72
 
73
  default:
74
- return parent::getSectionStrings( $sSectionSlug );
75
  }
76
 
77
  return [
@@ -82,16 +82,16 @@ class Strings extends Base\Strings {
82
  }
83
 
84
  /**
85
- * @param string $sOptKey
86
  * @return array
87
  * @throws \Exception
88
  */
89
- public function getOptionStrings( $sOptKey ) {
90
  /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $oMod */
91
  $oMod = $this->getMod();
92
  $sModName = $this->getMod()->getMainFeatureName();
93
 
94
- switch ( $sOptKey ) {
95
 
96
  case 'enable_comments_filter' :
97
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -186,7 +186,7 @@ class Strings extends Base\Strings {
186
  break;
187
 
188
  default:
189
- return parent::getOptionStrings( $sOptKey );
190
  }
191
 
192
  return [
26
  }
27
 
28
  /**
29
+ * @param string $section
30
  * @return array
31
  * @throws \Exception
32
  */
33
+ public function getSectionStrings( $section ) {
34
 
35
+ switch ( $section ) {
36
 
37
  case 'section_enable_plugin_feature_spam_comments_protection_filter' :
38
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
71
  break;
72
 
73
  default:
74
+ return parent::getSectionStrings( $section );
75
  }
76
 
77
  return [
82
  }
83
 
84
  /**
85
+ * @param string $key
86
  * @return array
87
  * @throws \Exception
88
  */
89
+ public function getOptionStrings( $key ) {
90
  /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $oMod */
91
  $oMod = $this->getMod();
92
  $sModName = $this->getMod()->getMainFeatureName();
93
 
94
+ switch ( $key ) {
95
 
96
  case 'enable_comments_filter' :
97
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
186
  break;
187
 
188
  default:
189
+ return parent::getOptionStrings( $key );
190
  }
191
 
192
  return [
src/lib/src/Modules/CommentsFilter/UI.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class UI extends Base\ShieldUI {
8
+
9
+ /**
10
+ * @return array
11
+ */
12
+ public function getInsightsConfigCardData() {
13
+ /** @var \ICWP_WPSF_FeatureHandler_CommentsFilter $mod */
14
+ $mod = $this->getMod();
15
+ /** @var Options $opts */
16
+ $opts = $this->getOptions();
17
+
18
+ $data = [
19
+ 'strings' => [
20
+ 'title' => __( 'SPAM Blocking', 'wp-simple-firewall' ),
21
+ 'sub' => __( 'Block Bot & Human Comment SPAM', 'wp-simple-firewall' ),
22
+ ],
23
+ 'key_opts' => [],
24
+ 'href_options' => $mod->getUrl_AdminPage()
25
+ ];
26
+
27
+ if ( !$mod->isModOptEnabled() ) {
28
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
29
+ }
30
+ else {
31
+ $data[ 'key_opts' ][ 'bot' ] = [
32
+ 'name' => __( 'Bot SPAM', 'wp-simple-firewall' ),
33
+ 'enabled' => $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha(),
34
+ 'summary' => ( $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha() ) ?
35
+ __( 'Bot SPAM comments are blocked', 'wp-simple-firewall' )
36
+ : __( 'There is no protection against Bot SPAM comments', 'wp-simple-firewall' ),
37
+ 'weight' => 2,
38
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_bot_comment_spam_protection_filter' ),
39
+ ];
40
+ $data[ 'key_opts' ][ 'human' ] = [
41
+ 'name' => __( 'Human SPAM', 'wp-simple-firewall' ),
42
+ 'enabled' => $opts->isEnabledHumanCheck(),
43
+ 'summary' => $opts->isEnabledHumanCheck() ?
44
+ __( 'Comments posted by humans are checked for SPAM', 'wp-simple-firewall' )
45
+ : __( "Comments posted by humans aren't checked for SPAM", 'wp-simple-firewall' ),
46
+ 'weight' => 1,
47
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_human_spam_filter' ),
48
+ ];
49
+ }
50
+
51
+ return $data;
52
+ }
53
+ }
src/lib/src/Modules/Events/AjaxHandler.php CHANGED
@@ -9,12 +9,12 @@ use FernleafSystems\Wordpress\Services\Services;
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
11
  /**
12
- * @param string $sAction
13
  * @return array
14
  */
15
- protected function processAjaxAction( $sAction ) {
16
 
17
- switch ( $sAction ) {
18
  case 'render_chart':
19
  $aResponse = $this->ajaxExec_RenderChart();
20
  break;
@@ -24,7 +24,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
24
  break;
25
 
26
  default:
27
- $aResponse = parent::processAjaxAction( $sAction );
28
  }
29
 
30
  return $aResponse;
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
11
  /**
12
+ * @param string $action
13
  * @return array
14
  */
15
+ protected function processAjaxAction( $action ) {
16
 
17
+ switch ( $action ) {
18
  case 'render_chart':
19
  $aResponse = $this->ajaxExec_RenderChart();
20
  break;
24
  break;
25
 
26
  default:
27
+ $aResponse = parent::processAjaxAction( $action );
28
  }
29
 
30
  return $aResponse;
src/lib/src/Modules/Events/Options.php CHANGED
@@ -8,6 +8,7 @@ class Options extends Base\ShieldOptions {
8
 
9
  /**
10
  * @return string[]
 
11
  */
12
  public function getDbColumns_Events() {
13
  return $this->getDef( 'events_table_columns' );
8
 
9
  /**
10
  * @return string[]
11
+ * @deprecated 9.2.0
12
  */
13
  public function getDbColumns_Events() {
14
  return $this->getDef( 'events_table_columns' );
src/lib/src/Modules/Firewall/Strings.php CHANGED
@@ -7,13 +7,13 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
  class Strings extends Base\Strings {
8
 
9
  /**
10
- * @param string $sSectionSlug
11
  * @return array
12
  * @throws \Exception
13
  */
14
- public function getSectionStrings( $sSectionSlug ) {
15
 
16
- switch ( $sSectionSlug ) {
17
 
18
  case 'section_enable_plugin_feature_wordpress_firewall' :
19
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -55,7 +55,7 @@ class Strings extends Base\Strings {
55
  break;
56
 
57
  default:
58
- return parent::getSectionStrings( $sSectionSlug );
59
  }
60
 
61
  return [
@@ -66,15 +66,15 @@ class Strings extends Base\Strings {
66
  }
67
 
68
  /**
69
- * @param string $sOptKey
70
  * @return array
71
  * @throws \Exception
72
  */
73
- public function getOptionStrings( $sOptKey ) {
74
 
75
  $sModName = $this->getMod()->getMainFeatureName();
76
 
77
- switch ( $sOptKey ) {
78
 
79
  case 'enable_firewall' :
80
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -169,7 +169,7 @@ class Strings extends Base\Strings {
169
  break;
170
 
171
  default:
172
- return parent::getOptionStrings( $sOptKey );
173
  }
174
 
175
  return [
7
  class Strings extends Base\Strings {
8
 
9
  /**
10
+ * @param string $section
11
  * @return array
12
  * @throws \Exception
13
  */
14
+ public function getSectionStrings( $section ) {
15
 
16
+ switch ( $section ) {
17
 
18
  case 'section_enable_plugin_feature_wordpress_firewall' :
19
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
55
  break;
56
 
57
  default:
58
+ return parent::getSectionStrings( $section );
59
  }
60
 
61
  return [
66
  }
67
 
68
  /**
69
+ * @param string $key
70
  * @return array
71
  * @throws \Exception
72
  */
73
+ public function getOptionStrings( $key ) {
74
 
75
  $sModName = $this->getMod()->getMainFeatureName();
76
 
77
+ switch ( $key ) {
78
 
79
  case 'enable_firewall' :
80
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
169
  break;
170
 
171
  default:
172
+ return parent::getOptionStrings( $key );
173
  }
174
 
175
  return [
src/lib/src/Modules/Firewall/UI.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class UI extends Base\ShieldUI {
8
+
9
+ /**
10
+ * @return array
11
+ */
12
+ public function getInsightsConfigCardData() {
13
+ /** @var \ICWP_WPSF_FeatureHandler_Firewall $mod */
14
+ $mod = $this->getMod();
15
+ /** @var Options $opts */
16
+ $opts = $this->getOptions();
17
+
18
+ $data = [
19
+ 'strings' => [
20
+ 'title' => __( 'Firewall', 'wp-simple-firewall' ),
21
+ 'sub' => __( 'Block Malicious Requests', 'wp-simple-firewall' ),
22
+ ],
23
+ 'key_opts' => [],
24
+ 'href_options' => $mod->getUrl_AdminPage()
25
+ ];
26
+
27
+ if ( !$mod->isModOptEnabled() ) {
28
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
29
+ }
30
+ else {
31
+ $data[ 'key_opts' ][ 'mod' ] = [
32
+ 'name' => __( 'Firewall', 'wp-simple-firewall' ),
33
+ 'enabled' => $mod->isModOptEnabled(),
34
+ 'summary' => $mod->isModOptEnabled() ?
35
+ __( 'Your site is protected against malicious requests', 'wp-simple-firewall' )
36
+ : __( 'Your site is not protected against malicious requests', 'wp-simple-firewall' ),
37
+ 'weight' => 2,
38
+ 'href' => $mod->getUrl_DirectLinkToOption( $mod->getEnableModOptKey() ),
39
+ ];
40
+
41
+ //ignoring admin isn't a good idea
42
+ $bAdminIncluded = !$opts->isIgnoreAdmin();
43
+ $data[ 'key_opts' ][ 'admin' ] = [
44
+ 'name' => __( 'Ignore Admins', 'wp-simple-firewall' ),
45
+ 'enabled' => $bAdminIncluded,
46
+ 'summary' => $bAdminIncluded ?
47
+ __( "Firewall rules are also applied to admins", 'wp-simple-firewall' )
48
+ : __( "Firewall rules aren't applied to admins", 'wp-simple-firewall' ),
49
+ 'weight' => 1,
50
+ 'href' => $mod->getUrl_DirectLinkToOption( 'whitelist_admins' ),
51
+ ];
52
+ }
53
+
54
+ return $data;
55
+ }
56
+ }
src/lib/src/Modules/HackGuard/AjaxHandler.php CHANGED
@@ -11,13 +11,13 @@ use FernleafSystems\Wordpress\Services\Services;
11
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
12
 
13
  /**
14
- * @param string $sAction
15
  * @return array
16
  */
17
- protected function processAjaxAction( $sAction ) {
18
 
19
  $oReq = Services::Request();
20
- switch ( $sAction ) {
21
 
22
  case 'scans_start':
23
  $aResponse = $this->ajaxExec_StartScans();
@@ -40,7 +40,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
40
  case 'item_delete':
41
  case 'item_ignore':
42
  case 'item_repair':
43
- $aResponse = $this->ajaxExec_ScanItemAction( str_replace( 'item_', '', $sAction ) );
44
  break;
45
 
46
  case 'render_table_scan':
@@ -60,7 +60,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
60
  break;
61
 
62
  default:
63
- $aResponse = parent::processAjaxAction( $sAction );
64
  }
65
 
66
  return $aResponse;
11
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
12
 
13
  /**
14
+ * @param string $action
15
  * @return array
16
  */
17
+ protected function processAjaxAction( $action ) {
18
 
19
  $oReq = Services::Request();
20
+ switch ( $action ) {
21
 
22
  case 'scans_start':
23
  $aResponse = $this->ajaxExec_StartScans();
40
  case 'item_delete':
41
  case 'item_ignore':
42
  case 'item_repair':
43
+ $aResponse = $this->ajaxExec_ScanItemAction( str_replace( 'item_', '', $action ) );
44
  break;
45
 
46
  case 'render_table_scan':
60
  break;
61
 
62
  default:
63
+ $aResponse = parent::processAjaxAction( $action );
64
  }
65
 
66
  return $aResponse;
src/lib/src/Modules/HackGuard/Lib/FileLocker/File.php CHANGED
@@ -26,36 +26,36 @@ class File {
26
  * @return string[]
27
  */
28
  public function getExistingPossiblePaths() {
29
- $aPaths = array_filter(
30
  $this->getPossiblePaths(),
31
  function ( $sPath ) {
32
  return Services::WpFs()->isFile( $sPath );
33
  }
34
  );
35
-
36
- if ( (int)$this->max_paths > 0 ) {
37
- $aPaths = array_slice( $aPaths, 0, $this->max_paths );
38
- }
39
- return $aPaths;
40
  }
41
 
42
  /**
43
  * @return string[]
44
  */
45
  public function getPossiblePaths() {
46
- $aPossible = [];
47
- $nLimiter = 1;
48
- $sDir = realpath( $this->dir );
49
  do {
50
- if ( empty( $sDir ) ) {
51
  break;
52
  }
53
- $aPossible[] = path_join( $sDir, $this->file );
54
- $sDir = dirname( $sDir );
55
- $nLimiter++;
56
- } while ( $nLimiter <= $this->getMaxDirLevels() );
 
 
 
 
 
57
 
58
- return $aPossible;
59
  }
60
 
61
  /**
26
  * @return string[]
27
  */
28
  public function getExistingPossiblePaths() {
29
+ return array_filter(
30
  $this->getPossiblePaths(),
31
  function ( $sPath ) {
32
  return Services::WpFs()->isFile( $sPath );
33
  }
34
  );
 
 
 
 
 
35
  }
36
 
37
  /**
38
  * @return string[]
39
  */
40
  public function getPossiblePaths() {
41
+ $paths = [];
42
+ $dirCount = 0;
43
+ $workingDir = realpath( $this->dir );
44
  do {
45
+ if ( empty( $workingDir ) ) {
46
  break;
47
  }
48
+ $paths[] = path_join( $workingDir, $this->file );
49
+
50
+ $workingDir = dirname( $workingDir );
51
+ $dirCount++;
52
+
53
+ } while (
54
+ $dirCount < $this->getMaxDirLevels()
55
+ && ( empty( $this->max_paths ) || count( $paths ) < $this->max_paths )
56
+ );
57
 
58
+ return $paths;
59
  }
60
 
61
  /**
src/lib/src/Modules/HackGuard/Lib/FileLocker/FileLockerController.php CHANGED
@@ -123,15 +123,15 @@ class FileLockerController {
123
  }
124
 
125
  public function deleteAllLocks() {
126
- /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
127
- $oMod = $this->getMod();
128
- $oMod->getDbHandler_FileLocker()->tableDelete( true );
129
  }
130
 
131
  public function purge() {
132
- /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
133
- $oMod = $this->getMod();
134
- $oMod->getDbHandler_FileLocker()->tableDelete();
135
  }
136
 
137
  /**
@@ -181,14 +181,26 @@ class FileLockerController {
181
  switch ( $sFileKey ) {
182
  case 'wpconfig':
183
  $sFileKey = 'wp-config.php';
184
- $nLevels = $bIsSplitWp ? 3 : 2;
185
  $nMaxPaths = 1;
 
 
 
 
 
 
186
  // TODO: is split URL?
187
  break;
 
188
  case 'root_htaccess':
189
  $sFileKey = '.htaccess';
190
  $nLevels = $bIsSplitWp ? 2 : 1;
191
  break;
 
 
 
 
 
 
192
  case 'root_index':
193
  $sFileKey = 'index.php';
194
  $nLevels = $bIsSplitWp ? 2 : 1;
123
  }
124
 
125
  public function deleteAllLocks() {
126
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
127
+ $mod = $this->getMod();
128
+ $mod->getDbHandler_FileLocker()->tableDelete( true );
129
  }
130
 
131
  public function purge() {
132
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
133
+ $mod = $this->getMod();
134
+ $mod->getDbHandler_FileLocker()->tableDelete();
135
  }
136
 
137
  /**
181
  switch ( $sFileKey ) {
182
  case 'wpconfig':
183
  $sFileKey = 'wp-config.php';
 
184
  $nMaxPaths = 1;
185
+ $nLevels = $bIsSplitWp ? 3 : 2;
186
+
187
+ $openBaseDir = ini_get( 'open_basedir' );
188
+ if ( !empty( $openBaseDir ) ) {
189
+ $nLevels--;
190
+ }
191
  // TODO: is split URL?
192
  break;
193
+
194
  case 'root_htaccess':
195
  $sFileKey = '.htaccess';
196
  $nLevels = $bIsSplitWp ? 2 : 1;
197
  break;
198
+
199
+ case 'root_webconfig':
200
+ $sFileKey = 'Web.Config';
201
+ $nLevels = $bIsSplitWp ? 2 : 1;
202
+ break;
203
+
204
  case 'root_index':
205
  $sFileKey = 'index.php';
206
  $nLevels = $bIsSplitWp ? 2 : 1;
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/CleanAll.php CHANGED
@@ -7,8 +7,6 @@ use FernleafSystems\Wordpress\Services\Services;
7
 
8
  class CleanAll extends BaseBulk {
9
 
10
- /**
11
- */
12
  public function run() {
13
  /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
14
  $oMod = $this->getMod();
7
 
8
  class CleanAll extends BaseBulk {
9
 
 
 
10
  public function run() {
11
  /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
12
  $oMod = $this->getMod();
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/Delete.php CHANGED
@@ -6,8 +6,6 @@ use FernleafSystems\Wordpress\Services\Services;
6
 
7
  class Delete extends BaseAction {
8
 
9
- /**
10
- */
11
  public function run() {
12
  try {
13
  $oStore = ( new Load() )
6
 
7
  class Delete extends BaseAction {
8
 
 
 
9
  public function run() {
10
  try {
11
  $oStore = ( new Load() )
src/lib/src/Modules/HackGuard/Lib/Snapshots/StoreAction/TouchAll.php CHANGED
@@ -7,8 +7,6 @@ use FernleafSystems\Wordpress\Services\Services;
7
 
8
  class TouchAll extends BaseBulk {
9
 
10
- /**
11
- */
12
  public function run() {
13
  foreach ( ( new FindAssetsToSnap() )->setMod( $this->getMod() )->run() as $oAsset ) {
14
  try {
7
 
8
  class TouchAll extends BaseBulk {
9
 
 
 
10
  public function run() {
11
  foreach ( ( new FindAssetsToSnap() )->setMod( $this->getMod() )->run() as $oAsset ) {
12
  try {
src/lib/src/Modules/HackGuard/Options.php CHANGED
@@ -9,6 +9,7 @@ class Options extends Base\ShieldOptions {
9
 
10
  /**
11
  * @return string[]
 
12
  */
13
  public function getDbColumns_FileLocker() {
14
  return $this->getDef( 'table_columns_filelocker' );
@@ -16,6 +17,7 @@ class Options extends Base\ShieldOptions {
16
 
17
  /**
18
  * @return string[]
 
19
  */
20
  public function getDbColumns_Scanner() {
21
  return $this->getDef( 'table_columns_scanner' );
@@ -23,6 +25,7 @@ class Options extends Base\ShieldOptions {
23
 
24
  /**
25
  * @return string[]
 
26
  */
27
  public function getDbColumns_ScanQueue() {
28
  return $this->getDef( 'table_columns_scanqueue' );
@@ -53,8 +56,8 @@ class Options extends Base\ShieldOptions {
53
  * @return array
54
  */
55
  public function getFilesToLock() {
56
- $aLocks = $this->getOpt( 'file_locker', [] );
57
- return is_array( $aLocks ) ? $aLocks : [];
58
  }
59
 
60
  /**
9
 
10
  /**
11
  * @return string[]
12
+ * @deprecated 9.2.0
13
  */
14
  public function getDbColumns_FileLocker() {
15
  return $this->getDef( 'table_columns_filelocker' );
17
 
18
  /**
19
  * @return string[]
20
+ * @deprecated 9.2.0
21
  */
22
  public function getDbColumns_Scanner() {
23
  return $this->getDef( 'table_columns_scanner' );
25
 
26
  /**
27
  * @return string[]
28
+ * @deprecated 9.2.0
29
  */
30
  public function getDbColumns_ScanQueue() {
31
  return $this->getDef( 'table_columns_scanqueue' );
56
  * @return array
57
  */
58
  public function getFilesToLock() {
59
+ $locks = $this->getOpt( 'file_locker', [] );
60
+ return is_array( $locks ) ? $locks : [];
61
  }
62
 
63
  /**
src/lib/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php CHANGED
@@ -21,22 +21,23 @@ class CompleteQueue {
21
  * Take care here not to confuse the 2x DB Handlers
22
  */
23
  public function complete() {
24
- /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
25
- $oMod = $this->getMod();
 
26
  /** @var Databases\ScanQueue\Handler $oDbH */
27
  $oDbH = $this->getDbHandler();
28
  $oSel = $oDbH->getQuerySelector();
29
 
30
  foreach ( $oSel->getDistinctForColumn( 'scan' ) as $sScanSlug ) {
31
 
32
- $oScanCon = $oMod->getScanCon( $sScanSlug );
33
 
34
  $oResultsSet = ( new CollateResults() )
35
  ->setScanController( $oScanCon )
36
  ->setDbHandler( $oDbH )
37
  ->collate( $sScanSlug );
38
 
39
- $this->getCon()->fireEvent( $sScanSlug.'_scan_run' );
40
 
41
  if ( $oResultsSet instanceof Scans\Base\BaseResultsSet ) {
42
  ( new HackGuard\Scan\Results\ResultsUpdate() )
@@ -44,7 +45,7 @@ class CompleteQueue {
44
  ->update( $oResultsSet );
45
 
46
  if ( $oResultsSet->countItems() > 0 ) {
47
- $this->getCon()->fireEvent( $sScanSlug.'_scan_found' );
48
  }
49
  }
50
 
@@ -54,14 +55,14 @@ class CompleteQueue {
54
  ->query();
55
  }
56
 
57
- /** @var HackGuard\Options $oOpts */
58
- $oOpts = $this->getOptions();
59
- if ( $oOpts->isScanCron() && !wp_next_scheduled( $oMod->prefix( 'post_scan' ) ) ) {
60
  wp_schedule_single_event(
61
  Services::Request()->ts() + 5,
62
- $oMod->prefix( 'post_scan' )
63
  );
64
  }
65
- $oOpts->setIsScanCron( false );
66
  }
67
  }
21
  * Take care here not to confuse the 2x DB Handlers
22
  */
23
  public function complete() {
24
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
25
+ $mod = $this->getMod();
26
+ $con = $this->getCon();
27
  /** @var Databases\ScanQueue\Handler $oDbH */
28
  $oDbH = $this->getDbHandler();
29
  $oSel = $oDbH->getQuerySelector();
30
 
31
  foreach ( $oSel->getDistinctForColumn( 'scan' ) as $sScanSlug ) {
32
 
33
+ $oScanCon = $mod->getScanCon( $sScanSlug );
34
 
35
  $oResultsSet = ( new CollateResults() )
36
  ->setScanController( $oScanCon )
37
  ->setDbHandler( $oDbH )
38
  ->collate( $sScanSlug );
39
 
40
+ $con->fireEvent( $sScanSlug.'_scan_run' );
41
 
42
  if ( $oResultsSet instanceof Scans\Base\BaseResultsSet ) {
43
  ( new HackGuard\Scan\Results\ResultsUpdate() )
45
  ->update( $oResultsSet );
46
 
47
  if ( $oResultsSet->countItems() > 0 ) {
48
+ $con->fireEvent( $sScanSlug.'_scan_found' );
49
  }
50
  }
51
 
55
  ->query();
56
  }
57
 
58
+ /** @var HackGuard\Options $opts */
59
+ $opts = $this->getOptions();
60
+ if ( $opts->isScanCron() && !wp_next_scheduled( $con->prefix( 'post_scan' ) ) ) {
61
  wp_schedule_single_event(
62
  Services::Request()->ts() + 5,
63
+ $con->prefix( 'post_scan' )
64
  );
65
  }
66
+ $opts->setIsScanCron( false );
67
  }
68
  }
src/lib/src/Modules/HackGuard/Scan/Queue/ConvertBetweenTypes.php CHANGED
@@ -32,7 +32,7 @@ class ConvertBetweenTypes {
32
  */
33
  public function fromActionToDbEntry( $oAction ) {
34
  $oEntry = new Databases\ScanQueue\EntryVO();
35
- foreach ( $this->getDbHandler()->getColumnsDefinition() as $sField ) {
36
  if ( isset( $oAction->{$sField} ) ) {
37
  $oEntry->{$sField} = $oAction->{$sField};
38
  }
32
  */
33
  public function fromActionToDbEntry( $oAction ) {
34
  $oEntry = new Databases\ScanQueue\EntryVO();
35
+ foreach ( $this->getDbHandler()->getColumns() as $sField ) {
36
  if ( isset( $oAction->{$sField} ) ) {
37
  $oEntry->{$sField} = $oAction->{$sField};
38
  }
src/lib/src/Modules/HackGuard/Scan/Queue/QueueProcessor.php CHANGED
@@ -140,8 +140,6 @@ class QueueProcessor extends Utilities\BackgroundProcessing\BackgroundProcess {
140
  return $this;
141
  }
142
 
143
- /**
144
- */
145
  public function handleExpiredItems() {
146
  $nBoundary = Services::Request()
147
  ->carbon()
140
  return $this;
141
  }
142
 
 
 
143
  public function handleExpiredItems() {
144
  $nBoundary = Services::Request()
145
  ->carbon()
src/lib/src/Modules/HackGuard/Strings.php CHANGED
@@ -61,15 +61,15 @@ class Strings extends Base\Strings {
61
  }
62
 
63
  /**
64
- * @param string $sSectionSlug
65
  * @return array
66
  * @throws \Exception
67
  */
68
- public function getSectionStrings( $sSectionSlug ) {
69
 
70
  $sModName = $this->getMod()->getMainFeatureName();
71
 
72
- switch ( $sSectionSlug ) {
73
 
74
  case 'section_scan_options' :
75
  $sTitle = __( 'Scan Options', 'wp-simple-firewall' );
@@ -159,7 +159,7 @@ class Strings extends Base\Strings {
159
  break;
160
 
161
  default:
162
- return parent::getSectionStrings( $sSectionSlug );
163
  }
164
 
165
  return [
@@ -170,16 +170,16 @@ class Strings extends Base\Strings {
170
  }
171
 
172
  /**
173
- * @param string $sOptKey
174
  * @return array
175
  * @throws \Exception
176
  */
177
- public function getOptionStrings( $sOptKey ) {
178
- /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
179
- $oMod = $this->getMod();
180
- $sModName = $oMod->getMainFeatureName();
181
 
182
- switch ( $sOptKey ) {
183
 
184
  case 'enable_hack_protect' :
185
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -247,9 +247,9 @@ class Strings extends Base\Strings {
247
  sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ), __( "Doesn't currently detect missing files.", 'wp-simple-firewall' ) ),
248
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Keep this feature turned on, at all times.', 'wp-simple-firewall' ) )
249
  ];
250
- if ( !$oMod->canCacheDirWrite() ) {
251
  $sDescription[] = sprintf( __( 'Sorry, this feature is not available because we cannot write to disk at this location: %s', 'wp-simple-firewall' ),
252
- '<code>'.$oMod->getPtgSnapsBaseDir().'</code>' );
253
  }
254
  break;
255
 
@@ -270,6 +270,7 @@ class Strings extends Base\Strings {
270
  $sSummary = __( 'Lock Files Against Tampering And Changes', 'wp-simple-firewall' );
271
  $sDescription = [
272
  __( 'Detects changes to the files, then lets you examine contents and revert as required.', 'wp-simple-firewall' ),
 
273
  ];
274
 
275
  $aLocks = ( new LoadFileLocks() )
@@ -299,7 +300,7 @@ class Strings extends Base\Strings {
299
  case 'ufc_exclusions' :
300
  $sName = __( 'File Exclusions', 'wp-simple-firewall' );
301
  $sSummary = __( 'Provide A List Of Files To Be Excluded From The Scan', 'wp-simple-firewall' );
302
- $sDefaults = implode( ', ', $oMod->getOptions()->getOptDefault( 'ufc_exclusions' ) );
303
  $sDescription = __( 'Take a new line for each file you wish to exclude from the scan.', 'wp-simple-firewall' )
304
  .'<br/><strong>'.__( 'No commas are necessary.', 'wp-simple-firewall' ).'</strong>'
305
  .'<br/>'.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $sDefaults );
@@ -415,7 +416,7 @@ class Strings extends Base\Strings {
415
  .'<br/>'.__( 'Remove all extensions to scan all file type (not recommended).', 'wp-simple-firewall' );
416
  break;
417
  default:
418
- return parent::getOptionStrings( $sOptKey );
419
  }
420
 
421
  return [
61
  }
62
 
63
  /**
64
+ * @param string $section
65
  * @return array
66
  * @throws \Exception
67
  */
68
+ public function getSectionStrings( $section ) {
69
 
70
  $sModName = $this->getMod()->getMainFeatureName();
71
 
72
+ switch ( $section ) {
73
 
74
  case 'section_scan_options' :
75
  $sTitle = __( 'Scan Options', 'wp-simple-firewall' );
159
  break;
160
 
161
  default:
162
+ return parent::getSectionStrings( $section );
163
  }
164
 
165
  return [
170
  }
171
 
172
  /**
173
+ * @param string $key
174
  * @return array
175
  * @throws \Exception
176
  */
177
+ public function getOptionStrings( $key ) {
178
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
179
+ $mod = $this->getMod();
180
+ $sModName = $mod->getMainFeatureName();
181
 
182
+ switch ( $key ) {
183
 
184
  case 'enable_hack_protect' :
185
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
247
  sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ), __( "Doesn't currently detect missing files.", 'wp-simple-firewall' ) ),
248
  sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'Keep this feature turned on, at all times.', 'wp-simple-firewall' ) )
249
  ];
250
+ if ( !$mod->canCacheDirWrite() ) {
251
  $sDescription[] = sprintf( __( 'Sorry, this feature is not available because we cannot write to disk at this location: %s', 'wp-simple-firewall' ),
252
+ '<code>'.$mod->getPtgSnapsBaseDir().'</code>' );
253
  }
254
  break;
255
 
270
  $sSummary = __( 'Lock Files Against Tampering And Changes', 'wp-simple-firewall' );
271
  $sDescription = [
272
  __( 'Detects changes to the files, then lets you examine contents and revert as required.', 'wp-simple-firewall' ),
273
+ sprintf( '%s: %s', __( 'Note', 'wp-simple-firewall' ), __( 'Web.Config is only available for Windows/IIS.', 'wp-simple-firewall' ) )
274
  ];
275
 
276
  $aLocks = ( new LoadFileLocks() )
300
  case 'ufc_exclusions' :
301
  $sName = __( 'File Exclusions', 'wp-simple-firewall' );
302
  $sSummary = __( 'Provide A List Of Files To Be Excluded From The Scan', 'wp-simple-firewall' );
303
+ $sDefaults = implode( ', ', $this->getOptions()->getOptDefault( 'ufc_exclusions' ) );
304
  $sDescription = __( 'Take a new line for each file you wish to exclude from the scan.', 'wp-simple-firewall' )
305
  .'<br/><strong>'.__( 'No commas are necessary.', 'wp-simple-firewall' ).'</strong>'
306
  .'<br/>'.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $sDefaults );
416
  .'<br/>'.__( 'Remove all extensions to scan all file type (not recommended).', 'wp-simple-firewall' );
417
  break;
418
  default:
419
+ return parent::getOptionStrings( $key );
420
  }
421
 
422
  return [
src/lib/src/Modules/HackGuard/UI.php ADDED
@@ -0,0 +1,703 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Lib\FileLocker\Ops\LoadFileLocks;
8
+ use FernleafSystems\Wordpress\Services\Core\VOs\WpPluginVo;
9
+ use FernleafSystems\Wordpress\Services\Services;
10
+
11
+ class UI extends Base\ShieldUI {
12
+
13
+ /**
14
+ * @return array
15
+ */
16
+ public function buildInsightsVars() {
17
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
18
+ $mod = $this->getMod();
19
+ /** @var Options $opts */
20
+ $opts = $this->getOptions();
21
+
22
+ $aLatestScans = array_map(
23
+ function ( $nTime ) {
24
+ return sprintf(
25
+ __( 'Last Scan: %s', 'wp-simple-firewall' ),
26
+ ( $nTime > 0 ) ?
27
+ Services::Request()->carbon()->setTimestamp( $nTime )->diffForHumans()
28
+ : __( 'Never', 'wp-simple-firewall' )
29
+ );
30
+ },
31
+ $mod->getLastScansAt()
32
+ );
33
+
34
+ $aUiTrack = $mod->getUiTrack();
35
+ if ( empty( $aUiTrack[ 'selected_scans' ] ) ) {
36
+ $aUiTrack[ 'selected_scans' ] = $opts->getScanSlugs();
37
+ }
38
+
39
+ // Can Scan Checks:
40
+ $aReasonCantScan = $mod->getProcessor()
41
+ ->getSubProScanner()
42
+ ->getReasonsScansCantExecute();
43
+
44
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner\Select $oSelector */
45
+ $oSelector = $mod->getDbHandler_ScanResults()->getQuerySelector();
46
+ $aData = [
47
+ 'ajax' => [
48
+ 'scans_start' => $mod->getAjaxActionData( 'scans_start', true ),
49
+ 'scans_check' => $mod->getAjaxActionData( 'scans_check', true ),
50
+ 'render_table_scan' => $mod->getAjaxActionData( 'render_table_scan', true ),
51
+ 'bulk_action' => $mod->getAjaxActionData( 'bulk_action', true ),
52
+ 'item_asset_deactivate' => $mod->getAjaxActionData( 'item_asset_deactivate', true ),
53
+ 'item_asset_reinstall' => $mod->getAjaxActionData( 'item_asset_reinstall', true ),
54
+ 'item_delete' => $mod->getAjaxActionData( 'item_delete', true ),
55
+ 'item_ignore' => $mod->getAjaxActionData( 'item_ignore', true ),
56
+ 'item_repair' => $mod->getAjaxActionData( 'item_repair', true ),
57
+ 'item_action' => $mod->getAjaxActionData( 'item_action', true ),
58
+ ],
59
+ 'flags' => [
60
+ 'is_premium' => $this->getCon()->isPremiumActive(),
61
+ 'can_scan' => count( $aReasonCantScan ) === 0,
62
+ ],
63
+ 'strings' => [
64
+ 'never' => __( 'Never', 'wp-simple-firewall' ),
65
+ 'not_available' => __( 'Sorry, this scan is not available.', 'wp-simple-firewall' ),
66
+ 'not_enabled' => __( 'This scan is not currently enabled.', 'wp-simple-firewall' ),
67
+ 'please_enable' => __( 'Please turn on this scan in the options.', 'wp-simple-firewall' ),
68
+ 'click_see_results' => __( 'Click a scan to see its results', 'wp-simple-firewall' ),
69
+ 'title_scan_site_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
70
+ 'title_scan_now' => __( 'Scan Your Site Now', 'wp-simple-firewall' ),
71
+ 'subtitle_scan_now' => __( 'Run the selected scans on your site now to get the latest results', 'wp-simple-firewall' ),
72
+ 'more_items_longer' => __( 'The more scans that are selected, the longer the scan may take.', 'wp-simple-firewall' ),
73
+ 'scan_options' => __( 'Scan Options', 'wp-simple-firewall' ),
74
+ 'scanselect' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
75
+ 'scanselect_file_areas' => __( 'Select File Scans To Run', 'wp-simple-firewall' ),
76
+ 'scanselect_assets' => __( 'Select Scans For Plugins and Themes', 'wp-simple-firewall' ),
77
+ 'select_view_results' => __( 'View Scan Results', 'wp-simple-firewall' ),
78
+ 'select_what_to_scan' => __( 'Select Scans To Run', 'wp-simple-firewall' ),
79
+ 'clear_ignore' => __( 'Clear Ignore Flags', 'wp-simple-firewall' ),
80
+ 'clear_ignore_sub' => __( 'Previously ignored results will be revealed (for the selected scans only)', 'wp-simple-firewall' ),
81
+ 'clear_suppression' => __( 'Remove Notification Suppression', 'wp-simple-firewall' ),
82
+ 'clear_suppression_sub' => __( 'Allow notification emails to be resent (for the selected scans only)', 'wp-simple-firewall' ),
83
+ 'run_scans_now' => __( 'Run Scans Now', 'wp-simple-firewall' ),
84
+ 'no_entries_to_display' => __( "The previous scan either didn't detect any items that require your attention or they've already been repaired.", 'wp-simple-firewall' ),
85
+ 'scan_progress' => __( 'Scan Progress', 'wp-simple-firewall' ),
86
+ 'reason_not_call_self' => __( "This site currently can't make HTTP requests to itself.", 'wp-simple-firewall' ),
87
+ ],
88
+ 'vars' => [
89
+ 'initial_check' => $mod->getScanQueueController()->hasRunningScans(),
90
+ 'cannot_scan_reasons' => $aReasonCantScan
91
+ ],
92
+ 'scan_results' => [
93
+ ],
94
+ 'aggregate' => [
95
+ 'flags' => [
96
+ 'has_items' => true,
97
+ ],
98
+ 'hrefs' => [
99
+ 'options' => $mod->getUrl_DirectLinkToSection( 'section_scan_options' )
100
+ ],
101
+ 'vars' => [
102
+ ],
103
+ 'strings' => [
104
+ 'title' => __( 'File Scan', 'wp-simple-firewall' ),
105
+ 'subtitle' => __( "Results of all file scans", 'wp-simple-firewall' )
106
+ ],
107
+ 'count' => $oSelector->filterByScans( [ 'ptg', 'mal', 'wcf', 'ufc' ] )
108
+ ->filterByNotIgnored()
109
+ ->count()
110
+ ],
111
+ 'file_locker' => $this->getFileLockerVars(),
112
+ 'scans' => [
113
+ 'apc' => [
114
+ 'flags' => [
115
+ 'has_items' => true,
116
+ 'show_table' => true,
117
+ ],
118
+ 'hrefs' => [],
119
+ 'vars' => [],
120
+ 'strings' => [
121
+ 'subtitle' => __( "Discover plugins that may have been abandoned by their authors", 'wp-simple-firewall' )
122
+ ],
123
+ ],
124
+ 'wcf' => [
125
+ 'flags' => [
126
+ 'has_items' => true,
127
+ 'show_table' => false,
128
+ ],
129
+ 'hrefs' => [],
130
+ 'vars' => [],
131
+ 'strings' => [
132
+ 'subtitle' => __( "Detect changes to core WordPress files when compared to the official distribution", 'wp-simple-firewall' ),
133
+ ],
134
+ ],
135
+ 'ufc' => [
136
+ 'flags' => [
137
+ 'has_items' => true,
138
+ 'show_table' => false,
139
+ ],
140
+ 'hrefs' => [],
141
+ 'vars' => [],
142
+ 'strings' => [
143
+ 'subtitle' => __( "Detect files which aren't part of the official WordPress.org distribution", 'wp-simple-firewall' )
144
+ ],
145
+ ],
146
+ 'mal' => [
147
+ 'flags' => [
148
+ 'has_items' => true,
149
+ 'show_table' => false,
150
+ ],
151
+ 'hrefs' => [],
152
+ 'vars' => [],
153
+ 'strings' => [
154
+ 'subtitle' => __( "Detect files that may be infected with malware", 'wp-simple-firewall' )
155
+ ],
156
+ ],
157
+ 'ptg' => $this->getInsightVarsScan_Ptg(),
158
+ 'wpv' => [
159
+ 'flags' => [
160
+ 'has_items' => true,
161
+ 'show_table' => true,
162
+ ],
163
+ 'hrefs' => [],
164
+ 'vars' => [],
165
+ 'strings' => [
166
+ 'subtitle' => __( "Be alerted to plugins and themes with known security vulnerabilities", 'wp-simple-firewall' )
167
+ ],
168
+ ],
169
+ ],
170
+ ];
171
+
172
+ /** @var Strings $oStrings */
173
+ $oStrings = $mod->getStrings();
174
+ $aScanNames = $oStrings->getScanNames();
175
+ foreach ( $aData[ 'scans' ] as $sSlug => &$aScanData ) {
176
+ $oScanCon = $mod->getScanCon( $sSlug );
177
+ $aScanData[ 'flags' ][ 'is_available' ] = $oScanCon->isScanningAvailable();
178
+ $aScanData[ 'flags' ][ 'is_restricted' ] = !$oScanCon->isScanningAvailable();
179
+ $aScanData[ 'flags' ][ 'is_enabled' ] = $oScanCon->isEnabled();
180
+ $aScanData[ 'flags' ][ 'is_selected' ] = $oScanCon->isScanningAvailable() && in_array( $sSlug, $aUiTrack[ 'selected_scans' ] );
181
+ $aScanData[ 'flags' ][ 'has_last_scan' ] = $mod->getLastScanAt( $sSlug ) > 0;
182
+ $aScanData[ 'vars' ][ 'last_scan_at' ] = $aLatestScans[ $sSlug ];
183
+ $aScanData[ 'strings' ][ 'title' ] = $aScanNames[ $sSlug ];
184
+ $aScanData[ 'hrefs' ][ 'options' ] = $mod->getUrl_DirectLinkToSection( 'section_scan_'.$sSlug );
185
+ $aScanData[ 'hrefs' ][ 'please_enable' ] = $mod->getUrl_DirectLinkToSection( 'section_scan_'.$sSlug );
186
+ $aScanData[ 'count' ] = $oSelector->countForScan( $sSlug );
187
+ }
188
+
189
+ return $aData;
190
+ }
191
+
192
+ /**
193
+ * @param array $aOptParams
194
+ * @return array
195
+ */
196
+ protected function buildOptionForUi( $aOptParams ) {
197
+ $aOptParams = parent::buildOptionForUi( $aOptParams );
198
+ if ( $aOptParams[ 'key' ] === 'file_locker' && !Services::Data()->isWindows() ) {
199
+ $aOptParams[ 'value_options' ][ 'root_webconfig' ] .= sprintf( ' (%s)', __( 'unavailable', 'wp-simple-firewall' ) );
200
+ }
201
+ return $aOptParams;
202
+ }
203
+
204
+ /**
205
+ * @return array
206
+ */
207
+ protected function getFileLockerVars() {
208
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
209
+ $mod = $this->getMod();
210
+
211
+ $oLockCon = $mod->getFileLocker();
212
+ $oLockLoader = ( new LoadFileLocks() )->setMod( $mod );
213
+ $aProblemLocks = $oLockLoader->withProblems();
214
+ $aGoodLocks = $oLockLoader->withoutProblems();
215
+
216
+ return [
217
+ 'ajax' => [
218
+ 'filelocker_showdiff' => $mod->getAjaxActionData( 'filelocker_showdiff', true ),
219
+ 'filelocker_fileaction' => $mod->getAjaxActionData( 'filelocker_fileaction', true ),
220
+ ],
221
+ 'flags' => [
222
+ 'is_enabled' => $oLockCon->isEnabled(),
223
+ 'is_restricted' => !$this->getCon()->isPremiumActive(),
224
+ ],
225
+ 'hrefs' => [
226
+ 'options' => $mod->getUrl_DirectLinkToSection( 'section_realtime' ),
227
+ 'please_enable' => $mod->getUrl_DirectLinkToSection( 'section_realtime' ),
228
+ ],
229
+ 'vars' => [
230
+ 'file_locks' => [
231
+ 'good' => $aGoodLocks,
232
+ 'bad' => $aProblemLocks,
233
+ ],
234
+ ],
235
+ 'strings' => [
236
+ 'title' => __( 'File Locker', 'wp-simple-firewall' ),
237
+ 'subtitle' => __( 'Results of file locker monitoring', 'wp-simple-firewall' ),
238
+ 'please_select' => __( 'Please select a file to review.', 'wp-simple-firewall' ),
239
+ ],
240
+ 'count' => count( $aProblemLocks )
241
+ ];
242
+ }
243
+
244
+ /**
245
+ * @return array
246
+ */
247
+ private function getInsightVarsScan_Ptg() {
248
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $oMod */
249
+ $oMod = $this->getMod();
250
+ $oReq = Services::Request();
251
+
252
+ /** @var \ICWP_WPSF_Processor_HackProtect $oPro */
253
+ $oPro = $oMod->getProcessor();
254
+ $oProPtg = $oPro->getSubProScanner()->getSubProcessorPtg();
255
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner\Select $oSelector */
256
+ $oSelector = $oMod->getDbHandler_ScanResults()->getQuerySelector();
257
+
258
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Databases\Scanner\EntryVO[] $aPtgResults */
259
+ $aPtgResults = $oSelector->filterByNotIgnored()
260
+ ->filterByScan( 'ptg' )
261
+ ->query();
262
+ /** @var Shield\Scans\Ptg\ResultsSet $oFullResults */
263
+ $oFullResults = ( new Shield\Modules\HackGuard\Scan\Results\ConvertBetweenTypes() )
264
+ ->setScanController( $oMod->getScanCon( 'ptg' ) )
265
+ ->fromVOsToResultsSet( $aPtgResults );
266
+
267
+ // Process Plugins
268
+ $aPlugins = $oFullResults->getAllResultsSetsForPluginsContext();
269
+ $oWpPlugins = Services::WpPlugins();
270
+ foreach ( $aPlugins as $sSlug => $oItemRS ) {
271
+ $aItems = $oItemRS->getAllItems();
272
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg\ResultItem $oIT */
273
+ $oIT = array_pop( $aItems );
274
+ $aMeta = $oProPtg->getSnapshotItemMeta( $oIT->slug );
275
+ if ( !empty( $aMeta[ 'ts' ] ) ) {
276
+ $aMeta[ 'ts' ] = $oReq->carbon()->setTimestamp( $aMeta[ 'ts' ] )->diffForHumans();
277
+ }
278
+ else {
279
+ $aMeta[ 'ts' ] = __( 'unknown', 'wp-simple-firewall' );
280
+ }
281
+
282
+ $bInstalled = $oWpPlugins->isInstalled( $oIT->slug );
283
+ $oPlgn = $oWpPlugins->getPluginAsVo( $oIT->slug );
284
+ $bIsWpOrg = $bInstalled && $oPlgn instanceof WpPluginVo && $oPlgn->isWpOrg();
285
+ $bHasUpdate = $bIsWpOrg && $oPlgn->hasUpdate();
286
+ $aProfile = [
287
+ 'id' => $oSelector->filterByHash( $oIT->hash )->first()->id,
288
+ 'name' => __( 'unknown', 'wp-simple-firewall' ),
289
+ 'version' => __( 'unknown', 'wp-simple-firewall' ),
290
+ 'root_dir' => $oWpPlugins->getInstallationDir( $oIT->slug ),
291
+ 'slug' => $sSlug,
292
+ 'is_wporg' => $bIsWpOrg,
293
+ 'can_reinstall' => $bIsWpOrg,
294
+ 'can_deactivate' => $bInstalled && ( $sSlug !== $this->getCon()->getPluginBaseFile() ),
295
+ 'has_update' => $bHasUpdate,
296
+ 'count_files' => $oItemRS->countItems(),
297
+ 'date_snapshot' => $aMeta[ 'ts' ],
298
+ ];
299
+
300
+ if ( $bInstalled ) {
301
+ $oP = $oWpPlugins->getPluginAsVo( $oIT->slug );
302
+ $aProfile[ 'name' ] = $oP->Name;
303
+ $aProfile[ 'version' ] = $oP->Version;
304
+ }
305
+ else {
306
+ // MISSING!
307
+ if ( is_array( $aMeta ) ) {
308
+ $aProfile[ 'name' ] = isset( $aMeta[ 'name' ] ) ? $aMeta[ 'name' ] : __( 'unknown', 'wp-simple-firewall' );
309
+ $aProfile[ 'version' ] = isset( $aMeta[ 'version' ] ) ? $aMeta[ 'version' ] : __( 'unknown', 'wp-simple-firewall' );
310
+ }
311
+ }
312
+ $aProfile[ 'name' ] = sprintf( '%s: %s', __( 'Plugin' ), $aProfile[ 'name' ] );
313
+
314
+ $aPlugins[ $sSlug ] = $aProfile;
315
+ }
316
+
317
+ // Process Themes
318
+ $aThemes = $oFullResults->getAllResultsSetsForThemesContext();
319
+ $oWpThemes = Services::WpThemes();
320
+ foreach ( $aThemes as $sSlug => $oItemRS ) {
321
+ $aItems = $oItemRS->getAllItems();
322
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Scans\Ptg\ResultItem $oIT */
323
+ $oIT = array_pop( $aItems );
324
+ $aMeta = $oProPtg->getSnapshotItemMeta( $oIT->slug );
325
+ if ( !empty( $aMeta[ 'ts' ] ) ) {
326
+ $aMeta[ 'ts' ] = $oReq->carbon()->setTimestamp( $aMeta[ 'ts' ] )->diffForHumans();
327
+ }
328
+ else {
329
+ $aMeta[ 'ts' ] = __( 'unknown', 'wp-simple-firewall' );
330
+ }
331
+
332
+ $bInstalled = $oWpThemes->isInstalled( $oIT->slug );
333
+ $bIsWpOrg = $bInstalled && $oWpThemes->isWpOrg( $sSlug );
334
+ $bHasUpdate = $bIsWpOrg && $oWpThemes->isUpdateAvailable( $sSlug );
335
+ $aProfile = [
336
+ 'id' => $oSelector->filterByHash( $oIT->hash )->first()->id,
337
+ 'name' => __( 'unknown', 'wp-simple-firewall' ),
338
+ 'version' => __( 'unknown', 'wp-simple-firewall' ),
339
+ 'root_dir' => __( 'unknown', 'wp-simple-firewall' ),
340
+ 'slug' => $sSlug,
341
+ 'is_wporg' => $bIsWpOrg,
342
+ 'can_reinstall' => $bIsWpOrg,
343
+ 'can_deactivate' => false,
344
+ 'has_update' => $bHasUpdate,
345
+ 'count_files' => $oItemRS->countItems(),
346
+ 'date_snapshot' => $aMeta[ 'ts' ],
347
+ ];
348
+ if ( $bInstalled ) {
349
+ $oT = $oWpThemes->getTheme( $oIT->slug );
350
+ $aProfile[ 'name' ] = $oT->get( 'Name' );
351
+ $aProfile[ 'version' ] = $oT->get( 'Version' );
352
+ $aProfile[ 'root_dir' ] = $oWpThemes->getInstallationDir( $oIT->slug );
353
+ }
354
+ $aProfile[ 'name' ] = sprintf( '%s: %s', __( 'Theme' ), $aProfile[ 'name' ] );
355
+
356
+ $aThemes[ $sSlug ] = $aProfile;
357
+ }
358
+
359
+ return [
360
+ 'flags' => [
361
+ 'has_items' => $oMod->isPtgEnabled() ? $oFullResults->hasItems() : false,
362
+ 'has_plugins' => !empty( $aPlugins ),
363
+ 'has_themes' => !empty( $aThemes ),
364
+ 'show_table' => false,
365
+ ],
366
+ 'hrefs' => [],
367
+ 'vars' => [],
368
+ 'assets' => $oMod->isPtgEnabled() ? array_merge( $aPlugins, $aThemes ) : [],
369
+ 'strings' => [
370
+ 'subtitle' => __( "Detects unauthorized changes to plugins/themes", 'wp-simple-firewall' ),
371
+ 'files_with_problems' => __( 'Files with problems', 'wp-simple-firewall' ),
372
+ 'root_dir' => __( 'Root directory', 'wp-simple-firewall' ),
373
+ 'date_snapshot' => __( 'Snapshot taken', 'wp-simple-firewall' ),
374
+ 'reinstall' => __( 'Re-Install', 'wp-simple-firewall' ),
375
+ 'deactivate' => __( 'Deactivate and Ignore', 'wp-simple-firewall' ),
376
+ 'accept' => __( 'Accept', 'wp-simple-firewall' ),
377
+ 'update' => __( 'Upgrade', 'wp-simple-firewall' ),
378
+ ]
379
+ ];
380
+ }
381
+
382
+ /**
383
+ * @return array
384
+ */
385
+ public function getInsightsConfigCardData() {
386
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
387
+ $mod = $this->getMod();
388
+ /** @var Options $opts */
389
+ $opts = $this->getOptions();
390
+ $aScanNames = $mod->getStrings()->getScanNames();
391
+
392
+ $data = [
393
+ 'strings' => [
394
+ 'title' => __( 'Hack Guard', 'wp-simple-firewall' ),
395
+ 'sub' => __( 'Threats/Intrusions Detection & Repair', 'wp-simple-firewall' ),
396
+ ],
397
+ 'key_opts' => [],
398
+ 'href_options' => $mod->getUrl_AdminPage()
399
+ ];
400
+
401
+ if ( !$mod->isModOptEnabled() ) {
402
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
403
+ }
404
+ else {
405
+ $bGoodFrequency = $opts->getScanFrequency() > 1;
406
+ $data[ 'key_opts' ][ 'frequency' ] = [
407
+ 'name' => __( 'Scan Frequency', 'wp-simple-firewall' ),
408
+ 'enabled' => $bGoodFrequency,
409
+ 'summary' => $bGoodFrequency ?
410
+ __( 'Automatic scanners run more than once per day', 'wp-simple-firewall' )
411
+ : __( "Automatic scanners only run once per day", 'wp-simple-firewall' ),
412
+ 'weight' => 1,
413
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_options' ),
414
+ ];
415
+
416
+ $bCore = $mod->getScanCon( 'wcf' )->isEnabled();
417
+ $data[ 'key_opts' ][ 'wcf' ] = [
418
+ 'name' => __( 'WP Core File Scan', 'wp-simple-firewall' ),
419
+ 'enabled' => $bCore,
420
+ 'summary' => $bCore ?
421
+ __( 'Core files scanned regularly for hacks', 'wp-simple-firewall' )
422
+ : __( "Core files are never scanned for hacks!", 'wp-simple-firewall' ),
423
+ 'weight' => 2,
424
+ 'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
425
+ ];
426
+ if ( $bCore && !$opts->isRepairFileWP() ) {
427
+ $data[ 'key_opts' ][ 'wcf_repair' ] = [
428
+ 'name' => __( 'WP Core File Repair', 'wp-simple-firewall' ),
429
+ 'enabled' => $opts->isRepairFileWP(),
430
+ 'summary' => $opts->isRepairFileWP() ?
431
+ __( 'Core files are automatically repaired', 'wp-simple-firewall' )
432
+ : __( "Core files aren't automatically repaired!", 'wp-simple-firewall' ),
433
+ 'weight' => 1,
434
+ 'href' => $mod->getUrl_DirectLinkToOption( 'file_repair_areas' ),
435
+ ];
436
+ }
437
+
438
+ $bUcf = $mod->getScanCon( 'ufc' )->isEnabled();
439
+ $data[ 'key_opts' ][ 'ufc' ] = [
440
+ 'name' => __( 'Unrecognised Files', 'wp-simple-firewall' ),
441
+ 'enabled' => $bUcf,
442
+ 'summary' => $bUcf ?
443
+ __( 'Core directories scanned regularly for unrecognised files', 'wp-simple-firewall' )
444
+ : __( "WP Core is never scanned for unrecognised files!", 'wp-simple-firewall' ),
445
+ 'weight' => 2,
446
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
447
+ ];
448
+ if ( $bUcf && !$opts->isUfsDeleteFiles() ) {
449
+ $data[ 'key_opts' ][ 'ufc_repair' ] = [
450
+ 'name' => __( 'Unrecognised Files Removal', 'wp-simple-firewall' ),
451
+ 'enabled' => $opts->isUfsDeleteFiles(),
452
+ 'summary' => $opts->isUfsDeleteFiles() ?
453
+ __( 'Unrecognised files are automatically removed', 'wp-simple-firewall' )
454
+ : __( "Unrecognised files aren't automatically removed!", 'wp-simple-firewall' ),
455
+ 'weight' => 1,
456
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
457
+ ];
458
+ }
459
+
460
+ $bWpv = $mod->getScanCon( 'wpv' )->isEnabled();
461
+ $data[ 'key_opts' ][ 'wpv' ] = [
462
+ 'name' => __( 'Vulnerability Scan', 'wp-simple-firewall' ),
463
+ 'enabled' => $bWpv,
464
+ 'summary' => $bWpv ?
465
+ __( 'Regularly scanning for known vulnerabilities', 'wp-simple-firewall' )
466
+ : __( "Plugins/Themes never scanned for vulnerabilities!", 'wp-simple-firewall' ),
467
+ 'weight' => 2,
468
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
469
+ ];
470
+ $bWpvAutoUpdates = $opts->isWpvulnAutoupdatesEnabled();
471
+ if ( $bWpv && !$bWpvAutoUpdates ) {
472
+ $data[ 'key_opts' ][ 'wpv_repair' ] = [
473
+ 'name' => __( 'Auto Update', 'wp-simple-firewall' ),
474
+ 'enabled' => $bWpvAutoUpdates,
475
+ 'summary' => $bWpvAutoUpdates ?
476
+ __( 'Vulnerable items are automatically updated', 'wp-simple-firewall' )
477
+ : __( "Vulnerable items aren't automatically updated!", 'wp-simple-firewall' ),
478
+ 'weight' => 1,
479
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
480
+ ];
481
+ }
482
+
483
+ $bPtg = $mod->getScanCon( 'ptg' )->isEnabled();
484
+ $data[ 'key_opts' ][ 'ptg' ] = [
485
+ 'title' => $aScanNames[ 'ptg' ],
486
+ 'name' => __( 'Plugin/Theme Guard', 'wp-simple-firewall' ),
487
+ 'enabled' => $bPtg,
488
+ 'summary' => $bPtg ?
489
+ __( 'Plugins and Themes are guarded against tampering', 'wp-simple-firewall' )
490
+ : __( "Plugins and Themes are never scanned for tampering!", 'wp-simple-firewall' ),
491
+ 'weight' => 2,
492
+ 'href' => $mod->getUrl_DirectLinkToOption( 'ptg_enable' ),
493
+ ];
494
+
495
+ $bMal = $mod->getScanCon( 'mal' )->isEnabled();
496
+ $data[ 'key_opts' ][ 'mal' ] = [
497
+ 'title' => $aScanNames[ 'mal' ],
498
+ 'name' => $aScanNames[ 'mal' ],
499
+ 'enabled' => $bMal,
500
+ 'summary' => $bMal ?
501
+ sprintf( __( '%s Scanner is enabled.' ), $aScanNames[ 'mal' ] )
502
+ : sprintf( __( '%s Scanner is not enabled.' ), $aScanNames[ 'mal' ] ),
503
+ 'weight' => 2,
504
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_mal' ),
505
+ ];
506
+
507
+ $bApc = $mod->getScanCon( 'apc' )->isEnabled();
508
+ $data[ 'key_opts' ][ 'apc' ] = [
509
+ 'title' => $aScanNames[ 'apc' ],
510
+ 'name' => $aScanNames[ 'apc' ],
511
+ 'enabled' => $bApc,
512
+ 'summary' => $bApc ?
513
+ sprintf( __( '%s Scanner is enabled.' ), $aScanNames[ 'apc' ] )
514
+ : sprintf( __( '%s Scanner is not enabled.' ), $aScanNames[ 'apc' ] ),
515
+ 'weight' => 2,
516
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_apc' ),
517
+ ];
518
+ }
519
+
520
+ return $data;
521
+ }
522
+
523
+ /**
524
+ * @return array
525
+ */
526
+ public function getInsightsNoticesData() {
527
+ /** @var \ICWP_WPSF_FeatureHandler_HackProtect $mod */
528
+ $mod = $this->getMod();
529
+ /** @var Strings $oStrings */
530
+ $oStrings = $mod->getStrings();
531
+ $aScanNames = $oStrings->getScanNames();
532
+
533
+ $notices = [
534
+ 'title' => __( 'Scans', 'wp-simple-firewall' ),
535
+ 'messages' => []
536
+ ];
537
+
538
+ $sScansUrl = $this->getCon()->getModule_Insights()->getUrl_SubInsightsPage( 'scans' );
539
+
540
+ {// Malware
541
+ $scan = $mod->getScanCon( 'mal' );
542
+ if ( !$scan->isEnabled() ) {
543
+ $notices[ 'messages' ][ 'mal' ] = [
544
+ 'title' => $aScanNames[ 'mal' ],
545
+ 'message' => sprintf( __( '%s Scanner is not enabled.' ), $aScanNames[ 'mal' ] ),
546
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_mal' ),
547
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
548
+ 'rec' => __( 'Automatic detection of Malware is recommended.', 'wp-simple-firewall' )
549
+ ];
550
+ }
551
+ elseif ( $scan->getScanHasProblem() ) {
552
+ $notices[ 'messages' ][ 'mal' ] = [
553
+ 'title' => $aScanNames[ 'mal' ],
554
+ 'message' => __( 'At least 1 file with potential Malware has been discovered.', 'wp-simple-firewall' ),
555
+ 'href' => $sScansUrl,
556
+ 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
557
+ 'rec' => __( 'Files identified as potential malware should be examined as soon as possible.', 'wp-simple-firewall' )
558
+ ];
559
+ }
560
+ }
561
+
562
+ {// Core files
563
+ $scan = $mod->getScanCon( 'wcf' );
564
+ if ( !$scan->isEnabled() ) {
565
+ $notices[ 'messages' ][ 'wcf' ] = [
566
+ 'title' => $aScanNames[ 'wcf' ],
567
+ 'message' => __( 'Core File scanner is not enabled.', 'wp-simple-firewall' ),
568
+ 'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
569
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
570
+ 'rec' => __( 'Automatic WordPress Core File scanner should be turned-on.', 'wp-simple-firewall' )
571
+ ];
572
+ }
573
+ elseif ( $scan->getScanHasProblem() ) {
574
+ $notices[ 'messages' ][ 'wcf' ] = [
575
+ 'title' => $aScanNames[ 'wcf' ],
576
+ 'message' => __( 'Modified WordPress core files found.', 'wp-simple-firewall' ),
577
+ 'href' => $sScansUrl,
578
+ 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
579
+ 'rec' => __( 'Scan WP core files and repair any files that are flagged as modified.', 'wp-simple-firewall' )
580
+ ];
581
+ }
582
+ }
583
+
584
+ {// Unrecognised
585
+ $scan = $mod->getScanCon( 'ufc' );
586
+ if ( !$scan->isEnabled() ) {
587
+ $notices[ 'messages' ][ 'ufc' ] = [
588
+ 'title' => $aScanNames[ 'ufc' ],
589
+ 'message' => __( 'Unrecognised File scanner is not enabled.', 'wp-simple-firewall' ),
590
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_ufc' ),
591
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
592
+ 'rec' => __( 'Automatic scanning for non-WordPress core files is recommended.', 'wp-simple-firewall' )
593
+ ];
594
+ }
595
+ elseif ( $scan->getScanHasProblem() ) {
596
+ $notices[ 'messages' ][ 'ufc' ] = [
597
+ 'title' => $aScanNames[ 'ufc' ],
598
+ 'message' => __( 'Unrecognised files found in WordPress Core directory.', 'wp-simple-firewall' ),
599
+ 'href' => $sScansUrl,
600
+ 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
601
+ 'rec' => __( 'Scan and remove any files that are not meant to be in the WP core directories.', 'wp-simple-firewall' )
602
+ ];
603
+ }
604
+ }
605
+
606
+ {// Plugin/Theme Guard
607
+ $scan = $mod->getScanCon( 'ptg' );
608
+ if ( !$scan->isEnabled() ) {
609
+ $notices[ 'messages' ][ 'ptg' ] = [
610
+ 'title' => $aScanNames[ 'ptg' ],
611
+ 'message' => __( 'Automatic Plugin/Themes Guard is not enabled.', 'wp-simple-firewall' ),
612
+ 'href' => $mod->getUrl_DirectLinkToOption( 'ptg_enable' ),
613
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
614
+ 'rec' => __( 'Automatic detection of plugin/theme modifications is recommended.', 'wp-simple-firewall' )
615
+ ];
616
+ }
617
+ elseif ( $scan->getScanHasProblem() ) {
618
+ $notices[ 'messages' ][ 'ptg' ] = [
619
+ 'title' => $aScanNames[ 'ptg' ],
620
+ 'message' => __( 'A plugin/theme was found to have been modified.', 'wp-simple-firewall' ),
621
+ 'href' => $sScansUrl,
622
+ 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
623
+ 'rec' => __( 'Reviewing modifications to your plugins/themes is recommended.', 'wp-simple-firewall' )
624
+ ];
625
+ }
626
+ }
627
+
628
+ {// Vulnerability Scanner
629
+ $scan = $mod->getScanCon( 'wpv' );
630
+ if ( !$scan->isEnabled() ) {
631
+ $notices[ 'messages' ][ 'wpv' ] = [
632
+ 'title' => $aScanNames[ 'wpv' ],
633
+ 'message' => __( 'Vulnerability Scanner is not enabled.', 'wp-simple-firewall' ),
634
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_wpv' ),
635
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
636
+ 'rec' => __( 'Automatic detection of vulnerabilities is recommended.', 'wp-simple-firewall' )
637
+ ];
638
+ }
639
+ elseif ( $scan->getScanHasProblem() ) {
640
+ $notices[ 'messages' ][ 'wpv' ] = [
641
+ 'title' => $aScanNames[ 'wpv' ],
642
+ 'message' => __( 'At least 1 item has known vulnerabilities.', 'wp-simple-firewall' ),
643
+ 'href' => $sScansUrl,
644
+ 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
645
+ 'rec' => __( 'Items with known vulnerabilities should be updated, removed, or replaced.', 'wp-simple-firewall' )
646
+ ];
647
+ }
648
+ }
649
+
650
+ {// Abandoned Plugins
651
+ $scan = $mod->getScanCon( 'apc' );
652
+ if ( !$scan->isEnabled() ) {
653
+ $notices[ 'messages' ][ 'apc' ] = [
654
+ 'title' => $aScanNames[ 'apc' ],
655
+ 'message' => __( 'Abandoned Plugins Scanner is not enabled.', 'wp-simple-firewall' ),
656
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_apc' ),
657
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
658
+ 'rec' => __( 'Automatic detection of abandoned plugins is recommended.', 'wp-simple-firewall' )
659
+ ];
660
+ }
661
+ elseif ( $scan->getScanHasProblem() ) {
662
+ $notices[ 'messages' ][ 'apc' ] = [
663
+ 'title' => $aScanNames[ 'apc' ],
664
+ 'message' => __( 'At least 1 plugin on your site is abandoned.', 'wp-simple-firewall' ),
665
+ 'href' => $sScansUrl,
666
+ 'action' => __( 'Run Scan', 'wp-simple-firewall' ),
667
+ 'rec' => __( 'Plugins that have been abandoned represent a potential risk to your site.', 'wp-simple-firewall' )
668
+ ];
669
+ }
670
+ }
671
+
672
+ return $notices;
673
+ }
674
+
675
+ /**
676
+ * @param string $section
677
+ * @return array
678
+ */
679
+ protected function getSectionWarnings( $section ) {
680
+ $aWarnings = [];
681
+
682
+ switch ( $section ) {
683
+
684
+ case 'section_realtime':
685
+ $bCanHandshake = $this->getCon()
686
+ ->getModule_Plugin()
687
+ ->getShieldNetApiController()
688
+ ->canHandshake();
689
+ if ( !$bCanHandshake ) {
690
+ $aWarnings[] = sprintf( __( 'Not available as your site cannot handshake with ShieldNET API.', 'wp-simple-firewall' ), 'OpenSSL' );
691
+ }
692
+ // if ( !Services::Encrypt()->isSupportedOpenSslDataEncryption() ) {
693
+ // $aWarnings[] = sprintf( __( 'Not available because the %s extension is not available.', 'wp-simple-firewall' ), 'OpenSSL' );
694
+ // }
695
+ // if ( !Services::WpFs()->isFilesystemAccessDirect() ) {
696
+ // $aWarnings[] = sprintf( __( "Not available because PHP/WordPress doesn't have direct filesystem access.", 'wp-simple-firewall' ), 'OpenSSL' );
697
+ // }
698
+ break;
699
+ }
700
+
701
+ return $aWarnings;
702
+ }
703
+ }
src/lib/src/Modules/Headers/Strings.php CHANGED
@@ -7,13 +7,13 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
7
  class Strings extends Base\Strings {
8
 
9
  /**
10
- * @param string $sSectionSlug
11
  * @return array
12
  * @throws \Exception
13
  */
14
- public function getSectionStrings( $sSectionSlug ) {
15
 
16
- switch ( $sSectionSlug ) {
17
 
18
  case 'section_enable_plugin_feature_headers' :
19
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -44,7 +44,7 @@ class Strings extends Base\Strings {
44
  break;
45
 
46
  default:
47
- return parent::getSectionStrings( $sSectionSlug );
48
  }
49
 
50
  return [
@@ -55,14 +55,14 @@ class Strings extends Base\Strings {
55
  }
56
 
57
  /**
58
- * @param string $sOptKey
59
  * @return array
60
  * @throws \Exception
61
  */
62
- public function getOptionStrings( $sOptKey ) {
63
  $sModName = $this->getMod()->getMainFeatureName();
64
 
65
- switch ( $sOptKey ) {
66
 
67
  case 'enable_headers' :
68
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -149,7 +149,7 @@ class Strings extends Base\Strings {
149
  break;
150
 
151
  default:
152
- return parent::getOptionStrings( $sOptKey );
153
  }
154
 
155
  return [
7
  class Strings extends Base\Strings {
8
 
9
  /**
10
+ * @param string $section
11
  * @return array
12
  * @throws \Exception
13
  */
14
+ public function getSectionStrings( $section ) {
15
 
16
+ switch ( $section ) {
17
 
18
  case 'section_enable_plugin_feature_headers' :
19
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
44
  break;
45
 
46
  default:
47
+ return parent::getSectionStrings( $section );
48
  }
49
 
50
  return [
55
  }
56
 
57
  /**
58
+ * @param string $key
59
  * @return array
60
  * @throws \Exception
61
  */
62
+ public function getOptionStrings( $key ) {
63
  $sModName = $this->getMod()->getMainFeatureName();
64
 
65
+ switch ( $key ) {
66
 
67
  case 'enable_headers' :
68
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
149
  break;
150
 
151
  default:
152
+ return parent::getOptionStrings( $key );
153
  }
154
 
155
  return [
src/lib/src/Modules/Headers/UI.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Headers;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class UI extends Base\ShieldUI {
8
+
9
+ /**
10
+ * @return array
11
+ */
12
+ public function getInsightsConfigCardData() {
13
+ /** @var \ICWP_WPSF_FeatureHandler_Headers $mod */
14
+ $mod = $this->getMod();
15
+ /** @var Options $opts */
16
+ $opts = $this->getOptions();
17
+
18
+ $data = [
19
+ 'strings' => [
20
+ 'title' => __( 'HTTP Security Headers', 'wp-simple-firewall' ),
21
+ 'sub' => __( 'Protect Visitors With Powerful HTTP Headers', 'wp-simple-firewall' ),
22
+ ],
23
+ 'key_opts' => [],
24
+ 'href_options' => $mod->getUrl_AdminPage()
25
+ ];
26
+
27
+ if ( !$mod->isModOptEnabled() ) {
28
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
29
+ }
30
+ else {
31
+ $bAllEnabled = $opts->isEnabledXFrame() && $opts->isEnabledXssProtection()
32
+ && $opts->isEnabledContentTypeHeader() && $opts->isReferrerPolicyEnabled();
33
+ $data[ 'key_opts' ][ 'all' ] = [
34
+ 'name' => __( 'HTTP Headers', 'wp-simple-firewall' ),
35
+ 'enabled' => $bAllEnabled,
36
+ 'summary' => $bAllEnabled ?
37
+ __( 'All important security Headers have been set', 'wp-simple-firewall' )
38
+ : __( "At least one of the HTTP Headers hasn't been set", 'wp-simple-firewall' ),
39
+ 'weight' => 2,
40
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_security_headers' ),
41
+ ];
42
+ $bCsp = $opts->isEnabledContentSecurityPolicy();
43
+ $data[ 'key_opts' ][ 'csp' ] = [
44
+ 'name' => __( 'Content Security Policies', 'wp-simple-firewall' ),
45
+ 'enabled' => $bCsp,
46
+ 'summary' => $bCsp ?
47
+ __( 'Content Security Policy is turned on', 'wp-simple-firewall' )
48
+ : __( "Content Security Policies aren't active", 'wp-simple-firewall' ),
49
+ 'weight' => 1,
50
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_content_security_policy' ),
51
+ ];
52
+ }
53
+
54
+ return $data;
55
+ }
56
+ }
src/lib/src/Modules/IPs/AjaxHandler.php CHANGED
@@ -8,12 +8,12 @@ use FernleafSystems\Wordpress\Services\Services;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
- * @param string $sAction
12
  * @return array
13
  */
14
- protected function processAjaxAction( $sAction ) {
15
 
16
- switch ( $sAction ) {
17
  case 'ip_insert':
18
  $aResponse = $this->ajaxExec_AddIp();
19
  break;
@@ -27,7 +27,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
27
  break;
28
 
29
  default:
30
- $aResponse = parent::processAjaxAction( $sAction );
31
  }
32
 
33
  return $aResponse;
@@ -37,8 +37,8 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
37
  * @return array
38
  */
39
  private function ajaxExec_AddIp() {
40
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
41
- $oMod = $this->getMod();
42
  $oIpServ = Services::IP();
43
 
44
  $aFormParams = $this->getAjaxFormParams();
@@ -53,7 +53,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
53
  || $oIpServ->isValidIp4Range( $sIp )
54
  || $oIpServ->isValidIp6Range( $sIp );
55
 
56
- $bIsBlackList = $sList != $oMod::LIST_MANUAL_WHITE;
57
 
58
  // TODO: Bring this IP verification out of here and make it more accessible
59
  if ( empty( $sIp ) ) {
@@ -65,7 +65,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
65
  elseif ( !$bAcceptableIp ) {
66
  $sMessage = __( "IP address isn't either a valid IP or a CIDR range", 'wp-simple-firewall' );
67
  }
68
- elseif ( $bIsBlackList && !$oMod->isPremium() ) {
69
  $sMessage = __( "Please upgrade to Pro if you'd like to add IPs to the black list manually.", 'wp-simple-firewall' );
70
  }
71
  elseif ( $bIsBlackList && $oIpServ->checkIp( $oIpServ->getRequestIp(), $sIp ) ) {
@@ -78,10 +78,10 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
78
  $sLabel = isset( $aFormParams[ 'label' ] ) ? $aFormParams[ 'label' ] : '';
79
  $oIP = null;
80
  switch ( $sList ) {
81
- case $oMod::LIST_MANUAL_WHITE:
82
  try {
83
  $oIP = ( new Shield\Modules\IPs\Lib\Ops\AddIp() )
84
- ->setMod( $oMod )
85
  ->setIP( $sIp )
86
  ->toManualWhitelist( $sLabel );
87
  }
@@ -89,10 +89,10 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
89
  }
90
  break;
91
 
92
- case $oMod::LIST_MANUAL_BLACK:
93
  try {
94
  $oIP = ( new Shield\Modules\IPs\Lib\Ops\AddIp() )
95
- ->setMod( $oMod )
96
  ->setIP( $sIp )
97
  ->toManualBlacklist( $sLabel );
98
  }
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
+ * @param string $action
12
  * @return array
13
  */
14
+ protected function processAjaxAction( $action ) {
15
 
16
+ switch ( $action ) {
17
  case 'ip_insert':
18
  $aResponse = $this->ajaxExec_AddIp();
19
  break;
27
  break;
28
 
29
  default:
30
+ $aResponse = parent::processAjaxAction( $action );
31
  }
32
 
33
  return $aResponse;
37
  * @return array
38
  */
39
  private function ajaxExec_AddIp() {
40
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
41
+ $mod = $this->getMod();
42
  $oIpServ = Services::IP();
43
 
44
  $aFormParams = $this->getAjaxFormParams();
53
  || $oIpServ->isValidIp4Range( $sIp )
54
  || $oIpServ->isValidIp6Range( $sIp );
55
 
56
+ $bIsBlackList = $sList != $mod::LIST_MANUAL_WHITE;
57
 
58
  // TODO: Bring this IP verification out of here and make it more accessible
59
  if ( empty( $sIp ) ) {
65
  elseif ( !$bAcceptableIp ) {
66
  $sMessage = __( "IP address isn't either a valid IP or a CIDR range", 'wp-simple-firewall' );
67
  }
68
+ elseif ( $bIsBlackList && !$mod->isPremium() ) {
69
  $sMessage = __( "Please upgrade to Pro if you'd like to add IPs to the black list manually.", 'wp-simple-firewall' );
70
  }
71
  elseif ( $bIsBlackList && $oIpServ->checkIp( $oIpServ->getRequestIp(), $sIp ) ) {
78
  $sLabel = isset( $aFormParams[ 'label' ] ) ? $aFormParams[ 'label' ] : '';
79
  $oIP = null;
80
  switch ( $sList ) {
81
+ case $mod::LIST_MANUAL_WHITE:
82
  try {
83
  $oIP = ( new Shield\Modules\IPs\Lib\Ops\AddIp() )
84
+ ->setMod( $mod )
85
  ->setIP( $sIp )
86
  ->toManualWhitelist( $sLabel );
87
  }
89
  }
90
  break;
91
 
92
+ case $mod::LIST_MANUAL_BLACK:
93
  try {
94
  $oIP = ( new Shield\Modules\IPs\Lib\Ops\AddIp() )
95
+ ->setMod( $mod )
96
  ->setIP( $sIp )
97
  ->toManualBlacklist( $sLabel );
98
  }
src/lib/src/Modules/IPs/BotTrack/TrackLinkCheese.php CHANGED
@@ -30,28 +30,27 @@ class TrackLinkCheese extends Base {
30
  $sTempl = Services::WpGeneral()->isPermalinksEnabled() ? "Disallow: /%s-*/\n" : "Disallow: /*?*%s=\n";
31
  $sRobotsText = rtrim( $sRobotsText, "\n" )."\n";
32
  foreach ( $this->getPossibleWords() as $sWord ) {
33
- $sRobotsText .= sprintf( $sTempl, $this->getMod()->prefix( $sWord ) );
34
  }
35
  return $sRobotsText;
36
  }
37
 
38
  private function isCheese() {
39
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oFO */
40
- $oFO = $this->getMod();
41
- $oReq = Services::Request();
42
 
43
  $bIsCheese = false;
44
  if ( Services::WpGeneral()->isPermalinksEnabled() ) {
45
  preg_match(
46
- sprintf( '#^%s-(%s)-([a-z0-9]{7,9})$#i', $oFO->prefix(), implode( '|', $this->getPossibleWords() ) ),
47
- trim( $oReq->getPath(), '/' ),
48
  $aMatches
49
  );
50
  $bIsCheese = isset( $aMatches[ 2 ] );
51
  }
52
  else {
53
  foreach ( $this->getPossibleWords() as $sWord ) {
54
- if ( preg_match( '#^[a-z0-9]{7,9}$#i', $oReq->query( $oFO->prefix( $sWord ) ) ) ) {
55
  $bIsCheese = true;
56
  break;
57
  }
@@ -74,17 +73,16 @@ class TrackLinkCheese extends Base {
74
  * @return string
75
  */
76
  private function buildTrapHref() {
77
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oFO */
78
- $oFO = $this->getMod();
79
 
80
- $oWp = Services::WpGeneral();
81
  $sKey = substr( md5( wp_generate_password() ), 5, rand( 7, 9 ) );
82
  $sWord = $this->getPossibleWords()[ rand( 1, count( $this->getPossibleWords() ) ) - 1 ];
83
- if ( $oWp->isPermalinksEnabled() ) {
84
- $sLink = $oWp->getHomeUrl( sprintf( '/%s-%s/', $oFO->prefix( $sWord ), $sKey ) );
85
  }
86
  else {
87
- $sLink = add_query_arg( [ $oFO->prefix( $sWord ) => $sKey ], $oWp->getHomeUrl() );
88
  }
89
  return $sLink;
90
  }
30
  $sTempl = Services::WpGeneral()->isPermalinksEnabled() ? "Disallow: /%s-*/\n" : "Disallow: /*?*%s=\n";
31
  $sRobotsText = rtrim( $sRobotsText, "\n" )."\n";
32
  foreach ( $this->getPossibleWords() as $sWord ) {
33
+ $sRobotsText .= sprintf( $sTempl, $this->getCon()->prefix( $sWord ) );
34
  }
35
  return $sRobotsText;
36
  }
37
 
38
  private function isCheese() {
39
+ $con = $this->getCon();
40
+ $req = Services::Request();
 
41
 
42
  $bIsCheese = false;
43
  if ( Services::WpGeneral()->isPermalinksEnabled() ) {
44
  preg_match(
45
+ sprintf( '#^%s-(%s)-([a-z0-9]{7,9})$#i', $con->prefix(), implode( '|', $this->getPossibleWords() ) ),
46
+ trim( $req->getPath(), '/' ),
47
  $aMatches
48
  );
49
  $bIsCheese = isset( $aMatches[ 2 ] );
50
  }
51
  else {
52
  foreach ( $this->getPossibleWords() as $sWord ) {
53
+ if ( preg_match( '#^[a-z0-9]{7,9}$#i', $req->query( $con->prefix( $sWord ) ) ) ) {
54
  $bIsCheese = true;
55
  break;
56
  }
73
  * @return string
74
  */
75
  private function buildTrapHref() {
76
+ $con = $this->getCon();
 
77
 
78
+ $oWP = Services::WpGeneral();
79
  $sKey = substr( md5( wp_generate_password() ), 5, rand( 7, 9 ) );
80
  $sWord = $this->getPossibleWords()[ rand( 1, count( $this->getPossibleWords() ) ) - 1 ];
81
+ if ( $oWP->isPermalinksEnabled() ) {
82
+ $sLink = $oWP->getHomeUrl( sprintf( '/%s-%s/', $con->prefix( $sWord ), $sKey ) );
83
  }
84
  else {
85
+ $sLink = add_query_arg( [ $con->prefix( $sWord ) => $sKey ], $oWP->getHomeUrl() );
86
  }
87
  return $sLink;
88
  }
src/lib/src/Modules/IPs/BotTrack/TrackLoginFailed.php CHANGED
@@ -29,7 +29,7 @@ class TrackLoginFailed extends Base {
29
 
30
  // Adds an extra message to login failed
31
  $oUser->add(
32
- $this->getMod()->prefix( 'transgression-warning' ),
33
  $this->getMod()->getTextOpt( 'text_loginfailed' )
34
  );
35
  }
29
 
30
  // Adds an extra message to login failed
31
  $oUser->add(
32
+ $this->getCon()->prefix( 'transgression-warning' ),
33
  $this->getMod()->getTextOpt( 'text_loginfailed' )
34
  );
35
  }
src/lib/src/Modules/IPs/Components/ProcessOffense.php CHANGED
@@ -16,18 +16,16 @@ class ProcessOffense {
16
  use Shield\Modules\ModConsumer;
17
  use IpAddressConsumer;
18
 
19
- /**
20
- */
21
  public function run() {
22
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
23
- $oMod = $this->getMod();
24
- $oCon = $this->getCon();
25
- /** @var IPs\Options $oOpts */
26
- $oOpts = $oMod->getOptions();
27
 
28
  try {
29
  $oIP = ( new IPs\Lib\Ops\AddIp() )
30
- ->setMod( $oMod )
31
  ->setIP( $this->getIP() )
32
  ->toAutoBlacklist();
33
  }
@@ -38,16 +36,16 @@ class ProcessOffense {
38
  if ( $oIP instanceof Databases\IPs\EntryVO ) {
39
  $nCurrent = $oIP->transgressions;
40
 
41
- $oTracker = $oMod->loadOffenseTracker();
42
  $nNewTotal = $oIP->transgressions + $oTracker->getOffenseCount();
43
  $bToBlock = $oTracker->isBlocked() ||
44
- ( $oIP->blocked_at == 0 && ( $nNewTotal >= $oOpts->getOffenseLimit() ) );
45
 
46
  /** @var Databases\IPs\Update $oUp */
47
- $oUp = $oMod->getDbHandler_IPs()->getQueryUpdater();
48
  $oUp->updateTransgressions( $oIP, $nNewTotal );
49
 
50
- $oCon->fireEvent( $bToBlock ? 'ip_blocked' : 'ip_offense',
51
  [
52
  'audit' => [
53
  'from' => $nCurrent,
@@ -62,9 +60,9 @@ class ProcessOffense {
62
  * so we fire ip_offense but suppress the audit
63
  */
64
  if ( $bToBlock ) {
65
- $oUp = $oMod->getDbHandler_IPs()->getQueryUpdater();
66
  $oUp->setBlocked( $oIP );
67
- $oCon->fireEvent( 'ip_offense', [ 'suppress_audit' => true ] );
68
  }
69
  }
70
  }
16
  use Shield\Modules\ModConsumer;
17
  use IpAddressConsumer;
18
 
 
 
19
  public function run() {
20
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
21
+ $mod = $this->getMod();
22
+ $con = $this->getCon();
23
+ /** @var IPs\Options $opts */
24
+ $opts = $this->getOptions();
25
 
26
  try {
27
  $oIP = ( new IPs\Lib\Ops\AddIp() )
28
+ ->setMod( $mod )
29
  ->setIP( $this->getIP() )
30
  ->toAutoBlacklist();
31
  }
36
  if ( $oIP instanceof Databases\IPs\EntryVO ) {
37
  $nCurrent = $oIP->transgressions;
38
 
39
+ $oTracker = $mod->loadOffenseTracker();
40
  $nNewTotal = $oIP->transgressions + $oTracker->getOffenseCount();
41
  $bToBlock = $oTracker->isBlocked() ||
42
+ ( $oIP->blocked_at == 0 && ( $nNewTotal >= $opts->getOffenseLimit() ) );
43
 
44
  /** @var Databases\IPs\Update $oUp */
45
+ $oUp = $mod->getDbHandler_IPs()->getQueryUpdater();
46
  $oUp->updateTransgressions( $oIP, $nNewTotal );
47
 
48
+ $con->fireEvent( $bToBlock ? 'ip_blocked' : 'ip_offense',
49
  [
50
  'audit' => [
51
  'from' => $nCurrent,
60
  * so we fire ip_offense but suppress the audit
61
  */
62
  if ( $bToBlock ) {
63
+ $oUp = $mod->getDbHandler_IPs()->getQueryUpdater();
64
  $oUp->setBlocked( $oIP );
65
+ $con->fireEvent( 'ip_offense', [ 'suppress_audit' => true ] );
66
  }
67
  }
68
  }
src/lib/src/Modules/IPs/Components/UnblockIpByMagicLink.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class UnblockIpByMagicLink {
10
+
11
+ use Shield\Modules\ModConsumer;
12
+
13
+ public function run() {
14
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
15
+ $oMod = $this->getMod();
16
+ $oFS = Services::WpFs();
17
+
18
+ $sPathUnblockFlag = $oFS->findFileInDir( 'unblock', $this->getCon()->getPath_Flags() );
19
+ if ( $oFS->isFile( $sPathUnblockFlag ) ) {
20
+ $sContent = $oFS->getFileContent( $sPathUnblockFlag );
21
+ if ( !empty( $sContent ) ) {
22
+
23
+ $aLines = array_map( 'trim', explode( "\n", $sContent ) );
24
+ foreach ( $aLines as $sIp ) {
25
+ $bRemoved = ( new IPs\Lib\Ops\DeleteIp() )
26
+ ->setDbHandler( $oMod->getDbHandler_IPs() )
27
+ ->setIP( $sIp )
28
+ ->fromBlacklist();
29
+ if ( $bRemoved ) {
30
+ $this->getCon()->fireEvent( 'ip_unblock_flag', [ 'audit' => [ 'ip' => $sIp ] ] );
31
+ }
32
+ }
33
+ }
34
+ $oFS->deleteFile( $sPathUnblockFlag );
35
+ }
36
+ }
37
+ }
src/lib/src/Modules/IPs/Lib/AutoUnblock.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class AutoUnblock {
10
+
11
+ use ModConsumer;
12
+
13
+ /**
14
+ * This should only be run if the current IP has been verified as being blocked
15
+ * @return bool - true if IP is unblocked, false otherwise.
16
+ */
17
+ public function run() {
18
+ try {
19
+ $bUnblocked = $this->processAutoUnblockRequest();
20
+ }
21
+ catch ( \Exception $oE ) {
22
+ $bUnblocked = false;
23
+ }
24
+ if ( !$bUnblocked ) {
25
+ try {
26
+ $bUnblocked = $this->processUserMagicLink();
27
+ }
28
+ catch ( \Exception $oE ) {
29
+ }
30
+ }
31
+ return $bUnblocked;
32
+ }
33
+
34
+ /**
35
+ * @return bool
36
+ * @throws \Exception
37
+ */
38
+ private function processAutoUnblockRequest() {
39
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
40
+ $mod = $this->getMod();
41
+ /** @var IPs\Options $opts */
42
+ $opts = $this->getOptions();
43
+ $req = Services::Request();
44
+
45
+ $unblocked = false;
46
+
47
+ if ( $opts->isEnabledAutoVisitorRecover() && $req->isPost()
48
+ && $req->request( 'action' ) == $mod->prefix() && $req->request( 'exec' ) == 'uau' ) {
49
+
50
+ if ( check_admin_referer( $req->request( 'exec' ), 'exec_nonce' ) !== 1 ) {
51
+ throw new \Exception( 'Nonce failed' );
52
+ }
53
+ if ( strlen( $req->post( 'icwp_wpsf_login_email' ) ) > 0 ) {
54
+ throw new \Exception( 'Email should not be provided in honeypot' );
55
+ }
56
+
57
+ $sIP = Services::IP()->getRequestIp();
58
+ if ( $req->post( 'ip' ) != $sIP ) {
59
+ throw new \Exception( 'IP does not match' );
60
+ }
61
+
62
+ $oLoginMod = $this->getCon()->getModule_LoginGuard();
63
+ $sGasp = $req->post( $oLoginMod->getGaspKey() );
64
+ if ( empty( $sGasp ) ) {
65
+ throw new \Exception( 'GASP failed' );
66
+ }
67
+
68
+ if ( !$opts->getCanIpRequestAutoUnblock( $sIP ) ) {
69
+ throw new \Exception( 'IP already processed in the last 24hrs' );
70
+ }
71
+
72
+ {
73
+ $aExistingIps = $opts->getAutoUnblockIps();
74
+ $aExistingIps[ $sIP ] = Services::Request()->ts();
75
+ $opts->setOpt( 'autounblock_ips',
76
+ array_filter( $aExistingIps, function ( $nTS ) {
77
+ return Services::Request()
78
+ ->carbon()
79
+ ->subDays( 1 )->timestamp < $nTS;
80
+ } )
81
+ );
82
+ }
83
+
84
+ ( new IPs\Lib\Ops\DeleteIp() )
85
+ ->setDbHandler( $mod->getDbHandler_IPs() )
86
+ ->setIP( $sIP )
87
+ ->fromBlacklist();
88
+ $unblocked = true;
89
+ }
90
+
91
+ return $unblocked;
92
+ }
93
+
94
+ /**
95
+ * @return bool
96
+ * @throws \Exception
97
+ */
98
+ private function processUserMagicLink() {
99
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
100
+ $mod = $this->getMod();
101
+ /** @var IPs\Options $opts */
102
+ $opts = $this->getOptions();
103
+ $req = Services::Request();
104
+
105
+ $unblocked = false;
106
+
107
+ if ( $opts->isEnabledMagicEmailLinkRecover()
108
+ && $req->query( 'action' ) == $mod->prefix()
109
+ && strpos( $req->query( 'exec' ), 'uaum-' ) === 0 ) {
110
+
111
+ if ( check_admin_referer( $req->request( 'exec' ), 'exec_nonce' ) !== 1 ) {
112
+ throw new \Exception( 'Nonce failed' );
113
+ }
114
+
115
+ $user = Services::WpUsers()->getCurrentWpUser();
116
+ if ( !$user instanceof \WP_User ) {
117
+ throw new \Exception( 'There is no user currently logged-in.' );
118
+ }
119
+
120
+ $linkParts = explode( '-', $req->query( 'exec' ), 3 );
121
+
122
+ if ( !hash_equals( substr( sha1( $user->user_login ), 0, 6 ), $linkParts[ 2 ] ) ) {
123
+ throw new \Exception( 'Users do not match.' );
124
+ }
125
+
126
+ if ( $req->query( 'ip' ) !== Services::IP()->getRequestIp() ) {
127
+ throw new \Exception( 'IP does not match.' );
128
+ }
129
+
130
+ if ( $linkParts[ 1 ] === 'init' ) {
131
+ if ( !$opts->getCanRequestAutoUnblockEmailLink( $user ) ) {
132
+ throw new \Exception( 'User already processed recently.' );
133
+ }
134
+
135
+ $this->sendMagicLinkEmail();
136
+ {
137
+ $existing = $opts->getAutoUnblockEmailIDs();
138
+ $existing[ $user->ID ] = Services::Request()->ts();
139
+ $opts->setOpt( 'autounblock_emailids',
140
+ array_filter( $existing, function ( $nTS ) {
141
+ return Services::Request()
142
+ ->carbon()
143
+ ->subHours( 1 )->timestamp < $nTS;
144
+ } )
145
+ );
146
+ }
147
+ wp_die( 'Email sent.' );
148
+ }
149
+ elseif ( $linkParts[ 1 ] === 'go' ) {
150
+ ( new IPs\Lib\Ops\DeleteIp() )
151
+ ->setDbHandler( $mod->getDbHandler_IPs() )
152
+ ->setIP( Services::IP()->getRequestIp() )
153
+ ->fromBlacklist();
154
+ $unblocked = true;
155
+ }
156
+ else {
157
+ throw new \Exception( 'Not a supported UAUM action.' );
158
+ }
159
+ }
160
+
161
+ return $unblocked;
162
+ }
163
+
164
+ /**
165
+ * @throws \Exception
166
+ */
167
+ private function sendMagicLinkEmail() {
168
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
169
+ $mod = $this->getMod();
170
+ $user = Services::WpUsers()->getCurrentWpUser();
171
+
172
+ $mod->getEmailProcessor()
173
+ ->sendEmailWithTemplate(
174
+ '/email/uaum_init',
175
+ $user->user_email,
176
+ __( 'Automatic IP Unblock Request', 'wp-simple-firewall' ),
177
+ [
178
+ 'flags' => [
179
+ 'show_login_link' => !$this->getCon()->isRelabelled()
180
+ ],
181
+ 'vars' => [
182
+ ],
183
+ 'hrefs' => [
184
+ 'unblock' => add_query_arg(
185
+ array_merge(
186
+ $mod->getNonceActionData( 'uaum-go-'.substr( sha1( $user->user_login ), 0, 6 ) ),
187
+ [
188
+ 'ip' => Services::IP()->getRequestIp()
189
+ ]
190
+ ),
191
+ Services::WpGeneral()->getHomeUrl()
192
+ )
193
+ ],
194
+ 'strings' => [
195
+ 'looks_like' => __( "It looks like you've been blocked and have clicked to have your IP address removed from the blocklist.", 'wp-simple-firewall' ),
196
+ 'please_click' => __( 'Please click the link provided below to do so.', 'wp-simple-firewall' ),
197
+ 'details' => __( 'Details', 'wp-simple-firewall' ),
198
+ 'unblock_my_ip' => sprintf( '%s: %s',
199
+ __( 'Unblock My IP', 'wp-simple-firewall' ), Services::IP()->getRequestIp() ),
200
+ 'or_copy' => __( 'Or Copy-Paste', 'wp-simple-firewall' ),
201
+ 'details_url' => sprintf( '%s: %s',
202
+ __( 'URL', 'wp-simple-firewall' ), Services::WpGeneral()->getHomeUrl() ),
203
+ 'details_username' => sprintf( '%s: %s', __( 'Username', 'wp-simple-firewall' ), $user->user_login ),
204
+ 'details_ip' => sprintf( '%s: %s', __( 'IP Address', 'wp-simple-firewall' ), Services::IP()
205
+ ->getRequestIp() ),
206
+ 'important' => __( 'Important', 'wp-simple-firewall' ),
207
+ 'imp_limit' => __( "You'll need to wait for a further 60 minutes if your IP address gets blocked again.", 'wp-simple-firewall' ),
208
+ 'imp_browser' => __( "This link will ONLY work if it opens in the same web browser that you used to request this email.", 'wp-simple-firewall' ),
209
+ ]
210
+ ]
211
+ );
212
+ }
213
+ }
src/lib/src/Modules/IPs/Lib/BlacklistHandler.php CHANGED
@@ -12,8 +12,8 @@ class BlacklistHandler {
12
  use Modules\Base\OneTimeExecute;
13
 
14
  protected function run() {
15
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
16
- $oMod = $this->getMod();
17
  /** @var IPs\Options $oOpts */
18
  $oOpts = $this->getOptions();
19
  if ( $oOpts->isEnabledAutoBlackList() ) {
@@ -24,62 +24,68 @@ class BlacklistHandler {
24
  }
25
 
26
  ( new IPs\Components\UnblockIpByFlag() )
27
- ->setMod( $oMod )
28
  ->run();
29
 
30
  add_action( 'init', [ $this, 'loadBotDetectors' ] ); // hook in the bot detection
31
 
32
- if ( !$oMod->isVisitorWhitelisted() && !$this->isRequestWhitelisted() && !$oMod->isVerifiedBot() ) {
33
- ( new BlockRequest() )
34
- ->setMod( $oMod )
35
- ->run();
36
- ( new BlackmarkRequest() )
37
- ->setMod( $oMod )
38
  ->run();
 
 
 
 
 
 
39
  }
40
  }
41
  }
42
 
43
  public function loadBotDetectors() {
44
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
45
- $oMod = $this->getMod();
46
- /** @var IPs\Options $oOpts */
47
- $oOpts = $oMod->getOptions();
48
 
49
  if ( !Services::WpUsers()->isUserLoggedIn() ) {
50
 
51
- if ( !$oMod->isVerifiedBot() ) {
52
- if ( $oOpts->isEnabledTrackXmlRpc() ) {
53
  ( new IPs\BotTrack\TrackXmlRpc() )
54
- ->setMod( $oMod )
55
  ->run();
56
  }
57
- if ( $oOpts->isEnabledTrack404() ) {
58
  ( new IPs\BotTrack\Track404() )
59
- ->setMod( $oMod )
60
  ->run();
61
  }
62
- if ( $oOpts->isEnabledTrackLoginFailed() ) {
63
  ( new IPs\BotTrack\TrackLoginFailed() )
64
- ->setMod( $oMod )
65
  ->run();
66
  }
67
- if ( $oOpts->isEnabledTrackLoginInvalid() ) {
68
  ( new IPs\BotTrack\TrackLoginInvalid() )
69
- ->setMod( $oMod )
70
  ->run();
71
  }
72
- if ( $oOpts->isEnabledTrackFakeWebCrawler() ) {
73
  ( new IPs\BotTrack\TrackFakeWebCrawler() )
74
- ->setMod( $oMod )
75
  ->run();
76
  }
77
  }
78
 
79
  /** Always run link cheese regardless of the verified bot or not */
80
- if ( $oOpts->isEnabledTrackLinkCheese() ) {
81
  ( new IPs\BotTrack\TrackLinkCheese() )
82
- ->setMod( $oMod )
83
  ->run();
84
  }
85
  }
12
  use Modules\Base\OneTimeExecute;
13
 
14
  protected function run() {
15
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
16
+ $mod = $this->getMod();
17
  /** @var IPs\Options $oOpts */
18
  $oOpts = $this->getOptions();
19
  if ( $oOpts->isEnabledAutoBlackList() ) {
24
  }
25
 
26
  ( new IPs\Components\UnblockIpByFlag() )
27
+ ->setMod( $mod )
28
  ->run();
29
 
30
  add_action( 'init', [ $this, 'loadBotDetectors' ] ); // hook in the bot detection
31
 
32
+ if ( !$mod->isVisitorWhitelisted()
33
+ && !$this->isRequestWhitelisted() && !$mod->isVerifiedBot() ) {
34
+
35
+ // We setup offenses processing immediately but run the blocks on 'init
36
+ ( new ProcessOffenses() )
37
+ ->setMod( $this->getMod() )
38
  ->run();
39
+ add_action( 'init', function () {
40
+ ( new BlockRequest() )
41
+ ->setMod( $this->getMod() )
42
+ ->run();
43
+ }, -100000 );
44
+
45
  }
46
  }
47
  }
48
 
49
  public function loadBotDetectors() {
50
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
51
+ $mod = $this->getMod();
52
+ /** @var IPs\Options $opts */
53
+ $opts = $this->getOptions();
54
 
55
  if ( !Services::WpUsers()->isUserLoggedIn() ) {
56
 
57
+ if ( !$mod->isVerifiedBot() ) {
58
+ if ( $opts->isEnabledTrackXmlRpc() ) {
59
  ( new IPs\BotTrack\TrackXmlRpc() )
60
+ ->setMod( $mod )
61
  ->run();
62
  }
63
+ if ( $opts->isEnabledTrack404() ) {
64
  ( new IPs\BotTrack\Track404() )
65
+ ->setMod( $mod )
66
  ->run();
67
  }
68
+ if ( $opts->isEnabledTrackLoginFailed() ) {
69
  ( new IPs\BotTrack\TrackLoginFailed() )
70
+ ->setMod( $mod )
71
  ->run();
72
  }
73
+ if ( $opts->isEnabledTrackLoginInvalid() ) {
74
  ( new IPs\BotTrack\TrackLoginInvalid() )
75
+ ->setMod( $mod )
76
  ->run();
77
  }
78
+ if ( $opts->isEnabledTrackFakeWebCrawler() ) {
79
  ( new IPs\BotTrack\TrackFakeWebCrawler() )
80
+ ->setMod( $mod )
81
  ->run();
82
  }
83
  }
84
 
85
  /** Always run link cheese regardless of the verified bot or not */
86
+ if ( $opts->isEnabledTrackLinkCheese() ) {
87
  ( new IPs\BotTrack\TrackLinkCheese() )
88
+ ->setMod( $mod )
89
  ->run();
90
  }
91
  }
src/lib/src/Modules/IPs/Lib/BlockRequest.php CHANGED
@@ -5,111 +5,79 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Services\Services;
 
8
 
9
  class BlockRequest {
10
 
11
  use ModConsumer;
12
 
13
  public function run() {
14
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
15
- $oMod = $this->getMod();
16
 
17
- $bIpBlocked = ( new IPs\Components\QueryIpBlock() )
18
- ->setMod( $oMod )
19
- ->setIp( Services::IP()->getRequestIp() )
20
- ->run();
21
 
22
- if ( $bIpBlocked ) {
23
  // don't log killed requests
24
  add_filter( $this->getCon()->prefix( 'is_log_traffic' ), '__return_false' );
25
- try {
26
- if ( $this->processAutoUnblockRequest() ) {
27
- return;
28
- }
29
- }
30
- catch ( \Exception $oE ) {
31
- }
32
  $this->getCon()->fireEvent( 'conn_kill' );
33
  $this->renderKillPage();
34
  }
35
  }
36
 
37
  /**
38
- * @throws \Exception
39
  */
40
- private function processAutoUnblockRequest() {
41
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
42
- $oMod = $this->getMod();
43
- /** @var IPs\Options $oOpts */
44
- $oOpts = $oMod->getOptions();
45
- $oReq = Services::Request();
46
-
47
- if ( $oOpts->isEnabledAutoUserRecover() && $oReq->isPost()
48
- && $oReq->request( 'action' ) == $oMod->prefix() && $oReq->request( 'exec' ) == 'uau' ) {
49
-
50
- if ( check_admin_referer( $oReq->request( 'exec' ), 'exec_nonce' ) !== 1 ) {
51
- throw new \Exception( 'Nonce failed' );
52
- }
53
- if ( strlen( $oReq->post( 'icwp_wpsf_login_email' ) ) > 0 ) {
54
- throw new \Exception( 'Email should not be provided in honeypot' );
55
- }
56
-
57
- $sIp = Services::IP()->getRequestIp();
58
- if ( $oReq->post( 'ip' ) != $sIp ) {
59
- throw new \Exception( 'IP does not match' );
60
- }
61
-
62
- $oLoginMod = $this->getCon()->getModule_LoginGuard();
63
- $sGasp = $oReq->post( $oLoginMod->getGaspKey() );
64
- if ( empty( $sGasp ) ) {
65
- throw new \Exception( 'GASP failed' );
66
- }
67
-
68
- if ( !$oOpts->getCanIpRequestAutoUnblock( $sIp ) ) {
69
- throw new \Exception( 'IP already processed in the last 24hrs' );
70
- }
71
-
72
- {
73
- $aExistingIps = $oOpts->getAutoUnblockIps();
74
- $aExistingIps[ $sIp ] = Services::Request()->ts();
75
- $oOpts->setOpt( 'autounblock_ips', $aExistingIps );
76
- }
77
-
78
- ( new IPs\Lib\Ops\DeleteIp() )
79
- ->setDbHandler( $oMod->getDbHandler_IPs() )
80
- ->setIP( $sIp )
81
- ->fromBlacklist();
82
- Services::Response()->redirectToHome();
83
- }
84
 
85
- return false;
 
 
 
 
 
 
86
  }
87
 
88
  private function renderKillPage() {
89
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
90
- $oMod = $this->getMod();
91
- /** @var IPs\Options $oOpts */
92
- $oOpts = $oMod->getOptions();
93
- $oCon = $this->getCon();
94
- $oLoginMod = $oCon->getModule_LoginGuard();
95
 
96
  $sUniqId = 'uau'.uniqid();
97
 
98
- $sIp = Services::IP()->getRequestIp();
99
- $nTimeRemaining = max( floor( $oOpts->getAutoExpireTime()/60 ), 0 );
 
 
 
 
 
 
 
 
100
  $aData = [
101
  'strings' => [
102
  'title' => sprintf( __( "You've been blocked by the %s plugin", 'wp-simple-firewall' ),
103
  sprintf( '<a href="%s" target="_blank">%s</a>',
104
- $oCon->getPluginSpec()[ 'meta' ][ 'url_repo_home' ],
105
- $oCon->getHumanName()
106
  )
107
  ),
108
  'lines' => [
109
  sprintf( __( 'Time remaining on black list: %s', 'wp-simple-firewall' ),
110
  sprintf( _n( '%s minute', '%s minutes', $nTimeRemaining, 'wp-simple-firewall' ), $nTimeRemaining )
111
  ),
112
- sprintf( __( 'You tripped the security plugin defenses a total of %s times making you a suspect.', 'wp-simple-firewall' ), $oOpts->getOffenseLimit() ),
113
  sprintf( __( 'If you believe this to be in error, please contact the site owner and quote your IP address below.', 'wp-simple-firewall' ) ),
114
  ],
115
  'your_ip' => 'Your IP address',
@@ -119,10 +87,13 @@ class BlockRequest {
119
  'button' => __( 'Unblock My IP Address', 'wp-simple-firewall' ),
120
  ],
121
  ],
 
 
 
122
  'vars' => [
123
- 'nonce' => $oMod->getNonceActionData( 'uau' ),
124
- 'ip' => $sIp,
125
- 'gasp_element' => $oMod->renderTemplate(
126
  'snippets/gasp_js.php',
127
  [
128
  'sCbName' => $oLoginMod->getGaspKey(),
@@ -138,13 +109,68 @@ class BlockRequest {
138
  ),
139
  ],
140
  'flags' => [
141
- 'is_autorecover' => $oOpts->isEnabledAutoUserRecover(),
142
- 'is_uau_permitted' => $oOpts->getCanIpRequestAutoUnblock( $sIp ),
 
143
  ],
144
  ];
145
  Services::WpGeneral()
146
  ->wpDie(
147
- $oMod->renderTemplate( '/snippets/blacklist_die.twig', $aData, true )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  );
 
 
 
 
149
  }
150
  }
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Services\Services;
8
+ use FernleafSystems\Wordpress\Services\Utilities\Obfuscate;
9
 
10
  class BlockRequest {
11
 
12
  use ModConsumer;
13
 
14
  public function run() {
15
+ if ( $this->isBlocked() ) {
 
16
 
17
+ if ( $this->isAutoUnBlocked() ) {
18
+ // TODO: flash message
19
+ Services::Response()->redirectToAdmin();
20
+ }
21
 
 
22
  // don't log killed requests
23
  add_filter( $this->getCon()->prefix( 'is_log_traffic' ), '__return_false' );
 
 
 
 
 
 
 
24
  $this->getCon()->fireEvent( 'conn_kill' );
25
  $this->renderKillPage();
26
  }
27
  }
28
 
29
  /**
30
+ * @return bool
31
  */
32
+ private function isBlocked() {
33
+ return ( new IPs\Components\QueryIpBlock() )
34
+ ->setMod( $this->getMod() )
35
+ ->setIp( Services::IP()->getRequestIp() )
36
+ ->run();
37
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ /**
40
+ * @return bool
41
+ */
42
+ private function isAutoUnBlocked() {
43
+ return ( new AutoUnblock() )
44
+ ->setMod( $this->getMod() )
45
+ ->run();
46
  }
47
 
48
  private function renderKillPage() {
49
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
50
+ $mod = $this->getMod();
51
+ /** @var IPs\Options $opts */
52
+ $opts = $this->getOptions();
53
+ $con = $this->getCon();
54
+ $oLoginMod = $con->getModule_LoginGuard();
55
 
56
  $sUniqId = 'uau'.uniqid();
57
 
58
+ $sIP = Services::IP()->getRequestIp();
59
+ $nTimeRemaining = max( floor( $opts->getAutoExpireTime()/60 ), 0 );
60
+
61
+ $user = Services::WpUsers()->getCurrentWpUser();
62
+ $bCanUauGasp = $opts->isEnabledAutoVisitorRecover() && $opts->getCanIpRequestAutoUnblock( $sIP );
63
+ $bCanUauMagic = $opts->isEnabledMagicEmailLinkRecover() &&
64
+ $user instanceof \WP_User
65
+ && $opts->getCanRequestAutoUnblockEmailLink( $user );
66
+ $bCanAutoRecover = $bCanUauGasp || $bCanUauMagic;
67
+
68
  $aData = [
69
  'strings' => [
70
  'title' => sprintf( __( "You've been blocked by the %s plugin", 'wp-simple-firewall' ),
71
  sprintf( '<a href="%s" target="_blank">%s</a>',
72
+ $con->getPluginSpec()[ 'meta' ][ 'url_repo_home' ],
73
+ $con->getHumanName()
74
  )
75
  ),
76
  'lines' => [
77
  sprintf( __( 'Time remaining on black list: %s', 'wp-simple-firewall' ),
78
  sprintf( _n( '%s minute', '%s minutes', $nTimeRemaining, 'wp-simple-firewall' ), $nTimeRemaining )
79
  ),
80
+ sprintf( __( 'You tripped the security plugin defenses a total of %s times making you a suspect.', 'wp-simple-firewall' ), $opts->getOffenseLimit() ),
81
  sprintf( __( 'If you believe this to be in error, please contact the site owner and quote your IP address below.', 'wp-simple-firewall' ) ),
82
  ],
83
  'your_ip' => 'Your IP address',
87
  'button' => __( 'Unblock My IP Address', 'wp-simple-firewall' ),
88
  ],
89
  ],
90
+ 'content' => [
91
+ 'email_unblock' => $this->renderEmailMagicLinkContent()
92
+ ],
93
  'vars' => [
94
+ 'nonce' => $mod->getNonceActionData( 'uau' ),
95
+ 'ip' => $sIP,
96
+ 'gasp_element' => $mod->renderTemplate(
97
  'snippets/gasp_js.php',
98
  [
99
  'sCbName' => $oLoginMod->getGaspKey(),
109
  ),
110
  ],
111
  'flags' => [
112
+ 'is_autorecover' => $bCanAutoRecover,
113
+ 'is_uaug_permitted' => $bCanUauGasp,
114
+ 'is_uaum_permitted' => $bCanUauMagic,
115
  ],
116
  ];
117
  Services::WpGeneral()
118
  ->wpDie(
119
+ $mod->renderTemplate( '/pages/block/blocklist_die.twig', $aData, true )
120
+ );
121
+ }
122
+
123
+ /**
124
+ * @return string
125
+ */
126
+ private function renderEmailMagicLinkContent() {
127
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
128
+ $mod = $this->getMod();
129
+ /** @var IPs\Options $opts */
130
+ $opts = $this->getOptions();
131
+ $con = $this->getCon();
132
+
133
+ $content = '';
134
+
135
+ $user = Services::WpUsers()->getCurrentWpUser();
136
+ if ( $user instanceof \WP_User &&
137
+ $opts->isEnabledMagicEmailLinkRecover()
138
+ && $opts->getCanRequestAutoUnblockEmailLink( $user ) ) {
139
+
140
+ if ( apply_filters( $con->prefix( 'can_user_magic_link' ), true ) ) {
141
+ $content = $mod->renderTemplate(
142
+ '/pages/block/magic_link.twig',
143
+ [
144
+ 'flags' => [
145
+ ],
146
+ 'hrefs' => [
147
+ 'unblock' => add_query_arg(
148
+ array_merge(
149
+ $mod->getNonceActionData( 'uaum-init-'.substr( sha1( $user->user_login ), 0, 6 ) ),
150
+ [
151
+ 'ip' => Services::IP()->getRequestIp()
152
+ ]
153
+ ),
154
+ Services::WpGeneral()->getHomeUrl()
155
+ )
156
+ ],
157
+ 'vars' => [
158
+ 'email' => Obfuscate::Email( $user->user_email )
159
+ ],
160
+ 'strings' => [
161
+ 'you_may' => __( 'You can automatically unblock your IP address by clicking the link below.', 'wp-simple-firewall' ),
162
+ 'this_will_send' => __( 'Clicking the button will send you an email letting you unblock your IP address.', 'wp-simple-firewall' ),
163
+ 'assumes_email' => __( 'This assumes that your WordPress site has been properly configured to send email - many are not.', 'wp-simple-firewall' ),
164
+ 'dont_receive' => __( "If you don't receive the email, check your spam and contact your site admin.", 'wp-simple-firewall' ),
165
+ 'limit_60' => __( "You may only use this link once every 60 minutes. If you're repeatedly blocked, ask your site admin to review the audit trail to determine the cause.", 'wp-simple-firewall' ),
166
+ 'same_browser' => __( "When you click the link from your email, it must open up in this web browser.", 'wp-simple-firewall' ),
167
+ 'click_to_send' => __( 'Send Auto-Unblock Link To My Email', 'wp-simple-firewall' )
168
+ ],
169
+ ]
170
  );
171
+ }
172
+ }
173
+
174
+ return $content;
175
  }
176
  }
src/lib/src/Modules/IPs/Lib/Ops/DeleteIp.php CHANGED
@@ -15,11 +15,6 @@ class DeleteIp {
15
  use Databases\Base\HandlerConsumer;
16
  use IPs\Components\IpAddressConsumer;
17
 
18
- /**
19
- * @var string
20
- */
21
- private $sIpAddress;
22
-
23
  /**
24
  * @return bool
25
  */
@@ -47,20 +42,4 @@ class DeleteIp {
47
  return $oDel->filterByIp( $this->getIP() )
48
  ->setLimit( 1 );
49
  }
50
-
51
- /**
52
- * @return string
53
- */
54
- public function getIP() {
55
- return $this->sIpAddress;
56
- }
57
-
58
- /**
59
- * @param string $sIP
60
- * @return $this
61
- */
62
- public function setIP( $sIP ) {
63
- $this->sIpAddress = $sIP;
64
- return $this;
65
- }
66
  }
15
  use Databases\Base\HandlerConsumer;
16
  use IPs\Components\IpAddressConsumer;
17
 
 
 
 
 
 
18
  /**
19
  * @return bool
20
  */
42
  return $oDel->filterByIp( $this->getIP() )
43
  ->setLimit( 1 );
44
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
src/lib/src/Modules/IPs/Lib/{BlackmarkRequest.php → ProcessOffenses.php} RENAMED
@@ -6,32 +6,33 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
- class BlackmarkRequest {
10
 
11
  use ModConsumer;
12
 
13
  public function run() {
14
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
15
- $oMod = $this->getMod();
16
 
17
- $oMod->loadOffenseTracker()->setIfCommit( true );
18
 
19
- $oCon = $this->getCon();
20
- add_filter( $oCon->prefix( 'firewall_die_message' ), [ $this, 'augmentFirewallDieMessage' ] );
21
- add_action( $oCon->prefix( 'pre_plugin_shutdown' ), function () {
22
  $this->processOffense();
23
  } );
24
  add_action( 'shield_security_offense', [ $this, 'processCustomShieldOffense' ], 10, 3 );
25
  }
26
 
27
  private function processOffense() {
28
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
29
- $oMod = $this->getMod();
30
 
31
- $oTracker = $oMod->loadOffenseTracker();
32
- if ( !$this->getCon()->plugin_deleting && $oTracker->hasVisitorOffended() && $oTracker->isCommit() ) {
 
33
  ( new IPs\Components\ProcessOffense() )
34
- ->setMod( $oMod )
35
  ->setIp( Services::IP()->getRequestIp() )
36
  ->run();
37
  }
@@ -48,10 +49,10 @@ class BlackmarkRequest {
48
 
49
  $aMessages[] = sprintf( '<p>%s</p>', sprintf(
50
  $this->getMod()->getTextOpt( 'text_remainingtrans' ),
51
- ( new IPs\Components\QueryRemainingOffenses() )
52
  ->setMod( $this->getMod() )
53
  ->setIP( Services::IP()->getRequestIp() )
54
- ->run()
55
  ) );
56
 
57
  return $aMessages;
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Services\Services;
8
 
9
+ class ProcessOffenses {
10
 
11
  use ModConsumer;
12
 
13
  public function run() {
14
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
15
+ $mod = $this->getMod();
16
 
17
+ $mod->loadOffenseTracker()->setIfCommit( true );
18
 
19
+ $con = $this->getCon();
20
+ add_filter( $con->prefix( 'firewall_die_message' ), [ $this, 'augmentFirewallDieMessage' ] );
21
+ add_action( $con->prefix( 'pre_plugin_shutdown' ), function () {
22
  $this->processOffense();
23
  } );
24
  add_action( 'shield_security_offense', [ $this, 'processCustomShieldOffense' ], 10, 3 );
25
  }
26
 
27
  private function processOffense() {
28
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $mod */
29
+ $mod = $this->getMod();
30
 
31
+ $oTracker = $mod->loadOffenseTracker();
32
+ if ( !$this->getCon()->plugin_deleting
33
+ && $oTracker->hasVisitorOffended() && $oTracker->isCommit() ) {
34
  ( new IPs\Components\ProcessOffense() )
35
+ ->setMod( $mod )
36
  ->setIp( Services::IP()->getRequestIp() )
37
  ->run();
38
  }
49
 
50
  $aMessages[] = sprintf( '<p>%s</p>', sprintf(
51
  $this->getMod()->getTextOpt( 'text_remainingtrans' ),
52
+ max( 0, ( new IPs\Components\QueryRemainingOffenses() )
53
  ->setMod( $this->getMod() )
54
  ->setIP( Services::IP()->getRequestIp() )
55
+ ->run() )
56
  ) );
57
 
58
  return $aMessages;
src/lib/src/Modules/IPs/Options.php CHANGED
@@ -23,13 +23,31 @@ class Options extends Base\ShieldOptions {
23
  }
24
 
25
  /**
26
- * @param string $sIp
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  * @return bool
28
  */
29
- public function getCanIpRequestAutoUnblock( $sIp ) {
30
- $aExistingIps = $this->getAutoUnblockIps();
31
- return !array_key_exists( $sIp, $aExistingIps )
32
- || ( Services::Request()->carbon()->subDay( 1 )->timestamp > $aExistingIps[ $sIp ] );
33
  }
34
 
35
  /**
@@ -41,6 +59,7 @@ class Options extends Base\ShieldOptions {
41
 
42
  /**
43
  * @return string[]
 
44
  */
45
  public function getDbColumns_IPs() {
46
  return $this->getDef( 'ip_list_table_columns' );
@@ -75,8 +94,15 @@ class Options extends Base\ShieldOptions {
75
  /**
76
  * @return bool
77
  */
78
- public function isEnabledAutoUserRecover() {
79
- return !$this->isOpt( 'user_auto_recover', 'disabled' );
 
 
 
 
 
 
 
80
  }
81
 
82
  /**
@@ -122,34 +148,34 @@ class Options extends Base\ShieldOptions {
122
  }
123
 
124
  /**
125
- * @param string $sOptionKey
126
  * @return bool
127
  */
128
- public function isTrackOptTransgression( $sOptionKey ) {
129
- return strpos( $this->getOpt( $sOptionKey ), 'transgression' ) !== false;
130
  }
131
 
132
  /**
133
- * @param string $sOptionKey
134
  * @return bool
135
  */
136
- public function isTrackOptDoubleTransgression( $sOptionKey ) {
137
- return $this->isOpt( $sOptionKey, 'transgression-double' );
138
  }
139
 
140
  /**
141
- * @param string $sOptionKey
142
  * @return bool
143
  */
144
- public function isTrackOptImmediateBlock( $sOptionKey ) {
145
- return $this->isOpt( $sOptionKey, 'block' );
146
  }
147
 
148
  /**
149
- * @param string $sOptionKey
150
  * @return bool
151
  */
152
- protected function isSelectOptionEnabled( $sOptionKey ) {
153
- return !$this->isOpt( $sOptionKey, 'disabled' );
154
  }
155
  }
23
  }
24
 
25
  /**
26
+ * @return array
27
+ */
28
+ public function getAutoUnblockEmailIDs() {
29
+ $aIps = $this->getOpt( 'autounblock_emailids', [] );
30
+ return is_array( $aIps ) ? $aIps : [];
31
+ }
32
+
33
+ /**
34
+ * @param string $ip
35
+ * @return bool
36
+ */
37
+ public function getCanIpRequestAutoUnblock( $ip ) {
38
+ $existing = $this->getAutoUnblockIps();
39
+ return !array_key_exists( $ip, $existing )
40
+ || ( Services::Request()->carbon()->subDay( 1 )->timestamp > $existing[ $ip ] );
41
+ }
42
+
43
+ /**
44
+ * @param \WP_User $user
45
  * @return bool
46
  */
47
+ public function getCanRequestAutoUnblockEmailLink( \WP_User $user ) {
48
+ $existing = $this->getAutoUnblockEmailIDs();
49
+ return !array_key_exists( $user->ID, $existing )
50
+ || ( Services::Request()->carbon()->subHour( 1 )->timestamp > $existing[ $user->ID ] );
51
  }
52
 
53
  /**
59
 
60
  /**
61
  * @return string[]
62
+ * @deprecated 9.2.0
63
  */
64
  public function getDbColumns_IPs() {
65
  return $this->getDef( 'ip_list_table_columns' );
94
  /**
95
  * @return bool
96
  */
97
+ public function isEnabledAutoVisitorRecover() {
98
+ return in_array( 'gasp', (array)$this->getOpt( 'user_auto_recover', [] ) );
99
+ }
100
+
101
+ /**
102
+ * @return bool
103
+ */
104
+ public function isEnabledMagicEmailLinkRecover() {
105
+ return in_array( 'email', (array)$this->getOpt( 'user_auto_recover', [] ) );
106
  }
107
 
108
  /**
148
  }
149
 
150
  /**
151
+ * @param string $key
152
  * @return bool
153
  */
154
+ public function isTrackOptTransgression( $key ) {
155
+ return strpos( $this->getOpt( $key ), 'transgression' ) !== false;
156
  }
157
 
158
  /**
159
+ * @param string $key
160
  * @return bool
161
  */
162
+ public function isTrackOptDoubleTransgression( $key ) {
163
+ return $this->isOpt( $key, 'transgression-double' );
164
  }
165
 
166
  /**
167
+ * @param string $key
168
  * @return bool
169
  */
170
+ public function isTrackOptImmediateBlock( $key ) {
171
+ return $this->isOpt( $key, 'block' );
172
  }
173
 
174
  /**
175
+ * @param string $key
176
  * @return bool
177
  */
178
+ protected function isSelectOptionEnabled( $key ) {
179
+ return !$this->isOpt( $key, 'disabled' );
180
  }
181
  }
src/lib/src/Modules/IPs/Strings.php CHANGED
@@ -8,17 +8,17 @@ use FernleafSystems\Wordpress\Services\Services;
8
  class Strings extends Base\Strings {
9
 
10
  /**
11
- * @param string $sSectionSlug
12
  * @return array
13
  * @throws \Exception
14
  */
15
- public function getSectionStrings( $sSectionSlug ) {
16
  /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
17
  $oMod = $this->getMod();
18
  $sPlugName = $this->getCon()->getHumanName();
19
  $sModName = $oMod->getMainFeatureName();
20
 
21
- switch ( $sSectionSlug ) {
22
 
23
  case 'section_enable_plugin_feature_ips' :
24
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -39,7 +39,7 @@ class Strings extends Base\Strings {
39
  __( "Think of 'offenses' as just a counter for the number of times a visitor does something bad.", 'wp-simple-firewall' )
40
  .' '.sprintf(
41
  __( 'When the counter reaches the limit below (default: %s), %s will block that IP completely.', 'wp-simple-firewall' ),
42
- $oMod->getOptions()->getOptDefault( 'transgression_limit' ),
43
  $sPlugName
44
  )
45
  ];
@@ -91,7 +91,7 @@ class Strings extends Base\Strings {
91
  break;
92
 
93
  default:
94
- return parent::getSectionStrings( $sSectionSlug );
95
  }
96
 
97
  return [
@@ -102,16 +102,16 @@ class Strings extends Base\Strings {
102
  }
103
 
104
  /**
105
- * @param string $sOptKey
106
  * @return array
107
  * @throws \Exception
108
  */
109
- public function getOptionStrings( $sOptKey ) {
110
 
111
  $sPlugName = $this->getCon()->getHumanName();
112
  $sModName = $this->getMod()->getMainFeatureName();
113
 
114
- switch ( $sOptKey ) {
115
 
116
  case 'enable_ips' :
117
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -122,17 +122,22 @@ class Strings extends Base\Strings {
122
  case 'transgression_limit' :
123
  $sName = __( 'Offense Limit', 'wp-simple-firewall' );
124
  $sSummary = __( 'Visitor IP address will be Black Listed after X bad actions on your site', 'wp-simple-firewall' );
125
- $sDescription = sprintf( __( 'A black mark is set against an IP address each time a visitor trips the defenses of the %s plugin.', 'wp-simple-firewall' ), $sPlugName )
126
- .'<br />'.__( 'When the number of these offenses exceeds the limit, they are automatically blocked from accessing the site.', 'wp-simple-firewall' )
127
- .'<br />'.sprintf( __( 'Set this to "0" to turn off the %s feature.', 'wp-simple-firewall' ), __( 'Automatic IP Black List', 'wp-simple-firewall' ) );
 
 
128
  break;
129
 
130
  case 'auto_expire' :
131
  $sName = __( 'Auto Block Expiration', 'wp-simple-firewall' );
132
  $sSummary = __( 'After 1 "X" a black listed IP will be removed from the black list', 'wp-simple-firewall' );
133
- $sDescription = __( 'Permanent and lengthy IP Black Lists are harmful to performance.', 'wp-simple-firewall' )
134
- .'<br />'.__( 'You should allow IP addresses on the black list to be eventually removed over time.', 'wp-simple-firewall' )
135
- .'<br />'.__( 'Shorter IP black lists are more efficient and a more intelligent use of an IP-based blocking system.', 'wp-simple-firewall' );
 
 
 
136
  break;
137
 
138
  case 'user_auto_recover' :
@@ -203,19 +208,26 @@ class Strings extends Base\Strings {
203
  case 'track_fakewebcrawler' :
204
  $sName = __( 'Fake Web Crawler', 'wp-simple-firewall' );
205
  $sSummary = __( 'Detect Fake Search Engine Crawlers', 'wp-simple-firewall' );
206
- $sDescription = __( "Identify a Bot when it presents as an official web crawler, but analysis shows it's fake.", 'wp-simple-firewall' );
 
 
 
 
207
  break;
208
 
209
  case 'track_useragent' :
210
  $sName = __( 'Empty User Agents', 'wp-simple-firewall' );
211
  $sSummary = __( 'Detect Requests With Empty User Agents', 'wp-simple-firewall' );
212
- $sDescription = __( "Identify a bot when the user agent is not provided.", 'wp-simple-firewall' )
213
- .'<br />'.sprintf( '%s: <code>%s</code>',
214
- __( 'Your user agent is', 'wp-simple-firewall' ), Services::Request()->getUserAgent() );
 
 
 
215
  break;
216
 
217
  default:
218
- return parent::getOptionStrings( $sOptKey );
219
  }
220
 
221
  return [
8
  class Strings extends Base\Strings {
9
 
10
  /**
11
+ * @param string $section
12
  * @return array
13
  * @throws \Exception
14
  */
15
+ public function getSectionStrings( $section ) {
16
  /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
17
  $oMod = $this->getMod();
18
  $sPlugName = $this->getCon()->getHumanName();
19
  $sModName = $oMod->getMainFeatureName();
20
 
21
+ switch ( $section ) {
22
 
23
  case 'section_enable_plugin_feature_ips' :
24
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
39
  __( "Think of 'offenses' as just a counter for the number of times a visitor does something bad.", 'wp-simple-firewall' )
40
  .' '.sprintf(
41
  __( 'When the counter reaches the limit below (default: %s), %s will block that IP completely.', 'wp-simple-firewall' ),
42
+ $this->getOptions()->getOptDefault( 'transgression_limit' ),
43
  $sPlugName
44
  )
45
  ];
91
  break;
92
 
93
  default:
94
+ return parent::getSectionStrings( $section );
95
  }
96
 
97
  return [
102
  }
103
 
104
  /**
105
+ * @param string $key
106
  * @return array
107
  * @throws \Exception
108
  */
109
+ public function getOptionStrings( $key ) {
110
 
111
  $sPlugName = $this->getCon()->getHumanName();
112
  $sModName = $this->getMod()->getMainFeatureName();
113
 
114
+ switch ( $key ) {
115
 
116
  case 'enable_ips' :
117
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
122
  case 'transgression_limit' :
123
  $sName = __( 'Offense Limit', 'wp-simple-firewall' );
124
  $sSummary = __( 'Visitor IP address will be Black Listed after X bad actions on your site', 'wp-simple-firewall' );
125
+ $sDescription = [
126
+ sprintf( __( 'An offense is registered against an IP address each time a visitor trips the defenses of the %s plugin.', 'wp-simple-firewall' ), $sPlugName ),
127
+ __( 'When the number of these offenses exceeds the limit, they are automatically blocked from accessing the site.', 'wp-simple-firewall' ),
128
+ sprintf( __( 'Set this to "0" to turn off the %s feature.', 'wp-simple-firewall' ), __( 'Automatic IP Black List', 'wp-simple-firewall' ) )
129
+ ];
130
  break;
131
 
132
  case 'auto_expire' :
133
  $sName = __( 'Auto Block Expiration', 'wp-simple-firewall' );
134
  $sSummary = __( 'After 1 "X" a black listed IP will be removed from the black list', 'wp-simple-firewall' );
135
+ $sDescription = [
136
+ __( 'Blocked IP addresses are eventually removed.', 'wp-simple-firewall' )
137
+ .'<br/>'.__( 'This option lets you specify how long they should be kept.', 'wp-simple-firewall' ),
138
+ __( 'Large, permanent IP Block Lists will degrade site performance.', 'wp-simple-firewall' ),
139
+ __( 'Shorter IP black lists are more efficient and a more intelligent use of an IP-based blocking system.', 'wp-simple-firewall' )
140
+ ];
141
  break;
142
 
143
  case 'user_auto_recover' :
208
  case 'track_fakewebcrawler' :
209
  $sName = __( 'Fake Web Crawler', 'wp-simple-firewall' );
210
  $sSummary = __( 'Detect Fake Search Engine Crawlers', 'wp-simple-firewall' );
211
+ $sDescription = [
212
+ __( "Identify a visitor as a Bot when it presents as an official web crawler, but analysis shows it's fake.", 'wp-simple-firewall' ),
213
+ __( "Many bots pretend to be a Google Bot.", 'wp-simple-firewall' )
214
+ .'<br/>'.__( "We can then know that a bot isn't here for anything good and block them.", 'wp-simple-firewall' ),
215
+ ];
216
  break;
217
 
218
  case 'track_useragent' :
219
  $sName = __( 'Empty User Agents', 'wp-simple-firewall' );
220
  $sSummary = __( 'Detect Requests With Empty User Agents', 'wp-simple-firewall' );
221
+ $sDescription = [
222
+ __( "Identify a bot when the user agent is not provided.", 'wp-simple-firewall' ),
223
+ sprintf( '%s:<br/><code>%s</code>',
224
+ __( 'For example, your browser user agent is', 'wp-simple-firewall' ), Services::Request()
225
+ ->getUserAgent() )
226
+ ];
227
  break;
228
 
229
  default:
230
+ return parent::getOptionStrings( $key );
231
  }
232
 
233
  return [
src/lib/src/Modules/IPs/UI.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class UI extends Base\ShieldUI {
9
+
10
+ /**
11
+ * @param string $section
12
+ * @return array
13
+ */
14
+ protected function getSectionWarnings( $section ) {
15
+ $aWarnings = [];
16
+
17
+ /** @var Options $opts */
18
+ $opts = $this->getOptions();
19
+
20
+ switch ( $section ) {
21
+
22
+ case 'section_auto_black_list':
23
+ if ( !$opts->isEnabledAutoBlackList() ) {
24
+ $aWarnings[] = sprintf( '%s: %s', __( 'Note', 'wp-simple-firewall' ), __( "IP blocking is turned-off because the offenses limit is set to 0.", 'wp-simple-firewall' ) );
25
+ }
26
+ break;
27
+
28
+ case 'section_behaviours':
29
+ case 'section_probes':
30
+ case 'section_logins':
31
+ if ( !$opts->isEnabledAutoBlackList() ) {
32
+ $aWarnings[] = __( "Since the offenses limit is set to 0, these options have no effect.", 'wp-simple-firewall' );
33
+ }
34
+
35
+ if ( $section == 'section_behaviours' && strlen( Services::Request()->getUserAgent() ) == 0 ) {
36
+ $aWarnings[] = __( "Your User Agent appears to be empty. We recommend not turning on this option.", 'wp-simple-firewall' );
37
+ }
38
+ break;
39
+ }
40
+
41
+ return $aWarnings;
42
+ }
43
+ }
src/lib/src/Modules/IPs/Upgrade.php CHANGED
@@ -16,4 +16,30 @@ class Upgrade extends Base\Upgrade {
16
  $oDBH->getTable(), 'ip', $oDBH->enumerateColumns()[ 'ip' ] )
17
  );
18
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
16
  $oDBH->getTable(), 'ip', $oDBH->enumerateColumns()[ 'ip' ] )
17
  );
18
  }
19
+
20
+ /**
21
+ * Support larger transgression counts [smallint(1) => int(10)]
22
+ */
23
+ protected function upgrade_911() {
24
+ /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
25
+ $oMod = $this->getMod();
26
+ $oDBH = $oMod->getDbHandler_IPs();
27
+ Services::WpDb()->doSql(
28
+ sprintf( "ALTER TABLE `%s` MODIFY `%s` %s;",
29
+ $oDBH->getTable(), 'transgressions', $oDBH->enumerateColumns()[ 'transgressions' ] )
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Support Magic Links for logged-in users.
35
+ */
36
+ protected function upgrade_920() {
37
+ /** @var Options $oOpts */
38
+ $oOpts = $this->getOptions();
39
+ $current = $oOpts->getOpt( 'user_auto_recover' );
40
+ if ( !is_array( $current ) ) {
41
+ $current = ( $current === 'gasp' ) ? [ 'gasp' ] : [];
42
+ $oOpts->setOpt( 'user_auto_recover', $current );
43
+ }
44
+ }
45
  }
src/lib/src/Modules/License/AjaxHandler.php CHANGED
@@ -9,12 +9,12 @@ use FernleafSystems\Wordpress\Services\Utilities\Licenses\Keyless;
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
11
  /**
12
- * @param string $sAction
13
  * @return array
14
  */
15
- protected function processAjaxAction( $sAction ) {
16
 
17
- switch ( $sAction ) {
18
  case 'license_handling':
19
  $aResponse = $this->ajaxExec_LicenseHandling();
20
  break;
@@ -23,7 +23,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
23
  break;
24
 
25
  default:
26
- $aResponse = parent::processAjaxAction( $sAction );
27
  }
28
 
29
  return $aResponse;
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
11
  /**
12
+ * @param string $action
13
  * @return array
14
  */
15
+ protected function processAjaxAction( $action ) {
16
 
17
+ switch ( $action ) {
18
  case 'license_handling':
19
  $aResponse = $this->ajaxExec_LicenseHandling();
20
  break;
23
  break;
24
 
25
  default:
26
+ $aResponse = parent::processAjaxAction( $action );
27
  }
28
 
29
  return $aResponse;
src/lib/src/Modules/License/Lib/WpHashes/ApiTokenManager.php CHANGED
@@ -64,14 +64,6 @@ class ApiTokenManager {
64
  return empty( $aT[ 'token' ] ) ? '' : $aT[ 'token' ];
65
  }
66
 
67
- /**
68
- * @return string
69
- * @deprecated 9.0.3
70
- */
71
- private function getTheToken() {
72
- return $this->loadToken()[ 'token' ];
73
- }
74
-
75
  /**
76
  * @return bool
77
  */
64
  return empty( $aT[ 'token' ] ) ? '' : $aT[ 'token' ];
65
  }
66
 
 
 
 
 
 
 
 
 
67
  /**
68
  * @return bool
69
  */
src/lib/src/Modules/License/UI.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\License;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class UI extends Base\ShieldUI {
9
+
10
+ /**
11
+ * @return array
12
+ */
13
+ public function buildInsightsVars() {
14
+ /** @var \ICWP_WPSF_FeatureHandler_License $mod */
15
+ $mod = $this->getMod();
16
+ $con = $this->getCon();
17
+ $opts = $this->getOptions();
18
+ $oWp = Services::WpGeneral();
19
+ $oCarbon = Services::Request()->carbon();
20
+
21
+ $oCurrent = $mod->getLicenseHandler()->getLicense();
22
+
23
+ $nExpiresAt = $oCurrent->getExpiresAt();
24
+ if ( $nExpiresAt > 0 && $nExpiresAt != PHP_INT_MAX ) {
25
+ $sExpiresAt = $oCarbon->setTimestamp( $nExpiresAt )->diffForHumans()
26
+ .sprintf( '<br/><small>%s</small>', $oWp->getTimeStampForDisplay( $nExpiresAt ) );
27
+ }
28
+ else {
29
+ $sExpiresAt = 'n/a';
30
+ }
31
+
32
+ $nLastReqAt = $oCurrent->last_request_at;
33
+ if ( empty( $nLastReqAt ) ) {
34
+ $sChecked = __( 'Never', 'wp-simple-firewall' );
35
+ }
36
+ else {
37
+ $sChecked = $oCarbon->setTimestamp( $nLastReqAt )->diffForHumans()
38
+ .sprintf( '<br/><small>%s</small>', $oWp->getTimeStampForDisplay( $nLastReqAt ) );
39
+ }
40
+ $aLicenseTableVars = [
41
+ 'product_name' => $oCurrent->is_central ?
42
+ $opts->getDef( 'license_item_name_sc' ) :
43
+ $opts->getDef( 'license_item_name' ),
44
+ 'license_active' => $mod->getLicenseHandler()->hasValidWorkingLicense() ?
45
+ __( '&#10004;', 'wp-simple-firewall' ) : __( '&#10006;', 'wp-simple-firewall' ),
46
+ 'license_expires' => $sExpiresAt,
47
+ 'license_email' => $oCurrent->customer_email,
48
+ 'last_checked' => $sChecked,
49
+ 'last_errors' => $mod->hasLastErrors() ? $mod->getLastErrors( true ) : '',
50
+ 'wphashes_token' => $mod->getWpHashesTokenManager()->hasToken() ?
51
+ __( '&#10004;', 'wp-simple-firewall' ) : __( '&#10006;', 'wp-simple-firewall' ),
52
+ 'installation_id' => $con->getSiteInstallationId(),
53
+ ];
54
+ return [
55
+ 'vars' => [
56
+ 'license_table' => $aLicenseTableVars,
57
+ 'activation_url' => $oWp->getHomeUrl(),
58
+ 'error' => $mod->getLastErrors( true )
59
+ ],
60
+ 'inputs' => [
61
+ 'license_key' => [
62
+ 'name' => $con->prefixOption( 'license_key' ),
63
+ 'maxlength' => $opts->getDef( 'license_key_length' ),
64
+ ]
65
+ ],
66
+ 'ajax' => [
67
+ 'license_handling' => $mod->getAjaxActionData( 'license_handling' ),
68
+ 'connection_debug' => $mod->getAjaxActionData( 'connection_debug' )
69
+ ],
70
+ 'aHrefs' => [
71
+ 'shield_pro_url' => 'https://shsec.io/shieldpro',
72
+ 'shield_pro_more_info_url' => 'https://shsec.io/shld1',
73
+ 'iframe_url' => $opts->getDef( 'landing_page_url' ),
74
+ 'keyless_cp' => $opts->getDef( 'keyless_cp' ),
75
+ ],
76
+ 'flags' => [
77
+ 'show_ads' => false,
78
+ 'button_enabled_check' => true,
79
+ 'show_standard_options' => false,
80
+ 'show_alt_content' => true,
81
+ 'is_pro' => $con->isPremiumActive(),
82
+ 'has_error' => $mod->hasLastErrors()
83
+ ],
84
+ 'strings' => $mod->getStrings()->getDisplayStrings(),
85
+ ];
86
+ }
87
+
88
+ /**
89
+ * @return bool
90
+ */
91
+ public function isEnabledForUiSummary() {
92
+ /** @var \ICWP_WPSF_FeatureHandler_License $mod */
93
+ $mod = $this->getMod();
94
+ return $mod->getLicenseHandler()->hasValidWorkingLicense();
95
+ }
96
+ }
src/lib/src/Modules/Lockdown/Lib/CleanRubbish.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Lockdown\Lib;
4
+
5
+ use FernleafSystems\Utilities\Logic\OneTimeExecute;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class CleanRubbish {
10
+
11
+ use ModConsumer;
12
+ use OneTimeExecute;
13
+
14
+ protected function run() {
15
+ if ( Services::WpGeneral()->isCron() && $this->getOptions()->isOpt( 'clean_wp_rubbish', 'Y' ) ) {
16
+ add_action( $this->getCon()->prefix( 'daily_cron' ), function () {
17
+ $FS = Services::WpFs();
18
+ $allFiles = $FS->getAllFilesInDir( ABSPATH, false );
19
+ foreach ( $allFiles as $file ) {
20
+ if ( in_array( basename( $file ), $this->getFilesToClean() ) ) {
21
+ $FS->deleteFile( $file );
22
+ }
23
+ }
24
+ } );
25
+ }
26
+ }
27
+
28
+ /**
29
+ * @return string[]
30
+ */
31
+ private function getFilesToClean() {
32
+ return [
33
+ 'wp-config-sample.php',
34
+ 'readme.html',
35
+ 'license.txt',
36
+ ];
37
+ }
38
+ }
src/lib/src/Modules/Lockdown/Options.php CHANGED
@@ -6,4 +6,32 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
 
7
  class Options extends Base\ShieldOptions {
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
6
 
7
  class Options extends Base\ShieldOptions {
8
 
9
+ /**
10
+ * @return string[]
11
+ */
12
+ public function getRestApiAnonymousExclusions() {
13
+ $ex = $this->getOpt( 'api_namespace_exclusions' );
14
+ return array_merge( $this->getDef( 'default_restapi_exclusions' ), is_array( $ex ) ? $ex : [] );
15
+ }
16
+
17
+ /**
18
+ * @return bool
19
+ */
20
+ public function isOptFileEditingDisabled() {
21
+ return $this->isOpt( 'disable_file_editing', 'Y' );
22
+ }
23
+
24
+ /**
25
+ * @return bool
26
+ */
27
+ public function isRestApiAnonymousAccessDisabled() {
28
+ return $this->isOpt( 'disable_anonymous_restapi', 'Y' );
29
+ }
30
+
31
+ /**
32
+ * @return bool
33
+ */
34
+ public function isXmlrpcDisabled() {
35
+ return $this->isOpt( 'disable_xmlrpc', 'Y' );
36
+ }
37
  }
src/lib/src/Modules/Lockdown/Strings.php CHANGED
@@ -18,13 +18,13 @@ class Strings extends Base\Strings {
18
  }
19
 
20
  /**
21
- * @param string $sSectionSlug
22
  * @return array
23
  * @throws \Exception
24
  */
25
- public function getSectionStrings( $sSectionSlug ) {
26
 
27
- switch ( $sSectionSlug ) {
28
 
29
  case 'section_enable_plugin_feature_wordpress_lockdown' :
30
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
@@ -64,7 +64,7 @@ class Strings extends Base\Strings {
64
  break;
65
 
66
  default:
67
- return parent::getSectionStrings( $sSectionSlug );
68
  }
69
 
70
  return [
@@ -75,15 +75,15 @@ class Strings extends Base\Strings {
75
  }
76
 
77
  /**
78
- * @param string $sOptKey
79
  * @return array
80
  * @throws \Exception
81
  */
82
- public function getOptionStrings( $sOptKey ) {
83
 
84
  $sModName = $this->getMod()->getMainFeatureName();
85
 
86
- switch ( $sOptKey ) {
87
 
88
  case 'enable_lockdown' :
89
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -132,6 +132,17 @@ class Strings extends Base\Strings {
132
  $sDescription = __( 'Remove a meta tag from your WordPress pages that publicly displays that your site is WordPress and its current version.', 'wp-simple-firewall' );
133
  break;
134
 
 
 
 
 
 
 
 
 
 
 
 
135
  case 'block_author_discovery' :
136
  $sName = __( 'Block Username Fishing', 'wp-simple-firewall' );
137
  $sSummary = __( 'Block the ability to discover WordPress usernames based on author IDs', 'wp-simple-firewall' );
@@ -140,7 +151,7 @@ class Strings extends Base\Strings {
140
  break;
141
 
142
  default:
143
- return parent::getOptionStrings( $sOptKey );
144
  }
145
 
146
  return [
18
  }
19
 
20
  /**
21
+ * @param string $section
22
  * @return array
23
  * @throws \Exception
24
  */
25
+ public function getSectionStrings( $section ) {
26
 
27
+ switch ( $section ) {
28
 
29
  case 'section_enable_plugin_feature_wordpress_lockdown' :
30
  $sTitleShort = sprintf( '%s/%s', __( 'On', 'wp-simple-firewall' ), __( 'Off', 'wp-simple-firewall' ) );
64
  break;
65
 
66
  default:
67
+ return parent::getSectionStrings( $section );
68
  }
69
 
70
  return [
75
  }
76
 
77
  /**
78
+ * @param string $key
79
  * @return array
80
  * @throws \Exception
81
  */
82
+ public function getOptionStrings( $key ) {
83
 
84
  $sModName = $this->getMod()->getMainFeatureName();
85
 
86
+ switch ( $key ) {
87
 
88
  case 'enable_lockdown' :
89
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
132
  $sDescription = __( 'Remove a meta tag from your WordPress pages that publicly displays that your site is WordPress and its current version.', 'wp-simple-firewall' );
133
  break;
134
 
135
+ case 'clean_wp_rubbish' :
136
+ $sName = __( 'Clean WP Files', 'wp-simple-firewall' );
137
+ $sSummary = __( 'Automatically Delete Unnecessary WP Files', 'wp-simple-firewall' );
138
+ $sDescription = [
139
+ __( "Automatically delete WordPress files that aren't necessary.", 'wp-simple-firewall' ),
140
+ __( "The cleanup process runs once each day.", 'wp-simple-firewall' ),
141
+ sprintf( '%s: <code>%s</code>', __( 'Files Deleted', 'wp-simple-firewall' ),
142
+ implode( '</code><code>', [ 'wp-config-sample.php', 'readme.html', 'license.txt' ] ) )
143
+ ];
144
+ break;
145
+
146
  case 'block_author_discovery' :
147
  $sName = __( 'Block Username Fishing', 'wp-simple-firewall' );
148
  $sSummary = __( 'Block the ability to discover WordPress usernames based on author IDs', 'wp-simple-firewall' );
151
  break;
152
 
153
  default:
154
+ return parent::getOptionStrings( $key );
155
  }
156
 
157
  return [
src/lib/src/Modules/Lockdown/UI.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Lockdown;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class UI extends Base\ShieldUI {
8
+
9
+ /**
10
+ * @return array
11
+ */
12
+ public function getInsightsConfigCardData() {
13
+ /** @var \ICWP_WPSF_FeatureHandler_Lockdown $mod */
14
+ $mod = $this->getMod();
15
+ /** @var Options $opts */
16
+ $opts = $this->getOptions();
17
+
18
+ $data = [
19
+ 'strings' => [
20
+ 'title' => __( 'WordPress Lockdown', 'wp-simple-firewall' ),
21
+ 'sub' => __( 'Restrict WP Functionality e.g. XMLRPC & REST API', 'wp-simple-firewall' ),
22
+ ],
23
+ 'key_opts' => [],
24
+ 'href_options' => $mod->getUrl_AdminPage()
25
+ ];
26
+
27
+ if ( !$mod->isModOptEnabled() ) {
28
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
29
+ }
30
+ else {
31
+ $bEditingDisabled = $opts->isOptFileEditingDisabled() || !current_user_can( 'edit_plugins' );
32
+ $data[ 'key_opts' ][ 'editing' ] = [
33
+ 'name' => __( 'File Editing via WP', 'wp-simple-firewall' ),
34
+ 'enabled' => $bEditingDisabled,
35
+ 'summary' => $bEditingDisabled ?
36
+ __( 'File editing is disabled', 'wp-simple-firewall' )
37
+ : __( "File editing is permitted through WP admin", 'wp-simple-firewall' ),
38
+ 'weight' => 2,
39
+ 'href' => $mod->getUrl_DirectLinkToOption( 'disable_file_editing' ),
40
+ ];
41
+
42
+ $bXml = $opts->isXmlrpcDisabled();
43
+ $data[ 'key_opts' ][ 'xml' ] = [
44
+ 'name' => __( 'XML-RPC', 'wp-simple-firewall' ),
45
+ 'enabled' => $bXml,
46
+ 'summary' => $bXml ?
47
+ __( 'XML-RPC is disabled', 'wp-simple-firewall' )
48
+ : __( "XML-RPC is not blocked", 'wp-simple-firewall' ),
49
+ 'weight' => 1,
50
+ 'href' => $mod->getUrl_DirectLinkToOption( 'disable_xmlrpc' ),
51
+ ];
52
+
53
+ $bApi = $opts->isRestApiAnonymousAccessDisabled();
54
+ $data[ 'key_opts' ][ 'api' ] = [
55
+ 'name' => __( 'REST API', 'wp-simple-firewall' ),
56
+ 'enabled' => $bApi,
57
+ 'summary' => $bApi ?
58
+ __( 'Anonymous REST API is disabled', 'wp-simple-firewall' )
59
+ : __( "Anonymous REST API is allowed", 'wp-simple-firewall' ),
60
+ 'weight' => 1,
61
+ 'href' => $mod->getUrl_DirectLinkToOption( 'disable_anonymous_restapi' ),
62
+ ];
63
+ }
64
+
65
+ return $data;
66
+ }
67
+
68
+ /**
69
+ * @return array
70
+ */
71
+ public function getInsightsNoticesData() {
72
+ /** @var \ICWP_WPSF_FeatureHandler_Lockdown $mod */
73
+ $mod = $this->getMod();
74
+ /** @var Options $opts */
75
+ $opts = $this->getOptions();
76
+
77
+ $notices = [
78
+ 'title' => __( 'WP Lockdown', 'wp-simple-firewall' ),
79
+ 'messages' => []
80
+ ];
81
+
82
+ { //edit plugins
83
+ $bEditingDisabled = $opts->isOptFileEditingDisabled() || !current_user_can( 'edit_plugins' );
84
+ if ( !$bEditingDisabled ) { //assumes current user is admin
85
+ $notices[ 'messages' ][ 'disallow_file_edit' ] = [
86
+ 'title' => __( 'File Editing via WP', 'wp-simple-firewall' ),
87
+ 'message' => __( 'Direct editing of plugin/theme files is permitted.', 'wp-simple-firewall' ),
88
+ 'href' => $mod->getUrl_DirectLinkToOption( 'disable_file_editing' ),
89
+ 'action' => sprintf( __( 'Go To %s', 'wp-simple-firewall' ), __( 'Options', 'wp-simple-firewall' ) ),
90
+ 'rec' => __( 'WP Plugin file editing should be disabled.', 'wp-simple-firewall' )
91
+ ];
92
+ }
93
+ }
94
+
95
+ return $notices;
96
+ }
97
+ }
src/lib/src/Modules/LoginGuard/AjaxHandler.php CHANGED
@@ -9,12 +9,12 @@ use FernleafSystems\Wordpress\Services\Services;
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
11
  /**
12
- * @param string $sAction
13
  * @return array
14
  */
15
- protected function processAjaxAction( $sAction ) {
16
 
17
- switch ( $sAction ) {
18
  case 'gen_backup_codes':
19
  $aResponse = $this->ajaxExec_GenBackupCodes();
20
  break;
@@ -40,7 +40,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
40
  break;
41
 
42
  default:
43
- $aResponse = parent::processAjaxAction( $sAction );
44
  }
45
 
46
  return $aResponse;
9
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
10
 
11
  /**
12
+ * @param string $action
13
  * @return array
14
  */
15
+ protected function processAjaxAction( $action ) {
16
 
17
+ switch ( $action ) {
18
  case 'gen_backup_codes':
19
  $aResponse = $this->ajaxExec_GenBackupCodes();
20
  break;
40
  break;
41
 
42
  default:
43
+ $aResponse = parent::processAjaxAction( $action );
44
  }
45
 
46
  return $aResponse;
src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php CHANGED
@@ -3,10 +3,9 @@
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
6
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
7
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
 
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib\Captcha\CaptchaConfigVO;
9
- use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib\TestCacheDirWrite;
10
  use FernleafSystems\Wordpress\Services\Services;
11
 
12
  class AntibotSetup {
@@ -24,31 +23,31 @@ class AntibotSetup {
24
  }
25
 
26
  private function run() {
27
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
28
- $oMod = $this->getMod();
29
- /** @var LoginGuard\Options $oOpts */
30
- $oOpts = $this->getOptions();
31
 
32
  $aProtectionProviders = [];
33
- if ( $oOpts->isEnabledCooldown() && $oMod->canCacheDirWrite() ) {
34
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\CoolDown() )
35
- ->setMod( $oMod );
36
  }
37
 
38
- if ( $oOpts->isEnabledGaspCheck() ) {
39
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\GaspJs() )
40
- ->setMod( $oMod );
41
  }
42
 
43
- if ( $oMod->isEnabledCaptcha() ) {
44
- $oCfg = $oMod->getCaptchaCfg();
45
  if ( $oCfg->provider === CaptchaConfigVO::PROV_GOOGLE_RECAP2 ) {
46
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\GoogleRecaptcha() )
47
- ->setMod( $oMod );
48
  }
49
  elseif ( $oCfg->provider === CaptchaConfigVO::PROV_HCAPTCHA ) {
50
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\HCaptcha() )
51
- ->setMod( $oMod );
52
  }
53
  }
54
 
@@ -85,13 +84,16 @@ class AntibotSetup {
85
  if ( @class_exists( 'WooCommerce' ) ) {
86
  $aFormProviders[] = new AntiBot\FormProviders\WooCommerce();
87
  }
 
 
 
88
  if ( false && @class_exists( 'UserRegistration' ) && @function_exists( 'UR' ) ) {
89
  $aFormProviders[] = new AntiBot\FormProviders\UserRegistration();
90
  }
91
  }
92
 
93
  foreach ( $aFormProviders as $oForm ) {
94
- $oForm->setMod( $oMod )->run();
95
  }
96
  }
97
  }
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
4
 
5
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
 
6
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
8
  use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib\Captcha\CaptchaConfigVO;
 
9
  use FernleafSystems\Wordpress\Services\Services;
10
 
11
  class AntibotSetup {
23
  }
24
 
25
  private function run() {
26
+ /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $mod */
27
+ $mod = $this->getMod();
28
+ /** @var LoginGuard\Options $opts */
29
+ $opts = $this->getOptions();
30
 
31
  $aProtectionProviders = [];
32
+ if ( $opts->isEnabledCooldown() && $mod->canCacheDirWrite() ) {
33
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\CoolDown() )
34
+ ->setMod( $mod );
35
  }
36
 
37
+ if ( $opts->isEnabledGaspCheck() ) {
38
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\GaspJs() )
39
+ ->setMod( $mod );
40
  }
41
 
42
+ if ( $mod->isEnabledCaptcha() ) {
43
+ $oCfg = $mod->getCaptchaCfg();
44
  if ( $oCfg->provider === CaptchaConfigVO::PROV_GOOGLE_RECAP2 ) {
45
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\GoogleRecaptcha() )
46
+ ->setMod( $mod );
47
  }
48
  elseif ( $oCfg->provider === CaptchaConfigVO::PROV_HCAPTCHA ) {
49
  $aProtectionProviders[] = ( new AntiBot\ProtectionProviders\HCaptcha() )
50
+ ->setMod( $mod );
51
  }
52
  }
53
 
84
  if ( @class_exists( 'WooCommerce' ) ) {
85
  $aFormProviders[] = new AntiBot\FormProviders\WooCommerce();
86
  }
87
+ if ( defined( 'WPMEM_VERSION' ) && function_exists( 'wpmem_init' ) ) {
88
+ $aFormProviders[] = new AntiBot\FormProviders\WPMembers();
89
+ }
90
  if ( false && @class_exists( 'UserRegistration' ) && @function_exists( 'UR' ) ) {
91
  $aFormProviders[] = new AntiBot\FormProviders\UserRegistration();
92
  }
93
  }
94
 
95
  foreach ( $aFormProviders as $oForm ) {
96
+ $oForm->setMod( $mod )->run();
97
  }
98
  }
99
  }
src/lib/src/Modules/LoginGuard/Lib/AntiBot/FormProviders/MemberPress.php CHANGED
@@ -30,7 +30,7 @@ class MemberPress extends BaseFormProvider {
30
  * @return array
31
  */
32
  public function checkLogin( $aErrors ) {
33
- if ( !empty( $aErrors ) ) {
34
  try {
35
  $this->setActionToAudit( 'memberpress-login' )
36
  ->checkProviders();
@@ -47,8 +47,7 @@ class MemberPress extends BaseFormProvider {
47
  * @return array
48
  */
49
  public function checkLostPassword( $aErrors ) {
50
- error_log( __FUNCTION__ );
51
- if ( !empty( $aErrors ) ) {
52
  try {
53
  $this->setActionToAudit( 'memberpress-lostpassword' )
54
  ->checkProviders();
@@ -66,7 +65,7 @@ class MemberPress extends BaseFormProvider {
66
  * @return string[]
67
  */
68
  public function checkRegister( $aErrors ) {
69
- if ( !empty( $aErrors ) ) {
70
  try {
71
  $this->setActionToAudit( 'memberpress-register' )
72
  ->checkProviders();
30
  * @return array
31
  */
32
  public function checkLogin( $aErrors ) {
33
+ if ( empty( $aErrors ) ) {
34
  try {
35
  $this->setActionToAudit( 'memberpress-login' )
36
  ->checkProviders();
47
  * @return array
48
  */
49
  public function checkLostPassword( $aErrors ) {
50
+ if ( empty( $aErrors ) ) {
 
51
  try {
52
  $this->setActionToAudit( 'memberpress-lostpassword' )
53
  ->checkProviders();
65
  * @return string[]
66
  */
67
  public function checkRegister( $aErrors ) {
68
+ if ( empty( $aErrors ) ) {
69
  try {
70
  $this->setActionToAudit( 'memberpress-register' )
71
  ->checkProviders();
src/lib/src/Modules/LoginGuard/Lib/AntiBot/FormProviders/WPMembers.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot\FormProviders;
4
+
5
+ /**
6
+ * Class WPMembers
7
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot\FormProviders
8
+ * https://wordpress.org/plugins/wp-members/
9
+ */
10
+ class WPMembers extends BaseFormProvider {
11
+
12
+ protected function register() {
13
+ add_action( 'wpmem_pre_register_data', [ $this, 'checkRegister' ], 5, 0 );
14
+ }
15
+
16
+ protected function lostpassword() {
17
+ add_action( 'wpmem_pwdreset_args', [ $this, 'checkLostPassword' ], 5, 1 );
18
+ }
19
+
20
+ /**
21
+ * Again, nowhere to add custom validation so we hack it a little and clear
22
+ * the argument for user and email and this triggers a failure.
23
+ * @param array $args
24
+ * @return array
25
+ */
26
+ public function checkLostPassword( array $args ) {
27
+ try {
28
+ $this->setActionToAudit( 'wpmembers-lostpassword' )
29
+ ->checkProviders();
30
+ }
31
+ catch ( \Exception $oE ) {
32
+ $args[ 'user' ] = null;
33
+ $args[ 'email' ] = null;
34
+ }
35
+ return $args;
36
+ }
37
+
38
+ /**
39
+ * Offers no direct validation filter, so we jump in right before the DB insert.
40
+ */
41
+ public function checkRegister() {
42
+ try {
43
+ $this->setActionToAudit( 'wpmembers-register' )
44
+ ->checkProviders();
45
+ }
46
+ catch ( \Exception $oE ) {
47
+ global $wpmem_themsg;
48
+ $wpmem_themsg = $oE->getMessage();
49
+ }
50
+ }
51
+ }
src/lib/src/Modules/LoginGuard/Lib/AntiBot/ProtectionProviders/GaspJs.php CHANGED
@@ -70,19 +70,19 @@ class GaspJs extends BaseProtectionProvider {
70
  }
71
 
72
  public function onWpEnqueueJs() {
73
- $oCon = $this->getCon();
74
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
75
- $oMod = $this->getMod();
76
  /** @var LoginGuard\Options $oOpts */
77
  $oOpts = $this->getOptions();
78
 
79
  $sAsset = 'shield-antibot';
80
- $sUnique = $oMod->prefix( $sAsset );
81
  wp_register_script(
82
  $sUnique,
83
- $oCon->getPluginUrl_Js( $sAsset ),
84
  [ 'jquery' ],
85
- $oCon->getVersion()
86
  );
87
  wp_enqueue_script( $sUnique );
88
 
@@ -92,15 +92,15 @@ class GaspJs extends BaseProtectionProvider {
92
  [
93
  'form_selectors' => implode( ',', $oOpts->getAntiBotFormSelectors() ),
94
  'uniq' => preg_replace( '#[^a-zA-Z0-9]#', '', apply_filters( 'icwp_shield_lp_gasp_uniqid', uniqid() ) ),
95
- 'cbname' => $oMod->getGaspKey(),
96
  'strings' => [
97
- 'label' => $oMod->getTextImAHuman(),
98
- 'alert' => $oMod->getTextPleaseCheckBox(),
99
  'loading' => __( 'Loading', 'wp-simple-firewall' )
100
  ],
101
  'flags' => [
102
  'gasp' => $oOpts->isEnabledGaspCheck(),
103
- 'captcha' => $oMod->isEnabledCaptcha(),
104
  ]
105
  ]
106
  );
70
  }
71
 
72
  public function onWpEnqueueJs() {
73
+ $con = $this->getCon();
74
+ /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $mod */
75
+ $mod = $this->getMod();
76
  /** @var LoginGuard\Options $oOpts */
77
  $oOpts = $this->getOptions();
78
 
79
  $sAsset = 'shield-antibot';
80
+ $sUnique = $con->prefix( $sAsset );
81
  wp_register_script(
82
  $sUnique,
83
+ $con->getPluginUrl_Js( $sAsset ),
84
  [ 'jquery' ],
85
+ $con->getVersion()
86
  );
87
  wp_enqueue_script( $sUnique );
88
 
92
  [
93
  'form_selectors' => implode( ',', $oOpts->getAntiBotFormSelectors() ),
94
  'uniq' => preg_replace( '#[^a-zA-Z0-9]#', '', apply_filters( 'icwp_shield_lp_gasp_uniqid', uniqid() ) ),
95
+ 'cbname' => $mod->getGaspKey(),
96
  'strings' => [
97
+ 'label' => $mod->getTextImAHuman(),
98
+ 'alert' => $mod->getTextPleaseCheckBox(),
99
  'loading' => __( 'Loading', 'wp-simple-firewall' )
100
  ],
101
  'flags' => [
102
  'gasp' => $oOpts->isEnabledGaspCheck(),
103
+ 'captcha' => $mod->isEnabledCaptcha(),
104
  ]
105
  ]
106
  );
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php CHANGED
@@ -11,8 +11,6 @@ class LoginIntentPage {
11
 
12
  use MfaControllerConsumer;
13
 
14
- /**
15
- */
16
  public function loadPage() {
17
  echo $this->renderPage();
18
  }
@@ -22,25 +20,25 @@ class LoginIntentPage {
22
  */
23
  public function renderForm() {
24
  $oIC = $this->getMfaCon();
25
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
26
- $oMod = $oIC->getMod();
27
- /** @var LoginGuard\Options $oOpts */
28
- $oOpts = $oIC->getOptions();
29
- $oCon = $oIC->getCon();
30
- $oReq = Services::Request();
31
- $oWP = Services::WpGeneral();
32
-
33
- $oNotice = $oCon->getAdminNotices()->getFlashNotice();
34
  if ( $oNotice instanceof NoticeVO ) {
35
  $sMessage = $oNotice->render_data[ 'message' ];
36
  }
37
  else {
38
- $sMessage = $oOpts->isChainedAuth() ?
39
  __( 'Please supply all authentication codes', 'wp-simple-firewall' )
40
  : __( 'Please supply at least 1 authentication code', 'wp-simple-firewall' );
41
  }
42
 
43
- $sReferUrl = $oReq->server( 'HTTP_REFERER', '' );
44
  if ( strpos( $sReferUrl, '?' ) ) {
45
  list( $sReferUrl, $sReferQuery ) = explode( '?', $sReferUrl, 2 );
46
  }
@@ -56,17 +54,17 @@ class LoginIntentPage {
56
  }
57
  }
58
  if ( empty( $sRedirectTo ) ) {
59
- $sRedirectTo = rawurlencode( $oReq->post( 'redirect_to', $oReq->getUri() ) );
60
  }
61
 
62
- $sCancelHref = $oReq->post( 'cancel_href', '' );
63
  if ( empty( $sCancelHref ) && Services::Data()->isValidWebUrl( $sReferUrl ) ) {
64
  $sCancelHref = parse_url( $sReferUrl, PHP_URL_PATH );
65
  }
66
 
67
- $nMfaSkip = (int)( $oOpts->getMfaSkip()/DAY_IN_SECONDS );
68
- $nTimeRemaining = $oMod->getSession()->login_intent_expires_at - $oReq->ts();
69
- $aDisplayData = [
70
  'strings' => [
71
  'cancel' => __( 'Cancel Login', 'wp-simple-firewall' ),
72
  'time_remaining' => __( 'Time Remaining', 'wp-simple-firewall' ),
@@ -89,21 +87,25 @@ class LoginIntentPage {
89
  ) ),
90
  'time_remaining' => $nTimeRemaining,
91
  'message_type' => 'info',
92
- 'login_intent_flag' => $oMod->getLoginIntentRequestFlag(),
93
  ],
94
  'hrefs' => [
95
- 'form_action' => parse_url( $oWP->getAdminUrl( '', true ), PHP_URL_PATH ),
96
  'redirect_to' => $sRedirectTo,
97
  'cancel_href' => $sCancelHref
98
  ],
99
  'flags' => [
100
- 'can_skip_mfa' => $oOpts->isMfaSkip(),
101
- 'show_branded_links' => !$oMod->isWlEnabled(), // white label mitigation
102
  ]
103
  ];
104
 
105
- return $oMod->renderTemplate( '/snippets/login_intent/form.twig',
106
- Services::DataManipulation()->mergeArraysRecursive( $oMod->getBaseDisplayData(), $aDisplayData ), true );
 
 
 
 
107
  }
108
 
109
  /**
@@ -162,6 +164,7 @@ class LoginIntentPage {
162
  }
163
 
164
  return $oMod->renderTemplate( '/pages/login_intent/index.twig',
165
- Services::DataManipulation()->mergeArraysRecursive( $oMod->getBaseDisplayData(), $aDisplayData ), true );
 
166
  }
167
  }
11
 
12
  use MfaControllerConsumer;
13
 
 
 
14
  public function loadPage() {
15
  echo $this->renderPage();
16
  }
20
  */
21
  public function renderForm() {
22
  $oIC = $this->getMfaCon();
23
+ /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $mod */
24
+ $mod = $oIC->getMod();
25
+ /** @var LoginGuard\Options $opts */
26
+ $opts = $oIC->getOptions();
27
+ $con = $oIC->getCon();
28
+ $req = Services::Request();
29
+ $WP = Services::WpGeneral();
30
+
31
+ $oNotice = $con->getAdminNotices()->getFlashNotice();
32
  if ( $oNotice instanceof NoticeVO ) {
33
  $sMessage = $oNotice->render_data[ 'message' ];
34
  }
35
  else {
36
+ $sMessage = $opts->isChainedAuth() ?
37
  __( 'Please supply all authentication codes', 'wp-simple-firewall' )
38
  : __( 'Please supply at least 1 authentication code', 'wp-simple-firewall' );
39
  }
40
 
41
+ $sReferUrl = $req->server( 'HTTP_REFERER', '' );
42
  if ( strpos( $sReferUrl, '?' ) ) {
43
  list( $sReferUrl, $sReferQuery ) = explode( '?', $sReferUrl, 2 );
44
  }
54
  }
55
  }
56
  if ( empty( $sRedirectTo ) ) {
57
+ $sRedirectTo = rawurlencode( $req->post( 'redirect_to', $req->getUri() ) );
58
  }
59
 
60
+ $sCancelHref = $req->post( 'cancel_href', '' );
61
  if ( empty( $sCancelHref ) && Services::Data()->isValidWebUrl( $sReferUrl ) ) {
62
  $sCancelHref = parse_url( $sReferUrl, PHP_URL_PATH );
63
  }
64
 
65
+ $nMfaSkip = (int)( $opts->getMfaSkip()/DAY_IN_SECONDS );
66
+ $nTimeRemaining = $mod->getSession()->login_intent_expires_at - $req->ts();
67
+ $data = [
68
  'strings' => [
69
  'cancel' => __( 'Cancel Login', 'wp-simple-firewall' ),
70
  'time_remaining' => __( 'Time Remaining', 'wp-simple-firewall' ),
87
  ) ),
88
  'time_remaining' => $nTimeRemaining,
89
  'message_type' => 'info',
90
+ 'login_intent_flag' => $mod->getLoginIntentRequestFlag(),
91
  ],
92
  'hrefs' => [
93
+ 'form_action' => parse_url( $WP->getAdminUrl( '', true ), PHP_URL_PATH ),
94
  'redirect_to' => $sRedirectTo,
95
  'cancel_href' => $sCancelHref
96
  ],
97
  'flags' => [
98
+ 'can_skip_mfa' => $opts->isMfaSkip(),
99
+ 'show_branded_links' => !$mod->isWlEnabled(), // white label mitigation
100
  ]
101
  ];
102
 
103
+ return $mod->renderTemplate(
104
+ '/snippets/login_intent/form.twig',
105
+ Services::DataManipulation()->mergeArraysRecursive(
106
+ $mod->getUIHandler()->getBaseDisplayData(), $data ),
107
+ true
108
+ );
109
  }
110
 
111
  /**
164
  }
165
 
166
  return $oMod->renderTemplate( '/pages/login_intent/index.twig',
167
+ Services::DataManipulation()->mergeArraysRecursive(
168
+ $oMod->getUIHandler()->getBaseDisplayData(), $aDisplayData ), true );
169
  }
170
  }
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/CustomForms.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Profiles;
4
+
5
+ use FernleafSystems\Utilities\Logic\OneTimeExecute;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\MfaControllerConsumer;
7
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider\BaseProvider;
8
+ use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpUserConsumer;
9
+
10
+ class CustomForms {
11
+
12
+ use OneTimeExecute;
13
+ use MfaControllerConsumer;
14
+ use WpUserConsumer;
15
+
16
+ /**
17
+ * @var BaseProvider[]
18
+ */
19
+ private $aWorkingProviders = [];
20
+
21
+ public function run() {
22
+ // Enqueue Javascript.
23
+ add_action( 'wp_enqueue_scripts', function () {
24
+ $this->enqueueAssets();
25
+ }, 0 );
26
+ add_action( 'wp_footer', function () {
27
+ $this->maybeDequeueAssets();
28
+ }, 0 );
29
+ add_action( 'custom_profile_form_output', function ( array $aProviders ) {
30
+ $this->renderCustomProfileFormOutput( $aProviders );
31
+ } );
32
+ }
33
+
34
+ /**
35
+ * @param string[] $aPs - list of limited provider slugs
36
+ */
37
+ private function renderCustomProfileFormOutput( array $aPs ) {
38
+ $oMC = $this->getMfaCon();
39
+ $oUser = $this->getWpUser();
40
+
41
+ $aProviders = $oMC->getProvidersForUser( $oUser, true );
42
+ if ( !empty( $aPs ) ) {
43
+ $aProviders = array_filter(
44
+ $aProviders,
45
+ function ( $oP ) use ( $aPs ) {
46
+ return in_array( $oP::SLUG, array_map( 'strtolower', $aPs ) );
47
+ }
48
+ );
49
+ }
50
+
51
+ if ( !empty( $aProviders ) ) {
52
+ $this->aWorkingProviders = $aProviders;
53
+ foreach ( $aProviders as $oP ) {
54
+ }
55
+ }
56
+ }
57
+
58
+ private function enqueueAssets() {
59
+ //enqueue in footer
60
+ }
61
+
62
+ private function maybeDequeueAssets() {
63
+ if ( empty( $this->aWorkingProviders ) ) {
64
+ //dequeue
65
+ }
66
+ }
67
+ }
src/lib/src/Modules/LoginGuard/Strings.php CHANGED
@@ -55,13 +55,13 @@ class Strings extends Base\Strings {
55
  }
56
 
57
  /**
58
- * @param string $sSectionSlug
59
  * @return array
60
  * @throws \Exception
61
  */
62
- public function getSectionStrings( $sSectionSlug ) {
63
 
64
- switch ( $sSectionSlug ) {
65
 
66
  case 'section_enable_plugin_feature_login_protection' :
67
  $sTitle = sprintf( __( 'Enable Module: %s', 'wp-simple-firewall' ), $this->getMod()
@@ -129,7 +129,7 @@ class Strings extends Base\Strings {
129
  break;
130
 
131
  default:
132
- return parent::getSectionStrings( $sSectionSlug );
133
  }
134
 
135
  return [
@@ -140,16 +140,16 @@ class Strings extends Base\Strings {
140
  }
141
 
142
  /**
143
- * @param string $sOptKey
144
  * @return array
145
  * @throws \Exception
146
  */
147
- public function getOptionStrings( $sOptKey ) {
148
- /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $oMod */
149
- $oMod = $this->getMod();
150
- $sModName = $oMod->getMainFeatureName();
151
 
152
- switch ( $sOptKey ) {
153
 
154
  case 'enable_login_protect' :
155
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
@@ -249,7 +249,7 @@ class Strings extends Base\Strings {
249
  $sSummary = __( 'Limit account access requests to every X seconds', 'wp-simple-firewall' );
250
  $sDescription = __( 'WordPress will process only ONE account access attempt per number of seconds specified.', 'wp-simple-firewall' )
251
  .'<br />'.__( 'Zero (0) turns this off.', 'wp-simple-firewall' )
252
- .' '.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $oMod->getOptions()
253
  ->getOptDefault( 'login_limit_interval' ) );
254
  break;
255
 
@@ -307,14 +307,14 @@ class Strings extends Base\Strings {
307
  $sName = __( 'GASP Checkbox Text', 'wp-simple-firewall' );
308
  $sSummary = __( 'The User Message Displayed Next To The GASP Checkbox', 'wp-simple-firewall' );
309
  $sDescription = __( "You can change the text displayed to the user beside the checkbox if you need a custom message.", 'wp-simple-firewall' )
310
- .'<br />'.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $oMod->getTextOptDefault( 'text_imahuman' ) );
311
  break;
312
 
313
  case 'text_pleasecheckbox' :
314
  $sName = __( 'GASP Alert Text', 'wp-simple-firewall' );
315
  $sSummary = __( "The Message Displayed If The User Doesn't Check The Box", 'wp-simple-firewall' );
316
  $sDescription = __( "You can change the text displayed to the user in the alert message if they don't check the box.", 'wp-simple-firewall' )
317
- .'<br />'.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $oMod->getTextOptDefault( 'text_pleasecheckbox' ) );
318
  break;
319
 
320
  // removed 9.0
@@ -325,7 +325,7 @@ class Strings extends Base\Strings {
325
  break;
326
 
327
  default:
328
- return parent::getOptionStrings( $sOptKey );
329
  }
330
 
331
  return [
55
  }
56
 
57
  /**
58
+ * @param string $section
59
  * @return array
60
  * @throws \Exception
61
  */
62
+ public function getSectionStrings( $section ) {
63
 
64
+ switch ( $section ) {
65
 
66
  case 'section_enable_plugin_feature_login_protection' :
67
  $sTitle = sprintf( __( 'Enable Module: %s', 'wp-simple-firewall' ), $this->getMod()
129
  break;
130
 
131
  default:
132
+ return parent::getSectionStrings( $section );
133
  }
134
 
135
  return [
140
  }
141
 
142
  /**
143
+ * @param string $key
144
  * @return array
145
  * @throws \Exception
146
  */
147
+ public function getOptionStrings( $key ) {
148
+ /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $mod */
149
+ $mod = $this->getMod();
150
+ $sModName = $mod->getMainFeatureName();
151
 
152
+ switch ( $key ) {
153
 
154
  case 'enable_login_protect' :
155
  $sName = sprintf( __( 'Enable %s Module', 'wp-simple-firewall' ), $sModName );
249
  $sSummary = __( 'Limit account access requests to every X seconds', 'wp-simple-firewall' );
250
  $sDescription = __( 'WordPress will process only ONE account access attempt per number of seconds specified.', 'wp-simple-firewall' )
251
  .'<br />'.__( 'Zero (0) turns this off.', 'wp-simple-firewall' )
252
+ .' '.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $this->getOptions()
253
  ->getOptDefault( 'login_limit_interval' ) );
254
  break;
255
 
307
  $sName = __( 'GASP Checkbox Text', 'wp-simple-firewall' );
308
  $sSummary = __( 'The User Message Displayed Next To The GASP Checkbox', 'wp-simple-firewall' );
309
  $sDescription = __( "You can change the text displayed to the user beside the checkbox if you need a custom message.", 'wp-simple-firewall' )
310
+ .'<br />'.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $mod->getTextOptDefault( 'text_imahuman' ) );
311
  break;
312
 
313
  case 'text_pleasecheckbox' :
314
  $sName = __( 'GASP Alert Text', 'wp-simple-firewall' );
315
  $sSummary = __( "The Message Displayed If The User Doesn't Check The Box", 'wp-simple-firewall' );
316
  $sDescription = __( "You can change the text displayed to the user in the alert message if they don't check the box.", 'wp-simple-firewall' )
317
+ .'<br />'.sprintf( '%s: %s', __( 'Default', 'wp-simple-firewall' ), $mod->getTextOptDefault( 'text_pleasecheckbox' ) );
318
  break;
319
 
320
  // removed 9.0
325
  break;
326
 
327
  default:
328
+ return parent::getOptionStrings( $key );
329
  }
330
 
331
  return [
src/lib/src/Modules/LoginGuard/UI.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+
7
+ class UI extends Base\ShieldUI {
8
+
9
+ /**
10
+ * @return array
11
+ */
12
+ public function getInsightsConfigCardData() {
13
+ /** @var \ICWP_WPSF_FeatureHandler_LoginProtect $mod */
14
+ $mod = $this->getMod();
15
+ /** @var Options $opts */
16
+ $opts = $this->getOptions();
17
+
18
+ $data = [
19
+ 'strings' => [
20
+ 'title' => __( 'Login Guard', 'wp-simple-firewall' ),
21
+ 'sub' => __( 'Brute Force Protection & Identity Verification', 'wp-simple-firewall' ),
22
+ ],
23
+ 'key_opts' => [],
24
+ 'href_options' => $mod->getUrl_AdminPage()
25
+ ];
26
+
27
+ if ( !$mod->isModOptEnabled() ) {
28
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
29
+ }
30
+ else {
31
+ $bHasBotCheck = $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha();
32
+
33
+ $bBotLogin = $bHasBotCheck && $opts->isProtectLogin();
34
+ $bBotRegister = $bHasBotCheck && $opts->isProtectRegister();
35
+ $bBotPassword = $bHasBotCheck && $opts->isProtectLostPassword();
36
+ $data[ 'key_opts' ][ 'bot_login' ] = [
37
+ 'name' => __( 'Brute Force Login', 'wp-simple-firewall' ),
38
+ 'enabled' => $bBotLogin,
39
+ 'summary' => $bBotLogin ?
40
+ __( 'Login forms are protected against bot attacks', 'wp-simple-firewall' )
41
+ : __( 'Login forms are not protected against brute force bot attacks', 'wp-simple-firewall' ),
42
+ 'weight' => 2,
43
+ 'href' => $mod->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
44
+ ];
45
+ $data[ 'key_opts' ][ 'bot_register' ] = [
46
+ 'name' => __( 'Bot User Register', 'wp-simple-firewall' ),
47
+ 'enabled' => $bBotRegister,
48
+ 'summary' => $bBotRegister ?
49
+ __( 'Registration forms are protected against bot attacks', 'wp-simple-firewall' )
50
+ : __( 'Registration forms are not protected against automated bots', 'wp-simple-firewall' ),
51
+ 'weight' => 2,
52
+ 'href' => $mod->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
53
+ ];
54
+ $data[ 'key_opts' ][ 'bot_password' ] = [
55
+ 'name' => __( 'Brute Force Lost Password', 'wp-simple-firewall' ),
56
+ 'enabled' => $bBotPassword,
57
+ 'summary' => $bBotPassword ?
58
+ __( 'Lost Password forms are protected against bot attacks', 'wp-simple-firewall' )
59
+ : __( 'Lost Password forms are not protected against automated bots', 'wp-simple-firewall' ),
60
+ 'weight' => 2,
61
+ 'href' => $mod->getUrl_DirectLinkToOption( 'bot_protection_locations' ),
62
+ ];
63
+
64
+ $bHas2Fa = $opts->isEmailAuthenticationActive()
65
+ || $opts->isEnabledGoogleAuthenticator() || $opts->isEnabledYubikey();
66
+ $data[ 'key_opts' ][ '2fa' ] = [
67
+ 'name' => __( 'Identity Verification', 'wp-simple-firewall' ),
68
+ 'enabled' => $bHas2Fa,
69
+ 'summary' => $bHas2Fa ?
70
+ __( 'At least 1 2FA option is enabled', 'wp-simple-firewall' )
71
+ : __( 'No 2FA options, such as Google Authenticator, are active', 'wp-simple-firewall' ),
72
+ 'weight' => 2,
73
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_2fa_email' ),
74
+ ];
75
+ }
76
+
77
+ return $data;
78
+ }
79
+
80
+ /**
81
+ * @param string $section
82
+ * @return array
83
+ */
84
+ protected function getSectionWarnings( $section ) {
85
+ $aWarnings = [];
86
+
87
+ if ( $section == 'section_brute_force_login_protection' && !$this->getCon()->isPremiumActive() ) {
88
+ $sIntegration = $this->getPremiumOnlyIntegration();
89
+ if ( !empty( $sIntegration ) ) {
90
+ $aWarnings[] = sprintf( __( 'Support for login protection with %s is a Pro-only feature.', 'wp-simple-firewall' ), $sIntegration );
91
+ }
92
+ }
93
+
94
+ if ( $section == 'section_2fa_email' ) {
95
+ $aWarnings[] =
96
+ __( '2FA by email demands that your WP site is properly configured to send email.', 'wp-simple-firewall' )
97
+ .'<br/>'.__( 'This is a common problem and you may get locked out in the future if you ignore this.', 'wp-simple-firewall' )
98
+ .' '.sprintf( '<a href="%s" target="_blank" class="alert-link">%s</a>', 'https://shsec.io/dd', __( 'Learn More.', 'wp-simple-firewall' ) );
99
+ }
100
+
101
+ return $aWarnings;
102
+ }
103
+
104
+ /**
105
+ * @return string
106
+ */
107
+ private function getPremiumOnlyIntegration() {
108
+ $aIntegrations = [
109
+ 'WooCommerce' => 'WooCommerce',
110
+ 'Easy_Digital_Downloads' => 'Easy Digital Downloads',
111
+ 'BuddyPress' => 'BuddyPress',
112
+ ];
113
+
114
+ $sIntegration = '';
115
+ foreach ( $aIntegrations as $classToIntegrate => $sName ) {
116
+ if ( class_exists( $classToIntegrate ) ) {
117
+ $sIntegration = $sName;
118
+ break;
119
+ }
120
+ }
121
+ return $sIntegration;
122
+ }
123
+ }
src/lib/src/Modules/Plugin/AdminNotices.php CHANGED
@@ -28,6 +28,10 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
28
  $this->buildNotice_PluginDisabled( $oNotice );
29
  break;
30
 
 
 
 
 
31
  case 'compat-sgoptimize':
32
  $this->buildNotice_CompatSgOptimize( $oNotice );
33
  break;
@@ -36,10 +40,6 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
36
  $this->buildNotice_PluginMailingListSignup( $oNotice );
37
  break;
38
 
39
- case 'plugin-update-available':
40
- $this->buildNotice_UpdateAvailable( $oNotice );
41
- break;
42
-
43
  case 'wizard_welcome':
44
  $this->buildNotice_WelcomeWizard( $oNotice );
45
  break;
@@ -337,13 +337,12 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
337
  $bNeeded = $oOpts->isPluginGloballyDisabled();
338
  break;
339
 
340
- case 'compat-sgoptimize':
341
- $bNeeded = ( new Plugin\Components\SiteGroundPluginCompatibility() )->testIsIncompatible();
342
  break;
343
 
344
- case 'plugin-update-available':
345
- $bNeeded = !Services::WpPost()->isPage_Updates()
346
- && Services::WpPlugins()->isUpdateAvailable( !Services::WpPost()->isPage_Updates() );
347
  break;
348
 
349
  case 'allow-tracking':
28
  $this->buildNotice_PluginDisabled( $oNotice );
29
  break;
30
 
31
+ case 'update-available':
32
+ $this->buildNotice_UpdateAvailable( $oNotice );
33
+ break;
34
+
35
  case 'compat-sgoptimize':
36
  $this->buildNotice_CompatSgOptimize( $oNotice );
37
  break;
40
  $this->buildNotice_PluginMailingListSignup( $oNotice );
41
  break;
42
 
 
 
 
 
43
  case 'wizard_welcome':
44
  $this->buildNotice_WelcomeWizard( $oNotice );
45
  break;
337
  $bNeeded = $oOpts->isPluginGloballyDisabled();
338
  break;
339
 
340
+ case 'update-available':
341
+ $bNeeded = Services::WpPlugins()->isUpdateAvailable( $oCon->getPluginBaseFile() );
342
  break;
343
 
344
+ case 'compat-sgoptimize':
345
+ $bNeeded = ( new Plugin\Components\SiteGroundPluginCompatibility() )->testIsIncompatible();
 
346
  break;
347
 
348
  case 'allow-tracking':
src/lib/src/Modules/Plugin/AjaxHandler.php CHANGED
@@ -10,11 +10,11 @@ use FernleafSystems\Wordpress\Services\Utilities\Net\FindSourceFromIp;
10
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
11
 
12
  /**
13
- * @param string $sAction
14
  * @return array
15
  */
16
- protected function processAjaxAction( $sAction ) {
17
- switch ( $sAction ) {
18
  case 'bulk_action':
19
  $aResponse = $this->ajaxExec_BulkItemAction();
20
  break;
@@ -64,7 +64,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
64
  break;
65
 
66
  default:
67
- $aResponse = parent::processAjaxAction( $sAction );
68
  }
69
 
70
  return $aResponse;
10
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
11
 
12
  /**
13
+ * @param string $action
14
  * @return array
15
  */
16
+ protected function processAjaxAction( $action ) {
17
+ switch ( $action ) {
18
  case 'bulk_action':
19
  $aResponse = $this->ajaxExec_BulkItemAction();
20
  break;
64
  break;
65
 
66
  default:
67
+ $aResponse = parent::processAjaxAction( $action );
68
  }
69
 
70
  return $aResponse;
src/lib/src/Modules/Plugin/Lib/ImportExport/Export.php CHANGED
@@ -121,9 +121,9 @@ class Export {
121
  */
122
  private function getExportData() {
123
  $aAll = [];
124
- foreach ( $this->getCon()->modules as $oMod ) {
125
- $oOpts = $oMod->getOptions();
126
- $aAll[ $oMod->getOptionsStorageKey() ] = array_diff_key(
127
  $oOpts->getTransferableOptions(),
128
  array_flip( $oOpts->getXferExcluded() )
129
  );
@@ -132,24 +132,24 @@ class Export {
132
  }
133
 
134
  /**
135
- * @param string $sUrl
136
  * @return bool
137
  */
138
- private function isUrlOnWhitelist( $sUrl ) {
139
- /** @var Plugin\Options $oOpts */
140
- $oOpts = $this->getOptions();
141
- return !empty( $sUrl ) && in_array( $sUrl, $oOpts->getImportExportWhitelist() );
142
  }
143
 
144
  /**
145
- * @param string $sUrl
146
  * @return bool
147
  */
148
- private function verifyUrlWithHandshake( $sUrl ) {
149
  $bVerified = false;
150
 
151
- if ( !empty( $sUrl ) ) {
152
- $sReqUrl = add_query_arg( [ 'shield_action' => 'importexport_handshake' ], $sUrl );
153
  $aResp = @json_decode( Services::HttpRequest()->getContent( $sReqUrl ), true );
154
  $bVerified = is_array( $aResp ) && isset( $aResp[ 'success' ] ) && ( $aResp[ 'success' ] === true );
155
  }
121
  */
122
  private function getExportData() {
123
  $aAll = [];
124
+ foreach ( $this->getCon()->modules as $mod ) {
125
+ $oOpts = $mod->getOptions();
126
+ $aAll[ $mod->getOptionsStorageKey() ] = array_diff_key(
127
  $oOpts->getTransferableOptions(),
128
  array_flip( $oOpts->getXferExcluded() )
129
  );
132
  }
133
 
134
  /**
135
+ * @param string $url
136
  * @return bool
137
  */
138
+ private function isUrlOnWhitelist( $url ) {
139
+ /** @var Plugin\Options $opts */
140
+ $opts = $this->getOptions();
141
+ return !empty( $url ) && in_array( $url, $opts->getImportExportWhitelist() );
142
  }
143
 
144
  /**
145
+ * @param string $url
146
  * @return bool
147
  */
148
+ private function verifyUrlWithHandshake( $url ) {
149
  $bVerified = false;
150
 
151
+ if ( !empty( $url ) ) {
152
+ $sReqUrl = add_query_arg( [ 'shield_action' => 'importexport_handshake' ], $url );
153
  $aResp = @json_decode( Services::HttpRequest()->getContent( $sReqUrl ), true );
154
  $bVerified = is_array( $aResp ) && isset( $aResp[ 'success' ] ) && ( $aResp[ 'success' ] === true );
155
  }
src/lib/src/Modules/Plugin/Lib/ImportExport/Import.php CHANGED
@@ -213,18 +213,18 @@ class Import {
213
  $bImported = false;
214
 
215
  $bAnythingChanged = false;
216
- foreach ( $this->getCon()->modules as $oTheMod ) {
217
- if ( !empty( $aImportData[ $oTheMod->getOptionsStorageKey() ] ) ) {
218
- $oTheseOpts = $oTheMod->getOptions();
219
  $oTheseOpts->setMultipleOptions(
220
  array_diff_key(
221
- $aImportData[ $oTheMod->getOptionsStorageKey() ],
222
  array_flip( $oTheseOpts->getXferExcluded() )
223
  )
224
  );
225
 
226
  $bAnythingChanged = $bAnythingChanged || $oTheseOpts->getNeedSave();
227
- $oTheMod->saveModOptions( true );
228
  }
229
  }
230
 
213
  $bImported = false;
214
 
215
  $bAnythingChanged = false;
216
+ foreach ( $this->getCon()->modules as $mod ) {
217
+ if ( !empty( $aImportData[ $mod->getOptionsStorageKey() ] ) ) {
218
+ $oTheseOpts = $mod->getOptions();
219
  $oTheseOpts->setMultipleOptions(
220
  array_diff_key(
221
+ $aImportData[ $mod->getOptionsStorageKey() ],
222
  array_flip( $oTheseOpts->getXferExcluded() )
223
  )
224
  );
225
 
226
  $bAnythingChanged = $bAnythingChanged || $oTheseOpts->getNeedSave();
227
+ $mod->saveModOptions( true );
228
  }
229
  }
230
 
src/lib/src/Modules/Plugin/Lib/Ops/ResetPlugin.php CHANGED
@@ -13,11 +13,11 @@ class ResetPlugin {
13
  use PluginControllerConsumer;
14
 
15
  public function run() {
16
- foreach ( $this->getCon()->modules as $oMod ) {
17
- $oMod->getOptions()
18
- ->setOptionsValues( [] )
19
- ->deleteStorage();
20
- $oMod->saveModOptions();
21
  }
22
  }
23
  }
13
  use PluginControllerConsumer;
14
 
15
  public function run() {
16
+ foreach ( $this->getCon()->modules as $mod ) {
17
+ $mod->getOptions()
18
+ ->setOptionsValues( [] )
19
+ ->deleteStorage();
20
+ $mod->saveModOptions();
21
  }
22
  }
23
  }
src/lib/src/Modules/Plugin/Options.php CHANGED
@@ -23,6 +23,7 @@ class Options extends Base\ShieldOptions {
23
 
24
  /**
25
  * @return string[]
 
26
  */
27
  public function getDbColumns_GeoIp() {
28
  return $this->getDef( 'geoip_table_columns' );
@@ -30,6 +31,7 @@ class Options extends Base\ShieldOptions {
30
 
31
  /**
32
  * @return string[]
 
33
  */
34
  public function getDbColumns_Notes() {
35
  return $this->getDef( 'db_notes_table_columns' );
23
 
24
  /**
25
  * @return string[]
26
+ * @deprecated 9.2.0
27
  */
28
  public function getDbColumns_GeoIp() {
29
  return $this->getDef( 'geoip_table_columns' );
31
 
32
  /**
33
  * @return string[]
34
+ * @deprecated 9.2.0
35
  */
36
  public function getDbColumns_Notes() {
37
  return $this->getDef( 'db_notes_table_columns' );
src/lib/src/Modules/Plugin/Strings.php CHANGED
@@ -51,14 +51,14 @@ class Strings extends Base\Strings {
51
  }
52
 
53
  /**
54
- * @param string $sSectionSlug
55
  * @return array
56
  * @throws \Exception
57
  */
58
- public function getSectionStrings( $sSectionSlug ) {
59
  $sPlugName = $this->getCon()->getHumanName();
60
 
61
- switch ( $sSectionSlug ) {
62
 
63
  case 'section_global_security_options' :
64
  $sTitle = __( 'Global Security Plugin Disable', 'wp-simple-firewall' );
@@ -113,7 +113,7 @@ class Strings extends Base\Strings {
113
  break;
114
 
115
  default:
116
- return parent::getSectionStrings( $sSectionSlug );
117
  }
118
 
119
  return [
@@ -124,18 +124,18 @@ class Strings extends Base\Strings {
124
  }
125
 
126
  /**
127
- * @param string $sOptKey
128
  * @return array
129
  * @throws \Exception
130
  */
131
- public function getOptionStrings( $sOptKey ) {
132
  /** @var \ICWP_WPSF_FeatureHandler_Plugin $oMod */
133
  $oMod = $this->getMod();
134
  /** @var Options $oOpts */
135
  $oOpts = $this->getOptions();
136
  $sPlugName = $this->getCon()->getHumanName();
137
 
138
- switch ( $sOptKey ) {
139
 
140
  case 'global_enable_plugin_features' :
141
  $sName = sprintf( __( 'Enable %s Protection', 'wp-simple-firewall' ), $sPlugName );
@@ -201,8 +201,8 @@ class Strings extends Base\Strings {
201
  $sDescription = [
202
  __( 'Enabling this option helps support the plugin by spreading the word about it on your website.', 'wp-simple-firewall' )
203
  .' '.__( 'The plugin badge also lets visitors know your are taking your website security seriously.', 'wp-simple-firewall' ),
 
204
  sprintf( '<strong><a href="%s" target="_blank">%s</a></strong>', 'https://shsec.io/wpsf20', __( 'Read this carefully before enabling this option.', 'wp-simple-firewall' ) ),
205
- __( "This also acts as an affiliate link if you're running ShieldPRO so you can earn rewards for each referral.", 'wp-simple-firewall' ),
206
  ];
207
  break;
208
 
@@ -227,24 +227,30 @@ class Strings extends Base\Strings {
227
  case 'importexport_enable' :
228
  $sName = __( 'Allow Import/Export', 'wp-simple-firewall' );
229
  $sSummary = __( 'Allow Import And Export Of Options On This Site', 'wp-simple-firewall' );
230
- $sDescription = __( 'Uncheck this box to completely disable import and export of options.', 'wp-simple-firewall' )
231
- .'<br />'.sprintf( '%s: %s', __( 'Note', 'wp-simple-firewall' ), __( 'Import/Export is a premium-only feature.', 'wp-simple-firewall' ) );
 
 
232
  break;
233
 
234
  case 'importexport_whitelist' :
235
  $sName = __( 'Export Whitelist', 'wp-simple-firewall' );
236
  $sSummary = __( 'Whitelisted Sites To Export Options From This Site', 'wp-simple-firewall' );
237
- $sDescription = __( 'Whitelisted sites may export options from this site without the key.', 'wp-simple-firewall' )
238
- .'<br />'.__( 'List each site URL on a new line.', 'wp-simple-firewall' )
239
- .'<br />'.__( 'This is to be used in conjunction with the Master Import Site feature.', 'wp-simple-firewall' );
 
 
240
  break;
241
 
242
  case 'importexport_masterurl' :
243
  $sName = __( 'Master Import Site', 'wp-simple-firewall' );
244
  $sSummary = __( 'Automatically Import Options From This Site URL', 'wp-simple-firewall' );
245
- $sDescription = __( "Supplying a site URL here will make this site an 'Options Slave'.", 'wp-simple-firewall' )
246
- .'<br />'.__( 'Options will be automatically exported from the Master site each day.', 'wp-simple-firewall' )
247
- .'<br />'.sprintf( '%s: %s', __( 'Warning', 'wp-simple-firewall' ), __( 'Use of this feature will overwrite existing options and replace them with those from the Master Import Site.', 'wp-simple-firewall' ) );
 
 
248
  break;
249
 
250
  case 'importexport_whitelist_notify' :
@@ -281,15 +287,19 @@ class Strings extends Base\Strings {
281
  case 'google_recaptcha_secret_key' :
282
  $sName = __( 'CAPTCHA Secret', 'wp-simple-firewall' );
283
  $sSummary = __( 'CAPTCHA Secret Key', 'wp-simple-firewall' );
284
- $sDescription = __( 'Enter your CAPTCHA secret key for use throughout the plugin.', 'wp-simple-firewall' )
285
- .'<br />'.sprintf( '<strong>%s</strong>: %s', __( 'Important', 'wp-simple-firewall' ), __( 'Google reCAPTCHA v3 not supported.', 'wp-simple-firewall' ) );
 
 
286
  break;
287
 
288
  case 'google_recaptcha_site_key' :
289
  $sName = __( 'CAPTCHA Site Key', 'wp-simple-firewall' );
290
  $sSummary = __( 'CAPTCHA Site Key', 'wp-simple-firewall' );
291
- $sDescription = __( 'Enter your CAPTCHA site key for use throughout the plugin.', 'wp-simple-firewall' )
292
- .'<br />'.sprintf( '<strong>%s</strong>: %s', __( 'Important', 'wp-simple-firewall' ), __( 'Google reCAPTCHA v3 not supported.', 'wp-simple-firewall' ) );
 
 
293
  break;
294
 
295
  case 'google_recaptcha_style' :
@@ -299,7 +309,7 @@ class Strings extends Base\Strings {
299
  break;
300
 
301
  default:
302
- return parent::getOptionStrings( $sOptKey );
303
  }
304
 
305
  return [
51
  }
52
 
53
  /**
54
+ * @param string $section
55
  * @return array
56
  * @throws \Exception
57
  */
58
+ public function getSectionStrings( $section ) {
59
  $sPlugName = $this->getCon()->getHumanName();
60
 
61
+ switch ( $section ) {
62
 
63
  case 'section_global_security_options' :
64
  $sTitle = __( 'Global Security Plugin Disable', 'wp-simple-firewall' );
113
  break;
114
 
115
  default:
116
+ return parent::getSectionStrings( $section );
117
  }
118
 
119
  return [
124
  }
125
 
126
  /**
127
+ * @param string $key
128
  * @return array
129
  * @throws \Exception
130
  */
131
+ public function getOptionStrings( $key ) {
132
  /** @var \ICWP_WPSF_FeatureHandler_Plugin $oMod */
133
  $oMod = $this->getMod();
134
  /** @var Options $oOpts */
135
  $oOpts = $this->getOptions();
136
  $sPlugName = $this->getCon()->getHumanName();
137
 
138
+ switch ( $key ) {
139
 
140
  case 'global_enable_plugin_features' :
141
  $sName = sprintf( __( 'Enable %s Protection', 'wp-simple-firewall' ), $sPlugName );
201
  $sDescription = [
202
  __( 'Enabling this option helps support the plugin by spreading the word about it on your website.', 'wp-simple-firewall' )
203
  .' '.__( 'The plugin badge also lets visitors know your are taking your website security seriously.', 'wp-simple-firewall' ),
204
+ __( "This also acts as an affiliate link if you're running ShieldPRO so you can earn rewards for each referral.", 'wp-simple-firewall' ),
205
  sprintf( '<strong><a href="%s" target="_blank">%s</a></strong>', 'https://shsec.io/wpsf20', __( 'Read this carefully before enabling this option.', 'wp-simple-firewall' ) ),
 
206
  ];
207
  break;
208
 
227
  case 'importexport_enable' :
228
  $sName = __( 'Allow Import/Export', 'wp-simple-firewall' );
229
  $sSummary = __( 'Allow Import And Export Of Options On This Site', 'wp-simple-firewall' );
230
+ $sDescription = [
231
+ __( 'Uncheck this box to completely disable import and export of options.', 'wp-simple-firewall' ),
232
+ sprintf( '%s: %s', __( 'Note', 'wp-simple-firewall' ), __( 'Import/Export is a premium-only feature.', 'wp-simple-firewall' ) )
233
+ ];
234
  break;
235
 
236
  case 'importexport_whitelist' :
237
  $sName = __( 'Export Whitelist', 'wp-simple-firewall' );
238
  $sSummary = __( 'Whitelisted Sites To Export Options From This Site', 'wp-simple-firewall' );
239
+ $sDescription = [
240
+ __( 'Whitelisted sites may export options from this site without the key.', 'wp-simple-firewall' ),
241
+ __( 'List each site URL on a new line.', 'wp-simple-firewall' ),
242
+ __( 'This is to be used in conjunction with the Master Import Site feature.', 'wp-simple-firewall' )
243
+ ];
244
  break;
245
 
246
  case 'importexport_masterurl' :
247
  $sName = __( 'Master Import Site', 'wp-simple-firewall' );
248
  $sSummary = __( 'Automatically Import Options From This Site URL', 'wp-simple-firewall' );
249
+ $sDescription = [
250
+ __( "Supplying a site URL here will make this site an 'Options Slave'.", 'wp-simple-firewall' ),
251
+ __( 'Options will be automatically exported from the Master site each day.', 'wp-simple-firewall' ),
252
+ sprintf( '%s: %s', __( 'Warning', 'wp-simple-firewall' ), __( 'Use of this feature will overwrite existing options and replace them with those from the Master Import Site.', 'wp-simple-firewall' ) )
253
+ ];
254
  break;
255
 
256
  case 'importexport_whitelist_notify' :
287
  case 'google_recaptcha_secret_key' :
288
  $sName = __( 'CAPTCHA Secret', 'wp-simple-firewall' );
289
  $sSummary = __( 'CAPTCHA Secret Key', 'wp-simple-firewall' );
290
+ $sDescription = [
291
+ __( 'Enter your CAPTCHA secret key for use throughout the plugin.', 'wp-simple-firewall' ),
292
+ sprintf( '<strong>%s</strong>: %s', __( 'Important', 'wp-simple-firewall' ), __( 'Google reCAPTCHA v3 not supported.', 'wp-simple-firewall' ) )
293
+ ];
294
  break;
295
 
296
  case 'google_recaptcha_site_key' :
297
  $sName = __( 'CAPTCHA Site Key', 'wp-simple-firewall' );
298
  $sSummary = __( 'CAPTCHA Site Key', 'wp-simple-firewall' );
299
+ $sDescription = [
300
+ __( 'Enter your CAPTCHA site key for use throughout the plugin.', 'wp-simple-firewall' ),
301
+ sprintf( '<strong>%s</strong>: %s', __( 'Important', 'wp-simple-firewall' ), __( 'Google reCAPTCHA v3 not supported.', 'wp-simple-firewall' ) )
302
+ ];
303
  break;
304
 
305
  case 'google_recaptcha_style' :
309
  break;
310
 
311
  default:
312
+ return parent::getOptionStrings( $key );
313
  }
314
 
315
  return [
src/lib/src/Modules/Plugin/UI.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib\Captcha\CheckCaptchaSettings;
7
+ use FernleafSystems\Wordpress\Services\Services;
8
+
9
+ class UI extends Base\ShieldUI {
10
+
11
+ /**
12
+ * @param array $aOptParams
13
+ * @return array
14
+ */
15
+ protected function buildOptionForUi( $aOptParams ) {
16
+ $aOptParams = parent::buildOptionForUi( $aOptParams );
17
+ if ( $aOptParams[ 'key' ] === 'visitor_address_source' ) {
18
+ $aNewOptions = [];
19
+ $oIPDet = Services::IP()->getIpDetector();
20
+ foreach ( $aOptParams[ 'value_options' ] as $sValKey => $sSource ) {
21
+ if ( $sValKey == 'AUTO_DETECT_IP' ) {
22
+ $aNewOptions[ $sValKey ] = $sSource;
23
+ }
24
+ else {
25
+ $sIPs = implode( ', ', $oIPDet->getIpsFromSource( $sSource ) );
26
+ $aNewOptions[ $sValKey ] = sprintf( '%s (%s)',
27
+ $sSource, empty( $sIPs ) ? '-' : $sIPs );
28
+ }
29
+ }
30
+ $aOptParams[ 'value_options' ] = $aNewOptions;
31
+ }
32
+ return $aOptParams;
33
+ }
34
+
35
+ /**
36
+ * @return array
37
+ */
38
+ public function getInsightsConfigCardData() {
39
+ /** @var \ICWP_WPSF_FeatureHandler_Plugin $mod */
40
+ $mod = $this->getMod();
41
+ /** @var Options $opts */
42
+ $opts = $this->getOptions();
43
+ $data = [
44
+ 'strings' => [
45
+ 'title' => __( 'General Settings', 'wp-simple-firewall' ),
46
+ 'sub' => sprintf( __( 'General %s Settings', 'wp-simple-firewall' ), $this->getCon()
47
+ ->getHumanName() ),
48
+ ],
49
+ 'key_opts' => [],
50
+ 'href_options' => $mod->getUrl_AdminPage()
51
+ ];
52
+
53
+ if ( $mod->isModOptEnabled() ) {
54
+ $data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
55
+ }
56
+ else {
57
+ $data[ 'key_opts' ][ 'editing' ] = [
58
+ 'name' => __( 'Visitor IP', 'wp-simple-firewall' ),
59
+ 'enabled' => true,
60
+ 'summary' => sprintf( __( 'Visitor IP address source is: %s', 'wp-simple-firewall' ),
61
+ __( $opts->getSelectOptionValueText( 'visitor_address_source' ), 'wp-simple-firewall' ) ),
62
+ 'weight' => 0,
63
+ 'href' => $mod->getUrl_DirectLinkToOption( 'visitor_address_source' ),
64
+ ];
65
+
66
+ $bHasSupportEmail = Services::Data()->validEmail( $opts->getOpt( 'block_send_email_address' ) );
67
+ $data[ 'key_opts' ][ 'reports' ] = [
68
+ 'name' => __( 'Reporting Email', 'wp-simple-firewall' ),
69
+ 'enabled' => $bHasSupportEmail,
70
+ 'summary' => $bHasSupportEmail ?
71
+ sprintf( __( 'Email address for reports set to: %s', 'wp-simple-firewall' ), $mod->getPluginReportEmail() )
72
+ : sprintf( __( 'No address provided - defaulting to: %s', 'wp-simple-firewall' ), $mod->getPluginReportEmail() ),
73
+ 'weight' => 0,
74
+ 'href' => $mod->getUrl_DirectLinkToOption( 'block_send_email_address' ),
75
+ ];
76
+
77
+ $bRecap = $mod->getCaptchaCfg()->ready;
78
+ $data[ 'key_opts' ][ 'recap' ] = [
79
+ 'name' => __( 'CAPTCHA', 'wp-simple-firewall' ),
80
+ 'enabled' => $bRecap,
81
+ 'summary' => $bRecap ?
82
+ __( 'CAPTCHA keys have been provided', 'wp-simple-firewall' )
83
+ : __( "CAPTCHA keys haven't been provided", 'wp-simple-firewall' ),
84
+ 'weight' => 1,
85
+ 'href' => $mod->getUrl_DirectLinkToSection( 'section_third_party_captcha' ),
86
+ ];
87
+ }
88
+
89
+ return $data;
90
+ }
91
+
92
+ /**
93
+ * @param string $section
94
+ * @return array
95
+ */
96
+ protected function getSectionWarnings( $section ) {
97
+ /** @var \ICWP_WPSF_FeatureHandler_Plugin $mod */
98
+ $mod = $this->getMod();
99
+ $opts = $this->getOptions();
100
+ $aWarnings = [];
101
+
102
+ switch ( $section ) {
103
+ case 'section_third_party_captcha':
104
+ if ( $mod->getCaptchaCfg()->ready ) {
105
+ if ( $opts->getOpt( 'captcha_checked_at' ) < 0 ) {
106
+ ( new CheckCaptchaSettings() )
107
+ ->setMod( $mod )
108
+ ->checkAll();
109
+ }
110
+ if ( $opts->getOpt( 'captcha_checked_at' ) == 0 ) {
111
+ $aWarnings[] = sprintf(
112
+ __( "Your captcha key and secret haven't been verified.", 'wp-simple-firewall' ).' '
113
+ .__( "Please double-check and make sure you haven't mixed them about, and then re-save.", 'wp-simple-firewall' )
114
+ );
115
+ }
116
+ }
117
+ break;
118
+ }
119
+
120
+ return $aWarnings;
121
+ }
122
+ }
src/lib/src/Modules/Reporting/Options.php CHANGED
@@ -8,6 +8,7 @@ class Options extends Base\ShieldOptions {
8
 
9
  /**
10
  * @return string[]
 
11
  */
12
  public function getDbColumns_Reports() {
13
  return $this->getDef( 'reports_table_columns' );
8
 
9
  /**
10
  * @return string[]
11
+ * @deprecated 9.2.0
12
  */
13
  public function getDbColumns_Reports() {
14
  return $this->getDef( 'reports_table_columns' );
src/lib/src/Modules/Reporting/Strings.php CHANGED
@@ -54,14 +54,14 @@ class Strings extends Base\Strings {
54
  }
55
 
56
  /**
57
- * @param string $sOptKey
58
  * @return array
59
  * @throws \Exception
60
  */
61
- public function getOptionStrings( $sOptKey ) {
62
  $oCon = $this->getCon();
63
 
64
- switch ( $sOptKey ) {
65
 
66
  case 'frequency_alert' :
67
  $sName = __( 'Alert Frequency', 'wp-simple-firewall' );
@@ -90,7 +90,7 @@ class Strings extends Base\Strings {
90
  break;
91
 
92
  default:
93
- return parent::getOptionStrings( $sOptKey );
94
  }
95
 
96
  return [
@@ -101,13 +101,13 @@ class Strings extends Base\Strings {
101
  }
102
 
103
  /**
104
- * @param string $sSectionSlug
105
  * @return array
106
  * @throws \Exception
107
  */
108
- public function getSectionStrings( $sSectionSlug ) {
109
 
110
- switch ( $sSectionSlug ) {
111
 
112
  case 'section_timings' :
113
  $sTitle = __( 'Report Frequencies', 'wp-simple-firewall' );
@@ -126,7 +126,7 @@ class Strings extends Base\Strings {
126
  break;
127
 
128
  default:
129
- return parent::getSectionStrings( $sSectionSlug );
130
  }
131
 
132
  return [
54
  }
55
 
56
  /**
57
+ * @param string $key
58
  * @return array
59
  * @throws \Exception
60
  */
61
+ public function getOptionStrings( $key ) {
62
  $oCon = $this->getCon();
63
 
64
+ switch ( $key ) {
65
 
66
  case 'frequency_alert' :
67
  $sName = __( 'Alert Frequency', 'wp-simple-firewall' );
90
  break;
91
 
92
  default:
93
+ return parent::getOptionStrings( $key );
94
  }
95
 
96
  return [
101
  }
102
 
103
  /**
104
+ * @param string $section
105
  * @return array
106
  * @throws \Exception
107
  */
108
+ public function getSectionStrings( $section ) {
109
 
110
+ switch ( $section ) {
111
 
112
  case 'section_timings' :
113
  $sTitle = __( 'Report Frequencies', 'wp-simple-firewall' );
126
  break;
127
 
128
  default:
129
+ return parent::getSectionStrings( $section );
130
  }
131
 
132
  return [
src/lib/src/Modules/SecurityAdmin/AdminNotices.php CHANGED
@@ -90,10 +90,8 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
90
  * @return bool
91
  */
92
  protected function isDisplayNeeded( $oNotice ) {
93
- /** @var \ICWP_WPSF_FeatureHandler_Ips $oMod */
94
- $oMod = $this->getMod();
95
  /** @var Options $oOpts */
96
- $oOpts = $oMod->getOptions();
97
 
98
  $sCurrentPage = Services::WpPost()->getCurrentPage();
99
 
90
  * @return bool
91
  */
92
  protected function isDisplayNeeded( $oNotice ) {
 
 
93
  /** @var Options $oOpts */
94
+ $oOpts = $this->getOptions();
95
 
96
  $sCurrentPage = Services::WpPost()->getCurrentPage();
97
 
src/lib/src/Modules/SecurityAdmin/AjaxHandler.php CHANGED
@@ -8,12 +8,12 @@ use FernleafSystems\Wordpress\Services\Services;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
- * @param string $sAction
12
  * @return array
13
  */
14
- protected function processAjaxAction( $sAction ) {
15
 
16
- switch ( $sAction ) {
17
  case 'sec_admin_check':
18
  $aResponse = $this->ajaxExec_SecAdminCheck();
19
  break;
@@ -32,7 +32,7 @@ class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
32
  break;
33
 
34
  default:
35
- $aResponse = parent::processAjaxAction( $sAction );
36
  }
37
 
38
  return $aResponse;
8
  class AjaxHandler extends Shield\Modules\Base\AjaxHandlerShield {
9
 
10
  /**
11
+ * @param string $action
12
  * @return array
13
  */
14
+ protected function processAjaxAction( $action ) {
15
 
16
+ switch ( $action ) {
17
  case 'sec_admin_check':
18
  $aResponse = $this->ajaxExec_SecAdminCheck();
19
  break;
32
  break;
33
 
34
  default:
35
+ $aResponse = parent::processAjaxAction( $action );
36
  }
37
 
38
  return $aResponse;
src/lib/src/Modules/SecurityAdmin/Lib/Actions/RemoveSecAdmin.php CHANGED
@@ -11,10 +11,10 @@ class RemoveSecAdmin {
11
  use ModConsumer;
12
 
13
  public function remove() {
14
- /** @var SecurityAdmin\Options $oOpts */
15
- $oOpts = $this->getOptions();
16
- if ( $oOpts->hasAccessKey() ) {
17
- $oOpts->clearSecurityAdminKey();
18
  $this->getMod()->saveModOptions();
19
  $this->sendNotificationEmail();
20
  }
11
  use ModConsumer;
12
 
13
  public function remove() {
14
+ /** @var SecurityAdmin\Options $opts */
15
+ $opts = $this->getOptions();
16
+ if ( $opts->hasSecurityPIN() ) {
17
+ $opts->clearSecurityAdminKey();
18
  $this->getMod()->saveModOptions();
19
  $this->sendNotificationEmail();
20
  }
src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php CHANGED
@@ -10,8 +10,6 @@ class ApplyLabels {
10
 
11
  use ModConsumer;
12
 
13
- /**
14
- */
15
  public function run() {
16
  $oCon = $this->getCon();
17
  add_action( 'init', [ $this, 'onWpInit' ] );
10
 
11
  use ModConsumer;
12
 
 
 
13
  public function run() {
14
  $oCon = $this->getCon();
15
  add_action( 'init', [ $this, 'onWpInit' ] );
src/lib/src/Modules/SecurityAdmin/Options.php CHANGED
@@ -61,31 +61,31 @@ class Options extends Base\ShieldOptions {
61
 
62
  /**
63
  * TODO: Bug where if $sType is defined, it'll be set to 'wp' anyway
64
- * @param string $sType - wp or wpms
65
  * @return array
66
  */
67
- public function getOptionsToRestrict( $sType = '' ) {
68
- $sType = empty( $sType ) ? ( Services::WpGeneral()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
69
  $aOptions = $this->getRestrictedOptions();
70
- return ( isset( $aOptions[ $sType.'_options' ] ) && is_array( $aOptions[ $sType.'_options' ] ) ) ? $aOptions[ $sType.'_options' ] : [];
71
  }
72
 
73
  /**
74
- * @param string $sType - wp or wpms
75
  * @return array
76
  */
77
- public function getOptionsPagesToRestrict( $sType = '' ) {
78
- $sType = empty( $sType ) ? ( Services::WpGeneral()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
79
  $aOptions = $this->getRestrictedOptions();
80
- return ( isset( $aOptions[ $sType.'_pages' ] ) && is_array( $aOptions[ $sType.'_pages' ] ) ) ? $aOptions[ $sType.'_pages' ] : [];
81
  }
82
 
83
  /**
84
  * @return array
85
  */
86
  public function getSecurityAdminUsers() {
87
- $aU = $this->getOpt( 'sec_admin_users', [] );
88
- return ( is_array( $aU ) && $this->isPremium() ) ? $aU : [];
89
  }
90
 
91
  /**
@@ -132,18 +132,17 @@ class Options extends Base\ShieldOptions {
132
 
133
  /**
134
  * @return bool
135
- *
61
 
62
  /**
63
  * TODO: Bug where if $sType is defined, it'll be set to 'wp' anyway
64
+ * @param string $type - wp or wpms
65
  * @return array
66
  */
67
+ public function getOptionsToRestrict( $type = '' ) {
68
+ $type = empty( $type ) ? ( Services::WpGeneral()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
69
  $aOptions = $this->getRestrictedOptions();
70
+ return ( isset( $aOptions[ $type.'_options' ] ) && is_array( $aOptions[ $type.'_options' ] ) ) ? $aOptions[ $type.'_options' ] : [];
71
  }
72
 
73
  /**
74
+ * @param string $type - wp or wpms
75
  * @return array
76
  */
77
+ public function getOptionsPagesToRestrict( $type = '' ) {
78
+ $type = empty( $type ) ? ( Services::WpGeneral()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
79
  $aOptions = $this->getRestrictedOptions();
80
+ return ( isset( $aOptions[ $type.'_pages' ] ) && is_array( $aOptions[ $type.'_pages' ] ) ) ? $aOptions[ $type.'_pages' ] : [];
81
  }
82
 
83
  /**
84
  * @return array
85
  */
86
  public function getSecurityAdminUsers() {
87
+ $users = $this->getOpt( 'sec_admin_users', [] );
88
+ return ( is_array( $users ) && $this->isPremium() ) ? $users : [];
89
  }
90
 
91
  /**
132
 
133
  /**
134
  * @return bool