Version Description
Download this release
Release Info
Developer | paultgoodchild |
Plugin | Shield Security for WordPress |
Version | 11.2.0 |
Comparing to | |
See all releases |
Code changes from version 11.1.1 to 11.2.0
- cl.json +59 -5
- icwp-wpsf.php +1 -1
- plugin-spec.php +91 -63
- readme.txt +2 -2
- resources/css/featherlight.css +0 -141
- resources/css/global-plugin.css +5 -3
- resources/css/jquery.fancybox.min.css +0 -1
- resources/css/jquery.steps.css +0 -383
- resources/css/jquery/fancybox.min.css +1 -0
- resources/css/plugin.css +58 -2
- resources/css/shield/dialog.css +7 -0
- resources/css/{pages.css → shield/pages.css} +0 -0
- resources/css/shield/wizard.css +542 -0
- resources/css/wizard.css +0 -163
- resources/images/bootstrap/envelope-fill.svg +3 -0
- resources/images/bootstrap/facebook.svg +3 -0
- resources/images/bootstrap/file-earmark-play.svg +4 -0
- resources/images/bootstrap/play-btn-fill.svg +3 -0
- resources/images/bootstrap/play-btn.svg +4 -0
- resources/images/bootstrap/play-circle.svg +4 -0
- resources/images/bootstrap/play-fill.svg +3 -0
- resources/images/bootstrap/shield-fill-check.svg +3 -0
- resources/images/bootstrap/shield-fill-exclamation.svg +3 -0
- resources/images/bootstrap/shield-fill-plus.svg +3 -0
- resources/images/bootstrap/twitter.svg +3 -0
- resources/js/featherlight.js +0 -641
- resources/js/global-plugin.js +1 -45
- resources/js/jquery.fancybox.min.js +0 -12
- resources/js/jquery.steps.min.js +0 -6
- resources/js/jquery/fancybox.min.js +13 -0
- resources/js/{jquery.fileDownload.js → jquery/fileDownload.js} +0 -0
- resources/js/{u2f-frontend.js → login/u2f.js} +0 -0
- resources/js/plugin.js +1 -1
- resources/js/shield/antibot.js +15 -1
- resources/js/shield/dialog.js +10 -0
- resources/js/shield/navigation.js +1 -1
- resources/js/shield/tours.js +20 -3
- resources/js/shield/u2f-admin.js +0 -64
- resources/js/shield/userprofile.js +182 -17
- resources/js/shield/wizard.js +0 -0
- src/config/feature-autoupdates.php +2 -2
- src/config/feature-comments_filter.php +1 -1
- src/config/feature-integrations.php +81 -14
- src/config/feature-ips.php +4 -3
- src/config/feature-login_protect.php +12 -12
- src/config/feature-plugin.php +32 -21
- src/lib/src/Controller/Admin/MainAdminMenu.php +1 -17
- src/lib/src/Controller/Ajax/Response.php +1 -1
- src/lib/src/Controller/Assets/Enqueue.php +33 -2
- src/lib/src/Controller/Assets/Svgs.php +19 -0
- src/lib/src/Controller/Controller.php +18 -4
- src/lib/src/Databases/AuditTrail/Handler.php +0 -8
- src/lib/src/Databases/Base/BaseQuery.php +89 -61
- src/lib/src/Databases/Base/Delete.php +41 -5
- src/lib/src/Databases/Base/EntryVO.php +1 -1
- src/lib/src/Databases/Base/Handler.php +2 -18
- src/lib/src/Databases/Base/Update.php +2 -5
- src/lib/src/Databases/BotSignals/EntryVO.php +1 -0
- src/lib/src/Databases/Events/Handler.php +0 -8
- src/lib/src/Databases/Events/Select.php +6 -7
- src/lib/src/Databases/FileLocker/Handler.php +0 -7
- src/lib/src/Databases/IPs/Handler.php +0 -8
- src/lib/src/Databases/ScanQueue/Common.php +3 -3
- src/lib/src/Databases/Scanner/Update.php +13 -17
- src/lib/src/Databases/Session/Handler.php +6 -8
- src/lib/src/Databases/Traffic/Handler.php +0 -8
- src/lib/src/License/EddLicenseVO.php +1 -1
- src/lib/src/Modules/AuditTrail/Insights/OverviewCards.php +7 -13
- src/lib/src/Modules/AuditTrail/Lib/AuditWriter.php +1 -1
- src/lib/src/Modules/Autoupdates/Insights/OverviewCards.php +23 -27
- src/lib/src/Modules/Base/AdminPage.php +120 -0
- src/lib/src/Modules/Base/Common/ExecOnceModConsumer.php +12 -0
- src/lib/src/Modules/Base/Insights/OverviewCards.php +41 -6
- src/lib/src/Modules/Base/Lib/Rest/Request/Process.php +144 -0
- src/lib/src/Modules/Base/Lib/Rest/Request/RequestVO.php +18 -0
- src/lib/src/Modules/Base/Lib/Rest/RequestVoConsumer.php +29 -0
- src/lib/src/Modules/Base/Lib/Rest/Route/RestRouteConsumer.php +27 -0
- src/lib/src/Modules/Base/Lib/Rest/Route/RouteBase.php +256 -0
- src/lib/src/Modules/Base/Lib/Rest/Route/RouteCache.php +47 -0
- src/lib/src/Modules/Base/Lib/Rest/Utility/PreChecks.php +33 -0
- src/lib/src/Modules/Base/Lib/Rest/Utility/RestLocker.php +65 -0
- src/lib/src/Modules/Base/ModCon.php +68 -29
- src/lib/src/Modules/Base/Options.php +7 -3
- src/lib/src/Modules/Base/RestHandler.php +66 -0
- src/lib/src/Modules/Base/Strings.php +2 -2
- src/lib/src/Modules/Base/UI.php +1 -1
- src/lib/src/Modules/Base/Upgrade.php +3 -7
- src/lib/src/Modules/Base/WpCli.php +12 -11
- src/lib/src/Modules/BaseShield/AdminPage.php +18 -0
- src/lib/src/Modules/BaseShield/ModCon.php +12 -28
- src/lib/src/Modules/BaseShield/UI.php +13 -5
- src/lib/src/Modules/CommentsFilter/Forms/Gasp.php +2 -6
- src/lib/src/Modules/CommentsFilter/Forms/GoogleRecaptcha.php +2 -6
- src/lib/src/Modules/CommentsFilter/Insights/OverviewCards.php +11 -13
- src/lib/src/Modules/CommentsFilter/ModCon.php +2 -2
- src/lib/src/Modules/CommentsFilter/Scan/CommentAdditiveCleaner.php +2 -6
- src/lib/src/Modules/CommentsFilter/Scan/Scanner.php +2 -6
- src/lib/src/Modules/CommentsFilter/Strings.php +10 -4
- src/lib/src/Modules/Email/Processor.php +2 -3
- src/lib/src/Modules/Events/Lib/EventsListener.php +2 -3
- src/lib/src/Modules/Events/Lib/StatsWriter.php +1 -1
- src/lib/src/Modules/Firewall/Insights/OverviewCards.php +29 -26
- src/lib/src/Modules/Firewall/Lib/Scan/PerformScan.php +2 -4
- src/lib/src/Modules/HackGuard/AjaxHandler.php +1 -1
- src/lib/src/Modules/HackGuard/Insights/OverviewCards.php +14 -16
- src/lib/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php +3 -3
- src/lib/src/Modules/HackGuard/Scan/Controller/Base.php +13 -7
- src/lib/src/Modules/HackGuard/Scan/Controller/Ptg.php +2 -2
- src/lib/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php +1 -2
- src/lib/src/Modules/HackGuard/Scan/ScansController.php +3 -6
- src/lib/src/Modules/HackGuard/UI.php +13 -9
- src/lib/src/Modules/Headers/Insights/OverviewCards.php +11 -13
- src/lib/src/Modules/IPs/AjaxHandler.php +4 -0
- src/lib/src/Modules/IPs/Components/IpAddressConsumer.php +11 -4
- src/lib/src/Modules/IPs/Lib/AutoUnblock.php +10 -26
- src/lib/src/Modules/IPs/Lib/BlockRequest.php +2 -6
- src/lib/src/Modules/IPs/Lib/Bots/BotEventListener.php +3 -7
- src/lib/src/Modules/IPs/Lib/Bots/BotSignalsController.php +2 -6
- src/lib/src/Modules/IPs/Lib/Bots/BotSignalsRecord.php +14 -0
- src/lib/src/Modules/IPs/Lib/Bots/Calculator/BuildScores.php +21 -14
- src/lib/src/Modules/IPs/Lib/Bots/NotBot/InsertNotBotJs.php +19 -6
- src/lib/src/Modules/IPs/Lib/Bots/NotBot/NotBotHandler.php +32 -15
- src/lib/src/Modules/IPs/Lib/IpAnalyse/BuildDisplay.php +2 -2
- src/lib/src/Modules/IPs/Lib/OffenseTracker.php +2 -4
- src/lib/src/Modules/IPs/Lib/Ops/LookupIpOnList.php +0 -18
- src/lib/src/Modules/IPs/Lib/ProcessOffenses.php +2 -6
- src/lib/src/Modules/IPs/Options.php +10 -23
- src/lib/src/Modules/IPs/Strings.php +3 -1
- src/lib/src/Modules/IPs/UI.php +5 -5
- src/lib/src/Modules/Insights/AdminPage.php +12 -0
- src/lib/src/Modules/Insights/Lib/Requests/DynamicPageLoader.php +18 -6
- src/lib/src/Modules/Insights/Lib/SideMenuBuilder.php +86 -49
- src/lib/src/Modules/Insights/Lib/SummaryCards.php +184 -0
- src/lib/src/Modules/Insights/ModCon.php +17 -8
- src/lib/src/Modules/Insights/UI.php +31 -17
- src/lib/src/Modules/Integrations/Lib/Bots/Common/BaseBotDetectionController.php +50 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Common/BaseHandler.php +49 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Base.php +32 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ContactForm7.php +20 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ElementorPro.php +26 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FluentForms.php +28 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FormidableForms.php +29 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Forminator.php +20 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/GravityForms.php +22 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Groundhogg.php +21 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Helpers/NinjaForms_ShieldSpamAction.php +47 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/KaliForms.php +27 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/NinjaForms.php +48 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WPForms.php +37 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WpForo.php +40 -0
- src/lib/src/Modules/Integrations/Lib/Bots/Spam/SpamController.php +30 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Base.php +101 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Buddypress.php +28 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/EasyDigitalDownloads.php +28 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LearnPress.php +48 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LifterLMS.php +50 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/MemberPress.php +71 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/PaidMemberSubscriptions.php +28 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/ProfileBuilder.php +35 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/UltimateMember.php +50 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WPMembers.php +52 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WooCommerce.php +66 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WordPress.php +92 -0
- src/lib/src/Modules/Integrations/Lib/Bots/UserForms/UserFormsController.php +43 -0
- src/lib/src/Modules/Integrations/Lib/MainWP/Controller.php +2 -6
- src/lib/src/Modules/Integrations/Lib/MainWP/Server/Data/SyncHandler.php +2 -6
- src/lib/src/Modules/Integrations/Lib/MainWP/Server/UI/ExtensionSettingsPage.php +2 -6
- src/lib/src/Modules/Integrations/Lib/Spam/Handlers/Base.php +2 -6
- src/lib/src/Modules/Integrations/Lib/Spam/SpamController.php +5 -0
- src/lib/src/Modules/Integrations/ModCon.php +13 -0
- src/lib/src/Modules/Integrations/Options.php +12 -0
- src/lib/src/Modules/Integrations/Processor.php +11 -4
- src/lib/src/Modules/Integrations/Strings.php +40 -2
- src/lib/src/Modules/Integrations/UI.php +71 -0
- src/lib/src/Modules/Integrations/Upgrade.php +25 -0
- src/lib/src/Modules/License/Lib/LookupRequest.php +15 -29
- src/lib/src/Modules/License/Lib/PluginNameSuffix.php +2 -4
- src/lib/src/Modules/License/Lib/Verify.php +25 -26
- src/lib/src/Modules/Lockdown/Insights/OverviewCards.php +11 -13
- src/lib/src/Modules/Lockdown/Lib/CleanRubbish.php +2 -6
- src/lib/src/Modules/LoginGuard/AjaxHandler.php +135 -35
- src/lib/src/Modules/LoginGuard/Insights/OverviewCards.php +12 -13
- src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php +4 -13
- src/lib/src/Modules/LoginGuard/Lib/AntiBot/FormProviders/BaseFormProvider.php +12 -12
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php +8 -8
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php +57 -24
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaProfilesController.php +93 -0
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/CustomForms.php +0 -67
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/RenderCustomForms.php +55 -0
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/{Backup.php → BackupCodes.php} +35 -35
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php +52 -18
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProviderV2.php +0 -279
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Email.php +25 -20
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/GoogleAuth.php +67 -35
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/ProviderInterface.php +0 -13
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/U2F.php +109 -106
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Yubikey.php +91 -71
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/UserProfile.php +62 -62
- src/lib/src/Modules/LoginGuard/Lib/TwoFactor/ValidateLoginIntentRequest.php +4 -4
- src/lib/src/Modules/LoginGuard/ModCon.php +6 -4
- src/lib/src/Modules/LoginGuard/Options.php +4 -0
- src/lib/src/Modules/LoginGuard/Strings.php +28 -12
- src/lib/src/Modules/LoginGuard/UI.php +26 -24
- src/lib/src/Modules/Plugin/AdminNotices.php +13 -6
- src/lib/src/Modules/Plugin/AjaxHandler.php +15 -0
- src/lib/src/Modules/Plugin/Components/PluginBadge.php +10 -5
- src/lib/src/Modules/Plugin/Insights/OverviewCards.php +12 -16
- src/lib/src/Modules/Plugin/Lib/PluginTelemetry.php +3 -6
- src/lib/src/Modules/Plugin/Strings.php +1 -1
- src/lib/src/Modules/Plugin/UI.php +27 -0
- src/lib/src/Modules/Reporting/Lib/ReportingController.php +2 -0
- src/lib/src/Modules/Reporting/Lib/Reports/CreateReportVO.php +34 -29
- src/lib/src/Modules/SecurityAdmin/Insights/OverviewCards.php +11 -10
- src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/Base.php +2 -5
- src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/WpOptions.php +0 -1
- src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php +19 -21
- src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php +1 -1
- src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/{ApplyLabels.php → WhitelabelController.php} +35 -20
- src/lib/src/Modules/SecurityAdmin/ModCon.php +6 -165
- src/lib/src/Modules/SecurityAdmin/Options.php +16 -4
- src/lib/src/Modules/SecurityAdmin/Processor.php +2 -159
- src/lib/src/Modules/Sessions/Lib/Ops/Retrieve.php +38 -0
- src/lib/src/Modules/Sessions/Lib/Ops/Terminate.php +9 -5
- src/lib/src/Modules/Sessions/Lib/SessionController.php +59 -3
- src/lib/src/Modules/Sessions/Processor.php +19 -7
- src/lib/src/Modules/Traffic/Strings.php +5 -2
- src/lib/src/Modules/UserManagement/AjaxHandler.php +19 -19
- src/lib/src/Modules/UserManagement/Insights/OverviewCards.php +11 -13
- src/lib/src/Modules/UserManagement/Lib/Password/UserPasswordHandler.php +2 -5
- src/lib/src/Modules/UserManagement/Lib/Session/UserSessionHandler.php +2 -8
- src/lib/src/Modules/UserManagement/Lib/Suspend/UserSuspendController.php +3 -5
- src/lib/src/Modules/UserManagement/ModCon.php +15 -15
- src/lib/src/Modules/UserManagement/Processor.php +19 -19
- src/lib/src/Tables/Build/Traffic.php +2 -2
- src/lib/src/Tables/Render/Common/BaseTable.php +151 -0
- src/lib/src/Tables/Render/DataTable/Base.php +10 -0
- src/lib/src/Tables/Render/DataTable/ScanBase.php +9 -0
- src/lib/src/Tables/Render/DataTable/ScanWcf.php +9 -0
- src/lib/src/Tables/Render/WpListTable/ScanBase.php +3 -3
- src/lib/src/Users/ShieldUserMeta.php +22 -22
- src/lib/src/Utilities/Consumer/WpLoginCapture.php +24 -1
- src/lib/src/Utilities/Consumer/WpUserConsumer.php +6 -6
- src/lib/vendor/bacon/bacon-qr-code/Module.php +37 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php +115 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php +435 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php +350 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php +51 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php +134 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php +65 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php +101 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php +62 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php +236 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php +70 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php +476 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php +687 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php +64 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php +158 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php +687 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php +291 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php +580 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php +201 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php +14 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php +14 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php +14 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php +14 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php +14 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php +14 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php +160 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php +37 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php +84 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php +148 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php +338 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php +63 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php +210 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php +152 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php +115 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php +61 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php +146 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php +26 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php +91 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php +150 -0
- src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Writer.php +105 -0
- src/lib/vendor/composer/autoload_classmap.php +213 -5
- src/lib/vendor/composer/autoload_files.php +2 -1
- src/lib/vendor/composer/autoload_namespaces.php +1 -0
- src/lib/vendor/composer/autoload_psr4.php +4 -0
- src/lib/vendor/composer/autoload_static.php +248 -6
- src/lib/vendor/dolondro/google-authenticator/src/GoogleAuthenticator.php +2 -1
- src/lib/vendor/dolondro/google-authenticator/src/QrImageGenerator/EndroidQrImageGenerator.php +4 -2
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Controller/QrCodeController.php +64 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Compiler/WriterRegistryCompilerPass.php +36 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Configuration.php +77 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/EndroidQrCodeExtension.php +34 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/EndroidQrCodeBundle.php +27 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Resources/config/routing.yml +11 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Resources/config/services.yml +31 -0
- src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Resources/views/QrCode/twigFunctions.html.twig +3 -0
- src/lib/vendor/endroid/qr-code/src/ErrorCorrectionLevel.php +20 -0
- src/lib/vendor/endroid/qr-code/src/Exception/InvalidPathException.php +14 -0
- src/lib/vendor/endroid/qr-code/src/Exception/InvalidWriterException.php +14 -0
- src/lib/vendor/endroid/qr-code/src/Exception/MissingFunctionException.php +14 -0
- src/lib/vendor/endroid/qr-code/src/Exception/QrCodeException.php +16 -0
- src/lib/vendor/endroid/qr-code/src/Exception/UnsupportedExtensionException.php +14 -0
- src/lib/vendor/endroid/qr-code/src/Exception/ValidationException.php +14 -0
- src/lib/vendor/endroid/qr-code/src/Factory/QrCodeFactory.php +120 -0
- src/lib/vendor/endroid/qr-code/src/LabelAlignment.php +19 -0
- src/lib/vendor/endroid/qr-code/src/QrCode.php +591 -0
- src/lib/vendor/endroid/qr-code/src/QrCodeInterface.php +95 -0
- src/lib/vendor/endroid/qr-code/src/StaticWriterRegistry.php +42 -0
- src/lib/vendor/endroid/qr-code/src/Twig/Extension/QrCodeExtension.php +117 -0
- src/lib/vendor/endroid/qr-code/src/Writer/AbstractBaconWriter.php +40 -0
- src/lib/vendor/endroid/qr-code/src/Writer/AbstractWriter.php +63 -0
- src/lib/vendor/endroid/qr-code/src/Writer/BinaryWriter.php +52 -0
- src/lib/vendor/endroid/qr-code/src/Writer/DebugWriter.php +58 -0
- src/lib/vendor/endroid/qr-code/src/Writer/EpsWriter.php +19 -0
cl.json
CHANGED
@@ -1,4 +1,63 @@
|
|
1 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
"11.1": {
|
3 |
"version": "11.1",
|
4 |
"released_at": 1616666000,
|
@@ -6,7 +65,6 @@
|
|
6 |
"release": "https://shsec.io/shieldrelease111",
|
7 |
"upgrade": "https://shsec.io/shieldupgradeguide111"
|
8 |
},
|
9 |
-
"href": "https://shsec.io/",
|
10 |
"title": "UI Cleanup and Enhancement",
|
11 |
"description": [
|
12 |
"With Shield being such a large plugin, it's been a challenge to get a UI that everyone is happy with.",
|
@@ -114,7 +172,6 @@
|
|
114 |
"release": "https://shsec.io/shieldrelease110",
|
115 |
"upgrade": "https://shsec.io/shieldupgradeguide110"
|
116 |
},
|
117 |
-
"href": "https://shsec.io/",
|
118 |
"title": "All-New Shield AntiBot Detection Engine",
|
119 |
"description": [
|
120 |
"WordPress security nearly always starts with bots - detecting bad bots and blocking them.",
|
@@ -224,7 +281,6 @@
|
|
224 |
"release": "https://shsec.io/shieldrelease102",
|
225 |
"upgrade": "https://shsec.io/shieldupgradeguide102"
|
226 |
},
|
227 |
-
"href": "https://shsec.io/",
|
228 |
"title": "Removal of simple Content Security Policy settings and bugfixes",
|
229 |
"description": [
|
230 |
"We've decided to remove our simple Content Security Policy options as this feature is too complex.",
|
@@ -353,7 +409,6 @@
|
|
353 |
"release": "https://shsec.io/shieldrelease101",
|
354 |
"upgrade": "https://shsec.io/shieldupgradeguide101"
|
355 |
},
|
356 |
-
"href": "https://shsec.io/",
|
357 |
"title": "Enhanced Dashboard + MainWP Integration",
|
358 |
"description": [
|
359 |
"We're continuing our improvements to the Shield UI with a brand new Dashboard.",
|
@@ -490,7 +545,6 @@
|
|
490 |
"release": "https://shsec.io/shieldrelease100",
|
491 |
"upgrade": "https://shsec.io/shieldupgradeguide100"
|
492 |
},
|
493 |
-
"href": "https://shsec.io/",
|
494 |
"title": "All-New PHP-7 Optimised Shield Security",
|
495 |
"description": [
|
496 |
"We've massively enhanced the Dashboard UI, making it much easier to secure your WordPress site by quickly identifying areas of improvement.",
|
1 |
{
|
2 |
+
"11.2": {
|
3 |
+
"version": "11.2",
|
4 |
+
"released_at": 1621844125,
|
5 |
+
"hrefs": {
|
6 |
+
"release": "https://shsec.io/shieldrelease112",
|
7 |
+
"upgrade": "https://shsec.io/shieldupgradeguide112"
|
8 |
+
},
|
9 |
+
"title": "AntiBot Scoring Improvements",
|
10 |
+
"description": [
|
11 |
+
"Shield 11.0 brought the new AntiBot Detection Engine, designed to detect bad bots and block them.",
|
12 |
+
"With feedback from customers and ongoing research, we've made some major improvements and adjustments to the system."
|
13 |
+
],
|
14 |
+
"items": [
|
15 |
+
{
|
16 |
+
"type": "new",
|
17 |
+
"pro_only": false,
|
18 |
+
"title": "New And Improved Welcome Wizard",
|
19 |
+
"description": [
|
20 |
+
"All-New Welcome Wizard designed to get you up and running with Shield quickly and effortlessly."
|
21 |
+
]
|
22 |
+
},
|
23 |
+
{
|
24 |
+
"type": "new",
|
25 |
+
"title": "Add Shield's Two-Factor Authentication User Settings Anywhere",
|
26 |
+
"description": [
|
27 |
+
"With the use of a WP Shortcode, you can add user configuration pages for 2FA into any page.",
|
28 |
+
"This is useful if you want to offer 2FA options to your customers."
|
29 |
+
]
|
30 |
+
},
|
31 |
+
{
|
32 |
+
"type": "improved",
|
33 |
+
"title": "AntiBot Detection Engine Improvements.",
|
34 |
+
"description": [
|
35 |
+
"We've adjusted some of the bot scoring and improved the ability to detect legitimate users based on earlier logins.",
|
36 |
+
"We've also removed the need for the small cookie that was needed to help track the NotBot status."
|
37 |
+
]
|
38 |
+
},
|
39 |
+
{
|
40 |
+
"type": "new",
|
41 |
+
"title": "Support For Groundhogg",
|
42 |
+
"description": [
|
43 |
+
"Added support for protecting Groundhogg forms from bots."
|
44 |
+
],
|
45 |
+
"href": "https://shsec.io/groundhogg"
|
46 |
+
},
|
47 |
+
{
|
48 |
+
"type": "new",
|
49 |
+
"title": "Support For LifterLMS.",
|
50 |
+
"description": [
|
51 |
+
"Added support for protecting LifterLMS login & registration forms from bots."
|
52 |
+
]
|
53 |
+
},
|
54 |
+
{
|
55 |
+
"type": "fixed",
|
56 |
+
"title": "The tour system would run multiple times.",
|
57 |
+
"description": []
|
58 |
+
}
|
59 |
+
]
|
60 |
+
},
|
61 |
"11.1": {
|
62 |
"version": "11.1",
|
63 |
"released_at": 1616666000,
|
65 |
"release": "https://shsec.io/shieldrelease111",
|
66 |
"upgrade": "https://shsec.io/shieldupgradeguide111"
|
67 |
},
|
|
|
68 |
"title": "UI Cleanup and Enhancement",
|
69 |
"description": [
|
70 |
"With Shield being such a large plugin, it's been a challenge to get a UI that everyone is happy with.",
|
172 |
"release": "https://shsec.io/shieldrelease110",
|
173 |
"upgrade": "https://shsec.io/shieldupgradeguide110"
|
174 |
},
|
|
|
175 |
"title": "All-New Shield AntiBot Detection Engine",
|
176 |
"description": [
|
177 |
"WordPress security nearly always starts with bots - detecting bad bots and blocking them.",
|
281 |
"release": "https://shsec.io/shieldrelease102",
|
282 |
"upgrade": "https://shsec.io/shieldupgradeguide102"
|
283 |
},
|
|
|
284 |
"title": "Removal of simple Content Security Policy settings and bugfixes",
|
285 |
"description": [
|
286 |
"We've decided to remove our simple Content Security Policy options as this feature is too complex.",
|
409 |
"release": "https://shsec.io/shieldrelease101",
|
410 |
"upgrade": "https://shsec.io/shieldupgradeguide101"
|
411 |
},
|
|
|
412 |
"title": "Enhanced Dashboard + MainWP Integration",
|
413 |
"description": [
|
414 |
"We're continuing our improvements to the Shield UI with a brand new Dashboard.",
|
545 |
"release": "https://shsec.io/shieldrelease100",
|
546 |
"upgrade": "https://shsec.io/shieldupgradeguide100"
|
547 |
},
|
|
|
548 |
"title": "All-New PHP-7 Optimised Shield Security",
|
549 |
"description": [
|
550 |
"We've massively enhanced the Dashboard UI, making it much easier to secure your WordPress site by quickly identifying areas of improvement.",
|
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: 11.
|
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: 11.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": "11.
|
4 |
-
"release_timestamp":
|
5 |
-
"build": "
|
6 |
"slug_parent": "icwp",
|
7 |
"slug_plugin": "wpsf",
|
8 |
"human_name": "Shield Security",
|
@@ -51,15 +51,15 @@
|
|
51 |
"css": [
|
52 |
"select2",
|
53 |
"plugin",
|
54 |
-
"featherlight",
|
55 |
"introjs",
|
56 |
"bootstrap-select"
|
57 |
],
|
58 |
"js": [
|
59 |
"select2",
|
60 |
"plugin",
|
61 |
-
"featherlight",
|
62 |
-
"jquery
|
63 |
"shield/tours",
|
64 |
"bootstrap-select"
|
65 |
]
|
@@ -73,38 +73,47 @@
|
|
73 |
"bootstrap": {
|
74 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css"
|
75 |
},
|
76 |
-
"select2": {
|
77 |
-
"url": "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css",
|
78 |
-
"deps": [
|
79 |
-
"plugin"
|
80 |
-
]
|
81 |
-
},
|
82 |
"bootstrap-datepicker": {
|
83 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css",
|
84 |
"deps": [
|
85 |
"bootstrap"
|
86 |
]
|
87 |
},
|
88 |
-
"bootstrap-select":
|
89 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.18/css/bootstrap-select.min.css",
|
90 |
"deps": [
|
91 |
"bootstrap"
|
92 |
]
|
93 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
"global-plugin": {},
|
95 |
"plugin": {
|
96 |
"deps": [
|
|
|
97 |
"bootstrap",
|
98 |
"global-plugin"
|
99 |
]
|
100 |
},
|
101 |
-
"wizard":
|
102 |
"deps": [
|
103 |
"bootstrap",
|
104 |
"global-plugin"
|
105 |
]
|
106 |
},
|
107 |
-
"featherlight":
|
|
|
|
|
108 |
"chartist": {
|
109 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.4/chartist.min.css"
|
110 |
},
|
@@ -121,159 +130,177 @@
|
|
121 |
"plugin"
|
122 |
]
|
123 |
},
|
124 |
-
"shield/
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
},
|
126 |
"js": {
|
127 |
-
"bootstrap":
|
128 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.bundle.min.js",
|
129 |
"deps": [
|
130 |
"wp-jquery"
|
131 |
]
|
132 |
},
|
133 |
-
"select2":
|
134 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js",
|
135 |
"deps": [
|
136 |
"plugin"
|
137 |
]
|
138 |
},
|
139 |
-
"bootstrap-datepicker":
|
140 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js",
|
141 |
"deps": [
|
142 |
"bootstrap"
|
143 |
]
|
144 |
},
|
145 |
-
"bootstrap-select":
|
146 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.18/js/bootstrap-select.min.js",
|
147 |
"deps": [
|
148 |
"bootstrap"
|
149 |
]
|
150 |
},
|
151 |
-
"
|
|
|
152 |
"deps": [
|
|
|
153 |
"wp-jquery"
|
154 |
]
|
155 |
},
|
156 |
-
"plugin":
|
|
|
|
|
|
|
|
|
|
|
157 |
"deps": [
|
158 |
"bootstrap",
|
|
|
159 |
"global-plugin",
|
160 |
"shield/navigation",
|
161 |
"base64.min",
|
162 |
"lz-string.min"
|
163 |
]
|
164 |
},
|
165 |
-
"base64.min":
|
166 |
"url": "https://cdn.jsdelivr.net/npm/js-base64@2.6.4/base64.min.js"
|
167 |
},
|
168 |
-
"lz-string.min":
|
169 |
-
"jquery
|
170 |
-
|
171 |
-
|
172 |
-
]
|
173 |
},
|
174 |
-
"featherlight":
|
175 |
-
"
|
176 |
-
"wp-jquery"
|
177 |
-
]
|
178 |
},
|
179 |
-
"chartist":
|
180 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.4/chartist.min.js"
|
181 |
},
|
182 |
-
"chartist-plugin-legend":
|
183 |
"deps": [
|
184 |
"chartist"
|
185 |
]
|
186 |
},
|
187 |
-
"introjs":
|
188 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/intro.js/3.3.1/intro.min.js"
|
189 |
},
|
190 |
-
"shield/charts":
|
191 |
"deps": [
|
192 |
"chartist",
|
193 |
"chartist-plugin-legend",
|
194 |
"plugin"
|
195 |
]
|
196 |
},
|
197 |
-
"shuffle":
|
198 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/Shuffle/5.3.0/shuffle.min.js"
|
199 |
},
|
200 |
-
"shield/shuffle":
|
201 |
"deps": [
|
202 |
"shuffle"
|
203 |
]
|
204 |
},
|
205 |
-
"shield/
|
|
|
|
|
|
|
|
|
|
|
206 |
"deps": [
|
207 |
"wp-jquery"
|
208 |
],
|
209 |
"footer": true
|
210 |
},
|
211 |
-
"shield/loginbot":
|
212 |
"deps": [
|
213 |
"wp-jquery"
|
214 |
]
|
215 |
},
|
216 |
-
"shield/navigation":
|
217 |
-
"shield/secadmin":
|
218 |
"deps": [
|
219 |
"wp-jquery"
|
220 |
]
|
221 |
},
|
222 |
-
"shield/tables":
|
223 |
"deps": [
|
224 |
"plugin"
|
225 |
]
|
226 |
},
|
227 |
-
"shield/tours":
|
228 |
"deps": [
|
229 |
"plugin",
|
230 |
"introjs"
|
231 |
]
|
232 |
},
|
233 |
-
"shield/antibot":
|
234 |
-
"footer": true
|
235 |
},
|
236 |
-
"shield/scans":
|
237 |
"deps": [
|
238 |
"shield/tables"
|
239 |
]
|
240 |
},
|
241 |
-
"shield/import":
|
242 |
"deps": [
|
243 |
"plugin"
|
244 |
]
|
245 |
},
|
246 |
-
"shield/ipanalyse":
|
247 |
"deps": [
|
248 |
"plugin"
|
249 |
]
|
250 |
},
|
251 |
-
"shield/mainwp":
|
252 |
"deps": [
|
253 |
"wp-jquery"
|
254 |
]
|
255 |
},
|
256 |
-
"shield/userprofile":
|
257 |
-
"deps":
|
258 |
-
"
|
259 |
-
|
|
|
|
|
260 |
},
|
261 |
-
"
|
262 |
-
"shield/u2f-admin": {
|
263 |
"deps": [
|
264 |
-
"
|
265 |
-
"
|
|
|
266 |
]
|
267 |
},
|
268 |
-
"
|
269 |
-
|
|
|
270 |
"attributes": {
|
271 |
"async": "async",
|
272 |
"defer": "defer"
|
273 |
}
|
274 |
},
|
275 |
-
"tp/hcaptcha":
|
276 |
-
"url":
|
277 |
"attributes": {
|
278 |
"async": "async",
|
279 |
"defer": "defer"
|
@@ -318,7 +345,8 @@
|
|
318 |
"9.2.0",
|
319 |
"9.2.2",
|
320 |
"10.1.0",
|
321 |
-
"10.2.1"
|
|
|
322 |
],
|
323 |
"action_links": {
|
324 |
"remove": null,
|
1 |
{
|
2 |
"properties": {
|
3 |
+
"version": "11.2.0",
|
4 |
+
"release_timestamp": 1622017666,
|
5 |
+
"build": "202105.2601",
|
6 |
"slug_parent": "icwp",
|
7 |
"slug_plugin": "wpsf",
|
8 |
"human_name": "Shield Security",
|
51 |
"css": [
|
52 |
"select2",
|
53 |
"plugin",
|
54 |
+
"jquery/featherlight",
|
55 |
"introjs",
|
56 |
"bootstrap-select"
|
57 |
],
|
58 |
"js": [
|
59 |
"select2",
|
60 |
"plugin",
|
61 |
+
"jquery/featherlight",
|
62 |
+
"jquery/fileDownload",
|
63 |
"shield/tours",
|
64 |
"bootstrap-select"
|
65 |
]
|
73 |
"bootstrap": {
|
74 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css"
|
75 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
"bootstrap-datepicker": {
|
77 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.min.css",
|
78 |
"deps": [
|
79 |
"bootstrap"
|
80 |
]
|
81 |
},
|
82 |
+
"bootstrap-select": {
|
83 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.18/css/bootstrap-select.min.css",
|
84 |
"deps": [
|
85 |
"bootstrap"
|
86 |
]
|
87 |
},
|
88 |
+
"select2": {
|
89 |
+
"url": "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css",
|
90 |
+
"deps": [
|
91 |
+
"plugin"
|
92 |
+
]
|
93 |
+
},
|
94 |
+
"datatables": {
|
95 |
+
"url": "https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/css/dataTables.bootstrap4.min.css",
|
96 |
+
"deps": [
|
97 |
+
"bootstrap"
|
98 |
+
]
|
99 |
+
},
|
100 |
"global-plugin": {},
|
101 |
"plugin": {
|
102 |
"deps": [
|
103 |
+
"datatables",
|
104 |
"bootstrap",
|
105 |
"global-plugin"
|
106 |
]
|
107 |
},
|
108 |
+
"shield/wizard": {
|
109 |
"deps": [
|
110 |
"bootstrap",
|
111 |
"global-plugin"
|
112 |
]
|
113 |
},
|
114 |
+
"jquery/featherlight": {
|
115 |
+
"url": "https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.13/featherlight.min.css"
|
116 |
+
},
|
117 |
"chartist": {
|
118 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.4/chartist.min.css"
|
119 |
},
|
130 |
"plugin"
|
131 |
]
|
132 |
},
|
133 |
+
"shield/dialog": {
|
134 |
+
"deps": [
|
135 |
+
"wp-wp-jquery-ui-dialog"
|
136 |
+
],
|
137 |
+
"footer": true
|
138 |
+
},
|
139 |
+
"shield/mainwp": {}
|
140 |
},
|
141 |
"js": {
|
142 |
+
"bootstrap": {
|
143 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.bundle.min.js",
|
144 |
"deps": [
|
145 |
"wp-jquery"
|
146 |
]
|
147 |
},
|
148 |
+
"select2": {
|
149 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js",
|
150 |
"deps": [
|
151 |
"plugin"
|
152 |
]
|
153 |
},
|
154 |
+
"bootstrap-datepicker": {
|
155 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js",
|
156 |
"deps": [
|
157 |
"bootstrap"
|
158 |
]
|
159 |
},
|
160 |
+
"bootstrap-select": {
|
161 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.18/js/bootstrap-select.min.js",
|
162 |
"deps": [
|
163 |
"bootstrap"
|
164 |
]
|
165 |
},
|
166 |
+
"datatables": {
|
167 |
+
"url": "https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js",
|
168 |
"deps": [
|
169 |
+
"bootstrap",
|
170 |
"wp-jquery"
|
171 |
]
|
172 |
},
|
173 |
+
"global-plugin": {
|
174 |
+
"deps": [
|
175 |
+
"wp-jquery"
|
176 |
+
]
|
177 |
+
},
|
178 |
+
"plugin": {
|
179 |
"deps": [
|
180 |
"bootstrap",
|
181 |
+
"datatables",
|
182 |
"global-plugin",
|
183 |
"shield/navigation",
|
184 |
"base64.min",
|
185 |
"lz-string.min"
|
186 |
]
|
187 |
},
|
188 |
+
"base64.min": {
|
189 |
"url": "https://cdn.jsdelivr.net/npm/js-base64@2.6.4/base64.min.js"
|
190 |
},
|
191 |
+
"lz-string.min": {},
|
192 |
+
"jquery/fileDownload": {},
|
193 |
+
"jquery/steps": {
|
194 |
+
"url": "https://cdnjs.cloudflare.com/ajax/libs/jquery-steps/1.1.0/jquery.steps.min.js"
|
|
|
195 |
},
|
196 |
+
"jquery/featherlight": {
|
197 |
+
"url": "https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.13/featherlight.min.js"
|
|
|
|
|
198 |
},
|
199 |
+
"chartist": {
|
200 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/chartist/0.11.4/chartist.min.js"
|
201 |
},
|
202 |
+
"chartist-plugin-legend": {
|
203 |
"deps": [
|
204 |
"chartist"
|
205 |
]
|
206 |
},
|
207 |
+
"introjs": {
|
208 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/intro.js/3.3.1/intro.min.js"
|
209 |
},
|
210 |
+
"shield/charts": {
|
211 |
"deps": [
|
212 |
"chartist",
|
213 |
"chartist-plugin-legend",
|
214 |
"plugin"
|
215 |
]
|
216 |
},
|
217 |
+
"shuffle": {
|
218 |
"url": "https://cdnjs.cloudflare.com/ajax/libs/Shuffle/5.3.0/shuffle.min.js"
|
219 |
},
|
220 |
+
"shield/shuffle": {
|
221 |
"deps": [
|
222 |
"shuffle"
|
223 |
]
|
224 |
},
|
225 |
+
"shield/dialog": {
|
226 |
+
"deps": [
|
227 |
+
"wp-jquery-ui-dialog"
|
228 |
+
]
|
229 |
+
},
|
230 |
+
"shield/comments": {
|
231 |
"deps": [
|
232 |
"wp-jquery"
|
233 |
],
|
234 |
"footer": true
|
235 |
},
|
236 |
+
"shield/loginbot": {
|
237 |
"deps": [
|
238 |
"wp-jquery"
|
239 |
]
|
240 |
},
|
241 |
+
"shield/navigation": {},
|
242 |
+
"shield/secadmin": {
|
243 |
"deps": [
|
244 |
"wp-jquery"
|
245 |
]
|
246 |
},
|
247 |
+
"shield/tables": {
|
248 |
"deps": [
|
249 |
"plugin"
|
250 |
]
|
251 |
},
|
252 |
+
"shield/tours": {
|
253 |
"deps": [
|
254 |
"plugin",
|
255 |
"introjs"
|
256 |
]
|
257 |
},
|
258 |
+
"shield/antibot": {
|
|
|
259 |
},
|
260 |
+
"shield/scans": {
|
261 |
"deps": [
|
262 |
"shield/tables"
|
263 |
]
|
264 |
},
|
265 |
+
"shield/import": {
|
266 |
"deps": [
|
267 |
"plugin"
|
268 |
]
|
269 |
},
|
270 |
+
"shield/ipanalyse": {
|
271 |
"deps": [
|
272 |
"plugin"
|
273 |
]
|
274 |
},
|
275 |
+
"shield/mainwp": {
|
276 |
"deps": [
|
277 |
"wp-jquery"
|
278 |
]
|
279 |
},
|
280 |
+
"shield/userprofile": {
|
281 |
+
"deps": [
|
282 |
+
"u2f-bundle",
|
283 |
+
"shield/dialog"
|
284 |
+
],
|
285 |
+
"footer": true
|
286 |
},
|
287 |
+
"shield/wizard": {
|
|
|
288 |
"deps": [
|
289 |
+
"bootstrap",
|
290 |
+
"global-plugin",
|
291 |
+
"jquery/steps"
|
292 |
]
|
293 |
},
|
294 |
+
"u2f-bundle": {},
|
295 |
+
"tp/grecaptcha": {
|
296 |
+
"url": "https://www.google.com/recaptcha/api.js",
|
297 |
"attributes": {
|
298 |
"async": "async",
|
299 |
"defer": "defer"
|
300 |
}
|
301 |
},
|
302 |
+
"tp/hcaptcha": {
|
303 |
+
"url": "https://hcaptcha.com/1/api.js",
|
304 |
"attributes": {
|
305 |
"async": "async",
|
306 |
"defer": "defer"
|
345 |
"9.2.0",
|
346 |
"9.2.2",
|
347 |
"10.1.0",
|
348 |
+
"10.2.1",
|
349 |
+
"11.2.0"
|
350 |
],
|
351 |
"action_links": {
|
352 |
"remove": null,
|
readme.txt
CHANGED
@@ -8,7 +8,7 @@ Requires at least: 3.5.2
|
|
8 |
Requires PHP: 7.0
|
9 |
Recommended PHP: 7.4
|
10 |
Tested up to: 5.7
|
11 |
-
Stable tag: 11.
|
12 |
Security against hackers and brute force bots with firewall, login security hiding and hardening, Antispam, Audit Trail, Live Traffic, and much more...
|
13 |
|
14 |
== Description ==
|
@@ -268,7 +268,7 @@ Login Cooldown prevents more than 1 login attempt to your site every "so-many" s
|
|
268 |
|
269 |
This system completely blocks any level of brute-force login attacks and a cooldown of just 1 second goes a long way.
|
270 |
|
271 |
-
More Info
|
272 |
|
273 |
= How does the GASP Login Guard work? =
|
274 |
|
8 |
Requires PHP: 7.0
|
9 |
Recommended PHP: 7.4
|
10 |
Tested up to: 5.7
|
11 |
+
Stable tag: 11.2.0
|
12 |
Security against hackers and brute force bots with firewall, login security hiding and hardening, Antispam, Audit Trail, Live Traffic, and much more...
|
13 |
|
14 |
== Description ==
|
268 |
|
269 |
This system completely blocks any level of brute-force login attacks and a cooldown of just 1 second goes a long way.
|
270 |
|
271 |
+
[More Info](https://shsec.io/2t)
|
272 |
|
273 |
= How does the GASP Login Guard work? =
|
274 |
|
resources/css/featherlight.css
DELETED
@@ -1,141 +0,0 @@
|
|
1 |
-
/**
|
2 |
-
* Featherlight – ultra slim jQuery lightbox
|
3 |
-
* Version 1.7.1 - http://noelboss.github.io/featherlight/
|
4 |
-
*
|
5 |
-
* Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
|
6 |
-
* MIT Licensed.
|
7 |
-
**/
|
8 |
-
@media all {
|
9 |
-
.featherlight {
|
10 |
-
display: none;
|
11 |
-
|
12 |
-
/* dimensions: spanning the background from edge to edge */
|
13 |
-
position:fixed;
|
14 |
-
top: 0; right: 0; bottom: 0; left: 0;
|
15 |
-
z-index: 2147483647; /* z-index needs to be >= elements on the site. */
|
16 |
-
|
17 |
-
/* position: centering content */
|
18 |
-
text-align: center;
|
19 |
-
|
20 |
-
/* insures that the ::before pseudo element doesn't force wrap with fixed width content; */
|
21 |
-
white-space: nowrap;
|
22 |
-
|
23 |
-
/* styling */
|
24 |
-
cursor: pointer;
|
25 |
-
background: #333;
|
26 |
-
/* IE8 "hack" for nested featherlights */
|
27 |
-
background: rgba(0, 0, 0, 0);
|
28 |
-
}
|
29 |
-
|
30 |
-
/* support for nested featherlights. Does not work in IE8 (use JS to fix) */
|
31 |
-
.featherlight:last-of-type {
|
32 |
-
background: rgba(0, 0, 0, 0.8);
|
33 |
-
}
|
34 |
-
|
35 |
-
.featherlight:before {
|
36 |
-
/* position: trick to center content vertically */
|
37 |
-
content: '';
|
38 |
-
display: inline-block;
|
39 |
-
height: 100%;
|
40 |
-
vertical-align: middle;
|
41 |
-
}
|
42 |
-
|
43 |
-
.featherlight .featherlight-content {
|
44 |
-
/* make content container for positioned elements (close button) */
|
45 |
-
position: relative;
|
46 |
-
|
47 |
-
/* position: centering vertical and horizontal */
|
48 |
-
text-align: left;
|
49 |
-
vertical-align: middle;
|
50 |
-
display: inline-block;
|
51 |
-
|
52 |
-
/* dimensions: cut off images */
|
53 |
-
overflow: auto;
|
54 |
-
padding: 25px 25px 0;
|
55 |
-
border-bottom: 25px solid transparent;
|
56 |
-
|
57 |
-
/* dimensions: handling large content */
|
58 |
-
margin-left: 5%;
|
59 |
-
margin-right: 5%;
|
60 |
-
max-height: 95%;
|
61 |
-
|
62 |
-
/* styling */
|
63 |
-
background: #fff;
|
64 |
-
cursor: auto;
|
65 |
-
|
66 |
-
/* reset white-space wrapping */
|
67 |
-
white-space: normal;
|
68 |
-
}
|
69 |
-
|
70 |
-
/* contains the content */
|
71 |
-
.featherlight .featherlight-inner {
|
72 |
-
/* make sure its visible */
|
73 |
-
display: block;
|
74 |
-
}
|
75 |
-
|
76 |
-
.featherlight .featherlight-close-icon {
|
77 |
-
/* position: centering vertical and horizontal */
|
78 |
-
position: absolute;
|
79 |
-
z-index: 9999;
|
80 |
-
top: 0;
|
81 |
-
right: 0;
|
82 |
-
|
83 |
-
/* dimensions: 25px x 25px */
|
84 |
-
line-height: 25px;
|
85 |
-
width: 25px;
|
86 |
-
|
87 |
-
/* styling */
|
88 |
-
cursor: pointer;
|
89 |
-
text-align: center;
|
90 |
-
font-family: Arial, sans-serif;
|
91 |
-
background: #fff; /* Set the background in case it overlaps the content */
|
92 |
-
background: rgba(255, 255, 255, 0.3);
|
93 |
-
color: #000;
|
94 |
-
border: none;
|
95 |
-
padding: 0;
|
96 |
-
}
|
97 |
-
|
98 |
-
/* See http://stackoverflow.com/questions/16077341/how-to-reset-all-default-styles-of-the-html5-button-element */
|
99 |
-
.featherlight .featherlight-close-icon::-moz-focus-inner {
|
100 |
-
border: 0;
|
101 |
-
padding: 0;
|
102 |
-
}
|
103 |
-
|
104 |
-
.featherlight .featherlight-image {
|
105 |
-
/* styling */
|
106 |
-
width: 100%;
|
107 |
-
}
|
108 |
-
|
109 |
-
|
110 |
-
.featherlight-iframe .featherlight-content {
|
111 |
-
/* removed the border for image croping since iframe is edge to edge */
|
112 |
-
border-bottom: 0;
|
113 |
-
padding: 0;
|
114 |
-
-webkit-overflow-scrolling: touch;
|
115 |
-
overflow-y: scroll;
|
116 |
-
}
|
117 |
-
|
118 |
-
.featherlight iframe {
|
119 |
-
/* styling */
|
120 |
-
border: none;
|
121 |
-
}
|
122 |
-
|
123 |
-
.featherlight * { /* See https://github.com/noelboss/featherlight/issues/42 */
|
124 |
-
-webkit-box-sizing: border-box;
|
125 |
-
-moz-box-sizing: border-box;
|
126 |
-
box-sizing: border-box;
|
127 |
-
}
|
128 |
-
}
|
129 |
-
|
130 |
-
/* handling phones and small screens */
|
131 |
-
@media only screen and (max-width: 1024px) {
|
132 |
-
.featherlight .featherlight-content {
|
133 |
-
/* dimensions: maximize lightbox with for small screens */
|
134 |
-
margin-left: 0;
|
135 |
-
margin-right: 0;
|
136 |
-
max-height: 98%;
|
137 |
-
|
138 |
-
padding: 10px 10px 0;
|
139 |
-
border-bottom: 10px solid transparent;
|
140 |
-
}
|
141 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/css/global-plugin.css
CHANGED
@@ -167,8 +167,8 @@ tr.icwp-plugin-vulnerability dd {
|
|
167 |
padding: 0 7px;
|
168 |
background-color: whitesmoke;
|
169 |
}
|
170 |
-
.wp-submenu-wrap a .
|
171 |
-
color: #
|
172 |
}
|
173 |
#icwp-wpsf-dashboard_widget {
|
174 |
}
|
@@ -351,4 +351,6 @@ tr.icwp-plugin-vulnerability dd {
|
|
351 |
border-radius: 50%;
|
352 |
margin-left: 6px;
|
353 |
/*background-color: rgb(0, 128, 0);*/
|
354 |
-
}
|
|
|
|
167 |
padding: 0 7px;
|
168 |
background-color: whitesmoke;
|
169 |
}
|
170 |
+
.wp-submenu-wrap a .shield_highlighted_menu {
|
171 |
+
color: #00ff00;
|
172 |
}
|
173 |
#icwp-wpsf-dashboard_widget {
|
174 |
}
|
351 |
border-radius: 50%;
|
352 |
margin-left: 6px;
|
353 |
/*background-color: rgb(0, 128, 0);*/
|
354 |
+
}
|
355 |
+
|
356 |
+
/* override boostrap */
|
resources/css/jquery.fancybox.min.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
@charset "UTF-8";body.fancybox-active{overflow:hidden}body.fancybox-iosfix{position:fixed;left:0;right:0}.fancybox-is-hidden{position:absolute;top:-9999px;left:-9999px;visibility:hidden}.fancybox-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:99992;-webkit-tap-highlight-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-stage{position:absolute;top:0;right:0;bottom:0;left:0}.fancybox-outer{overflow-y:auto;-webkit-overflow-scrolling:touch}.fancybox-bg{background:#1e1e1e;opacity:0;transition-duration:inherit;transition-property:opacity;transition-timing-function:cubic-bezier(.47,0,.74,.71)}.fancybox-is-open .fancybox-bg{opacity:.87;transition-timing-function:cubic-bezier(.22,.61,.36,1)}.fancybox-caption-wrap,.fancybox-infobar,.fancybox-toolbar{position:absolute;direction:ltr;z-index:99997;opacity:0;visibility:hidden;transition:opacity .25s,visibility 0s linear .25s;box-sizing:border-box}.fancybox-show-caption .fancybox-caption-wrap,.fancybox-show-infobar .fancybox-infobar,.fancybox-show-toolbar .fancybox-toolbar{opacity:1;visibility:visible;transition:opacity .25s,visibility 0s}.fancybox-infobar{top:0;left:0;font-size:13px;padding:0 10px;height:44px;min-width:44px;line-height:44px;color:#ccc;text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:subpixel-antialiased;mix-blend-mode:exclusion}.fancybox-toolbar{top:0;right:0;margin:0;padding:0}.fancybox-stage{overflow:hidden;direction:ltr;z-index:99994;-webkit-transform:translateZ(0)}.fancybox-is-closing .fancybox-stage{overflow:visible}.fancybox-slide{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;overflow:auto;outline:none;white-space:normal;box-sizing:border-box;text-align:center;z-index:99994;-webkit-overflow-scrolling:touch;display:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.fancybox-slide:before{content:"";display:inline-block;vertical-align:middle;height:100%;width:0}.fancybox-is-sliding .fancybox-slide,.fancybox-slide--current,.fancybox-slide--next,.fancybox-slide--previous{display:block}.fancybox-slide--image{overflow:visible}.fancybox-slide--image:before{display:none}.fancybox-slide--video .fancybox-content,.fancybox-slide--video iframe{background:#000}.fancybox-slide--map .fancybox-content,.fancybox-slide--map iframe{background:#e5e3df}.fancybox-slide--next{z-index:99995}.fancybox-slide>*{display:inline-block;position:relative;padding:24px;margin:44px 0;border-width:0;vertical-align:middle;text-align:left;background-color:#fff;overflow:auto;box-sizing:border-box}.fancybox-slide>base,.fancybox-slide>link,.fancybox-slide>meta,.fancybox-slide>script,.fancybox-slide>style,.fancybox-slide>title{display:none}.fancybox-slide .fancybox-image-wrap{position:absolute;top:0;left:0;margin:0;padding:0;border:0;z-index:99995;background:transparent;cursor:default;overflow:visible;-webkit-transform-origin:top left;transform-origin:top left;background-size:100% 100%;background-repeat:no-repeat;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform}.fancybox-can-zoomOut .fancybox-image-wrap{cursor:zoom-out}.fancybox-can-zoomIn .fancybox-image-wrap{cursor:zoom-in}.fancybox-can-drag .fancybox-image-wrap{cursor:-webkit-grab;cursor:grab}.fancybox-is-dragging .fancybox-image-wrap{cursor:-webkit-grabbing;cursor:grabbing}.fancybox-image,.fancybox-spaceball{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;border:0;max-width:none;max-height:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fancybox-spaceball{z-index:1}.fancybox-slide--iframe .fancybox-content{padding:0;width:80%;height:80%;max-width:calc(100% - 100px);max-height:calc(100% - 88px);overflow:visible;background:#fff}.fancybox-iframe{display:block;padding:0;border:0;height:100%}.fancybox-error,.fancybox-iframe{margin:0;width:100%;background:#fff}.fancybox-error{padding:40px;max-width:380px;cursor:default}.fancybox-error p{margin:0;padding:0;color:#444;font-size:16px;line-height:20px}.fancybox-button{box-sizing:border-box;display:inline-block;vertical-align:top;width:44px;height:44px;margin:0;padding:10px;border:0;border-radius:0;background:rgba(30,30,30,.6);transition:color .3s ease;cursor:pointer;outline:none}.fancybox-button,.fancybox-button:link,.fancybox-button:visited{color:#ccc}.fancybox-button:focus,.fancybox-button:hover{color:#fff}.fancybox-button[disabled]{color:#ccc;cursor:default;opacity:.6}.fancybox-button svg{display:block;position:relative;overflow:visible;shape-rendering:geometricPrecision}.fancybox-button svg path{fill:currentColor;stroke:currentColor;stroke-linejoin:round;stroke-width:3}.fancybox-button--share svg path{stroke-width:1}.fancybox-button--pause svg path:nth-child(1),.fancybox-button--play svg path:nth-child(2){display:none}.fancybox-button--zoom svg path{fill:transparent}.fancybox-navigation{display:none}.fancybox-show-nav .fancybox-navigation{display:block}.fancybox-navigation button{position:absolute;top:50%;margin:-50px 0 0;z-index:99997;background:transparent;width:60px;height:100px;padding:17px}.fancybox-navigation button:before{content:"";position:absolute;top:30px;right:10px;width:40px;height:40px;background:rgba(30,30,30,.6)}.fancybox-navigation .fancybox-button--arrow_left{left:0}.fancybox-navigation .fancybox-button--arrow_right{right:0}.fancybox-close-small{position:absolute;top:0;right:0;width:40px;height:40px;padding:0;margin:0;border:0;border-radius:0;background:transparent;z-index:10;cursor:pointer}.fancybox-close-small:after{content:"×";position:absolute;top:5px;right:5px;width:30px;height:30px;font:22px/30px Arial,Helvetica Neue,Helvetica,sans-serif;color:#888;font-weight:300;text-align:center;border-radius:50%;border-width:0;background-color:transparent;transition:background-color .25s;box-sizing:border-box;z-index:2}.fancybox-close-small:focus{outline:none}.fancybox-close-small:focus:after{outline:1px dotted #888}.fancybox-close-small:hover:after{color:#555;background:#eee}.fancybox-slide--iframe .fancybox-close-small,.fancybox-slide--image .fancybox-close-small{top:0;right:-40px}.fancybox-slide--iframe .fancybox-close-small:after,.fancybox-slide--image .fancybox-close-small:after{font-size:35px;color:#aaa}.fancybox-slide--iframe .fancybox-close-small:hover:after,.fancybox-slide--image .fancybox-close-small:hover:after{color:#fff;background:transparent}.fancybox-is-scaling .fancybox-close-small,.fancybox-is-zoomable.fancybox-can-drag .fancybox-close-small{display:none}.fancybox-caption-wrap{bottom:0;left:0;right:0;padding:60px 2vw 0;background:linear-gradient(180deg,transparent 0,rgba(0,0,0,.1) 20%,rgba(0,0,0,.2) 40%,rgba(0,0,0,.6) 80%,rgba(0,0,0,.8));pointer-events:none}.fancybox-caption{padding:30px 0;border-top:1px solid hsla(0,0%,100%,.4);font-size:14px;color:#fff;line-height:20px;-webkit-text-size-adjust:none}.fancybox-caption a,.fancybox-caption button,.fancybox-caption select{pointer-events:all;position:relative}.fancybox-caption a{color:#fff;text-decoration:underline}.fancybox-slide>.fancybox-loading{border:6px solid hsla(0,0%,39%,.4);border-top:6px solid hsla(0,0%,100%,.6);border-radius:100%;height:50px;width:50px;-webkit-animation:a .8s infinite linear;animation:a .8s infinite linear;background:transparent;position:absolute;top:50%;left:50%;margin-top:-30px;margin-left:-30px;z-index:99999}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fancybox-animated{transition-timing-function:cubic-bezier(0,0,.25,1)}.fancybox-fx-slide.fancybox-slide--previous{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.fancybox-fx-slide.fancybox-slide--next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.fancybox-fx-slide.fancybox-slide--current{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}.fancybox-fx-fade.fancybox-slide--next,.fancybox-fx-fade.fancybox-slide--previous{opacity:0;transition-timing-function:cubic-bezier(.19,1,.22,1)}.fancybox-fx-fade.fancybox-slide--current{opacity:1}.fancybox-fx-zoom-in-out.fancybox-slide--previous{-webkit-transform:scale3d(1.5,1.5,1.5);transform:scale3d(1.5,1.5,1.5);opacity:0}.fancybox-fx-zoom-in-out.fancybox-slide--next{-webkit-transform:scale3d(.5,.5,.5);transform:scale3d(.5,.5,.5);opacity:0}.fancybox-fx-zoom-in-out.fancybox-slide--current{-webkit-transform:scaleX(1);transform:scaleX(1);opacity:1}.fancybox-fx-rotate.fancybox-slide--previous{-webkit-transform:rotate(-1turn);transform:rotate(-1turn);opacity:0}.fancybox-fx-rotate.fancybox-slide--next{-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:0}.fancybox-fx-rotate.fancybox-slide--current{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.fancybox-fx-circular.fancybox-slide--previous{-webkit-transform:scale3d(0,0,0) translate3d(-100%,0,0);transform:scale3d(0,0,0) translate3d(-100%,0,0);opacity:0}.fancybox-fx-circular.fancybox-slide--next{-webkit-transform:scale3d(0,0,0) translate3d(100%,0,0);transform:scale3d(0,0,0) translate3d(100%,0,0);opacity:0}.fancybox-fx-circular.fancybox-slide--current{-webkit-transform:scaleX(1) translateZ(0);transform:scaleX(1) translateZ(0);opacity:1}.fancybox-fx-tube.fancybox-slide--previous{-webkit-transform:translate3d(-100%,0,0) scale(.1) skew(-10deg);transform:translate3d(-100%,0,0) scale(.1) skew(-10deg)}.fancybox-fx-tube.fancybox-slide--next{-webkit-transform:translate3d(100%,0,0) scale(.1) skew(10deg);transform:translate3d(100%,0,0) scale(.1) skew(10deg)}.fancybox-fx-tube.fancybox-slide--current{-webkit-transform:translateZ(0) scale(1);transform:translateZ(0) scale(1)}.fancybox-share{padding:30px;border-radius:3px;background:#f4f4f4;max-width:90%;text-align:center}.fancybox-share h1{color:#222;margin:0 0 20px;font-size:35px;font-weight:700}.fancybox-share p{margin:0;padding:0}p.fancybox-share__links{margin-right:-10px}.fancybox-share__button{display:inline-block;text-decoration:none;margin:0 10px 10px 0;padding:0 15px;min-width:130px;border:0;border-radius:3px;background:#fff;white-space:nowrap;font-size:14px;font-weight:700;line-height:40px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fff;transition:all .2s}.fancybox-share__button:hover{text-decoration:none}.fancybox-share__button--fb{background:#3b5998}.fancybox-share__button--fb:hover{background:#344e86}.fancybox-share__button--pt{background:#bd081d}.fancybox-share__button--pt:hover{background:#aa0719}.fancybox-share__button--tw{background:#1da1f2}.fancybox-share__button--tw:hover{background:#0d95e8}.fancybox-share__button svg{position:relative;top:-1px;width:25px;height:25px;margin-right:7px;vertical-align:middle}.fancybox-share__button svg path{fill:#fff}.fancybox-share__input{box-sizing:border-box;width:100%;margin:10px 0 0;padding:10px 15px;background:transparent;color:#5d5b5b;font-size:14px;outline:none;border:0;border-bottom:2px solid #d7d7d7}.fancybox-thumbs{display:none;position:absolute;top:0;bottom:0;right:0;width:212px;margin:0;padding:2px 2px 4px;background:#fff;-webkit-tap-highlight-color:transparent;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;box-sizing:border-box;z-index:99995}.fancybox-thumbs-x{overflow-y:hidden;overflow-x:auto}.fancybox-show-thumbs .fancybox-thumbs{display:block}.fancybox-show-thumbs .fancybox-inner{right:212px}.fancybox-thumbs>ul{list-style:none;position:absolute;position:relative;width:100%;height:100%;margin:0;padding:0;overflow-x:hidden;overflow-y:auto;font-size:0;white-space:nowrap}.fancybox-thumbs-x>ul{overflow:hidden}.fancybox-thumbs-y>ul::-webkit-scrollbar{width:7px}.fancybox-thumbs-y>ul::-webkit-scrollbar-track{background:#fff;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,.3)}.fancybox-thumbs-y>ul::-webkit-scrollbar-thumb{background:#2a2a2a;border-radius:10px}.fancybox-thumbs>ul>li{float:left;overflow:hidden;padding:0;margin:2px;width:100px;height:75px;max-width:calc(50% - 4px);max-height:calc(100% - 8px);position:relative;cursor:pointer;outline:none;-webkit-tap-highlight-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;box-sizing:border-box}li.fancybox-thumbs-loading{background:rgba(0,0,0,.1)}.fancybox-thumbs>ul>li>img{position:absolute;top:0;left:0;max-width:none;max-height:none;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fancybox-thumbs>ul>li:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border:4px solid #4ea7f9;z-index:99991;opacity:0;transition:all .2s cubic-bezier(.25,.46,.45,.94)}.fancybox-thumbs>ul>li.fancybox-thumbs-active:before{opacity:1}@media (max-width:800px){.fancybox-thumbs{width:110px}.fancybox-show-thumbs .fancybox-inner{right:110px}.fancybox-thumbs>ul>li{max-width:calc(100% - 10px)}}
|
|
resources/css/jquery.steps.css
DELETED
@@ -1,383 +0,0 @@
|
|
1 |
-
/*
|
2 |
-
Common
|
3 |
-
*/
|
4 |
-
|
5 |
-
.wizard,
|
6 |
-
.tabcontrol
|
7 |
-
{
|
8 |
-
display: block;
|
9 |
-
width: 100%;
|
10 |
-
overflow: hidden;
|
11 |
-
}
|
12 |
-
|
13 |
-
.wizard a,
|
14 |
-
.tabcontrol a
|
15 |
-
{
|
16 |
-
outline: 0;
|
17 |
-
}
|
18 |
-
|
19 |
-
.wizard ul,
|
20 |
-
.tabcontrol ul
|
21 |
-
{
|
22 |
-
list-style: none;
|
23 |
-
padding: 0;
|
24 |
-
margin: 0;
|
25 |
-
}
|
26 |
-
|
27 |
-
.wizard ul > li,
|
28 |
-
.tabcontrol ul > li
|
29 |
-
{
|
30 |
-
display: block;
|
31 |
-
padding: 0;
|
32 |
-
}
|
33 |
-
|
34 |
-
/* Accessibility */
|
35 |
-
.wizard > .steps .current-info,
|
36 |
-
.tabcontrol > .steps .current-info
|
37 |
-
{
|
38 |
-
position: absolute;
|
39 |
-
left: -999em;
|
40 |
-
}
|
41 |
-
|
42 |
-
.wizard > .content > .title,
|
43 |
-
.tabcontrol > .content > .title
|
44 |
-
{
|
45 |
-
position: absolute;
|
46 |
-
left: -999em;
|
47 |
-
}
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
/*
|
52 |
-
Wizard
|
53 |
-
*/
|
54 |
-
|
55 |
-
.wizard > .steps
|
56 |
-
{
|
57 |
-
position: relative;
|
58 |
-
display: block;
|
59 |
-
width: 100%;
|
60 |
-
}
|
61 |
-
|
62 |
-
.wizard.vertical > .steps
|
63 |
-
{
|
64 |
-
display: inline;
|
65 |
-
float: left;
|
66 |
-
width: 30%;
|
67 |
-
}
|
68 |
-
|
69 |
-
.wizard > .steps .number
|
70 |
-
{
|
71 |
-
font-size: 1.429em;
|
72 |
-
}
|
73 |
-
|
74 |
-
.wizard > .steps > ul > li
|
75 |
-
{
|
76 |
-
width: 25%;
|
77 |
-
}
|
78 |
-
|
79 |
-
.wizard > .steps > ul > li,
|
80 |
-
.wizard > .actions > ul > li
|
81 |
-
{
|
82 |
-
float: left;
|
83 |
-
}
|
84 |
-
|
85 |
-
.wizard.vertical > .steps > ul > li
|
86 |
-
{
|
87 |
-
float: none;
|
88 |
-
width: 100%;
|
89 |
-
}
|
90 |
-
|
91 |
-
.wizard > .steps a,
|
92 |
-
.wizard > .steps a:hover,
|
93 |
-
.wizard > .steps a:active
|
94 |
-
{
|
95 |
-
display: block;
|
96 |
-
width: auto;
|
97 |
-
margin: 0 0.5em 0.5em;
|
98 |
-
padding: 1em 1em;
|
99 |
-
text-decoration: none;
|
100 |
-
|
101 |
-
-webkit-border-radius: 5px;
|
102 |
-
-moz-border-radius: 5px;
|
103 |
-
border-radius: 5px;
|
104 |
-
}
|
105 |
-
|
106 |
-
.wizard > .steps .disabled a,
|
107 |
-
.wizard > .steps .disabled a:hover,
|
108 |
-
.wizard > .steps .disabled a:active
|
109 |
-
{
|
110 |
-
background: #eee;
|
111 |
-
color: #aaa;
|
112 |
-
cursor: default;
|
113 |
-
}
|
114 |
-
|
115 |
-
.wizard > .steps .current a,
|
116 |
-
.wizard > .steps .current a:hover,
|
117 |
-
.wizard > .steps .current a:active
|
118 |
-
{
|
119 |
-
background: rgba(69, 119, 0, 1);
|
120 |
-
color: #fff;
|
121 |
-
cursor: default;
|
122 |
-
}
|
123 |
-
|
124 |
-
.wizard > .steps .done a,
|
125 |
-
.wizard > .steps .done a:hover,
|
126 |
-
.wizard > .steps .done a:active
|
127 |
-
{
|
128 |
-
background: rgba(69, 119, 0, 0.5);
|
129 |
-
color: #fff;
|
130 |
-
}
|
131 |
-
|
132 |
-
.wizard > .steps .error a,
|
133 |
-
.wizard > .steps .error a:hover,
|
134 |
-
.wizard > .steps .error a:active
|
135 |
-
{
|
136 |
-
background: #ff3111;
|
137 |
-
color: #fff;
|
138 |
-
}
|
139 |
-
|
140 |
-
.wizard > .content
|
141 |
-
{
|
142 |
-
background: transparent;
|
143 |
-
display: block;
|
144 |
-
margin: 0.5em;
|
145 |
-
min-height: 35em;
|
146 |
-
overflow: hidden;
|
147 |
-
position: relative;
|
148 |
-
width: auto;
|
149 |
-
|
150 |
-
-webkit-border-radius: 5px;
|
151 |
-
-moz-border-radius: 5px;
|
152 |
-
border-radius: 5px;
|
153 |
-
border: 1px solid transparent;
|
154 |
-
}
|
155 |
-
|
156 |
-
.wizard.vertical > .content
|
157 |
-
{
|
158 |
-
display: inline;
|
159 |
-
float: left;
|
160 |
-
margin: 0 2.5% 0.5em 2.5%;
|
161 |
-
width: 65%;
|
162 |
-
}
|
163 |
-
|
164 |
-
.wizard > .content > .body
|
165 |
-
{
|
166 |
-
float: left;
|
167 |
-
position: absolute;
|
168 |
-
width: 95%;
|
169 |
-
height: 95%;
|
170 |
-
padding: 2.5%;
|
171 |
-
}
|
172 |
-
|
173 |
-
.wizard > .content > .body ul
|
174 |
-
{
|
175 |
-
list-style: disc ;
|
176 |
-
}
|
177 |
-
|
178 |
-
.wizard > .content > .body ul > li
|
179 |
-
{
|
180 |
-
display: list-item;
|
181 |
-
}
|
182 |
-
|
183 |
-
.wizard > .content > .body > iframe
|
184 |
-
{
|
185 |
-
border: 0 none;
|
186 |
-
width: 100%;
|
187 |
-
height: 100%;
|
188 |
-
}
|
189 |
-
|
190 |
-
.wizard > .content > .body input
|
191 |
-
{
|
192 |
-
/*display: block;*/
|
193 |
-
/*border: 1px solid #ccc;*/
|
194 |
-
}
|
195 |
-
|
196 |
-
.wizard > .content > .body input[type="checkbox"]
|
197 |
-
{
|
198 |
-
display: inline-block;
|
199 |
-
}
|
200 |
-
|
201 |
-
.wizard > .content > .body input.error
|
202 |
-
{
|
203 |
-
background: rgb(251, 227, 228);
|
204 |
-
border: 1px solid #fbc2c4;
|
205 |
-
color: #8a1f11;
|
206 |
-
}
|
207 |
-
|
208 |
-
.wizard > .content > .body label
|
209 |
-
{
|
210 |
-
/*display: inline-block;*/
|
211 |
-
/*margin-bottom: 0.5em;*/
|
212 |
-
}
|
213 |
-
|
214 |
-
.wizard > .content > .body label.error
|
215 |
-
{
|
216 |
-
color: #8a1f11;
|
217 |
-
display: inline-block;
|
218 |
-
margin-left: 1.5em;
|
219 |
-
}
|
220 |
-
|
221 |
-
.wizard > .actions
|
222 |
-
{
|
223 |
-
position: relative;
|
224 |
-
display: block;
|
225 |
-
text-align: right;
|
226 |
-
width: 100%;
|
227 |
-
}
|
228 |
-
|
229 |
-
.wizard.vertical > .actions
|
230 |
-
{
|
231 |
-
display: inline;
|
232 |
-
float: right;
|
233 |
-
margin: 0 2.5%;
|
234 |
-
width: 95%;
|
235 |
-
}
|
236 |
-
|
237 |
-
.wizard > .actions > ul
|
238 |
-
{
|
239 |
-
display: inline-block;
|
240 |
-
text-align: right;
|
241 |
-
}
|
242 |
-
|
243 |
-
.wizard > .actions > ul > li
|
244 |
-
{
|
245 |
-
margin: 0 0.5em;
|
246 |
-
}
|
247 |
-
|
248 |
-
.wizard.vertical > .actions > ul > li
|
249 |
-
{
|
250 |
-
margin: 0 0 0 1em;
|
251 |
-
}
|
252 |
-
|
253 |
-
.wizard > .actions a,
|
254 |
-
.wizard > .actions a:hover,
|
255 |
-
.wizard > .actions a:active
|
256 |
-
{
|
257 |
-
background: rgba(69, 119, 0, 1);
|
258 |
-
color: #fff;
|
259 |
-
display: block;
|
260 |
-
padding: 0.5em 1em;
|
261 |
-
text-decoration: none;
|
262 |
-
|
263 |
-
-webkit-border-radius: 5px;
|
264 |
-
-moz-border-radius: 5px;
|
265 |
-
border-radius: 5px;
|
266 |
-
}
|
267 |
-
|
268 |
-
.wizard > .actions .disabled a,
|
269 |
-
.wizard > .actions .disabled a:hover,
|
270 |
-
.wizard > .actions .disabled a:active
|
271 |
-
{
|
272 |
-
background: #eee;
|
273 |
-
color: #aaa;
|
274 |
-
}
|
275 |
-
|
276 |
-
.wizard > .loading
|
277 |
-
{
|
278 |
-
}
|
279 |
-
|
280 |
-
.wizard > .loading .spinner
|
281 |
-
{
|
282 |
-
}
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
/*
|
287 |
-
Tabcontrol
|
288 |
-
*/
|
289 |
-
|
290 |
-
.tabcontrol > .steps
|
291 |
-
{
|
292 |
-
position: relative;
|
293 |
-
display: block;
|
294 |
-
width: 100%;
|
295 |
-
}
|
296 |
-
|
297 |
-
.tabcontrol > .steps > ul
|
298 |
-
{
|
299 |
-
position: relative;
|
300 |
-
margin: 6px 0 0 0;
|
301 |
-
top: 1px;
|
302 |
-
z-index: 1;
|
303 |
-
}
|
304 |
-
|
305 |
-
.tabcontrol > .steps > ul > li
|
306 |
-
{
|
307 |
-
float: left;
|
308 |
-
margin: 5px 2px 0 0;
|
309 |
-
padding: 1px;
|
310 |
-
|
311 |
-
-webkit-border-top-left-radius: 5px;
|
312 |
-
-webkit-border-top-right-radius: 5px;
|
313 |
-
-moz-border-radius-topleft: 5px;
|
314 |
-
-moz-border-radius-topright: 5px;
|
315 |
-
border-top-left-radius: 5px;
|
316 |
-
border-top-right-radius: 5px;
|
317 |
-
}
|
318 |
-
|
319 |
-
.tabcontrol > .steps > ul > li:hover
|
320 |
-
{
|
321 |
-
background: #edecec;
|
322 |
-
border: 1px solid #bbb;
|
323 |
-
padding: 0;
|
324 |
-
}
|
325 |
-
|
326 |
-
.tabcontrol > .steps > ul > li.current
|
327 |
-
{
|
328 |
-
background: #fff;
|
329 |
-
border: 1px solid #bbb;
|
330 |
-
border-bottom: 0 none;
|
331 |
-
padding: 0 0 1px 0;
|
332 |
-
margin-top: 0;
|
333 |
-
}
|
334 |
-
|
335 |
-
.tabcontrol > .steps > ul > li > a
|
336 |
-
{
|
337 |
-
color: #5f5f5f;
|
338 |
-
display: inline-block;
|
339 |
-
border: 0 none;
|
340 |
-
margin: 0;
|
341 |
-
padding: 10px 30px;
|
342 |
-
text-decoration: none;
|
343 |
-
}
|
344 |
-
|
345 |
-
.tabcontrol > .steps > ul > li > a:hover
|
346 |
-
{
|
347 |
-
text-decoration: none;
|
348 |
-
}
|
349 |
-
|
350 |
-
.tabcontrol > .steps > ul > li.current > a
|
351 |
-
{
|
352 |
-
padding: 15px 30px 10px 30px;
|
353 |
-
}
|
354 |
-
|
355 |
-
.tabcontrol > .content
|
356 |
-
{
|
357 |
-
position: relative;
|
358 |
-
display: inline-block;
|
359 |
-
width: 100%;
|
360 |
-
height: 35em;
|
361 |
-
overflow: hidden;
|
362 |
-
border-top: 1px solid #bbb;
|
363 |
-
padding-top: 20px;
|
364 |
-
}
|
365 |
-
|
366 |
-
.tabcontrol > .content > .body
|
367 |
-
{
|
368 |
-
float: left;
|
369 |
-
position: absolute;
|
370 |
-
width: 95%;
|
371 |
-
height: 95%;
|
372 |
-
padding: 2.5%;
|
373 |
-
}
|
374 |
-
|
375 |
-
.tabcontrol > .content > .body ul
|
376 |
-
{
|
377 |
-
list-style: disc !important;
|
378 |
-
}
|
379 |
-
|
380 |
-
.tabcontrol > .content > .body ul > li
|
381 |
-
{
|
382 |
-
display: list-item;
|
383 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/css/jquery/fancybox.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
body.compensate-for-scrollbar{overflow:hidden}.fancybox-active{height:auto}.fancybox-is-hidden{left:-9999px;margin:0;position:absolute!important;top:-9999px;visibility:hidden}.fancybox-container{-webkit-backface-visibility:hidden;height:100%;left:0;outline:none;position:fixed;-webkit-tap-highlight-color:transparent;top:0;-ms-touch-action:manipulation;touch-action:manipulation;transform:translateZ(0);width:100%;z-index:99992}.fancybox-container *{box-sizing:border-box}.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-stage{bottom:0;left:0;position:absolute;right:0;top:0}.fancybox-outer{-webkit-overflow-scrolling:touch;overflow-y:auto}.fancybox-bg{background:#1e1e1e;opacity:0;transition-duration:inherit;transition-property:opacity;transition-timing-function:cubic-bezier(.47,0,.74,.71)}.fancybox-is-open .fancybox-bg{opacity:.9;transition-timing-function:cubic-bezier(.22,.61,.36,1)}.fancybox-caption,.fancybox-infobar,.fancybox-navigation .fancybox-button,.fancybox-toolbar{direction:ltr;opacity:0;position:absolute;transition:opacity .25s ease,visibility 0s ease .25s;visibility:hidden;z-index:99997}.fancybox-show-caption .fancybox-caption,.fancybox-show-infobar .fancybox-infobar,.fancybox-show-nav .fancybox-navigation .fancybox-button,.fancybox-show-toolbar .fancybox-toolbar{opacity:1;transition:opacity .25s ease 0s,visibility 0s ease 0s;visibility:visible}.fancybox-infobar{color:#ccc;font-size:13px;-webkit-font-smoothing:subpixel-antialiased;height:44px;left:0;line-height:44px;min-width:44px;mix-blend-mode:difference;padding:0 10px;pointer-events:none;top:0;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fancybox-toolbar{right:0;top:0}.fancybox-stage{direction:ltr;overflow:visible;transform:translateZ(0);z-index:99994}.fancybox-is-open .fancybox-stage{overflow:hidden}.fancybox-slide{-webkit-backface-visibility:hidden;display:none;height:100%;left:0;outline:none;overflow:auto;-webkit-overflow-scrolling:touch;padding:44px;position:absolute;text-align:center;top:0;transition-property:transform,opacity;white-space:normal;width:100%;z-index:99994}.fancybox-slide:before{content:"";display:inline-block;font-size:0;height:100%;vertical-align:middle;width:0}.fancybox-is-sliding .fancybox-slide,.fancybox-slide--current,.fancybox-slide--next,.fancybox-slide--previous{display:block}.fancybox-slide--image{overflow:hidden;padding:44px 0}.fancybox-slide--image:before{display:none}.fancybox-slide--html{padding:6px}.fancybox-content{background:#fff;display:inline-block;margin:0;max-width:100%;overflow:auto;-webkit-overflow-scrolling:touch;padding:44px;position:relative;text-align:left;vertical-align:middle}.fancybox-slide--image .fancybox-content{animation-timing-function:cubic-bezier(.5,0,.14,1);-webkit-backface-visibility:hidden;background:transparent;background-repeat:no-repeat;background-size:100% 100%;left:0;max-width:none;overflow:visible;padding:0;position:absolute;top:0;transform-origin:top left;transition-property:transform,opacity;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:99995}.fancybox-can-zoomOut .fancybox-content{cursor:zoom-out}.fancybox-can-zoomIn .fancybox-content{cursor:zoom-in}.fancybox-can-pan .fancybox-content,.fancybox-can-swipe .fancybox-content{cursor:grab}.fancybox-is-grabbing .fancybox-content{cursor:grabbing}.fancybox-container [data-selectable=true]{cursor:text}.fancybox-image,.fancybox-spaceball{background:transparent;border:0;height:100%;left:0;margin:0;max-height:none;max-width:none;padding:0;position:absolute;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.fancybox-spaceball{z-index:1}.fancybox-slide--iframe .fancybox-content,.fancybox-slide--map .fancybox-content,.fancybox-slide--pdf .fancybox-content,.fancybox-slide--video .fancybox-content{height:100%;overflow:visible;padding:0;width:100%}.fancybox-slide--video .fancybox-content{background:#000}.fancybox-slide--map .fancybox-content{background:#e5e3df}.fancybox-slide--iframe .fancybox-content{background:#fff}.fancybox-iframe,.fancybox-video{background:transparent;border:0;display:block;height:100%;margin:0;overflow:hidden;padding:0;width:100%}.fancybox-iframe{left:0;position:absolute;top:0}.fancybox-error{background:#fff;cursor:default;max-width:400px;padding:40px;width:100%}.fancybox-error p{color:#444;font-size:16px;line-height:20px;margin:0;padding:0}.fancybox-button{background:rgba(30,30,30,.6);border:0;border-radius:0;box-shadow:none;cursor:pointer;display:inline-block;height:44px;margin:0;padding:10px;position:relative;transition:color .2s;vertical-align:top;visibility:inherit;width:44px}.fancybox-button,.fancybox-button:link,.fancybox-button:visited{color:#ccc}.fancybox-button:hover{color:#fff}.fancybox-button:focus{outline:none}.fancybox-button.fancybox-focus{outline:1px dotted}.fancybox-button[disabled],.fancybox-button[disabled]:hover{color:#888;cursor:default;outline:none}.fancybox-button div{height:100%}.fancybox-button svg{display:block;height:100%;overflow:visible;position:relative;width:100%}.fancybox-button svg path{fill:currentColor;stroke-width:0}.fancybox-button--fsenter svg:nth-child(2),.fancybox-button--fsexit svg:first-child,.fancybox-button--pause svg:first-child,.fancybox-button--play svg:nth-child(2){display:none}.fancybox-progress{background:#ff5268;height:2px;left:0;position:absolute;right:0;top:0;transform:scaleX(0);transform-origin:0;transition-property:transform;transition-timing-function:linear;z-index:99998}.fancybox-close-small{background:transparent;border:0;border-radius:0;color:#ccc;cursor:pointer;opacity:.8;padding:8px;position:absolute;right:-12px;top:-44px;z-index:401}.fancybox-close-small:hover{color:#fff;opacity:1}.fancybox-slide--html .fancybox-close-small{color:currentColor;padding:10px;right:0;top:0}.fancybox-slide--image.fancybox-is-scaling .fancybox-content{overflow:hidden}.fancybox-is-scaling .fancybox-close-small,.fancybox-is-zoomable.fancybox-can-pan .fancybox-close-small{display:none}.fancybox-navigation .fancybox-button{background-clip:content-box;height:100px;opacity:0;position:absolute;top:calc(50% - 50px);width:70px}.fancybox-navigation .fancybox-button div{padding:7px}.fancybox-navigation .fancybox-button--arrow_left{left:0;left:env(safe-area-inset-left);padding:31px 26px 31px 6px}.fancybox-navigation .fancybox-button--arrow_right{padding:31px 6px 31px 26px;right:0;right:env(safe-area-inset-right)}.fancybox-caption{background:linear-gradient(0deg,rgba(0,0,0,.85) 0,rgba(0,0,0,.3) 50%,rgba(0,0,0,.15) 65%,rgba(0,0,0,.075) 75.5%,rgba(0,0,0,.037) 82.85%,rgba(0,0,0,.019) 88%,transparent);bottom:0;color:#eee;font-size:14px;font-weight:400;left:0;line-height:1.5;padding:75px 44px 25px;pointer-events:none;right:0;text-align:center;z-index:99996}@supports (padding:max(0px)){.fancybox-caption{padding:75px max(44px,env(safe-area-inset-right)) max(25px,env(safe-area-inset-bottom)) max(44px,env(safe-area-inset-left))}}.fancybox-caption--separate{margin-top:-50px}.fancybox-caption__body{max-height:50vh;overflow:auto;pointer-events:all}.fancybox-caption a,.fancybox-caption a:link,.fancybox-caption a:visited{color:#ccc;text-decoration:none}.fancybox-caption a:hover{color:#fff;text-decoration:underline}.fancybox-loading{animation:a 1s linear infinite;background:transparent;border:4px solid #888;border-bottom-color:#fff;border-radius:50%;height:50px;left:50%;margin:-25px 0 0 -25px;opacity:.7;padding:0;position:absolute;top:50%;width:50px;z-index:99999}@keyframes a{to{transform:rotate(1turn)}}.fancybox-animated{transition-timing-function:cubic-bezier(0,0,.25,1)}.fancybox-fx-slide.fancybox-slide--previous{opacity:0;transform:translate3d(-100%,0,0)}.fancybox-fx-slide.fancybox-slide--next{opacity:0;transform:translate3d(100%,0,0)}.fancybox-fx-slide.fancybox-slide--current{opacity:1;transform:translateZ(0)}.fancybox-fx-fade.fancybox-slide--next,.fancybox-fx-fade.fancybox-slide--previous{opacity:0;transition-timing-function:cubic-bezier(.19,1,.22,1)}.fancybox-fx-fade.fancybox-slide--current{opacity:1}.fancybox-fx-zoom-in-out.fancybox-slide--previous{opacity:0;transform:scale3d(1.5,1.5,1.5)}.fancybox-fx-zoom-in-out.fancybox-slide--next{opacity:0;transform:scale3d(.5,.5,.5)}.fancybox-fx-zoom-in-out.fancybox-slide--current{opacity:1;transform:scaleX(1)}.fancybox-fx-rotate.fancybox-slide--previous{opacity:0;transform:rotate(-1turn)}.fancybox-fx-rotate.fancybox-slide--next{opacity:0;transform:rotate(1turn)}.fancybox-fx-rotate.fancybox-slide--current{opacity:1;transform:rotate(0deg)}.fancybox-fx-circular.fancybox-slide--previous{opacity:0;transform:scale3d(0,0,0) translate3d(-100%,0,0)}.fancybox-fx-circular.fancybox-slide--next{opacity:0;transform:scale3d(0,0,0) translate3d(100%,0,0)}.fancybox-fx-circular.fancybox-slide--current{opacity:1;transform:scaleX(1) translateZ(0)}.fancybox-fx-tube.fancybox-slide--previous{transform:translate3d(-100%,0,0) scale(.1) skew(-10deg)}.fancybox-fx-tube.fancybox-slide--next{transform:translate3d(100%,0,0) scale(.1) skew(10deg)}.fancybox-fx-tube.fancybox-slide--current{transform:translateZ(0) scale(1)}@media (max-height:576px){.fancybox-slide{padding-left:6px;padding-right:6px}.fancybox-slide--image{padding:6px 0}.fancybox-close-small{right:-6px}.fancybox-slide--image .fancybox-close-small{background:#4e4e4e;color:#f2f4f6;height:36px;opacity:1;padding:6px;right:0;top:0;width:36px}.fancybox-caption{padding-left:12px;padding-right:12px}@supports (padding:max(0px)){.fancybox-caption{padding-left:max(12px,env(safe-area-inset-left));padding-right:max(12px,env(safe-area-inset-right))}}}.fancybox-share{background:#f4f4f4;border-radius:3px;max-width:90%;padding:30px;text-align:center}.fancybox-share h1{color:#222;font-size:35px;font-weight:700;margin:0 0 20px}.fancybox-share p{margin:0;padding:0}.fancybox-share__button{border:0;border-radius:3px;display:inline-block;font-size:14px;font-weight:700;line-height:40px;margin:0 5px 10px;min-width:130px;padding:0 15px;text-decoration:none;transition:all .2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap}.fancybox-share__button:link,.fancybox-share__button:visited{color:#fff}.fancybox-share__button:hover{text-decoration:none}.fancybox-share__button--fb{background:#3b5998}.fancybox-share__button--fb:hover{background:#344e86}.fancybox-share__button--pt{background:#bd081d}.fancybox-share__button--pt:hover{background:#aa0719}.fancybox-share__button--tw{background:#1da1f2}.fancybox-share__button--tw:hover{background:#0d95e8}.fancybox-share__button svg{height:25px;margin-right:7px;position:relative;top:-1px;vertical-align:middle;width:25px}.fancybox-share__button svg path{fill:#fff}.fancybox-share__input{background:transparent;border:0;border-bottom:1px solid #d7d7d7;border-radius:0;color:#5d5b5b;font-size:14px;margin:10px 0 0;outline:none;padding:10px 15px;width:100%}.fancybox-thumbs{background:#ddd;bottom:0;display:none;margin:0;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;padding:2px 2px 4px;position:absolute;right:0;-webkit-tap-highlight-color:rgba(0,0,0,0);top:0;width:212px;z-index:99995}.fancybox-thumbs-x{overflow-x:auto;overflow-y:hidden}.fancybox-show-thumbs .fancybox-thumbs{display:block}.fancybox-show-thumbs .fancybox-inner{right:212px}.fancybox-thumbs__list{font-size:0;height:100%;list-style:none;margin:0;overflow-x:hidden;overflow-y:auto;padding:0;position:absolute;position:relative;white-space:nowrap;width:100%}.fancybox-thumbs-x .fancybox-thumbs__list{overflow:hidden}.fancybox-thumbs-y .fancybox-thumbs__list::-webkit-scrollbar{width:7px}.fancybox-thumbs-y .fancybox-thumbs__list::-webkit-scrollbar-track{background:#fff;border-radius:10px;box-shadow:inset 0 0 6px rgba(0,0,0,.3)}.fancybox-thumbs-y .fancybox-thumbs__list::-webkit-scrollbar-thumb{background:#2a2a2a;border-radius:10px}.fancybox-thumbs__list a{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(0,0,0,.1);background-position:50%;background-repeat:no-repeat;background-size:cover;cursor:pointer;float:left;height:75px;margin:2px;max-height:calc(100% - 8px);max-width:calc(50% - 4px);outline:none;overflow:hidden;padding:0;position:relative;-webkit-tap-highlight-color:transparent;width:100px}.fancybox-thumbs__list a:before{border:6px solid #ff5268;bottom:0;content:"";left:0;opacity:0;position:absolute;right:0;top:0;transition:all .2s cubic-bezier(.25,.46,.45,.94);z-index:99991}.fancybox-thumbs__list a:focus:before{opacity:.5}.fancybox-thumbs__list a.fancybox-thumbs-active:before{opacity:1}@media (max-width:576px){.fancybox-thumbs{width:110px}.fancybox-show-thumbs .fancybox-inner{right:110px}.fancybox-thumbs__list a{max-width:calc(100% - 10px)}}
|
resources/css/plugin.css
CHANGED
@@ -1558,10 +1558,14 @@ body.folded #FooterBannerGoPro {
|
|
1558 |
}
|
1559 |
#NavSideBar a.nav-link.active {
|
1560 |
font-weight: bolder;
|
|
|
1561 |
}
|
1562 |
.primary_sub_menu {
|
1563 |
}
|
1564 |
-
|
|
|
|
|
|
|
1565 |
#SearchDialog .modal-body {
|
1566 |
min-height: 450px;
|
1567 |
}
|
@@ -1571,7 +1575,6 @@ body.folded #FooterBannerGoPro {
|
|
1571 |
#SearchDialog .bootstrap-select > .dropdown-toggle.bs-placeholder {
|
1572 |
color: #333333;
|
1573 |
}
|
1574 |
-
|
1575 |
#StatsNav {
|
1576 |
background-color: #f1f1f1;
|
1577 |
display: inline-block;
|
@@ -1588,4 +1591,57 @@ body.folded #FooterBannerGoPro {
|
|
1588 |
.stat_box .stat_count {
|
1589 |
font-size: 3rem;
|
1590 |
line-height: 3.5rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1591 |
}
|
1558 |
}
|
1559 |
#NavSideBar a.nav-link.active {
|
1560 |
font-weight: bolder;
|
1561 |
+
font-size: 1rem;
|
1562 |
}
|
1563 |
.primary_sub_menu {
|
1564 |
}
|
1565 |
+
.primary_sub_menu a.active {
|
1566 |
+
border-left: 3px solid rgba(0, 128, 0, 0.4);
|
1567 |
+
padding-left: 6px !important;
|
1568 |
+
}
|
1569 |
#SearchDialog .modal-body {
|
1570 |
min-height: 450px;
|
1571 |
}
|
1575 |
#SearchDialog .bootstrap-select > .dropdown-toggle.bs-placeholder {
|
1576 |
color: #333333;
|
1577 |
}
|
|
|
1578 |
#StatsNav {
|
1579 |
background-color: #f1f1f1;
|
1580 |
display: inline-block;
|
1591 |
.stat_box .stat_count {
|
1592 |
font-size: 3rem;
|
1593 |
line-height: 3.5rem;
|
1594 |
+
}
|
1595 |
+
#odp-PageContainer .summary-card.card {
|
1596 |
+
border-color: transparent;
|
1597 |
+
}
|
1598 |
+
.summary-card.card,
|
1599 |
+
.summary-card .card-body {
|
1600 |
+
background-color: transparent;
|
1601 |
+
}
|
1602 |
+
.summary-card .card-body {
|
1603 |
+
padding: 0.1rem;
|
1604 |
+
}
|
1605 |
+
.summary-card .card-footer {
|
1606 |
+
border: 1px solid transparent;
|
1607 |
+
background-color: transparent;
|
1608 |
+
}
|
1609 |
+
.summary-card .card-footer h6 {
|
1610 |
+
font-size: 0.8rem;
|
1611 |
+
margin: 0;
|
1612 |
+
text-align: center;
|
1613 |
+
}
|
1614 |
+
.summary-card.enabled .icon,
|
1615 |
+
.summary-card.enabled .card-footer a {
|
1616 |
+
color: #008000;
|
1617 |
+
}
|
1618 |
+
.summary-card.disabled .icon,
|
1619 |
+
.summary-card.disabled .card-footer a {
|
1620 |
+
color: #c23e0c;
|
1621 |
+
}
|
1622 |
+
.summary-card a[target="_blank"]::after {
|
1623 |
+
content: '' !important;
|
1624 |
+
margin: 0 !important;
|
1625 |
+
}
|
1626 |
+
.summary-card .icon > svg {
|
1627 |
+
width: 64px;
|
1628 |
+
height: 64px;
|
1629 |
+
padding: 12px;
|
1630 |
+
border: 1px solid #008000;
|
1631 |
+
border-radius: 32px;
|
1632 |
+
/* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#f8ffe8+0,e3f5ab+33,b7df2d+100;Green+3D+%234 */
|
1633 |
+
background: #f8ffe8; /* Old browsers */
|
1634 |
+
background: -moz-linear-gradient(top, #f8ffe8 0%, #e3f5ab 33%, #b7df2d 100%); /* FF3.6-15 */
|
1635 |
+
background: -webkit-linear-gradient(top, #f8ffe8 0%, #e3f5ab 33%, #b7df2d 100%); /* Chrome10-25,Safari5.1-6 */
|
1636 |
+
background: linear-gradient(to bottom, #f8ffe8 0%, #e3f5ab 33%, #b7df2d 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
1637 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8ffe8', endColorstr='#b7df2d', GradientType=0); /* IE6-9 */
|
1638 |
+
}
|
1639 |
+
.summary-card.disabled .icon > svg {
|
1640 |
+
border-color: #c23e0c;
|
1641 |
+
/* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#ffeded+0,fcd6d6+12,f9acac+88 */
|
1642 |
+
background: #ffeded; /* Old browsers */
|
1643 |
+
background: -moz-linear-gradient(top, #ffeded 0%, #fcd6d6 12%, #f9acac 88%); /* FF3.6-15 */
|
1644 |
+
background: -webkit-linear-gradient(top, #ffeded 0%, #fcd6d6 12%, #f9acac 88%); /* Chrome10-25,Safari5.1-6 */
|
1645 |
+
background: linear-gradient(to bottom, #ffeded 0%, #fcd6d6 12%, #f9acac 88%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
1646 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeded', endColorstr='#f9acac', GradientType=0); /* IE6-9 */
|
1647 |
}
|
resources/css/shield/dialog.css
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.shield_dialog {
|
2 |
+
color: black;
|
3 |
+
}
|
4 |
+
.shield_dialog .dialog-content,
|
5 |
+
.shield_dialog .ui-dialog-title {
|
6 |
+
color: black;
|
7 |
+
}
|
resources/css/{pages.css → shield/pages.css}
RENAMED
File without changes
|
resources/css/shield/wizard.css
ADDED
@@ -0,0 +1,542 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
html {
|
2 |
+
overflow-y: scroll;
|
3 |
+
}
|
4 |
+
body {
|
5 |
+
padding-bottom: 200px;
|
6 |
+
overflow-y: visible;
|
7 |
+
}
|
8 |
+
body.wait {
|
9 |
+
cursor: wait !important;
|
10 |
+
}
|
11 |
+
.wizard > .content {
|
12 |
+
background: #ffffff;
|
13 |
+
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
|
14 |
+
}
|
15 |
+
.wizard > .steps .current a {
|
16 |
+
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.1);
|
17 |
+
}
|
18 |
+
.wizard.vertical > .steps {
|
19 |
+
width: 20%; /** from 30 **/
|
20 |
+
}
|
21 |
+
/*
|
22 |
+
Common
|
23 |
+
*/
|
24 |
+
.wizard,
|
25 |
+
.tabcontrol {
|
26 |
+
display: block;
|
27 |
+
width: 100%;
|
28 |
+
overflow: hidden;
|
29 |
+
}
|
30 |
+
.wizard a,
|
31 |
+
.tabcontrol a {
|
32 |
+
outline: 0;
|
33 |
+
}
|
34 |
+
.wizard ul,
|
35 |
+
.tabcontrol ul {
|
36 |
+
list-style: none;
|
37 |
+
padding: 0;
|
38 |
+
margin: 0;
|
39 |
+
}
|
40 |
+
.wizard ul > li,
|
41 |
+
.tabcontrol ul > li {
|
42 |
+
display: block;
|
43 |
+
padding: 0;
|
44 |
+
}
|
45 |
+
/* Accessibility */
|
46 |
+
.wizard > .steps .current-info,
|
47 |
+
.tabcontrol > .steps .current-info {
|
48 |
+
position: absolute;
|
49 |
+
left: -999em;
|
50 |
+
}
|
51 |
+
.wizard > .content > .title,
|
52 |
+
.tabcontrol > .content > .title {
|
53 |
+
position: absolute;
|
54 |
+
left: -999em;
|
55 |
+
}
|
56 |
+
/*
|
57 |
+
Wizard
|
58 |
+
*/
|
59 |
+
.wizard > .steps {
|
60 |
+
position: relative;
|
61 |
+
display: block;
|
62 |
+
width: 100%;
|
63 |
+
}
|
64 |
+
.wizard.vertical > .steps {
|
65 |
+
display: inline;
|
66 |
+
float: left;
|
67 |
+
width: 30%;
|
68 |
+
}
|
69 |
+
.wizard > .steps .number {
|
70 |
+
font-size: 1.429em;
|
71 |
+
}
|
72 |
+
.wizard > .steps > ul > li {
|
73 |
+
width: 25%;
|
74 |
+
}
|
75 |
+
.wizard > .steps > ul > li,
|
76 |
+
.wizard > .actions > ul > li {
|
77 |
+
float: left;
|
78 |
+
}
|
79 |
+
.wizard.vertical > .steps > ul > li {
|
80 |
+
float: none;
|
81 |
+
width: 100%;
|
82 |
+
}
|
83 |
+
.wizard > .steps a,
|
84 |
+
.wizard > .steps a:hover,
|
85 |
+
.wizard > .steps a:active {
|
86 |
+
display: block;
|
87 |
+
width: auto;
|
88 |
+
margin: 0 0.5em 0.5em;
|
89 |
+
padding: 1em 1em;
|
90 |
+
text-decoration: none;
|
91 |
+
-webkit-border-radius: 5px;
|
92 |
+
-moz-border-radius: 5px;
|
93 |
+
border-radius: 5px;
|
94 |
+
}
|
95 |
+
.wizard > .steps .disabled a,
|
96 |
+
.wizard > .steps .disabled a:hover,
|
97 |
+
.wizard > .steps .disabled a:active {
|
98 |
+
background: #eeeeee;
|
99 |
+
color: #aaaaaa;
|
100 |
+
cursor: default;
|
101 |
+
}
|
102 |
+
.wizard > .steps .current a,
|
103 |
+
.wizard > .steps .current a:hover,
|
104 |
+
.wizard > .steps .current a:active {
|
105 |
+
background: rgba(69, 119, 0, 1);
|
106 |
+
color: #ffffff;
|
107 |
+
cursor: default;
|
108 |
+
}
|
109 |
+
.wizard > .steps .done a,
|
110 |
+
.wizard > .steps .done a:hover,
|
111 |
+
.wizard > .steps .done a:active {
|
112 |
+
background: rgba(69, 119, 0, 0.5);
|
113 |
+
color: #ffffff;
|
114 |
+
}
|
115 |
+
.wizard > .steps .error a,
|
116 |
+
.wizard > .steps .error a:hover,
|
117 |
+
.wizard > .steps .error a:active {
|
118 |
+
background: #ff3111;
|
119 |
+
color: #ffffff;
|
120 |
+
}
|
121 |
+
.wizard > .content {
|
122 |
+
background: transparent;
|
123 |
+
display: block;
|
124 |
+
margin: 0.5em;
|
125 |
+
min-height: 35em;
|
126 |
+
overflow: hidden;
|
127 |
+
position: relative;
|
128 |
+
width: auto;
|
129 |
+
-webkit-border-radius: 5px;
|
130 |
+
-moz-border-radius: 5px;
|
131 |
+
border-radius: 5px;
|
132 |
+
border: 1px solid transparent;
|
133 |
+
}
|
134 |
+
.wizard.vertical > .content {
|
135 |
+
display: inline;
|
136 |
+
float: left;
|
137 |
+
margin: 0 2.5% 0.5em 2.5%;
|
138 |
+
width: 65%;
|
139 |
+
}
|
140 |
+
.wizard > .content > .body {
|
141 |
+
float: left;
|
142 |
+
position: absolute;
|
143 |
+
width: 95%;
|
144 |
+
height: 95%;
|
145 |
+
padding: 2.5%;
|
146 |
+
}
|
147 |
+
.wizard > .content > .body ul {
|
148 |
+
list-style: disc;
|
149 |
+
}
|
150 |
+
.wizard > .content > .body ul > li {
|
151 |
+
display: list-item;
|
152 |
+
}
|
153 |
+
.wizard > .content > .body > iframe {
|
154 |
+
border: 0 none;
|
155 |
+
width: 100%;
|
156 |
+
height: 100%;
|
157 |
+
}
|
158 |
+
.wizard > .content > .body input {
|
159 |
+
/*display: block;*/
|
160 |
+
/*border: 1px solid #ccc;*/
|
161 |
+
}
|
162 |
+
.wizard > .content > .body input[type="checkbox"] {
|
163 |
+
display: inline-block;
|
164 |
+
}
|
165 |
+
.wizard > .content > .body input.error {
|
166 |
+
background: rgb(251, 227, 228);
|
167 |
+
border: 1px solid #fbc2c4;
|
168 |
+
color: #8a1f11;
|
169 |
+
}
|
170 |
+
.wizard > .content > .body label {
|
171 |
+
/*display: inline-block;*/
|
172 |
+
/*margin-bottom: 0.5em;*/
|
173 |
+
}
|
174 |
+
.wizard > .content > .body label.error {
|
175 |
+
color: #8a1f11;
|
176 |
+
display: inline-block;
|
177 |
+
margin-left: 1.5em;
|
178 |
+
}
|
179 |
+
.wizard > .actions {
|
180 |
+
position: relative;
|
181 |
+
display: block;
|
182 |
+
text-align: right;
|
183 |
+
width: 100%;
|
184 |
+
}
|
185 |
+
.wizard.vertical > .actions {
|
186 |
+
display: inline;
|
187 |
+
float: right;
|
188 |
+
margin: 0 2.5%;
|
189 |
+
width: 95%;
|
190 |
+
}
|
191 |
+
.wizard > .actions > ul {
|
192 |
+
display: inline-block;
|
193 |
+
text-align: right;
|
194 |
+
}
|
195 |
+
.wizard > .actions > ul > li {
|
196 |
+
margin: 0 0.5em;
|
197 |
+
}
|
198 |
+
.wizard.vertical > .actions > ul > li {
|
199 |
+
margin: 0 0 0 1em;
|
200 |
+
}
|
201 |
+
.wizard > .actions a,
|
202 |
+
.wizard > .actions a:hover,
|
203 |
+
.wizard > .actions a:active {
|
204 |
+
background: rgba(69, 119, 0, 1);
|
205 |
+
color: #ffffff;
|
206 |
+
display: block;
|
207 |
+
padding: 0.5em 1em;
|
208 |
+
text-decoration: none;
|
209 |
+
-webkit-border-radius: 5px;
|
210 |
+
-moz-border-radius: 5px;
|
211 |
+
border-radius: 5px;
|
212 |
+
}
|
213 |
+
.wizard > .actions .disabled a,
|
214 |
+
.wizard > .actions .disabled a:hover,
|
215 |
+
.wizard > .actions .disabled a:active {
|
216 |
+
background: #eeeeee;
|
217 |
+
color: #aaaaaa;
|
218 |
+
}
|
219 |
+
.wizard > .loading {
|
220 |
+
}
|
221 |
+
.wizard > .loading .spinner {
|
222 |
+
}
|
223 |
+
/*
|
224 |
+
Tabcontrol
|
225 |
+
*/
|
226 |
+
.tabcontrol > .steps {
|
227 |
+
position: relative;
|
228 |
+
display: block;
|
229 |
+
width: 100%;
|
230 |
+
}
|
231 |
+
.tabcontrol > .steps > ul {
|
232 |
+
position: relative;
|
233 |
+
margin: 6px 0 0 0;
|
234 |
+
top: 1px;
|
235 |
+
z-index: 1;
|
236 |
+
}
|
237 |
+
.tabcontrol > .steps > ul > li {
|
238 |
+
float: left;
|
239 |
+
margin: 5px 2px 0 0;
|
240 |
+
padding: 1px;
|
241 |
+
-webkit-border-top-left-radius: 5px;
|
242 |
+
-webkit-border-top-right-radius: 5px;
|
243 |
+
-moz-border-radius-topleft: 5px;
|
244 |
+
-moz-border-radius-topright: 5px;
|
245 |
+
border-top-left-radius: 5px;
|
246 |
+
border-top-right-radius: 5px;
|
247 |
+
}
|
248 |
+
.tabcontrol > .steps > ul > li:hover {
|
249 |
+
background: #edecec;
|
250 |
+
border: 1px solid #bbbbbb;
|
251 |
+
padding: 0;
|
252 |
+
}
|
253 |
+
.tabcontrol > .steps > ul > li.current {
|
254 |
+
background: #ffffff;
|
255 |
+
border: 1px solid #bbbbbb;
|
256 |
+
border-bottom: 0 none;
|
257 |
+
padding: 0 0 1px 0;
|
258 |
+
margin-top: 0;
|
259 |
+
}
|
260 |
+
.tabcontrol > .steps > ul > li > a {
|
261 |
+
color: #5f5f5f;
|
262 |
+
display: inline-block;
|
263 |
+
border: 0 none;
|
264 |
+
margin: 0;
|
265 |
+
padding: 10px 30px;
|
266 |
+
text-decoration: none;
|
267 |
+
}
|
268 |
+
.tabcontrol > .steps > ul > li > a:hover {
|
269 |
+
text-decoration: none;
|
270 |
+
}
|
271 |
+
.tabcontrol > .steps > ul > li.current > a {
|
272 |
+
padding: 15px 30px 10px 30px;
|
273 |
+
}
|
274 |
+
.tabcontrol > .content {
|
275 |
+
position: relative;
|
276 |
+
display: inline-block;
|
277 |
+
width: 100%;
|
278 |
+
height: 35em;
|
279 |
+
overflow: hidden;
|
280 |
+
border-top: 1px solid #bbbbbb;
|
281 |
+
padding-top: 20px;
|
282 |
+
}
|
283 |
+
.tabcontrol > .content > .body {
|
284 |
+
float: left;
|
285 |
+
position: absolute;
|
286 |
+
width: 95%;
|
287 |
+
height: 95%;
|
288 |
+
padding: 2.5%;
|
289 |
+
}
|
290 |
+
.tabcontrol > .content > .body ul {
|
291 |
+
list-style: disc !important;
|
292 |
+
}
|
293 |
+
.tabcontrol > .content > .body ul > li {
|
294 |
+
display: list-item;
|
295 |
+
}
|
296 |
+
.wizard.vertical > .content {
|
297 |
+
width: 75%; /** from 65 **/
|
298 |
+
}
|
299 |
+
.wizard > .content > .body {
|
300 |
+
height: auto;
|
301 |
+
position: relative;
|
302 |
+
padding: 0;
|
303 |
+
width: 100%
|
304 |
+
}
|
305 |
+
.wizard > .content > .body .slide-header {
|
306 |
+
padding: 3% 3% 0 3%;
|
307 |
+
}
|
308 |
+
.wizard > .content > .body .slide-header .btn-block {
|
309 |
+
margin-bottom: -1px;
|
310 |
+
}
|
311 |
+
.wizard > .content > .body .slide-header hr {
|
312 |
+
margin: 15px 0;
|
313 |
+
}
|
314 |
+
.wizard > .content > .body .slide-body {
|
315 |
+
padding: 0 6% 0 6%;
|
316 |
+
}
|
317 |
+
.wizard > .content > .body .slide-footer {
|
318 |
+
padding: 0 6% 3% 6%;
|
319 |
+
}
|
320 |
+
.wizard.vertical > .actions {
|
321 |
+
margin-bottom: 20px;
|
322 |
+
}
|
323 |
+
.wizard h3 {
|
324 |
+
margin-bottom: 20px;
|
325 |
+
}
|
326 |
+
.wizard h4 {
|
327 |
+
font-size: 2rem;
|
328 |
+
margin: 2rem 0;
|
329 |
+
}
|
330 |
+
.wizard li,
|
331 |
+
.wizard p {
|
332 |
+
font-size: 16px;
|
333 |
+
margin-bottom: 1.2rem;
|
334 |
+
}
|
335 |
+
.wizard .body ol,
|
336 |
+
.wizard .body ul {
|
337 |
+
margin-bottom: 20px;
|
338 |
+
padding-left: 20px;
|
339 |
+
}
|
340 |
+
.wizard .body ul {
|
341 |
+
list-style: square inside none;
|
342 |
+
}
|
343 |
+
.wizard p.wizard-response {
|
344 |
+
/*padding: 10px 15px;*/
|
345 |
+
}
|
346 |
+
.wizard .slide-body img {
|
347 |
+
}
|
348 |
+
.wizard .slide-body .media {
|
349 |
+
margin-top: 25px
|
350 |
+
}
|
351 |
+
.wizard .slide-body .media-object {
|
352 |
+
border: 1px solid #888888;
|
353 |
+
height: 64px;
|
354 |
+
width: 64px;
|
355 |
+
}
|
356 |
+
.wizard .indent_slight {
|
357 |
+
margin-left: 26px;
|
358 |
+
}
|
359 |
+
.wizard_slot {
|
360 |
+
border: 1px solid #dddddd;
|
361 |
+
border-radius: 3px;
|
362 |
+
margin-top: 30px;
|
363 |
+
padding: 0 20px 20px;
|
364 |
+
}
|
365 |
+
.wizard_slot:hover {
|
366 |
+
background-color: #ffffff;
|
367 |
+
}
|
368 |
+
.wizard form label {
|
369 |
+
}
|
370 |
+
.wizard form input[type="radio"]:checked + span {
|
371 |
+
font-weight: bolder;
|
372 |
+
letter-spacing: -0.4px;
|
373 |
+
}
|
374 |
+
.wizard form .form-check-label {
|
375 |
+
margin-bottom: 10px;
|
376 |
+
}
|
377 |
+
.wizard form .form-check-inline .form-check-label {
|
378 |
+
margin-bottom: 0;
|
379 |
+
}
|
380 |
+
.shield-go-pro {
|
381 |
+
min-width: 200px;
|
382 |
+
display: block;
|
383 |
+
margin: 5px auto 20px;
|
384 |
+
background-color: #1e7e34;
|
385 |
+
border-color: #1c7430;
|
386 |
+
}
|
387 |
+
#GoProBtn {
|
388 |
+
width: 128px;
|
389 |
+
display: block;
|
390 |
+
margin: 5px auto 20px;
|
391 |
+
}
|
392 |
+
#FooterWizardBanner {
|
393 |
+
position: fixed;
|
394 |
+
bottom: -50px;
|
395 |
+
height: 100px;
|
396 |
+
width: 100%;
|
397 |
+
}
|
398 |
+
#WizardTop {
|
399 |
+
height: 40px;
|
400 |
+
background-color: #fafafa;
|
401 |
+
background: linear-gradient(to top, rgba(250, 250, 250, 0.95), rgba(250, 250, 250, 0.7));
|
402 |
+
}
|
403 |
+
#WizardBanner {
|
404 |
+
height: 100px;
|
405 |
+
background-color: #eaffea;
|
406 |
+
border-top: 1px solid #bbbbbb;
|
407 |
+
padding-top: 10px;
|
408 |
+
text-align: center;
|
409 |
+
word-break: keep-all;
|
410 |
+
white-space: nowrap;
|
411 |
+
}
|
412 |
+
#WizardBanner p {
|
413 |
+
margin: 0;
|
414 |
+
line-height: 20px;
|
415 |
+
text-align: left;
|
416 |
+
}
|
417 |
+
#MoreDetails {
|
418 |
+
margin-top: 12px;
|
419 |
+
}
|
420 |
+
.more_details {
|
421 |
+
margin-bottom: 12px;
|
422 |
+
}
|
423 |
+
.more_details:hover {
|
424 |
+
cursor: pointer;
|
425 |
+
}
|
426 |
+
.more_details_body {
|
427 |
+
margin-bottom: 12px;
|
428 |
+
}
|
429 |
+
.scan-results-accordian {
|
430 |
+
}
|
431 |
+
.scan-results-accordian .card {
|
432 |
+
margin-bottom: 24px;
|
433 |
+
}
|
434 |
+
.scan-results-accordian .card-header {
|
435 |
+
padding: .5rem 1.25rem;
|
436 |
+
}
|
437 |
+
.scan-results-accordian .card-header button:hover,
|
438 |
+
.scan-results-accordian .card-header button {
|
439 |
+
color: #f1f1f1
|
440 |
+
}
|
441 |
+
.embed-vimeo {
|
442 |
+
margin-bottom: 20px;
|
443 |
+
border-radius: 3px;
|
444 |
+
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
|
445 |
+
}
|
446 |
+
span.shield-progress-bar {
|
447 |
+
position: relative;
|
448 |
+
top: 8px;
|
449 |
+
width: 130%;
|
450 |
+
background-color: #2271b1;
|
451 |
+
height: 2px;
|
452 |
+
left: 75%;
|
453 |
+
}
|
454 |
+
/* override jquery.steps.css */
|
455 |
+
.wizard > .actions a,
|
456 |
+
.wizard > .actions a:hover,
|
457 |
+
.wizard > .actions a:active,
|
458 |
+
.wizard > .steps .current a,
|
459 |
+
.wizard > .steps .current a:hover,
|
460 |
+
.wizard > .steps .current a:active,
|
461 |
+
.wizard > .steps .disabled a, .wizard > .steps .disabled a:hover, .wizard > .steps .disabled a:active,
|
462 |
+
.wizard > .steps .done a, .wizard > .steps .done a:hover, .wizard > .steps .done a:active {
|
463 |
+
background: none !important;
|
464 |
+
}
|
465 |
+
.wizard > .steps > ul > li {
|
466 |
+
}
|
467 |
+
div.steps ul {
|
468 |
+
display: flex;
|
469 |
+
flex-direction: row;
|
470 |
+
flex-wrap: nowrap;
|
471 |
+
justify-content: space-evenly;
|
472 |
+
}
|
473 |
+
div.step {
|
474 |
+
display: flex;
|
475 |
+
align-content: center;
|
476 |
+
justify-content: space-between;
|
477 |
+
flex-direction: column;
|
478 |
+
flex-wrap: nowrap;
|
479 |
+
align-items: center;
|
480 |
+
}
|
481 |
+
div.step-number {
|
482 |
+
width: 15px;
|
483 |
+
height: 15px;
|
484 |
+
border-radius: 100%;
|
485 |
+
}
|
486 |
+
li div.step-number {
|
487 |
+
background-color: rgba(34, 113, 177, 1);
|
488 |
+
z-index: 5;
|
489 |
+
}
|
490 |
+
li div.step-title {
|
491 |
+
color: rgba(34, 113, 177, 1);
|
492 |
+
text-align: center;
|
493 |
+
}
|
494 |
+
li.done div.step-number {
|
495 |
+
background-color: #95c125;
|
496 |
+
}
|
497 |
+
li.done div.step-title {
|
498 |
+
color: #95c125;
|
499 |
+
}
|
500 |
+
li.disabled div.step-number {
|
501 |
+
background-color: #aaaaaa;
|
502 |
+
}
|
503 |
+
li.disabled div.step-title {
|
504 |
+
color: #aaaaaa;
|
505 |
+
}
|
506 |
+
.wizard > .content {
|
507 |
+
-webkit-border-radius: 0;
|
508 |
+
border-radius: 0;
|
509 |
+
margin: 0;
|
510 |
+
}
|
511 |
+
li.disabled span.shield-progress-bar {
|
512 |
+
background-color: #aaaaaa;
|
513 |
+
}
|
514 |
+
div.steps ul li:last-child span.shield-progress-bar {
|
515 |
+
display: none;
|
516 |
+
}
|
517 |
+
/* override bootstrap */
|
518 |
+
a, a:not([href]):not([class]) {
|
519 |
+
color: #2271b1;
|
520 |
+
text-decoration: underline;
|
521 |
+
}
|
522 |
+
a:hover, a:visited {
|
523 |
+
color: #135e96;
|
524 |
+
}
|
525 |
+
.vimeo-feather img {
|
526 |
+
padding: 3px;
|
527 |
+
border: 1px solid #008000;
|
528 |
+
background: white;
|
529 |
+
}
|
530 |
+
.vimeo-feather img {
|
531 |
+
width: 400px;
|
532 |
+
}
|
533 |
+
.button > svg {
|
534 |
+
width: 24px;
|
535 |
+
height: 24px;
|
536 |
+
margin-right: 3px;
|
537 |
+
}
|
538 |
+
|
539 |
+
.wp-core-ui button.wizard-button-go-back {
|
540 |
+
border: 0 none;
|
541 |
+
background: transparent;
|
542 |
+
}
|
resources/css/wizard.css
DELETED
@@ -1,163 +0,0 @@
|
|
1 |
-
html {
|
2 |
-
overflow-y: scroll;
|
3 |
-
}
|
4 |
-
body {
|
5 |
-
padding-bottom: 200px;
|
6 |
-
}
|
7 |
-
body.wait {
|
8 |
-
cursor: wait !important;
|
9 |
-
}
|
10 |
-
.wizard > .content {
|
11 |
-
background: #ffffff;
|
12 |
-
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
|
13 |
-
}
|
14 |
-
.wizard > .steps .current a {
|
15 |
-
text-shadow: 1px 1px 0 rgba(0,0,0,0.1);
|
16 |
-
}
|
17 |
-
.wizard.vertical > .steps {
|
18 |
-
width: 20%; /** from 30 **/
|
19 |
-
}
|
20 |
-
.wizard.vertical > .content {
|
21 |
-
width: 75%; /** from 65 **/
|
22 |
-
}
|
23 |
-
.wizard > .content > .body {
|
24 |
-
height: auto;
|
25 |
-
position: relative;
|
26 |
-
padding: 0;
|
27 |
-
width: 100%
|
28 |
-
}
|
29 |
-
.wizard > .content > .body .slide-header {
|
30 |
-
padding: 3% 3% 0 3%;
|
31 |
-
}
|
32 |
-
.wizard > .content > .body .slide-header .btn-block {
|
33 |
-
margin-bottom: -1px;
|
34 |
-
}
|
35 |
-
.wizard > .content > .body .slide-header hr {
|
36 |
-
margin: 15px 0;
|
37 |
-
}
|
38 |
-
.wizard > .content > .body .slide-body {
|
39 |
-
padding: 0 6% 0 6%;
|
40 |
-
}
|
41 |
-
.wizard > .content > .body .slide-footer {
|
42 |
-
padding: 0 6% 3% 6%;
|
43 |
-
}
|
44 |
-
.wizard.vertical > .actions {
|
45 |
-
margin-bottom: 20px;
|
46 |
-
}
|
47 |
-
.wizard h3 {
|
48 |
-
margin-bottom: 20px;
|
49 |
-
}
|
50 |
-
.wizard p {
|
51 |
-
}
|
52 |
-
.wizard .body ol,
|
53 |
-
.wizard .body ul {
|
54 |
-
margin-bottom: 20px;
|
55 |
-
padding-left: 20px;
|
56 |
-
}
|
57 |
-
.wizard .body ul {
|
58 |
-
list-style: square inside none;
|
59 |
-
}
|
60 |
-
.wizard p.wizard-response {
|
61 |
-
/*padding: 10px 15px;*/
|
62 |
-
}
|
63 |
-
|
64 |
-
.wizard .slide-body img {
|
65 |
-
float: left;
|
66 |
-
width: 40%;
|
67 |
-
margin-right: 20px;
|
68 |
-
}
|
69 |
-
.wizard .slide-body .media {
|
70 |
-
margin-top: 25px
|
71 |
-
}
|
72 |
-
.wizard .slide-body .media-object {
|
73 |
-
border: 1px solid #888;
|
74 |
-
height: 64px;
|
75 |
-
width: 64px;
|
76 |
-
}
|
77 |
-
.wizard .indent_slight {
|
78 |
-
margin-left: 26px;
|
79 |
-
}
|
80 |
-
|
81 |
-
.wizard_slot {
|
82 |
-
border: 1px solid #dddddd;
|
83 |
-
border-radius: 3px;
|
84 |
-
margin-top: 30px;
|
85 |
-
padding: 0 20px 20px;
|
86 |
-
}
|
87 |
-
.wizard_slot:hover {
|
88 |
-
background-color: #ffffff;
|
89 |
-
}
|
90 |
-
|
91 |
-
.wizard form label {
|
92 |
-
}
|
93 |
-
.wizard form input[type="radio"]:checked + span {
|
94 |
-
font-weight: bolder;
|
95 |
-
letter-spacing: -0.4px;
|
96 |
-
}
|
97 |
-
.wizard form .form-check-label {
|
98 |
-
margin-bottom: 10px;
|
99 |
-
}
|
100 |
-
.wizard form .form-check-inline .form-check-label {
|
101 |
-
margin-bottom: 0;
|
102 |
-
}
|
103 |
-
|
104 |
-
#GoProBtn {
|
105 |
-
width: 128px;
|
106 |
-
display: block;
|
107 |
-
margin: 5px auto 20px;
|
108 |
-
}
|
109 |
-
|
110 |
-
#FooterWizardBanner {
|
111 |
-
position: fixed;
|
112 |
-
bottom: 0;
|
113 |
-
height: 100px;
|
114 |
-
width: 100%;
|
115 |
-
}
|
116 |
-
#WizardTop {
|
117 |
-
height: 40px;
|
118 |
-
background-color: #fafafa;
|
119 |
-
background: linear-gradient(to top, rgba(250,250,250,0.95), rgba(250,250,250,0.7));
|
120 |
-
}
|
121 |
-
#WizardBanner {
|
122 |
-
height: 100px;
|
123 |
-
background-color: #eaffea;
|
124 |
-
border-top: 1px solid #bbbbbb;
|
125 |
-
padding-top: 10px;
|
126 |
-
text-align: center;
|
127 |
-
word-break: keep-all;
|
128 |
-
white-space: nowrap;
|
129 |
-
}
|
130 |
-
#WizardBanner p {
|
131 |
-
margin: 0;
|
132 |
-
line-height: 20px;
|
133 |
-
text-align: left;
|
134 |
-
}
|
135 |
-
|
136 |
-
.more_details {
|
137 |
-
margin-bottom: 12px;
|
138 |
-
}
|
139 |
-
.more_details:hover {
|
140 |
-
cursor: pointer;
|
141 |
-
}
|
142 |
-
.more_details_body {
|
143 |
-
margin-bottom: 12px;
|
144 |
-
}
|
145 |
-
|
146 |
-
.scan-results-accordian {
|
147 |
-
}
|
148 |
-
.scan-results-accordian .card {
|
149 |
-
margin-bottom: 24px;
|
150 |
-
}
|
151 |
-
.scan-results-accordian .card-header {
|
152 |
-
padding: .5rem 1.25rem;
|
153 |
-
}
|
154 |
-
.scan-results-accordian .card-header button:hover,
|
155 |
-
.scan-results-accordian .card-header button {
|
156 |
-
color: #f1f1f1
|
157 |
-
}
|
158 |
-
|
159 |
-
.embed-vimeo {
|
160 |
-
margin-bottom: 20px;
|
161 |
-
border-radius: 3px;
|
162 |
-
box-shadow: 1px 1px 3px rgba(0,0,0,0.3);
|
163 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/images/bootstrap/envelope-fill.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-fill" viewBox="0 0 16 16">
|
2 |
+
<path d="M.05 3.555A2 2 0 0 1 2 2h12a2 2 0 0 1 1.95 1.555L8 8.414.05 3.555zM0 4.697v7.104l5.803-3.558L0 4.697zM6.761 8.83l-6.57 4.027A2 2 0 0 0 2 14h12a2 2 0 0 0 1.808-1.144l-6.57-4.027L8 9.586l-1.239-.757zm3.436-.586L16 11.801V4.697l-5.803 3.546z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/facebook.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-facebook" viewBox="0 0 16 16">
|
2 |
+
<path d="M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/file-earmark-play.svg
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-play" viewBox="0 0 16 16">
|
2 |
+
<path d="M6 6.883v4.234a.5.5 0 0 0 .757.429l3.528-2.117a.5.5 0 0 0 0-.858L6.757 6.454a.5.5 0 0 0-.757.43z"/>
|
3 |
+
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2zM9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5v2z"/>
|
4 |
+
</svg>
|
resources/images/bootstrap/play-btn-fill.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play-btn-fill" viewBox="0 0 16 16">
|
2 |
+
<path d="M0 12V4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm6.79-6.907A.5.5 0 0 0 6 5.5v5a.5.5 0 0 0 .79.407l3.5-2.5a.5.5 0 0 0 0-.814l-3.5-2.5z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/play-btn.svg
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play-btn" viewBox="0 0 16 16">
|
2 |
+
<path d="M6.79 5.093A.5.5 0 0 0 6 5.5v5a.5.5 0 0 0 .79.407l3.5-2.5a.5.5 0 0 0 0-.814l-3.5-2.5z"/>
|
3 |
+
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4zm15 0a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4z"/>
|
4 |
+
</svg>
|
resources/images/bootstrap/play-circle.svg
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play-circle" viewBox="0 0 16 16">
|
2 |
+
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
3 |
+
<path d="M6.271 5.055a.5.5 0 0 1 .52.038l3.5 2.5a.5.5 0 0 1 0 .814l-3.5 2.5A.5.5 0 0 1 6 10.5v-5a.5.5 0 0 1 .271-.445z"/>
|
4 |
+
</svg>
|
resources/images/bootstrap/play-fill.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play-fill" viewBox="0 0 16 16">
|
2 |
+
<path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/shield-fill-check.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-shield-fill-check" viewBox="0 0 16 16">
|
2 |
+
<path fill-rule="evenodd" d="M8 0c-.69 0-1.843.265-2.928.56-1.11.3-2.229.655-2.887.87a1.54 1.54 0 0 0-1.044 1.262c-.596 4.477.787 7.795 2.465 9.99a11.777 11.777 0 0 0 2.517 2.453c.386.273.744.482 1.048.625.28.132.581.24.829.24s.548-.108.829-.24a7.159 7.159 0 0 0 1.048-.625 11.775 11.775 0 0 0 2.517-2.453c1.678-2.195 3.061-5.513 2.465-9.99a1.541 1.541 0 0 0-1.044-1.263 62.467 62.467 0 0 0-2.887-.87C9.843.266 8.69 0 8 0zm2.146 5.146a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 7.793l2.646-2.647z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/shield-fill-exclamation.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-shield-fill-exclamation" viewBox="0 0 16 16">
|
2 |
+
<path fill-rule="evenodd" d="M8 0c-.69 0-1.843.265-2.928.56-1.11.3-2.229.655-2.887.87a1.54 1.54 0 0 0-1.044 1.262c-.596 4.477.787 7.795 2.465 9.99a11.777 11.777 0 0 0 2.517 2.453c.386.273.744.482 1.048.625.28.132.581.24.829.24s.548-.108.829-.24a7.159 7.159 0 0 0 1.048-.625 11.775 11.775 0 0 0 2.517-2.453c1.678-2.195 3.061-5.513 2.465-9.99a1.541 1.541 0 0 0-1.044-1.263 62.467 62.467 0 0 0-2.887-.87C9.843.266 8.69 0 8 0zm-.55 8.502L7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0zM8.002 12a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/shield-fill-plus.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-shield-fill-plus" viewBox="0 0 16 16">
|
2 |
+
<path fill-rule="evenodd" d="M8 0c-.69 0-1.843.265-2.928.56-1.11.3-2.229.655-2.887.87a1.54 1.54 0 0 0-1.044 1.262c-.596 4.477.787 7.795 2.465 9.99a11.777 11.777 0 0 0 2.517 2.453c.386.273.744.482 1.048.625.28.132.581.24.829.24s.548-.108.829-.24a7.159 7.159 0 0 0 1.048-.625 11.775 11.775 0 0 0 2.517-2.453c1.678-2.195 3.061-5.513 2.465-9.99a1.541 1.541 0 0 0-1.044-1.263 62.467 62.467 0 0 0-2.887-.87C9.843.266 8.69 0 8 0zm-.5 5a.5.5 0 0 1 1 0v1.5H10a.5.5 0 0 1 0 1H8.5V9a.5.5 0 0 1-1 0V7.5H6a.5.5 0 0 1 0-1h1.5V5z"/>
|
3 |
+
</svg>
|
resources/images/bootstrap/twitter.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitter" viewBox="0 0 16 16">
|
2 |
+
<path d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"/>
|
3 |
+
</svg>
|
resources/js/featherlight.js
DELETED
@@ -1,641 +0,0 @@
|
|
1 |
-
/**
|
2 |
-
* Featherlight - ultra slim jQuery lightbox
|
3 |
-
* Version 1.7.13 - http://noelboss.github.io/featherlight/
|
4 |
-
*
|
5 |
-
* Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
|
6 |
-
* MIT Licensed.
|
7 |
-
**/
|
8 |
-
(function($) {
|
9 |
-
"use strict";
|
10 |
-
|
11 |
-
if('undefined' === typeof $) {
|
12 |
-
if('console' in window){ window.console.info('Too much lightness, Featherlight needs jQuery.'); }
|
13 |
-
return;
|
14 |
-
}
|
15 |
-
if($.fn.jquery.match(/-ajax/)) {
|
16 |
-
if('console' in window){ window.console.info('Featherlight needs regular jQuery, not the slim version.'); }
|
17 |
-
return;
|
18 |
-
}
|
19 |
-
/* Featherlight is exported as $.featherlight.
|
20 |
-
It is a function used to open a featherlight lightbox.
|
21 |
-
|
22 |
-
[tech]
|
23 |
-
Featherlight uses prototype inheritance.
|
24 |
-
Each opened lightbox will have a corresponding object.
|
25 |
-
That object may have some attributes that override the
|
26 |
-
prototype's.
|
27 |
-
Extensions created with Featherlight.extend will have their
|
28 |
-
own prototype that inherits from Featherlight's prototype,
|
29 |
-
thus attributes can be overriden either at the object level,
|
30 |
-
or at the extension level.
|
31 |
-
To create callbacks that chain themselves instead of overriding,
|
32 |
-
use chainCallbacks.
|
33 |
-
For those familiar with CoffeeScript, this correspond to
|
34 |
-
Featherlight being a class and the Gallery being a class
|
35 |
-
extending Featherlight.
|
36 |
-
The chainCallbacks is used since we don't have access to
|
37 |
-
CoffeeScript's `super`.
|
38 |
-
*/
|
39 |
-
|
40 |
-
function Featherlight($content, config) {
|
41 |
-
if(this instanceof Featherlight) { /* called with new */
|
42 |
-
this.id = Featherlight.id++;
|
43 |
-
this.setup($content, config);
|
44 |
-
this.chainCallbacks(Featherlight._callbackChain);
|
45 |
-
} else {
|
46 |
-
var fl = new Featherlight($content, config);
|
47 |
-
fl.open();
|
48 |
-
return fl;
|
49 |
-
}
|
50 |
-
}
|
51 |
-
|
52 |
-
var opened = [],
|
53 |
-
pruneOpened = function(remove) {
|
54 |
-
opened = $.grep(opened, function(fl) {
|
55 |
-
return fl !== remove && fl.$instance.closest('body').length > 0;
|
56 |
-
} );
|
57 |
-
return opened;
|
58 |
-
};
|
59 |
-
|
60 |
-
// Removes keys of `set` from `obj` and returns the removed key/values.
|
61 |
-
function slice(obj, set) {
|
62 |
-
var r = {};
|
63 |
-
for (var key in obj) {
|
64 |
-
if (key in set) {
|
65 |
-
r[key] = obj[key];
|
66 |
-
delete obj[key];
|
67 |
-
}
|
68 |
-
}
|
69 |
-
return r;
|
70 |
-
}
|
71 |
-
|
72 |
-
// NOTE: List of available [iframe attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe).
|
73 |
-
var iFrameAttributeSet = {
|
74 |
-
allow: 1, allowfullscreen: 1, frameborder: 1, height: 1, longdesc: 1, marginheight: 1, marginwidth: 1,
|
75 |
-
mozallowfullscreen: 1, name: 1, referrerpolicy: 1, sandbox: 1, scrolling: 1, src: 1, srcdoc: 1, style: 1,
|
76 |
-
webkitallowfullscreen: 1, width: 1
|
77 |
-
};
|
78 |
-
|
79 |
-
// Converts camelCased attributes to dasherized versions for given prefix:
|
80 |
-
// parseAttrs({hello: 1, hellFrozeOver: 2}, 'hell') => {froze-over: 2}
|
81 |
-
function parseAttrs(obj, prefix) {
|
82 |
-
var attrs = {},
|
83 |
-
regex = new RegExp('^' + prefix + '([A-Z])(.*)');
|
84 |
-
for (var key in obj) {
|
85 |
-
var match = key.match(regex);
|
86 |
-
if (match) {
|
87 |
-
var dasherized = (match[1] + match[2].replace(/([A-Z])/g, '-$1')).toLowerCase();
|
88 |
-
attrs[dasherized] = obj[key];
|
89 |
-
}
|
90 |
-
}
|
91 |
-
return attrs;
|
92 |
-
}
|
93 |
-
|
94 |
-
/* document wide key handler */
|
95 |
-
var eventMap = { keyup: 'onKeyUp', resize: 'onResize' };
|
96 |
-
|
97 |
-
var globalEventHandler = function(event) {
|
98 |
-
$.each(Featherlight.opened().reverse(), function() {
|
99 |
-
if (!event.isDefaultPrevented()) {
|
100 |
-
if (false === this[eventMap[event.type]](event)) {
|
101 |
-
event.preventDefault(); event.stopPropagation(); return false;
|
102 |
-
}
|
103 |
-
}
|
104 |
-
});
|
105 |
-
};
|
106 |
-
|
107 |
-
var toggleGlobalEvents = function(set) {
|
108 |
-
if(set !== Featherlight._globalHandlerInstalled) {
|
109 |
-
Featherlight._globalHandlerInstalled = set;
|
110 |
-
var events = $.map(eventMap, function(_, name) { return name+'.'+Featherlight.prototype.namespace; } ).join(' ');
|
111 |
-
$(window)[set ? 'on' : 'off'](events, globalEventHandler);
|
112 |
-
}
|
113 |
-
};
|
114 |
-
|
115 |
-
Featherlight.prototype = {
|
116 |
-
constructor: Featherlight,
|
117 |
-
/*** defaults ***/
|
118 |
-
/* extend featherlight with defaults and methods */
|
119 |
-
namespace: 'featherlight', /* Name of the events and css class prefix */
|
120 |
-
targetAttr: 'data-featherlight', /* Attribute of the triggered element that contains the selector to the lightbox content */
|
121 |
-
variant: null, /* Class that will be added to change look of the lightbox */
|
122 |
-
resetCss: false, /* Reset all css */
|
123 |
-
background: null, /* Custom DOM for the background, wrapper and the closebutton */
|
124 |
-
openTrigger: 'click', /* Event that triggers the lightbox */
|
125 |
-
closeTrigger: 'click', /* Event that triggers the closing of the lightbox */
|
126 |
-
filter: null, /* Selector to filter events. Think $(...).on('click', filter, eventHandler) */
|
127 |
-
root: 'body', /* Where to append featherlights */
|
128 |
-
openSpeed: 250, /* Duration of opening animation */
|
129 |
-
closeSpeed: 250, /* Duration of closing animation */
|
130 |
-
closeOnClick: 'background', /* Close lightbox on click ('background', 'anywhere' or false) */
|
131 |
-
closeOnEsc: true, /* Close lightbox when pressing esc */
|
132 |
-
closeIcon: '✕', /* Close icon */
|
133 |
-
loading: '', /* Content to show while initial content is loading */
|
134 |
-
persist: false, /* If set, the content will persist and will be shown again when opened again. 'shared' is a special value when binding multiple elements for them to share the same content */
|
135 |
-
otherClose: null, /* Selector for alternate close buttons (e.g. "a.close") */
|
136 |
-
beforeOpen: $.noop, /* Called before open. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
|
137 |
-
beforeContent: $.noop, /* Called when content is loaded. Gets event as parameter, this contains all data */
|
138 |
-
beforeClose: $.noop, /* Called before close. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
|
139 |
-
afterOpen: $.noop, /* Called after open. Gets event as parameter, this contains all data */
|
140 |
-
afterContent: $.noop, /* Called after content is ready and has been set. Gets event as parameter, this contains all data */
|
141 |
-
afterClose: $.noop, /* Called after close. Gets event as parameter, this contains all data */
|
142 |
-
onKeyUp: $.noop, /* Called on key up for the frontmost featherlight */
|
143 |
-
onResize: $.noop, /* Called after new content and when a window is resized */
|
144 |
-
type: null, /* Specify type of lightbox. If unset, it will check for the targetAttrs value. */
|
145 |
-
contentFilters: ['jquery', 'image', 'html', 'ajax', 'iframe', 'text'], /* List of content filters to use to determine the content */
|
146 |
-
|
147 |
-
/*** methods ***/
|
148 |
-
/* setup iterates over a single instance of featherlight and prepares the background and binds the events */
|
149 |
-
setup: function(target, config){
|
150 |
-
/* all arguments are optional */
|
151 |
-
if (typeof target === 'object' && target instanceof $ === false && !config) {
|
152 |
-
config = target;
|
153 |
-
target = undefined;
|
154 |
-
}
|
155 |
-
|
156 |
-
var self = $.extend(this, config, {target: target}),
|
157 |
-
css = !self.resetCss ? self.namespace : self.namespace+'-reset', /* by adding -reset to the classname, we reset all the default css */
|
158 |
-
$background = $(self.background || [
|
159 |
-
'<div class="'+css+'-loading '+css+'">',
|
160 |
-
'<div class="'+css+'-content">',
|
161 |
-
'<button class="'+css+'-close-icon '+ self.namespace + '-close" aria-label="Close">',
|
162 |
-
self.closeIcon,
|
163 |
-
'</button>',
|
164 |
-
'<div class="'+self.namespace+'-inner">' + self.loading + '</div>',
|
165 |
-
'</div>',
|
166 |
-
'</div>'].join('')),
|
167 |
-
closeButtonSelector = '.'+self.namespace+'-close' + (self.otherClose ? ',' + self.otherClose : '');
|
168 |
-
|
169 |
-
self.$instance = $background.clone().addClass(self.variant); /* clone DOM for the background, wrapper and the close button */
|
170 |
-
|
171 |
-
/* close when click on background/anywhere/null or closebox */
|
172 |
-
self.$instance.on(self.closeTrigger+'.'+self.namespace, function(event) {
|
173 |
-
if(event.isDefaultPrevented()) {
|
174 |
-
return;
|
175 |
-
}
|
176 |
-
var $target = $(event.target);
|
177 |
-
if( ('background' === self.closeOnClick && $target.is('.'+self.namespace))
|
178 |
-
|| 'anywhere' === self.closeOnClick
|
179 |
-
|| $target.closest(closeButtonSelector).length ){
|
180 |
-
self.close(event);
|
181 |
-
event.preventDefault();
|
182 |
-
}
|
183 |
-
});
|
184 |
-
|
185 |
-
return this;
|
186 |
-
},
|
187 |
-
|
188 |
-
/* this method prepares the content and converts it into a jQuery object or a promise */
|
189 |
-
getContent: function(){
|
190 |
-
if(this.persist !== false && this.$content) {
|
191 |
-
return this.$content;
|
192 |
-
}
|
193 |
-
var self = this,
|
194 |
-
filters = this.constructor.contentFilters,
|
195 |
-
readTargetAttr = function(name){ return self.$currentTarget && self.$currentTarget.attr(name); },
|
196 |
-
targetValue = readTargetAttr(self.targetAttr),
|
197 |
-
data = self.target || targetValue || '';
|
198 |
-
|
199 |
-
/* Find which filter applies */
|
200 |
-
var filter = filters[self.type]; /* check explicit type like {type: 'image'} */
|
201 |
-
|
202 |
-
/* check explicit type like data-featherlight="image" */
|
203 |
-
if(!filter && data in filters) {
|
204 |
-
filter = filters[data];
|
205 |
-
data = self.target && targetValue;
|
206 |
-
}
|
207 |
-
data = data || readTargetAttr('href') || '';
|
208 |
-
|
209 |
-
/* check explicity type & content like {image: 'photo.jpg'} */
|
210 |
-
if(!filter) {
|
211 |
-
for(var filterName in filters) {
|
212 |
-
if(self[filterName]) {
|
213 |
-
filter = filters[filterName];
|
214 |
-
data = self[filterName];
|
215 |
-
}
|
216 |
-
}
|
217 |
-
}
|
218 |
-
|
219 |
-
/* otherwise it's implicit, run checks */
|
220 |
-
if(!filter) {
|
221 |
-
var target = data;
|
222 |
-
data = null;
|
223 |
-
$.each(self.contentFilters, function() {
|
224 |
-
filter = filters[this];
|
225 |
-
if(filter.test) {
|
226 |
-
data = filter.test(target);
|
227 |
-
}
|
228 |
-
if(!data && filter.regex && target.match && target.match(filter.regex)) {
|
229 |
-
data = target;
|
230 |
-
}
|
231 |
-
return !data;
|
232 |
-
});
|
233 |
-
if(!data) {
|
234 |
-
if('console' in window){ window.console.error('Featherlight: no content filter found ' + (target ? ' for "' + target + '"' : ' (no target specified)')); }
|
235 |
-
return false;
|
236 |
-
}
|
237 |
-
}
|
238 |
-
/* Process it */
|
239 |
-
return filter.process.call(self, data);
|
240 |
-
},
|
241 |
-
|
242 |
-
/* sets the content of $instance to $content */
|
243 |
-
setContent: function($content){
|
244 |
-
this.$instance.removeClass(this.namespace+'-loading');
|
245 |
-
|
246 |
-
/* we need a special class for the iframe */
|
247 |
-
this.$instance.toggleClass(this.namespace+'-iframe', $content.is('iframe'));
|
248 |
-
|
249 |
-
/* replace content by appending to existing one before it is removed
|
250 |
-
this insures that featherlight-inner remain at the same relative
|
251 |
-
position to any other items added to featherlight-content */
|
252 |
-
this.$instance.find('.'+this.namespace+'-inner')
|
253 |
-
.not($content) /* excluded new content, important if persisted */
|
254 |
-
.slice(1).remove().end() /* In the unexpected event where there are many inner elements, remove all but the first one */
|
255 |
-
.replaceWith($.contains(this.$instance[0], $content[0]) ? '' : $content);
|
256 |
-
|
257 |
-
this.$content = $content.addClass(this.namespace+'-inner');
|
258 |
-
|
259 |
-
return this;
|
260 |
-
},
|
261 |
-
|
262 |
-
/* opens the lightbox. "this" contains $instance with the lightbox, and with the config.
|
263 |
-
Returns a promise that is resolved after is successfully opened. */
|
264 |
-
open: function(event){
|
265 |
-
var self = this;
|
266 |
-
self.$instance.hide().appendTo(self.root);
|
267 |
-
if((!event || !event.isDefaultPrevented())
|
268 |
-
&& self.beforeOpen(event) !== false) {
|
269 |
-
|
270 |
-
if(event){
|
271 |
-
event.preventDefault();
|
272 |
-
}
|
273 |
-
var $content = self.getContent();
|
274 |
-
|
275 |
-
if($content) {
|
276 |
-
opened.push(self);
|
277 |
-
|
278 |
-
toggleGlobalEvents(true);
|
279 |
-
|
280 |
-
self.$instance.fadeIn(self.openSpeed);
|
281 |
-
self.beforeContent(event);
|
282 |
-
|
283 |
-
/* Set content and show */
|
284 |
-
return $.when($content)
|
285 |
-
.always(function($content){
|
286 |
-
self.setContent($content);
|
287 |
-
self.afterContent(event);
|
288 |
-
})
|
289 |
-
.then(self.$instance.promise())
|
290 |
-
/* Call afterOpen after fadeIn is done */
|
291 |
-
.done(function(){ self.afterOpen(event); });
|
292 |
-
}
|
293 |
-
}
|
294 |
-
self.$instance.detach();
|
295 |
-
return $.Deferred().reject().promise();
|
296 |
-
},
|
297 |
-
|
298 |
-
/* closes the lightbox. "this" contains $instance with the lightbox, and with the config
|
299 |
-
returns a promise, resolved after the lightbox is successfully closed. */
|
300 |
-
close: function(event){
|
301 |
-
var self = this,
|
302 |
-
deferred = $.Deferred();
|
303 |
-
|
304 |
-
if(self.beforeClose(event) === false) {
|
305 |
-
deferred.reject();
|
306 |
-
} else {
|
307 |
-
|
308 |
-
if (0 === pruneOpened(self).length) {
|
309 |
-
toggleGlobalEvents(false);
|
310 |
-
}
|
311 |
-
|
312 |
-
self.$instance.fadeOut(self.closeSpeed,function(){
|
313 |
-
self.$instance.detach();
|
314 |
-
self.afterClose(event);
|
315 |
-
deferred.resolve();
|
316 |
-
});
|
317 |
-
}
|
318 |
-
return deferred.promise();
|
319 |
-
},
|
320 |
-
|
321 |
-
/* resizes the content so it fits in visible area and keeps the same aspect ratio.
|
322 |
-
Does nothing if either the width or the height is not specified.
|
323 |
-
Called automatically on window resize.
|
324 |
-
Override if you want different behavior. */
|
325 |
-
resize: function(w, h) {
|
326 |
-
if (w && h) {
|
327 |
-
/* Reset apparent image size first so container grows */
|
328 |
-
this.$content.css('width', '').css('height', '');
|
329 |
-
/* Calculate the worst ratio so that dimensions fit */
|
330 |
-
/* Note: -1 to avoid rounding errors */
|
331 |
-
var ratio = Math.max(
|
332 |
-
w / (this.$content.parent().width()-1),
|
333 |
-
h / (this.$content.parent().height()-1));
|
334 |
-
/* Resize content */
|
335 |
-
if (ratio > 1) {
|
336 |
-
ratio = h / Math.floor(h / ratio); /* Round ratio down so height calc works */
|
337 |
-
this.$content.css('width', '' + w / ratio + 'px').css('height', '' + h / ratio + 'px');
|
338 |
-
}
|
339 |
-
}
|
340 |
-
},
|
341 |
-
|
342 |
-
/* Utility function to chain callbacks
|
343 |
-
[Warning: guru-level]
|
344 |
-
Used be extensions that want to let users specify callbacks but
|
345 |
-
also need themselves to use the callbacks.
|
346 |
-
The argument 'chain' has callback names as keys and function(super, event)
|
347 |
-
as values. That function is meant to call `super` at some point.
|
348 |
-
*/
|
349 |
-
chainCallbacks: function(chain) {
|
350 |
-
for (var name in chain) {
|
351 |
-
this[name] = $.proxy(chain[name], this, $.proxy(this[name], this));
|
352 |
-
}
|
353 |
-
}
|
354 |
-
};
|
355 |
-
|
356 |
-
$.extend(Featherlight, {
|
357 |
-
id: 0, /* Used to id single featherlight instances */
|
358 |
-
autoBind: '[data-featherlight]', /* Will automatically bind elements matching this selector. Clear or set before onReady */
|
359 |
-
defaults: Featherlight.prototype, /* You can access and override all defaults using $.featherlight.defaults, which is just a synonym for $.featherlight.prototype */
|
360 |
-
/* Contains the logic to determine content */
|
361 |
-
contentFilters: {
|
362 |
-
jquery: {
|
363 |
-
regex: /^[#.]\w/, /* Anything that starts with a class name or identifiers */
|
364 |
-
test: function(elem) { return elem instanceof $ && elem; },
|
365 |
-
process: function(elem) { return this.persist !== false ? $(elem) : $(elem).clone(true); }
|
366 |
-
},
|
367 |
-
image: {
|
368 |
-
regex: /\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?$/i,
|
369 |
-
process: function(url) {
|
370 |
-
var self = this,
|
371 |
-
deferred = $.Deferred(),
|
372 |
-
img = new Image(),
|
373 |
-
$img = $('<img src="'+url+'" alt="" class="'+self.namespace+'-image" />');
|
374 |
-
img.onload = function() {
|
375 |
-
/* Store naturalWidth & height for IE8 */
|
376 |
-
$img.naturalWidth = img.width; $img.naturalHeight = img.height;
|
377 |
-
deferred.resolve( $img );
|
378 |
-
};
|
379 |
-
img.onerror = function() { deferred.reject($img); };
|
380 |
-
img.src = url;
|
381 |
-
return deferred.promise();
|
382 |
-
}
|
383 |
-
},
|
384 |
-
html: {
|
385 |
-
regex: /^\s*<[\w!][^<]*>/, /* Anything that starts with some kind of valid tag */
|
386 |
-
process: function(html) { return $(html); }
|
387 |
-
},
|
388 |
-
ajax: {
|
389 |
-
regex: /./, /* At this point, any content is assumed to be an URL */
|
390 |
-
process: function(url) {
|
391 |
-
var self = this,
|
392 |
-
deferred = $.Deferred();
|
393 |
-
/* we are using load so one can specify a target with: url.html #targetelement */
|
394 |
-
var $container = $('<div></div>').load(url, function(response, status){
|
395 |
-
if ( status !== "error" ) {
|
396 |
-
deferred.resolve($container.contents());
|
397 |
-
}
|
398 |
-
deferred.fail();
|
399 |
-
});
|
400 |
-
return deferred.promise();
|
401 |
-
}
|
402 |
-
},
|
403 |
-
iframe: {
|
404 |
-
process: function(url) {
|
405 |
-
var deferred = new $.Deferred();
|
406 |
-
var $content = $('<iframe/>');
|
407 |
-
var css = parseAttrs(this, 'iframe');
|
408 |
-
var attrs = slice(css, iFrameAttributeSet);
|
409 |
-
$content.hide()
|
410 |
-
.attr('src', url)
|
411 |
-
.attr(attrs)
|
412 |
-
.css(css)
|
413 |
-
.on('load', function() { deferred.resolve($content.show()); })
|
414 |
-
// We can't move an <iframe> and avoid reloading it,
|
415 |
-
// so let's put it in place ourselves right now:
|
416 |
-
.appendTo(this.$instance.find('.' + this.namespace + '-content'));
|
417 |
-
return deferred.promise();
|
418 |
-
}
|
419 |
-
},
|
420 |
-
text: {
|
421 |
-
process: function(text) { return $('<div>', {text: text}); }
|
422 |
-
}
|
423 |
-
},
|
424 |
-
|
425 |
-
functionAttributes: ['beforeOpen', 'afterOpen', 'beforeContent', 'afterContent', 'beforeClose', 'afterClose'],
|
426 |
-
|
427 |
-
/*** class methods ***/
|
428 |
-
/* read element's attributes starting with data-featherlight- */
|
429 |
-
readElementConfig: function(element, namespace) {
|
430 |
-
var Klass = this,
|
431 |
-
regexp = new RegExp('^data-' + namespace + '-(.*)'),
|
432 |
-
config = {};
|
433 |
-
if (element && element.attributes) {
|
434 |
-
$.each(element.attributes, function(){
|
435 |
-
var match = this.name.match(regexp);
|
436 |
-
if (match) {
|
437 |
-
var val = this.value,
|
438 |
-
name = $.camelCase(match[1]);
|
439 |
-
if ($.inArray(name, Klass.functionAttributes) >= 0) { /* jshint -W054 */
|
440 |
-
val = new Function(val); /* jshint +W054 */
|
441 |
-
} else {
|
442 |
-
try { val = JSON.parse(val); }
|
443 |
-
catch(e) {}
|
444 |
-
}
|
445 |
-
config[name] = val;
|
446 |
-
}
|
447 |
-
});
|
448 |
-
}
|
449 |
-
return config;
|
450 |
-
},
|
451 |
-
|
452 |
-
/* Used to create a Featherlight extension
|
453 |
-
[Warning: guru-level]
|
454 |
-
Creates the extension's prototype that in turn
|
455 |
-
inherits Featherlight's prototype.
|
456 |
-
Could be used to extend an extension too...
|
457 |
-
This is pretty high level wizardy, it comes pretty much straight
|
458 |
-
from CoffeeScript and won't teach you anything about Featherlight
|
459 |
-
as it's not really specific to this library.
|
460 |
-
My suggestion: move along and keep your sanity.
|
461 |
-
*/
|
462 |
-
extend: function(child, defaults) {
|
463 |
-
/* Setup class hierarchy, adapted from CoffeeScript */
|
464 |
-
var Ctor = function(){ this.constructor = child; };
|
465 |
-
Ctor.prototype = this.prototype;
|
466 |
-
child.prototype = new Ctor();
|
467 |
-
child.__super__ = this.prototype;
|
468 |
-
/* Copy class methods & attributes */
|
469 |
-
$.extend(child, this, defaults);
|
470 |
-
child.defaults = child.prototype;
|
471 |
-
return child;
|
472 |
-
},
|
473 |
-
|
474 |
-
attach: function($source, $content, config) {
|
475 |
-
var Klass = this;
|
476 |
-
if (typeof $content === 'object' && $content instanceof $ === false && !config) {
|
477 |
-
config = $content;
|
478 |
-
$content = undefined;
|
479 |
-
}
|
480 |
-
/* make a copy */
|
481 |
-
config = $.extend({}, config);
|
482 |
-
|
483 |
-
/* Only for openTrigger, filter & namespace... */
|
484 |
-
var namespace = config.namespace || Klass.defaults.namespace,
|
485 |
-
tempConfig = $.extend({}, Klass.defaults, Klass.readElementConfig($source[0], namespace), config),
|
486 |
-
sharedPersist;
|
487 |
-
var handler = function(event) {
|
488 |
-
var $target = $(event.currentTarget);
|
489 |
-
/* ... since we might as well compute the config on the actual target */
|
490 |
-
var elemConfig = $.extend(
|
491 |
-
{$source: $source, $currentTarget: $target},
|
492 |
-
Klass.readElementConfig($source[0], tempConfig.namespace),
|
493 |
-
Klass.readElementConfig(event.currentTarget, tempConfig.namespace),
|
494 |
-
config);
|
495 |
-
var fl = sharedPersist || $target.data('featherlight-persisted') || new Klass($content, elemConfig);
|
496 |
-
if(fl.persist === 'shared') {
|
497 |
-
sharedPersist = fl;
|
498 |
-
} else if(fl.persist !== false) {
|
499 |
-
$target.data('featherlight-persisted', fl);
|
500 |
-
}
|
501 |
-
if (elemConfig.$currentTarget.blur) {
|
502 |
-
elemConfig.$currentTarget.blur(); // Otherwise 'enter' key might trigger the dialog again
|
503 |
-
}
|
504 |
-
fl.open(event);
|
505 |
-
};
|
506 |
-
|
507 |
-
$source.on(tempConfig.openTrigger+'.'+tempConfig.namespace, tempConfig.filter, handler);
|
508 |
-
|
509 |
-
return {filter: tempConfig.filter, handler: handler};
|
510 |
-
},
|
511 |
-
|
512 |
-
current: function() {
|
513 |
-
var all = this.opened();
|
514 |
-
return all[all.length - 1] || null;
|
515 |
-
},
|
516 |
-
|
517 |
-
opened: function() {
|
518 |
-
var klass = this;
|
519 |
-
pruneOpened();
|
520 |
-
return $.grep(opened, function(fl) { return fl instanceof klass; } );
|
521 |
-
},
|
522 |
-
|
523 |
-
close: function(event) {
|
524 |
-
var cur = this.current();
|
525 |
-
if(cur) { return cur.close(event); }
|
526 |
-
},
|
527 |
-
|
528 |
-
/* Does the auto binding on startup.
|
529 |
-
Meant only to be used by Featherlight and its extensions
|
530 |
-
*/
|
531 |
-
_onReady: function() {
|
532 |
-
var Klass = this;
|
533 |
-
if(Klass.autoBind){
|
534 |
-
var $autobound = $(Klass.autoBind);
|
535 |
-
/* Bind existing elements */
|
536 |
-
$autobound.each(function(){
|
537 |
-
Klass.attach($(this));
|
538 |
-
});
|
539 |
-
/* If a click propagates to the document level, then we have an item that was added later on */
|
540 |
-
$(document).on('click', Klass.autoBind, function(evt) {
|
541 |
-
if (evt.isDefaultPrevented()) {
|
542 |
-
return;
|
543 |
-
}
|
544 |
-
var $cur = $(evt.currentTarget);
|
545 |
-
var len = $autobound.length;
|
546 |
-
$autobound = $autobound.add($cur);
|
547 |
-
if(len === $autobound.length) {
|
548 |
-
return; /* already bound */
|
549 |
-
}
|
550 |
-
/* Bind featherlight */
|
551 |
-
var data = Klass.attach($cur);
|
552 |
-
/* Dispatch event directly */
|
553 |
-
if (!data.filter || $(evt.target).parentsUntil($cur, data.filter).length > 0) {
|
554 |
-
data.handler(evt);
|
555 |
-
}
|
556 |
-
});
|
557 |
-
}
|
558 |
-
},
|
559 |
-
|
560 |
-
/* Featherlight uses the onKeyUp callback to intercept the escape key.
|
561 |
-
Private to Featherlight.
|
562 |
-
*/
|
563 |
-
_callbackChain: {
|
564 |
-
onKeyUp: function(_super, event){
|
565 |
-
if(27 === event.keyCode) {
|
566 |
-
if (this.closeOnEsc) {
|
567 |
-
$.featherlight.close(event);
|
568 |
-
}
|
569 |
-
return false;
|
570 |
-
} else {
|
571 |
-
return _super(event);
|
572 |
-
}
|
573 |
-
},
|
574 |
-
|
575 |
-
beforeOpen: function(_super, event) {
|
576 |
-
// Used to disable scrolling
|
577 |
-
$(document.documentElement).addClass('with-featherlight');
|
578 |
-
|
579 |
-
// Remember focus:
|
580 |
-
this._previouslyActive = document.activeElement;
|
581 |
-
|
582 |
-
// Disable tabbing:
|
583 |
-
// See http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
|
584 |
-
this._$previouslyTabbable = $("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]")
|
585 |
-
.not('[tabindex]')
|
586 |
-
.not(this.$instance.find('button'));
|
587 |
-
|
588 |
-
this._$previouslyWithTabIndex = $('[tabindex]').not('[tabindex="-1"]');
|
589 |
-
this._previousWithTabIndices = this._$previouslyWithTabIndex.map(function(_i, elem) {
|
590 |
-
return $(elem).attr('tabindex');
|
591 |
-
});
|
592 |
-
|
593 |
-
this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr('tabindex', -1);
|
594 |
-
|
595 |
-
if (document.activeElement.blur) {
|
596 |
-
document.activeElement.blur();
|
597 |
-
}
|
598 |
-
return _super(event);
|
599 |
-
},
|
600 |
-
|
601 |
-
afterClose: function(_super, event) {
|
602 |
-
var r = _super(event);
|
603 |
-
// Restore focus
|
604 |
-
var self = this;
|
605 |
-
this._$previouslyTabbable.removeAttr('tabindex');
|
606 |
-
this._$previouslyWithTabIndex.each(function(i, elem) {
|
607 |
-
$(elem).attr('tabindex', self._previousWithTabIndices[i]);
|
608 |
-
});
|
609 |
-
this._previouslyActive.focus();
|
610 |
-
// Restore scroll
|
611 |
-
if(Featherlight.opened().length === 0) {
|
612 |
-
$(document.documentElement).removeClass('with-featherlight');
|
613 |
-
}
|
614 |
-
return r;
|
615 |
-
},
|
616 |
-
|
617 |
-
onResize: function(_super, event){
|
618 |
-
this.resize(this.$content.naturalWidth, this.$content.naturalHeight);
|
619 |
-
return _super(event);
|
620 |
-
},
|
621 |
-
|
622 |
-
afterContent: function(_super, event){
|
623 |
-
var r = _super(event);
|
624 |
-
this.$instance.find('[autofocus]:not([disabled])').focus();
|
625 |
-
this.onResize(event);
|
626 |
-
return r;
|
627 |
-
}
|
628 |
-
}
|
629 |
-
});
|
630 |
-
|
631 |
-
$.featherlight = Featherlight;
|
632 |
-
|
633 |
-
/* bind jQuery elements to trigger featherlight */
|
634 |
-
$.fn.featherlight = function($content, config) {
|
635 |
-
Featherlight.attach(this, $content, config);
|
636 |
-
return this;
|
637 |
-
};
|
638 |
-
|
639 |
-
/* bind featherlight on ready if config autoBind is set */
|
640 |
-
$(document).ready(function(){ Featherlight._onReady(); });
|
641 |
-
}(jQuery));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/js/global-plugin.js
CHANGED
@@ -131,7 +131,7 @@ if ( typeof icwp_wpsf_vars_hp !== 'undefined' ) {
|
|
131 |
},
|
132 |
open: function () {
|
133 |
// close dialog by clicking the overlay behind it
|
134 |
-
jQuery( '.ui-widget-overlay' ).
|
135 |
jQuery( this ).dialog( 'close' );
|
136 |
} )
|
137 |
},
|
@@ -221,50 +221,6 @@ if ( typeof icwp_wpsf_vars_hp !== 'undefined' ) {
|
|
221 |
iCWP_WPSF_HackGuard_Reinstall.initialise();
|
222 |
}
|
223 |
|
224 |
-
if ( typeof icwp_wpsf_vars_lg !== 'undefined' ) {
|
225 |
-
var iCWP_WPSF_LoginGuard_BackupCodes = new function () {
|
226 |
-
this.initialise = function () {
|
227 |
-
jQuery( document ).ready( function () {
|
228 |
-
jQuery( document ).on( "click", "a#IcwpWpsfGenBackupLoginCode", genBackupCode );
|
229 |
-
jQuery( document ).on( "click", "a#IcwpWpsfDelBackupLoginCode", deleteBackupCode );
|
230 |
-
} );
|
231 |
-
};
|
232 |
-
|
233 |
-
var genBackupCode = function ( event ) {
|
234 |
-
event.preventDefault();
|
235 |
-
iCWP_WPSF_BodyOverlay.show();
|
236 |
-
|
237 |
-
jQuery.post( ajaxurl, icwp_wpsf_vars_lg.ajax_gen_backup_codes,
|
238 |
-
function ( oResponse ) {
|
239 |
-
alert( 'Your login backup code: ' + oResponse.data.code );
|
240 |
-
}
|
241 |
-
).always( function () {
|
242 |
-
location.reload( true );
|
243 |
-
}
|
244 |
-
);
|
245 |
-
|
246 |
-
return false;
|
247 |
-
};
|
248 |
-
|
249 |
-
var deleteBackupCode = function ( event ) {
|
250 |
-
event.preventDefault();
|
251 |
-
iCWP_WPSF_BodyOverlay.show();
|
252 |
-
|
253 |
-
jQuery.post( ajaxurl, icwp_wpsf_vars_lg.ajax_del_backup_codes,
|
254 |
-
function ( oResponse ) {
|
255 |
-
}
|
256 |
-
).always( function () {
|
257 |
-
location.reload( true );
|
258 |
-
// iCWP_WPSF_BodyOverlay.hide();
|
259 |
-
}
|
260 |
-
);
|
261 |
-
|
262 |
-
return false;
|
263 |
-
};
|
264 |
-
}();
|
265 |
-
iCWP_WPSF_LoginGuard_BackupCodes.initialise();
|
266 |
-
}
|
267 |
-
|
268 |
var iCWP_WPSF_Growl = new function () {
|
269 |
|
270 |
this.showMessage = function ( sMessage, bSuccess ) {
|
131 |
},
|
132 |
open: function () {
|
133 |
// close dialog by clicking the overlay behind it
|
134 |
+
jQuery( '.ui-widget-overlay' ).on( 'click', function () {
|
135 |
jQuery( this ).dialog( 'close' );
|
136 |
} )
|
137 |
},
|
221 |
iCWP_WPSF_HackGuard_Reinstall.initialise();
|
222 |
}
|
223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
var iCWP_WPSF_Growl = new function () {
|
225 |
|
226 |
this.showMessage = function ( sMessage, bSuccess ) {
|
resources/js/jquery.fancybox.min.js
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
// ==================================================
|
2 |
-
// fancyBox v3.2.10
|
3 |
-
//
|
4 |
-
// Licensed GPLv3 for open source use
|
5 |
-
// or fancyBox Commercial License for commercial use
|
6 |
-
//
|
7 |
-
// http://fancyapps.com/fancybox/
|
8 |
-
// Copyright 2017 fancyApps
|
9 |
-
//
|
10 |
-
// ==================================================
|
11 |
-
!function(t,e,n,o){"use strict";function i(t){var e=n(t.currentTarget),o=t.data?t.data.options:{},i=e.attr("data-fancybox")||"",a=0,s=[];t.isDefaultPrevented()||(t.preventDefault(),i?(s=o.selector?n(o.selector):t.data?t.data.items:[],s=s.length?s.filter('[data-fancybox="'+i+'"]'):n('[data-fancybox="'+i+'"]'),a=s.index(e),a<0&&(a=0)):s=[e],n.fancybox.open(s,o,a))}if(n){if(n.fn.fancybox)return void("console"in t&&console.log("fancyBox already initialized"));var a={loop:!1,margin:[44,0],gutter:50,keyboard:!0,arrows:!0,infobar:!0,toolbar:!0,buttons:["slideShow","fullScreen","thumbs","share","close"],idleTime:3,smallBtn:"auto",protect:!1,modal:!1,image:{preload:"auto"},ajax:{settings:{data:{fancybox:!0}}},iframe:{tpl:'<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',preload:!0,css:{},attr:{scrolling:"auto"}},defaultType:"image",animationEffect:"zoom",animationDuration:500,zoomOpacity:"auto",transitionEffect:"fade",transitionDuration:366,slideClass:"",baseClass:"",baseTpl:'<div class="fancybox-container" role="dialog" tabindex="-1"><div class="fancybox-bg"></div><div class="fancybox-inner"><div class="fancybox-infobar"><span data-fancybox-index></span> / <span data-fancybox-count></span></div><div class="fancybox-toolbar">{{buttons}}</div><div class="fancybox-navigation">{{arrows}}</div><div class="fancybox-stage"></div><div class="fancybox-caption-wrap"><div class="fancybox-caption"></div></div></div></div>',spinnerTpl:'<div class="fancybox-loading"></div>',errorTpl:'<div class="fancybox-error"><p>{{ERROR}}<p></div>',btnTpl:{download:'<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}"><svg viewBox="0 0 40 40"><path d="M20,23 L20,8 L20,23 L13,16 L20,23 L27,16 L20,23 M26,28 L13,28 L27,28 L14,28" /></svg></a>',zoom:'<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}"><svg viewBox="0 0 40 40"><path d="M 18,17 m-8,0 a 8,8 0 1,0 16,0 a 8,8 0 1,0 -16,0 M25,23 L31,29 L25,23" /></svg></button>',close:'<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"><svg viewBox="0 0 40 40"><path d="M10,10 L30,30 M30,10 L10,30" /></svg></button>',smallBtn:'<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>',arrowLeft:'<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}"><svg viewBox="0 0 40 40"><path d="M10,20 L30,20 L10,20 L18,28 L10,20 L18,12 L10,20"></path></svg></button>',arrowRight:'<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}"><svg viewBox="0 0 40 40"><path d="M30,20 L10,20 L30,20 L22,28 L30,20 L22,12 L30,20"></path></svg></button>'},parentEl:"body",autoFocus:!1,backFocus:!0,trapFocus:!0,fullScreen:{autoStart:!1},touch:{vertical:!0,momentum:!0},hash:null,media:{},slideShow:{autoStart:!1,speed:4e3},thumbs:{autoStart:!1,hideOnClose:!0,parentEl:".fancybox-container",axis:"y"},wheel:"auto",onInit:n.noop,beforeLoad:n.noop,afterLoad:n.noop,beforeShow:n.noop,afterShow:n.noop,beforeClose:n.noop,afterClose:n.noop,onActivate:n.noop,onDeactivate:n.noop,clickContent:function(t,e){return"image"===t.type&&"zoom"},clickSlide:"close",clickOutside:"close",dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1,mobile:{idleTime:!1,margin:0,clickContent:function(t,e){return"image"===t.type&&"toggleControls"},clickSlide:function(t,e){return"image"===t.type?"toggleControls":"close"},dblclickContent:function(t,e){return"image"===t.type&&"zoom"},dblclickSlide:function(t,e){return"image"===t.type&&"zoom"}},lang:"en",i18n:{en:{CLOSE:"Close",NEXT:"Next",PREV:"Previous",ERROR:"The requested content cannot be loaded. <br/> Please try again later.",PLAY_START:"Start slideshow",PLAY_STOP:"Pause slideshow",FULL_SCREEN:"Full screen",THUMBS:"Thumbnails",DOWNLOAD:"Download",SHARE:"Share",ZOOM:"Zoom"},de:{CLOSE:"Schliessen",NEXT:"Weiter",PREV:"Zurück",ERROR:"Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.",PLAY_START:"Diaschau starten",PLAY_STOP:"Diaschau beenden",FULL_SCREEN:"Vollbild",THUMBS:"Vorschaubilder",DOWNLOAD:"Herunterladen",SHARE:"Teilen",ZOOM:"Maßstab"}}},s=n(t),r=n(e),c=0,l=function(t){return t&&t.hasOwnProperty&&t instanceof n},u=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),d=function(){var t,n=e.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in i)if(n.style[t]!==o)return i[t];return"transitionend"}(),f=function(t){return t&&t.length&&t[0].offsetHeight},p=function(t,o,i){var a=this;a.opts=n.extend(!0,{index:i},n.fancybox.defaults,o||{}),n.fancybox.isMobile&&(a.opts=n.extend(!0,{},a.opts,a.opts.mobile)),o&&n.isArray(o.buttons)&&(a.opts.buttons=o.buttons),a.id=a.opts.id||++c,a.group=[],a.currIndex=parseInt(a.opts.index,10)||0,a.prevIndex=null,a.prevPos=null,a.currPos=0,a.firstRun=null,a.createGroup(t),a.group.length&&(a.$lastFocus=n(e.activeElement).blur(),a.slides={},a.init())};n.extend(p.prototype,{init:function(){var i,a,s,c=this,l=c.group[c.currIndex],u=l.opts,d=n.fancybox.scrollbarWidth;c.scrollTop=r.scrollTop(),c.scrollLeft=r.scrollLeft(),n.fancybox.getInstance()||(n("body").addClass("fancybox-active"),/iPad|iPhone|iPod/.test(navigator.userAgent)&&!t.MSStream?"image"!==l.type&&n("body").css("top",n("body").scrollTop()*-1).addClass("fancybox-iosfix"):!n.fancybox.isMobile&&e.body.scrollHeight>t.innerHeight&&(d===o&&(i=n('<div style="width:50px;height:50px;overflow:scroll;" />').appendTo("body"),d=n.fancybox.scrollbarWidth=i[0].offsetWidth-i[0].clientWidth,i.remove()),n("head").append('<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar { margin-right: '+d+"px; }</style>"),n("body").addClass("compensate-for-scrollbar"))),s="",n.each(u.buttons,function(t,e){s+=u.btnTpl[e]||""}),a=n(c.translate(c,u.baseTpl.replace("{{buttons}}",s).replace("{{arrows}}",u.btnTpl.arrowLeft+u.btnTpl.arrowRight))).attr("id","fancybox-container-"+c.id).addClass("fancybox-is-hidden").addClass(u.baseClass).data("FancyBox",c).appendTo(u.parentEl),c.$refs={container:a},["bg","inner","infobar","toolbar","stage","caption","navigation"].forEach(function(t){c.$refs[t]=a.find(".fancybox-"+t)}),c.trigger("onInit"),c.activate(),c.jumpTo(c.currIndex)},translate:function(t,e){var n=t.opts.i18n[t.opts.lang];return e.replace(/\{\{(\w+)\}\}/g,function(t,e){var i=n[e];return i===o?t:i})},createGroup:function(t){var e=this,i=n.makeArray(t);n.each(i,function(t,i){var a,s,r,c,l,u={},d={};n.isPlainObject(i)?(u=i,d=i.opts||i):"object"===n.type(i)&&n(i).length?(a=n(i),d=a.data(),d=n.extend({},d,d.options||{}),d.$orig=a,u.src=d.src||a.attr("href"),u.type||u.src||(u.type="inline",u.src=i)):u={type:"html",src:i+""},u.opts=n.extend(!0,{},e.opts,d),n.isArray(d.buttons)&&(u.opts.buttons=d.buttons),s=u.type||u.opts.type,c=u.src||"",!s&&c&&(c.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)?s="image":c.match(/\.(pdf)((\?|#).*)?$/i)?s="pdf":(r=c.match(/\.(mp4|mov|ogv)((\?|#).*)?$/i))?(s="video",u.opts.videoFormat||(u.opts.videoFormat="video/"+("ogv"===r[1]?"ogg":r[1]))):"#"===c.charAt(0)&&(s="inline")),s?u.type=s:e.trigger("objectNeedsType",u),u.index=e.group.length,u.opts.$orig&&!u.opts.$orig.length&&delete u.opts.$orig,!u.opts.$thumb&&u.opts.$orig&&(u.opts.$thumb=u.opts.$orig.find("img:first")),u.opts.$thumb&&!u.opts.$thumb.length&&delete u.opts.$thumb,"function"===n.type(u.opts.caption)&&(u.opts.caption=u.opts.caption.apply(i,[e,u])),"function"===n.type(e.opts.caption)&&(u.opts.caption=e.opts.caption.apply(i,[e,u])),u.opts.caption instanceof n||(u.opts.caption=u.opts.caption===o?"":u.opts.caption+""),"ajax"===s&&(l=c.split(/\s+/,2),l.length>1&&(u.src=l.shift(),u.opts.filter=l.shift())),"auto"==u.opts.smallBtn&&(n.inArray(s,["html","inline","ajax"])>-1?(u.opts.toolbar=!1,u.opts.smallBtn=!0):u.opts.smallBtn=!1),"pdf"===s&&(u.type="iframe",u.opts.iframe.preload=!1),u.opts.modal&&(u.opts=n.extend(!0,u.opts,{infobar:0,toolbar:0,smallBtn:0,keyboard:0,slideShow:0,fullScreen:0,thumbs:0,touch:0,clickContent:!1,clickSlide:!1,clickOutside:!1,dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1})),e.group.push(u)})},addEvents:function(){var o=this;o.removeEvents(),o.$refs.container.on("click.fb-close","[data-fancybox-close]",function(t){t.stopPropagation(),t.preventDefault(),o.close(t)}).on("click.fb-prev touchend.fb-prev","[data-fancybox-prev]",function(t){t.stopPropagation(),t.preventDefault(),o.previous()}).on("click.fb-next touchend.fb-next","[data-fancybox-next]",function(t){t.stopPropagation(),t.preventDefault(),o.next()}).on("click.fb","[data-fancybox-zoom]",function(t){o[o.isScaledDown()?"scaleToActual":"scaleToFit"]()}),s.on("orientationchange.fb resize.fb",function(t){t&&t.originalEvent&&"resize"===t.originalEvent.type?u(function(){o.update()}):(o.$refs.stage.hide(),setTimeout(function(){o.$refs.stage.show(),o.update()},600))}),r.on("focusin.fb",function(t){var i=n.fancybox?n.fancybox.getInstance():null;i.isClosing||!i.current||!i.current.opts.trapFocus||n(t.target).hasClass("fancybox-container")||n(t.target).is(e)||i&&"fixed"!==n(t.target).css("position")&&!i.$refs.container.has(t.target).length&&(t.stopPropagation(),i.focus(),s.scrollTop(o.scrollTop).scrollLeft(o.scrollLeft))}),r.on("keydown.fb",function(t){var e=o.current,i=t.keyCode||t.which;if(e&&e.opts.keyboard&&!n(t.target).is("input")&&!n(t.target).is("textarea"))return 8===i||27===i?(t.preventDefault(),void o.close(t)):37===i||38===i?(t.preventDefault(),void o.previous()):39===i||40===i?(t.preventDefault(),void o.next()):void o.trigger("afterKeydown",t,i)}),o.group[o.currIndex].opts.idleTime&&(o.idleSecondsCounter=0,r.on("mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",function(t){o.idleSecondsCounter=0,o.isIdle&&o.showControls(),o.isIdle=!1}),o.idleInterval=t.setInterval(function(){o.idleSecondsCounter++,o.idleSecondsCounter>=o.group[o.currIndex].opts.idleTime&&!o.isDragging&&(o.isIdle=!0,o.idleSecondsCounter=0,o.hideControls())},1e3))},removeEvents:function(){var e=this;s.off("orientationchange.fb resize.fb"),r.off("focusin.fb keydown.fb .fb-idle"),this.$refs.container.off(".fb-close .fb-prev .fb-next"),e.idleInterval&&(t.clearInterval(e.idleInterval),e.idleInterval=null)},previous:function(t){return this.jumpTo(this.currPos-1,t)},next:function(t){return this.jumpTo(this.currPos+1,t)},jumpTo:function(t,e,i){var a,s,r,c,l,u,d,p=this,h=p.group.length;if(!(p.isDragging||p.isClosing||p.isAnimating&&p.firstRun)){if(t=parseInt(t,10),s=p.current?p.current.opts.loop:p.opts.loop,!s&&(t<0||t>=h))return!1;if(a=p.firstRun=null===p.firstRun,!(h<2&&!a&&p.isDragging)){if(c=p.current,p.prevIndex=p.currIndex,p.prevPos=p.currPos,r=p.createSlide(t),h>1&&((s||r.index>0)&&p.createSlide(t-1),(s||r.index<h-1)&&p.createSlide(t+1)),p.current=r,p.currIndex=r.index,p.currPos=r.pos,p.trigger("beforeShow",a),p.updateControls(),u=n.fancybox.getTranslate(r.$slide),r.isMoved=(0!==u.left||0!==u.top)&&!r.$slide.hasClass("fancybox-animated"),r.forcedDuration=o,n.isNumeric(e)?r.forcedDuration=e:e=r.opts[a?"animationDuration":"transitionDuration"],e=parseInt(e,10),a)return r.opts.animationEffect&&e&&p.$refs.container.css("transition-duration",e+"ms"),p.$refs.container.removeClass("fancybox-is-hidden"),f(p.$refs.container),p.$refs.container.addClass("fancybox-is-open"),r.$slide.addClass("fancybox-slide--current"),p.loadSlide(r),void p.preload("image");n.each(p.slides,function(t,e){n.fancybox.stop(e.$slide)}),r.$slide.removeClass("fancybox-slide--next fancybox-slide--previous").addClass("fancybox-slide--current"),r.isMoved?(l=Math.round(r.$slide.width()),n.each(p.slides,function(t,o){var i=o.pos-r.pos;n.fancybox.animate(o.$slide,{top:0,left:i*l+i*o.opts.gutter},e,function(){o.$slide.removeAttr("style").removeClass("fancybox-slide--next fancybox-slide--previous"),o.pos===p.currPos&&(r.isMoved=!1,p.complete())})})):p.$refs.stage.children().removeAttr("style"),r.isLoaded?p.revealContent(r):p.loadSlide(r),p.preload("image"),c.pos!==r.pos&&(d="fancybox-slide--"+(c.pos>r.pos?"next":"previous"),c.$slide.removeClass("fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous"),c.isComplete=!1,e&&(r.isMoved||r.opts.transitionEffect)&&(r.isMoved?c.$slide.addClass(d):(d="fancybox-animated "+d+" fancybox-fx-"+r.opts.transitionEffect,n.fancybox.animate(c.$slide,d,e,function(){c.$slide.removeClass(d).removeAttr("style")}))))}}},createSlide:function(t){var e,o,i=this;return o=t%i.group.length,o=o<0?i.group.length+o:o,!i.slides[t]&&i.group[o]&&(e=n('<div class="fancybox-slide"></div>').appendTo(i.$refs.stage),i.slides[t]=n.extend(!0,{},i.group[o],{pos:t,$slide:e,isLoaded:!1}),i.updateSlide(i.slides[t])),i.slides[t]},scaleToActual:function(t,e,i){var a,s,r,c,l,u=this,d=u.current,f=d.$content,p=parseInt(d.$slide.width(),10),h=parseInt(d.$slide.height(),10),g=d.width,b=d.height;"image"!=d.type||d.hasError||!f||u.isAnimating||(n.fancybox.stop(f),u.isAnimating=!0,t=t===o?.5*p:t,e=e===o?.5*h:e,a=n.fancybox.getTranslate(f),c=g/a.width,l=b/a.height,s=.5*p-.5*g,r=.5*h-.5*b,g>p&&(s=a.left*c-(t*c-t),s>0&&(s=0),s<p-g&&(s=p-g)),b>h&&(r=a.top*l-(e*l-e),r>0&&(r=0),r<h-b&&(r=h-b)),u.updateCursor(g,b),n.fancybox.animate(f,{top:r,left:s,scaleX:c,scaleY:l},i||330,function(){u.isAnimating=!1}),u.SlideShow&&u.SlideShow.isActive&&u.SlideShow.stop())},scaleToFit:function(t){var e,o=this,i=o.current,a=i.$content;"image"!=i.type||i.hasError||!a||o.isAnimating||(n.fancybox.stop(a),o.isAnimating=!0,e=o.getFitPos(i),o.updateCursor(e.width,e.height),n.fancybox.animate(a,{top:e.top,left:e.left,scaleX:e.width/a.width(),scaleY:e.height/a.height()},t||330,function(){o.isAnimating=!1}))},getFitPos:function(t){var e,o,i,a,s,r=this,c=t.$content,l=t.width,u=t.height,d=t.opts.margin;return!(!c||!c.length||!l&&!u)&&("number"===n.type(d)&&(d=[d,d]),2==d.length&&(d=[d[0],d[1],d[0],d[1]]),e=parseInt(r.$refs.stage.width(),10)-(d[1]+d[3]),o=parseInt(r.$refs.stage.height(),10)-(d[0]+d[2]),i=Math.min(1,e/l,o/u),a=Math.floor(i*l),s=Math.floor(i*u),{top:Math.floor(.5*(o-s))+d[0],left:Math.floor(.5*(e-a))+d[3],width:a,height:s})},update:function(){var t=this;n.each(t.slides,function(e,n){t.updateSlide(n)})},updateSlide:function(t,e){var o=this,i=t&&t.$content;i&&(t.width||t.height)&&(o.isAnimating=!1,n.fancybox.stop(i),n.fancybox.setTranslate(i,o.getFitPos(t)),t.pos===o.currPos&&o.updateCursor()),t.$slide.trigger("refresh"),o.trigger("onUpdate",t)},centerSlide:function(t,e){var i,a,s=this;s.current&&(i=Math.round(t.$slide.width()),a=t.pos-s.current.pos,n.fancybox.animate(t.$slide,{top:0,left:a*i+a*t.opts.gutter,opacity:1},e===o?0:e,null,!1))},updateCursor:function(t,e){var n,i=this,a=i.$refs.container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut");i.current&&!i.isClosing&&(i.isZoomable()?(a.addClass("fancybox-is-zoomable"),n=t!==o&&e!==o?t<i.current.width&&e<i.current.height:i.isScaledDown(),n?a.addClass("fancybox-can-zoomIn"):i.current.opts.touch?a.addClass("fancybox-can-drag"):a.addClass("fancybox-can-zoomOut")):i.current.opts.touch&&a.addClass("fancybox-can-drag"))},isZoomable:function(){var t,e=this,o=e.current;if(o&&!e.isClosing)return!!("image"===o.type&&o.isLoaded&&!o.hasError&&("zoom"===o.opts.clickContent||n.isFunction(o.opts.clickContent)&&"zoom"===o.opts.clickContent(o))&&(t=e.getFitPos(o),o.width>t.width||o.height>t.height))},isScaledDown:function(){var t=this,e=t.current,o=e.$content,i=!1;return o&&(i=n.fancybox.getTranslate(o),i=i.width<e.width||i.height<e.height),i},canPan:function(){var t=this,e=t.current,n=e.$content,o=!1;return n&&(o=t.getFitPos(e),o=Math.abs(n.width()-o.width)>1||Math.abs(n.height()-o.height)>1),o},loadSlide:function(t){var e,o,i,a=this;if(!t.isLoading&&!t.isLoaded){switch(t.isLoading=!0,a.trigger("beforeLoad",t),e=t.type,o=t.$slide,o.off("refresh").trigger("onReset").addClass("fancybox-slide--"+(e||"unknown")).addClass(t.opts.slideClass),e){case"image":a.setImage(t);break;case"iframe":a.setIframe(t);break;case"html":a.setContent(t,t.src||t.content);break;case"inline":n(t.src).length?a.setContent(t,n(t.src)):a.setError(t);break;case"ajax":a.showLoading(t),i=n.ajax(n.extend({},t.opts.ajax.settings,{url:t.src,success:function(e,n){"success"===n&&a.setContent(t,e)},error:function(e,n){e&&"abort"!==n&&a.setError(t)}})),o.one("onReset",function(){i.abort()});break;case"video":a.setContent(t,'<video controls><source src="'+t.src+'" type="'+t.opts.videoFormat+"\">Your browser doesn't support HTML5 video</video>");break;default:a.setError(t)}return!0}},setImage:function(e){var o,i,a,s,r=this,c=e.opts.srcset||e.opts.image.srcset;if(c){a=t.devicePixelRatio||1,s=t.innerWidth*a,i=c.split(",").map(function(t){var e={};return t.trim().split(/\s+/).forEach(function(t,n){var o=parseInt(t.substring(0,t.length-1),10);return 0===n?e.url=t:void(o&&(e.value=o,e.postfix=t[t.length-1]))}),e}),i.sort(function(t,e){return t.value-e.value});for(var l=0;l<i.length;l++){var u=i[l];if("w"===u.postfix&&u.value>=s||"x"===u.postfix&&u.value>=a){o=u;break}}!o&&i.length&&(o=i[i.length-1]),o&&(e.src=o.url,e.width&&e.height&&"w"==o.postfix&&(e.height=e.width/e.height*o.value,e.width=o.value))}e.$content=n('<div class="fancybox-image-wrap"></div>').addClass("fancybox-is-hidden").appendTo(e.$slide),e.opts.preload!==!1&&e.opts.width&&e.opts.height&&(e.opts.thumb||e.opts.$thumb)?(e.width=e.opts.width,e.height=e.opts.height,e.$ghost=n("<img />").one("error",function(){n(this).remove(),e.$ghost=null,r.setBigImage(e)}).one("load",function(){r.afterLoad(e),r.setBigImage(e)}).addClass("fancybox-image").appendTo(e.$content).attr("src",e.opts.thumb||e.opts.$thumb.attr("src"))):r.setBigImage(e)},setBigImage:function(t){var e=this,o=n("<img />");t.$image=o.one("error",function(){e.setError(t)}).one("load",function(){clearTimeout(t.timouts),t.timouts=null,e.isClosing||(t.width=t.opts.width||this.naturalWidth,t.height=t.opts.height||this.naturalHeight,t.opts.image.srcset&&o.attr("sizes","100vw").attr("srcset",t.opts.image.srcset),e.hideLoading(t),t.$ghost?t.timouts=setTimeout(function(){t.timouts=null,t.$ghost.hide()},Math.min(300,Math.max(1e3,t.height/1600))):e.afterLoad(t))}).addClass("fancybox-image").attr("src",t.src).appendTo(t.$content),(o[0].complete||"complete"==o[0].readyState)&&o[0].naturalWidth&&o[0].naturalHeight?o.trigger("load"):o[0].error?o.trigger("error"):t.timouts=setTimeout(function(){o[0].complete||t.hasError||e.showLoading(t)},100)},setIframe:function(t){var e,i=this,a=t.opts.iframe,s=t.$slide;t.$content=n('<div class="fancybox-content'+(a.preload?" fancybox-is-hidden":"")+'"></div>').css(a.css).appendTo(s),e=n(a.tpl.replace(/\{rnd\}/g,(new Date).getTime())).attr(a.attr).appendTo(t.$content),a.preload?(i.showLoading(t),e.on("load.fb error.fb",function(e){this.isReady=1,t.$slide.trigger("refresh"),i.afterLoad(t)}),s.on("refresh.fb",function(){var n,i,s,r=t.$content,c=a.css.width,l=a.css.height;if(1===e[0].isReady){try{i=e.contents(),s=i.find("body")}catch(t){}s&&s.length&&(c===o&&(n=e[0].contentWindow.document.documentElement.scrollWidth,c=Math.ceil(s.outerWidth(!0)+(r.width()-n)),c+=r.outerWidth()-r.innerWidth()),l===o&&(l=Math.ceil(s.outerHeight(!0)),l+=r.outerHeight()-r.innerHeight()),c&&r.width(c),l&&r.height(l)),r.removeClass("fancybox-is-hidden")}})):this.afterLoad(t),e.attr("src",t.src),t.opts.smallBtn===!0&&t.$content.prepend(i.translate(t,t.opts.btnTpl.smallBtn)),s.one("onReset",function(){try{n(this).find("iframe").hide().attr("src","//about:blank")}catch(t){}n(this).empty(),t.isLoaded=!1})},setContent:function(t,e){var o=this;o.isClosing||(o.hideLoading(t),t.$slide.empty(),l(e)&&e.parent().length?(e.parent(".fancybox-slide--inline").trigger("onReset"),t.$placeholder=n("<div></div>").hide().insertAfter(e),e.css("display","inline-block")):t.hasError||("string"===n.type(e)&&(e=n("<div>").append(n.trim(e)).contents(),3===e[0].nodeType&&(e=n("<div>").html(e))),t.opts.filter&&(e=n("<div>").html(e).find(t.opts.filter))),t.$slide.one("onReset",function(){n(this).find("video,audio").trigger("pause"),t.$placeholder&&(t.$placeholder.after(e.hide()).remove(),t.$placeholder=null),t.$smallBtn&&(t.$smallBtn.remove(),t.$smallBtn=null),t.hasError||(n(this).empty(),t.isLoaded=!1)}),t.$content=n(e).appendTo(t.$slide),this.afterLoad(t))},setError:function(t){t.hasError=!0,t.$slide.removeClass("fancybox-slide--"+t.type),this.setContent(t,this.translate(t,t.opts.errorTpl))},showLoading:function(t){var e=this;t=t||e.current,t&&!t.$spinner&&(t.$spinner=n(e.opts.spinnerTpl).appendTo(t.$slide))},hideLoading:function(t){var e=this;t=t||e.current,t&&t.$spinner&&(t.$spinner.remove(),delete t.$spinner)},afterLoad:function(t){var e=this;e.isClosing||(t.isLoading=!1,t.isLoaded=!0,e.trigger("afterLoad",t),e.hideLoading(t),t.opts.smallBtn&&!t.$smallBtn&&(t.$smallBtn=n(e.translate(t,t.opts.btnTpl.smallBtn)).appendTo(t.$content.filter("div,form").first())),t.opts.protect&&t.$content&&!t.hasError&&(t.$content.on("contextmenu.fb",function(t){return 2==t.button&&t.preventDefault(),!0}),"image"===t.type&&n('<div class="fancybox-spaceball"></div>').appendTo(t.$content)),e.revealContent(t))},revealContent:function(t){var e,i,a,s,r,c=this,l=t.$slide,u=!1;return e=t.opts[c.firstRun?"animationEffect":"transitionEffect"],a=t.opts[c.firstRun?"animationDuration":"transitionDuration"],a=parseInt(t.forcedDuration===o?a:t.forcedDuration,10),!t.isMoved&&t.pos===c.currPos&&a||(e=!1),"zoom"!==e||t.pos===c.currPos&&a&&"image"===t.type&&!t.hasError&&(u=c.getThumbPos(t))||(e="fade"),"zoom"===e?(r=c.getFitPos(t),r.scaleX=r.width/u.width,r.scaleY=r.height/u.height,delete r.width,delete r.height,s=t.opts.zoomOpacity,"auto"==s&&(s=Math.abs(t.width/t.height-u.width/u.height)>.1),s&&(u.opacity=.1,r.opacity=1),n.fancybox.setTranslate(t.$content.removeClass("fancybox-is-hidden"),u),f(t.$content),void n.fancybox.animate(t.$content,r,a,function(){c.complete()})):(c.updateSlide(t),e?(n.fancybox.stop(l),i="fancybox-animated fancybox-slide--"+(t.pos>=c.prevPos?"next":"previous")+" fancybox-fx-"+e,l.removeAttr("style").removeClass("fancybox-slide--current fancybox-slide--next fancybox-slide--previous").addClass(i),t.$content.removeClass("fancybox-is-hidden"),f(l),void n.fancybox.animate(l,"fancybox-slide--current",a,function(e){l.removeClass(i).removeAttr("style"),t.pos===c.currPos&&c.complete()},!0)):(f(l),t.$content.removeClass("fancybox-is-hidden"),void(t.pos===c.currPos&&c.complete())))},getThumbPos:function(o){var i,a=this,s=!1,r=function(e){for(var o,i=e[0],a=i.getBoundingClientRect(),s=[];null!==i.parentElement;)"hidden"!==n(i.parentElement).css("overflow")&&"auto"!==n(i.parentElement).css("overflow")||s.push(i.parentElement.getBoundingClientRect()),i=i.parentElement;return o=s.every(function(t){var e=Math.min(a.right,t.right)-Math.max(a.left,t.left),n=Math.min(a.bottom,t.bottom)-Math.max(a.top,t.top);return e>0&&n>0}),o&&a.bottom>0&&a.right>0&&a.left<n(t).width()&&a.top<n(t).height()},c=o.opts.$thumb,l=c?c.offset():0;return l&&c[0].ownerDocument===e&&r(c)&&(i=a.$refs.stage.offset(),s={top:l.top-i.top+parseFloat(c.css("border-top-width")||0),left:l.left-i.left+parseFloat(c.css("border-left-width")||0),width:c.width(),height:c.height(),scaleX:1,scaleY:1}),s},complete:function(){var t=this,o=t.current,i={};o.isMoved||!o.isLoaded||o.isComplete||(o.isComplete=!0,o.$slide.siblings().trigger("onReset"),t.preload("inline"),f(o.$slide),o.$slide.addClass("fancybox-slide--complete"),n.each(t.slides,function(e,o){o.pos>=t.currPos-1&&o.pos<=t.currPos+1?i[o.pos]=o:o&&(n.fancybox.stop(o.$slide),o.$slide.off().remove())}),t.slides=i,t.updateCursor(),t.trigger("afterShow"),o.$slide.find("video,audio").first().trigger("play"),(n(e.activeElement).is("[disabled]")||o.opts.autoFocus&&"image"!=o.type&&"iframe"!==o.type)&&t.focus())},preload:function(t){var e=this,n=e.slides[e.currPos+1],o=e.slides[e.currPos-1];n&&n.type===t&&e.loadSlide(n),o&&o.type===t&&e.loadSlide(o)},focus:function(){var t,e=this.current;this.isClosing||(e&&e.isComplete&&(t=e.$slide.find("input[autofocus]:enabled:visible:first"),t.length||(t=e.$slide.find("button,:input,[tabindex],a").filter(":enabled:visible:first"))),t=t&&t.length?t:this.$refs.container,t.focus())},activate:function(){var t=this;n(".fancybox-container").each(function(){var e=n(this).data("FancyBox");e&&e.id!==t.id&&!e.isClosing&&(e.trigger("onDeactivate"),e.removeEvents(),e.isVisible=!1)}),t.isVisible=!0,(t.current||t.isIdle)&&(t.update(),t.updateControls()),t.trigger("onActivate"),t.addEvents()},close:function(t,e){var o,i,a,s,r,c,l=this,p=l.current,h=function(){l.cleanUp(t)};return!l.isClosing&&(l.isClosing=!0,l.trigger("beforeClose",t)===!1?(l.isClosing=!1,u(function(){l.update()}),!1):(l.removeEvents(),p.timouts&&clearTimeout(p.timouts),a=p.$content,o=p.opts.animationEffect,i=n.isNumeric(e)?e:o?p.opts.animationDuration:0,p.$slide.off(d).removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated"),p.$slide.siblings().trigger("onReset").remove(),i&&l.$refs.container.removeClass("fancybox-is-open").addClass("fancybox-is-closing"),l.hideLoading(p),l.hideControls(),l.updateCursor(),"zoom"!==o||t!==!0&&a&&i&&"image"===p.type&&!p.hasError&&(c=l.getThumbPos(p))||(o="fade"),"zoom"===o?(n.fancybox.stop(a),r=n.fancybox.getTranslate(a),r.width=r.width*r.scaleX,r.height=r.height*r.scaleY,s=p.opts.zoomOpacity,"auto"==s&&(s=Math.abs(p.width/p.height-c.width/c.height)>.1),s&&(c.opacity=0),r.scaleX=r.width/c.width,r.scaleY=r.height/c.height,r.width=c.width,r.height=c.height,n.fancybox.setTranslate(p.$content,r),f(p.$content),n.fancybox.animate(p.$content,c,i,h),!0):(o&&i?t===!0?setTimeout(h,i):n.fancybox.animate(p.$slide.removeClass("fancybox-slide--current"),"fancybox-animated fancybox-slide--previous fancybox-fx-"+o,i,h):h(),!0)))},cleanUp:function(t){var o,i,a=this,r=n("body");a.current.$slide.trigger("onReset"),a.$refs.container.empty().remove(),a.trigger("afterClose",t),a.$lastFocus&&a.current.opts.backFocus&&a.$lastFocus.focus(),a.current=null,o=n.fancybox.getInstance(),o?o.activate():(s.scrollTop(a.scrollTop).scrollLeft(a.scrollLeft),r.removeClass("fancybox-active compensate-for-scrollbar"),r.hasClass("fancybox-iosfix")&&(i=parseInt(e.body.style.top,10),r.removeClass("fancybox-iosfix").css("top","").scrollTop(i*-1)),n("#fancybox-style-noscroll").remove())},trigger:function(t,e){var o,i=Array.prototype.slice.call(arguments,1),a=this,s=e&&e.opts?e:a.current;return s?i.unshift(s):s=a,i.unshift(a),n.isFunction(s.opts[t])&&(o=s.opts[t].apply(s,i)),o===!1?o:void("afterClose"!==t&&a.$refs?a.$refs.container.trigger(t+".fb",i):r.trigger(t+".fb",i))},updateControls:function(t){var e=this,n=e.current,o=n.index,i=n.opts.caption,a=e.$refs.container,s=e.$refs.caption;n.$slide.trigger("refresh"),e.$caption=i&&i.length?s.html(i):null,e.isHiddenControls||e.isIdle||e.showControls(),a.find("[data-fancybox-count]").html(e.group.length),a.find("[data-fancybox-index]").html(o+1),a.find("[data-fancybox-prev]").prop("disabled",!n.opts.loop&&o<=0),a.find("[data-fancybox-next]").prop("disabled",!n.opts.loop&&o>=e.group.length-1),"image"===n.type?a.find("[data-fancybox-download]").attr("href",n.opts.image.src||n.src).show():a.find("[data-fancybox-download],[data-fancybox-zoom]").hide()},hideControls:function(){this.isHiddenControls=!0,this.$refs.container.removeClass("fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav")},showControls:function(){var t=this,e=t.current?t.current.opts:t.opts,n=t.$refs.container;t.isHiddenControls=!1,t.idleSecondsCounter=0,n.toggleClass("fancybox-show-toolbar",!(!e.toolbar||!e.buttons)).toggleClass("fancybox-show-infobar",!!(e.infobar&&t.group.length>1)).toggleClass("fancybox-show-nav",!!(e.arrows&&t.group.length>1)).toggleClass("fancybox-is-modal",!!e.modal),t.$caption?n.addClass("fancybox-show-caption "):n.removeClass("fancybox-show-caption")},toggleControls:function(){this.isHiddenControls?this.showControls():this.hideControls()}}),n.fancybox={version:"3.2.10",defaults:a,getInstance:function(t){var e=n('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"),o=Array.prototype.slice.call(arguments,1);return e instanceof p&&("string"===n.type(t)?e[t].apply(e,o):"function"===n.type(t)&&t.apply(e,o),e)},open:function(t,e,n){return new p(t,e,n)},close:function(t){var e=this.getInstance();e&&(e.close(),t===!0&&this.close())},destroy:function(){this.close(!0),r.off("click.fb-start")},isMobile:e.createTouch!==o&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),use3d:function(){var n=e.createElement("div");return t.getComputedStyle&&t.getComputedStyle(n).getPropertyValue("transform")&&!(e.documentMode&&e.documentMode<11)}(),getTranslate:function(t){var e;if(!t||!t.length)return!1;if(e=t.eq(0).css("transform"),e&&e.indexOf("matrix")!==-1?(e=e.split("(")[1],e=e.split(")")[0],e=e.split(",")):e=[],e.length)e=e.length>10?[e[13],e[12],e[0],e[5]]:[e[5],e[4],e[0],e[3]],e=e.map(parseFloat);else{e=[0,0,1,1];var n=/\.*translate\((.*)px,(.*)px\)/i,o=n.exec(t.eq(0).attr("style"));o&&(e[0]=parseFloat(o[2]),e[1]=parseFloat(o[1]))}return{top:e[0],left:e[1],scaleX:e[2],scaleY:e[3],opacity:parseFloat(t.css("opacity")),width:t.width(),height:t.height()}},setTranslate:function(t,e){var n="",i={};if(t&&e)return e.left===o&&e.top===o||(n=(e.left===o?t.position().left:e.left)+"px, "+(e.top===o?t.position().top:e.top)+"px",n=this.use3d?"translate3d("+n+", 0px)":"translate("+n+")"),e.scaleX!==o&&e.scaleY!==o&&(n=(n.length?n+" ":"")+"scale("+e.scaleX+", "+e.scaleY+")"),n.length&&(i.transform=n),e.opacity!==o&&(i.opacity=e.opacity),e.width!==o&&(i.width=e.width),e.height!==o&&(i.height=e.height),t.css(i)},animate:function(t,e,i,a,s){n.isFunction(i)&&(a=i,i=null),n.isPlainObject(e)||t.removeAttr("style"),t.on(d,function(i){(!i||!i.originalEvent||t.is(i.originalEvent.target)&&"z-index"!=i.originalEvent.propertyName)&&(n.fancybox.stop(t),n.isPlainObject(e)?(e.scaleX!==o&&e.scaleY!==o&&(t.css("transition-duration",""),e.width=Math.round(t.width()*e.scaleX),e.height=Math.round(t.height()*e.scaleY),e.scaleX=1,e.scaleY=1,n.fancybox.setTranslate(t,e)),s===!1&&t.removeAttr("style")):s!==!0&&t.removeClass(e),n.isFunction(a)&&a(i))}),n.isNumeric(i)&&t.css("transition-duration",i+"ms"),n.isPlainObject(e)?n.fancybox.setTranslate(t,e):t.addClass(e),e.scaleX&&t.hasClass("fancybox-image-wrap")&&t.parent().addClass("fancybox-is-scaling"),t.data("timer",setTimeout(function(){t.trigger("transitionend")},i+16))},stop:function(t){clearTimeout(t.data("timer")),t.off("transitionend").css("transition-duration",""),t.hasClass("fancybox-image-wrap")&&t.parent().removeClass("fancybox-is-scaling")}},n.fn.fancybox=function(t){var e;return t=t||{},e=t.selector||!1,e?n("body").off("click.fb-start",e).on("click.fb-start",e,{options:t},i):this.off("click.fb-start").on("click.fb-start",{items:this,options:t},i),this},r.on("click.fb-start","[data-fancybox]",i)}}(window,document,window.jQuery||jQuery),function(t){"use strict";var e=function(e,n,o){if(e)return o=o||"","object"===t.type(o)&&(o=t.param(o,!0)),t.each(n,function(t,n){e=e.replace("$"+t,n||"")}),o.length&&(e+=(e.indexOf("?")>0?"&":"?")+o),e},n={youtube:{matcher:/(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,params:{autoplay:1,autohide:1,fs:1,rel:0,hd:1,wmode:"transparent",enablejsapi:1,html5:1},paramPlace:8,type:"iframe",url:"//www.youtube.com/embed/$4",thumb:"//img.youtube.com/vi/$4/hqdefault.jpg"
|
12 |
-
},vimeo:{matcher:/^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,params:{autoplay:1,hd:1,show_title:1,show_byline:1,show_portrait:0,fullscreen:1,api:1},paramPlace:3,type:"iframe",url:"//player.vimeo.com/video/$2"},metacafe:{matcher:/metacafe.com\/watch\/(\d+)\/(.*)?/,type:"iframe",url:"//www.metacafe.com/embed/$1/?ap=1"},dailymotion:{matcher:/dailymotion.com\/video\/(.*)\/?(.*)/,params:{additionalInfos:0,autoStart:1},type:"iframe",url:"//www.dailymotion.com/embed/video/$1"},vine:{matcher:/vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,type:"iframe",url:"//vine.co/v/$1/embed/simple"},instagram:{matcher:/(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,type:"image",url:"//$1/p/$2/media/?size=l"},gmap_place:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/?ll="+(t[9]?t[9]+"&z="+Math.floor(t[10])+(t[12]?t[12].replace(/^\//,"&"):""):t[12])+"&output="+(t[12]&&t[12].indexOf("layer=c")>0?"svembed":"embed")}},gmap_search:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/maps?q="+t[5].replace("query=","q=").replace("api=1","")+"&output=embed"}}};t(document).on("objectNeedsType.fb",function(o,i,a){var s,r,c,l,u,d,f,p=a.src||"",h=!1;s=t.extend(!0,{},n,a.opts.media),t.each(s,function(n,o){if(c=p.match(o.matcher)){if(h=o.type,d={},o.paramPlace&&c[o.paramPlace]){u=c[o.paramPlace],"?"==u[0]&&(u=u.substring(1)),u=u.split("&");for(var i=0;i<u.length;++i){var s=u[i].split("=",2);2==s.length&&(d[s[0]]=decodeURIComponent(s[1].replace(/\+/g," ")))}}return l=t.extend(!0,{},o.params,a.opts[n],d),p="function"===t.type(o.url)?o.url.call(this,c,l,a):e(o.url,c,l),r="function"===t.type(o.thumb)?o.thumb.call(this,c,l,a):e(o.thumb,c),"vimeo"===n&&(p=p.replace("&%23","#")),!1}}),h?(a.src=p,a.type=h,a.opts.thumb||a.opts.$thumb&&a.opts.$thumb.length||(a.opts.thumb=r),"iframe"===h&&(t.extend(!0,a.opts,{iframe:{preload:!1,attr:{scrolling:"no"}}}),a.contentProvider=f,a.opts.slideClass+=" fancybox-slide--"+("gmap_place"==f||"gmap_search"==f?"map":"video"))):p&&(a.type=a.opts.defaultType)})}(window.jQuery||jQuery),function(t,e,n){"use strict";var o=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),i=function(){return t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.mozCancelAnimationFrame||t.oCancelAnimationFrame||function(e){t.clearTimeout(e)}}(),a=function(e){var n=[];e=e.originalEvent||e||t.e,e=e.touches&&e.touches.length?e.touches:e.changedTouches&&e.changedTouches.length?e.changedTouches:[e];for(var o in e)e[o].pageX?n.push({x:e[o].pageX,y:e[o].pageY}):e[o].clientX&&n.push({x:e[o].clientX,y:e[o].clientY});return n},s=function(t,e,n){return e&&t?"x"===n?t.x-e.x:"y"===n?t.y-e.y:Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)):0},r=function(t){if(t.is('a,area,button,[role="button"],input,label,select,summary,textarea')||n.isFunction(t.get(0).onclick)||t.data("selectable"))return!0;for(var e=0,o=t[0].attributes,i=o.length;e<i;e++)if("data-fancybox-"===o[e].nodeName.substr(0,14))return!0;return!1},c=function(e){var n=t.getComputedStyle(e)["overflow-y"],o=t.getComputedStyle(e)["overflow-x"],i=("scroll"===n||"auto"===n)&&e.scrollHeight>e.clientHeight,a=("scroll"===o||"auto"===o)&&e.scrollWidth>e.clientWidth;return i||a},l=function(t){for(var e=!1;;){if(e=c(t.get(0)))break;if(t=t.parent(),!t.length||t.hasClass("fancybox-stage")||t.is("body"))break}return e},u=function(t){var e=this;e.instance=t,e.$bg=t.$refs.bg,e.$stage=t.$refs.stage,e.$container=t.$refs.container,e.destroy(),e.$container.on("touchstart.fb.touch mousedown.fb.touch",n.proxy(e,"ontouchstart"))};u.prototype.destroy=function(){this.$container.off(".fb.touch")},u.prototype.ontouchstart=function(o){var i=this,c=n(o.target),u=i.instance,d=u.current,f=d.$content,p="touchstart"==o.type;if(p&&i.$container.off("mousedown.fb.touch"),(!o.originalEvent||2!=o.originalEvent.button)&&c.length&&!r(c)&&!r(c.parent())&&(c.is("img")||!(o.originalEvent.clientX>c[0].clientWidth+c.offset().left))){if(!d||i.instance.isAnimating||i.instance.isClosing)return o.stopPropagation(),void o.preventDefault();if(i.realPoints=i.startPoints=a(o),i.startPoints){if(o.stopPropagation(),i.startEvent=o,i.canTap=!0,i.$target=c,i.$content=f,i.opts=d.opts.touch,i.isPanning=!1,i.isSwiping=!1,i.isZooming=!1,i.isScrolling=!1,i.sliderStartPos=i.sliderLastPos||{top:0,left:0},i.contentStartPos=n.fancybox.getTranslate(i.$content),i.contentLastPos=null,i.startTime=(new Date).getTime(),i.distanceX=i.distanceY=i.distance=0,i.canvasWidth=Math.round(d.$slide[0].clientWidth),i.canvasHeight=Math.round(d.$slide[0].clientHeight),n(e).off(".fb.touch").on(p?"touchend.fb.touch touchcancel.fb.touch":"mouseup.fb.touch mouseleave.fb.touch",n.proxy(i,"ontouchend")).on(p?"touchmove.fb.touch":"mousemove.fb.touch",n.proxy(i,"ontouchmove")),n.fancybox.isMobile&&e.addEventListener("scroll",i.onscroll,!0),!i.opts&&!u.canPan()||!c.is(i.$stage)&&!i.$stage.find(c).length)return void(c.is("img")&&o.preventDefault());n.fancybox.isMobile&&(l(c)||l(c.parent()))||o.preventDefault(),1===i.startPoints.length&&("image"===d.type&&(i.contentStartPos.width>i.canvasWidth+1||i.contentStartPos.height>i.canvasHeight+1)?(n.fancybox.stop(i.$content),i.$content.css("transition-duration",""),i.isPanning=!0):i.isSwiping=!0,i.$container.addClass("fancybox-controls--isGrabbing")),2!==i.startPoints.length||u.isAnimating||d.hasError||"image"!==d.type||!d.isLoaded&&!d.$ghost||(i.canTap=!1,i.isSwiping=!1,i.isPanning=!1,i.isZooming=!0,n.fancybox.stop(i.$content),i.$content.css("transition-duration",""),i.centerPointStartX=.5*(i.startPoints[0].x+i.startPoints[1].x)-n(t).scrollLeft(),i.centerPointStartY=.5*(i.startPoints[0].y+i.startPoints[1].y)-n(t).scrollTop(),i.percentageOfImageAtPinchPointX=(i.centerPointStartX-i.contentStartPos.left)/i.contentStartPos.width,i.percentageOfImageAtPinchPointY=(i.centerPointStartY-i.contentStartPos.top)/i.contentStartPos.height,i.startDistanceBetweenFingers=s(i.startPoints[0],i.startPoints[1]))}}},u.prototype.onscroll=function(t){self.isScrolling=!0},u.prototype.ontouchmove=function(t){var e=this,o=n(t.target);return e.isScrolling||!o.is(e.$stage)&&!e.$stage.find(o).length?void(e.canTap=!1):(e.newPoints=a(t),void((e.opts||e.instance.canPan())&&e.newPoints&&e.newPoints.length&&(e.isSwiping&&e.isSwiping===!0||t.preventDefault(),e.distanceX=s(e.newPoints[0],e.startPoints[0],"x"),e.distanceY=s(e.newPoints[0],e.startPoints[0],"y"),e.distance=s(e.newPoints[0],e.startPoints[0]),e.distance>0&&(e.isSwiping?e.onSwipe(t):e.isPanning?e.onPan():e.isZooming&&e.onZoom()))))},u.prototype.onSwipe=function(e){var a,s=this,r=s.isSwiping,c=s.sliderStartPos.left||0;if(r!==!0)"x"==r&&(s.distanceX>0&&(s.instance.group.length<2||0===s.instance.current.index&&!s.instance.current.opts.loop)?c+=Math.pow(s.distanceX,.8):s.distanceX<0&&(s.instance.group.length<2||s.instance.current.index===s.instance.group.length-1&&!s.instance.current.opts.loop)?c-=Math.pow(-s.distanceX,.8):c+=s.distanceX),s.sliderLastPos={top:"x"==r?0:s.sliderStartPos.top+s.distanceY,left:c},s.requestId&&(i(s.requestId),s.requestId=null),s.requestId=o(function(){s.sliderLastPos&&(n.each(s.instance.slides,function(t,e){var o=e.pos-s.instance.currPos;n.fancybox.setTranslate(e.$slide,{top:s.sliderLastPos.top,left:s.sliderLastPos.left+o*s.canvasWidth+o*e.opts.gutter})}),s.$container.addClass("fancybox-is-sliding"))});else if(Math.abs(s.distance)>10){if(s.canTap=!1,s.instance.group.length<2&&s.opts.vertical?s.isSwiping="y":s.instance.isDragging||s.opts.vertical===!1||"auto"===s.opts.vertical&&n(t).width()>800?s.isSwiping="x":(a=Math.abs(180*Math.atan2(s.distanceY,s.distanceX)/Math.PI),s.isSwiping=a>45&&a<135?"y":"x"),s.canTap=!1,"y"===s.isSwiping&&n.fancybox.isMobile&&(l(s.$target)||l(s.$target.parent())))return void(s.isScrolling=!0);s.instance.isDragging=s.isSwiping,s.startPoints=s.newPoints,n.each(s.instance.slides,function(t,e){n.fancybox.stop(e.$slide),e.$slide.css("transition-duration",""),e.inTransition=!1,e.pos===s.instance.current.pos&&(s.sliderStartPos.left=n.fancybox.getTranslate(e.$slide).left)}),s.instance.SlideShow&&s.instance.SlideShow.isActive&&s.instance.SlideShow.stop()}},u.prototype.onPan=function(){var t=this;return s(t.newPoints[0],t.realPoints[0])<(n.fancybox.isMobile?10:5)?void(t.startPoints=t.newPoints):(t.canTap=!1,t.contentLastPos=t.limitMovement(),t.requestId&&(i(t.requestId),t.requestId=null),void(t.requestId=o(function(){n.fancybox.setTranslate(t.$content,t.contentLastPos)})))},u.prototype.limitMovement=function(){var t,e,n,o,i,a,s=this,r=s.canvasWidth,c=s.canvasHeight,l=s.distanceX,u=s.distanceY,d=s.contentStartPos,f=d.left,p=d.top,h=d.width,g=d.height;return i=h>r?f+l:f,a=p+u,t=Math.max(0,.5*r-.5*h),e=Math.max(0,.5*c-.5*g),n=Math.min(r-h,.5*r-.5*h),o=Math.min(c-g,.5*c-.5*g),h>r&&(l>0&&i>t&&(i=t-1+Math.pow(-t+f+l,.8)||0),l<0&&i<n&&(i=n+1-Math.pow(n-f-l,.8)||0)),g>c&&(u>0&&a>e&&(a=e-1+Math.pow(-e+p+u,.8)||0),u<0&&a<o&&(a=o+1-Math.pow(o-p-u,.8)||0)),{top:a,left:i,scaleX:d.scaleX,scaleY:d.scaleY}},u.prototype.limitPosition=function(t,e,n,o){var i=this,a=i.canvasWidth,s=i.canvasHeight;return n>a?(t=t>0?0:t,t=t<a-n?a-n:t):t=Math.max(0,a/2-n/2),o>s?(e=e>0?0:e,e=e<s-o?s-o:e):e=Math.max(0,s/2-o/2),{top:e,left:t}},u.prototype.onZoom=function(){var e=this,a=e.contentStartPos.width,r=e.contentStartPos.height,c=e.contentStartPos.left,l=e.contentStartPos.top,u=s(e.newPoints[0],e.newPoints[1]),d=u/e.startDistanceBetweenFingers,f=Math.floor(a*d),p=Math.floor(r*d),h=(a-f)*e.percentageOfImageAtPinchPointX,g=(r-p)*e.percentageOfImageAtPinchPointY,b=(e.newPoints[0].x+e.newPoints[1].x)/2-n(t).scrollLeft(),m=(e.newPoints[0].y+e.newPoints[1].y)/2-n(t).scrollTop(),y=b-e.centerPointStartX,v=m-e.centerPointStartY,x=c+(h+y),w=l+(g+v),$={top:w,left:x,scaleX:e.contentStartPos.scaleX*d,scaleY:e.contentStartPos.scaleY*d};e.canTap=!1,e.newWidth=f,e.newHeight=p,e.contentLastPos=$,e.requestId&&(i(e.requestId),e.requestId=null),e.requestId=o(function(){n.fancybox.setTranslate(e.$content,e.contentLastPos)})},u.prototype.ontouchend=function(t){var o=this,s=Math.max((new Date).getTime()-o.startTime,1),r=o.isSwiping,c=o.isPanning,l=o.isZooming,u=o.isScrolling;return o.endPoints=a(t),o.$container.removeClass("fancybox-controls--isGrabbing"),n(e).off(".fb.touch"),e.removeEventListener("scroll",o.onscroll,!0),o.requestId&&(i(o.requestId),o.requestId=null),o.isSwiping=!1,o.isPanning=!1,o.isZooming=!1,o.isScrolling=!1,o.instance.isDragging=!1,o.canTap?o.onTap(t):(o.speed=366,o.velocityX=o.distanceX/s*.5,o.velocityY=o.distanceY/s*.5,o.speedX=Math.max(.5*o.speed,Math.min(1.5*o.speed,1/Math.abs(o.velocityX)*o.speed)),void(c?o.endPanning():l?o.endZooming():o.endSwiping(r,u)))},u.prototype.endSwiping=function(t,e){var o=this,i=!1,a=o.instance.group.length;o.sliderLastPos=null,"y"==t&&!e&&Math.abs(o.distanceY)>50?(n.fancybox.animate(o.instance.current.$slide,{top:o.sliderStartPos.top+o.distanceY+150*o.velocityY,opacity:0},150),i=o.instance.close(!0,300)):"x"==t&&o.distanceX>50&&a>1?i=o.instance.previous(o.speedX):"x"==t&&o.distanceX<-50&&a>1&&(i=o.instance.next(o.speedX)),i!==!1||"x"!=t&&"y"!=t||(e||a<2?o.instance.centerSlide(o.instance.current,150):o.instance.jumpTo(o.instance.current.index)),o.$container.removeClass("fancybox-is-sliding")},u.prototype.endPanning=function(){var t,e,o,i=this;i.contentLastPos&&(i.opts.momentum===!1?(t=i.contentLastPos.left,e=i.contentLastPos.top):(t=i.contentLastPos.left+i.velocityX*i.speed,e=i.contentLastPos.top+i.velocityY*i.speed),o=i.limitPosition(t,e,i.contentStartPos.width,i.contentStartPos.height),o.width=i.contentStartPos.width,o.height=i.contentStartPos.height,n.fancybox.animate(i.$content,o,330))},u.prototype.endZooming=function(){var t,e,o,i,a=this,s=a.instance.current,r=a.newWidth,c=a.newHeight;a.contentLastPos&&(t=a.contentLastPos.left,e=a.contentLastPos.top,i={top:e,left:t,width:r,height:c,scaleX:1,scaleY:1},n.fancybox.setTranslate(a.$content,i),r<a.canvasWidth&&c<a.canvasHeight?a.instance.scaleToFit(150):r>s.width||c>s.height?a.instance.scaleToActual(a.centerPointStartX,a.centerPointStartY,150):(o=a.limitPosition(t,e,r,c),n.fancybox.setTranslate(a.content,n.fancybox.getTranslate(a.$content)),n.fancybox.animate(a.$content,o,150)))},u.prototype.onTap=function(t){var e,o=this,i=n(t.target),s=o.instance,r=s.current,c=t&&a(t)||o.startPoints,l=c[0]?c[0].x-o.$stage.offset().left:0,u=c[0]?c[0].y-o.$stage.offset().top:0,d=function(e){var i=r.opts[e];if(n.isFunction(i)&&(i=i.apply(s,[r,t])),i)switch(i){case"close":s.close(o.startEvent);break;case"toggleControls":s.toggleControls(!0);break;case"next":s.next();break;case"nextOrClose":s.group.length>1?s.next():s.close(o.startEvent);break;case"zoom":"image"==r.type&&(r.isLoaded||r.$ghost)&&(s.canPan()?s.scaleToFit():s.isScaledDown()?s.scaleToActual(l,u):s.group.length<2&&s.close(o.startEvent))}};if((!t.originalEvent||2!=t.originalEvent.button)&&(i.is("img")||!(l>i[0].clientWidth+i.offset().left))){if(i.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container"))e="Outside";else if(i.is(".fancybox-slide"))e="Slide";else{if(!s.current.$content||!s.current.$content.find(i).addBack().filter(i).length)return;e="Content"}if(o.tapped){if(clearTimeout(o.tapped),o.tapped=null,Math.abs(l-o.tapX)>50||Math.abs(u-o.tapY)>50)return this;d("dblclick"+e)}else o.tapX=l,o.tapY=u,r.opts["dblclick"+e]&&r.opts["dblclick"+e]!==r.opts["click"+e]?o.tapped=setTimeout(function(){o.tapped=null,d("click"+e)},500):d("click"+e);return this}},n(e).on("onActivate.fb",function(t,e){e&&!e.Guestures&&(e.Guestures=new u(e))})}(window,document,window.jQuery||jQuery),function(t,e){"use strict";e.extend(!0,e.fancybox.defaults,{btnTpl:{slideShow:'<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"><svg viewBox="0 0 40 40"><path d="M13,12 L27,20 L13,27 Z" /><path d="M15,10 v19 M23,10 v19" /></svg></button>'},slideShow:{autoStart:!1,speed:3e3}});var n=function(t){this.instance=t,this.init()};e.extend(n.prototype,{timer:null,isActive:!1,$button:null,init:function(){var t=this;t.$button=t.instance.$refs.toolbar.find("[data-fancybox-play]").on("click",function(){t.toggle()}),(t.instance.group.length<2||!t.instance.group[t.instance.currIndex].opts.slideShow)&&t.$button.hide()},set:function(t){var e=this;e.instance&&e.instance.current&&(t===!0||e.instance.current.opts.loop||e.instance.currIndex<e.instance.group.length-1)?e.timer=setTimeout(function(){e.isActive&&e.instance.jumpTo((e.instance.currIndex+1)%e.instance.group.length)},e.instance.current.opts.slideShow.speed):(e.stop(),e.instance.idleSecondsCounter=0,e.instance.showControls())},clear:function(){var t=this;clearTimeout(t.timer),t.timer=null},start:function(){var t=this,e=t.instance.current;e&&(t.isActive=!0,t.$button.attr("title",e.opts.i18n[e.opts.lang].PLAY_STOP).removeClass("fancybox-button--play").addClass("fancybox-button--pause"),t.set(!0))},stop:function(){var t=this,e=t.instance.current;t.clear(),t.$button.attr("title",e.opts.i18n[e.opts.lang].PLAY_START).removeClass("fancybox-button--pause").addClass("fancybox-button--play"),t.isActive=!1},toggle:function(){var t=this;t.isActive?t.stop():t.start()}}),e(t).on({"onInit.fb":function(t,e){e&&!e.SlideShow&&(e.SlideShow=new n(e))},"beforeShow.fb":function(t,e,n,o){var i=e&&e.SlideShow;o?i&&n.opts.slideShow.autoStart&&i.start():i&&i.isActive&&i.clear()},"afterShow.fb":function(t,e,n){var o=e&&e.SlideShow;o&&o.isActive&&o.set()},"afterKeydown.fb":function(n,o,i,a,s){var r=o&&o.SlideShow;!r||!i.opts.slideShow||80!==s&&32!==s||e(t.activeElement).is("button,a,input")||(a.preventDefault(),r.toggle())},"beforeClose.fb onDeactivate.fb":function(t,e){var n=e&&e.SlideShow;n&&n.stop()}}),e(t).on("visibilitychange",function(){var n=e.fancybox.getInstance(),o=n&&n.SlideShow;o&&o.isActive&&(t.hidden?o.clear():o.set())})}(document,window.jQuery||jQuery),function(t,e){"use strict";var n=function(){var e,n,o,i=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],a={};for(n=0;n<i.length;n++)if(e=i[n],e&&e[1]in t){for(o=0;o<e.length;o++)a[i[0][o]]=e[o];return a}return!1}();if(!n)return void(e&&e.fancybox&&(e.fancybox.defaults.btnTpl.fullScreen=!1));var o={request:function(e){e=e||t.documentElement,e[n.requestFullscreen](e.ALLOW_KEYBOARD_INPUT)},exit:function(){t[n.exitFullscreen]()},toggle:function(e){e=e||t.documentElement,this.isFullscreen()?this.exit():this.request(e)},isFullscreen:function(){return Boolean(t[n.fullscreenElement])},enabled:function(){return Boolean(t[n.fullscreenEnabled])}};e.extend(!0,e.fancybox.defaults,{btnTpl:{fullScreen:'<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}"><svg viewBox="0 0 40 40"><path d="M9,12 h22 v16 h-22 v-16 v16 h22 v-16 Z" /></svg></button>'},fullScreen:{autoStart:!1}}),e(t).on({"onInit.fb":function(t,e){var n;e&&e.group[e.currIndex].opts.fullScreen?(n=e.$refs.container,n.on("click.fb-fullscreen","[data-fancybox-fullscreen]",function(t){t.stopPropagation(),t.preventDefault(),o.toggle(n[0])}),e.opts.fullScreen&&e.opts.fullScreen.autoStart===!0&&o.request(n[0]),e.FullScreen=o):e&&e.$refs.toolbar.find("[data-fancybox-fullscreen]").hide()},"afterKeydown.fb":function(t,e,n,o,i){e&&e.FullScreen&&70===i&&(o.preventDefault(),e.FullScreen.toggle(e.$refs.container[0]))},"beforeClose.fb":function(t){t&&t.FullScreen&&o.exit()}}),e(t).on(n.fullscreenchange,function(){var t=o.isFullscreen(),n=e.fancybox.getInstance();n&&(n.current&&"image"===n.current.type&&n.isAnimating&&(n.current.$content.css("transition","none"),n.isAnimating=!1,n.update(!0,!0,0)),n.trigger("onFullscreenChange",t),n.$refs.container.toggleClass("fancybox-is-fullscreen",t))})}(document,window.jQuery||jQuery),function(t,e){"use strict";e.fancybox.defaults=e.extend(!0,{btnTpl:{thumbs:'<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"><svg viewBox="0 0 120 120"><path d="M30,30 h14 v14 h-14 Z M50,30 h14 v14 h-14 Z M70,30 h14 v14 h-14 Z M30,50 h14 v14 h-14 Z M50,50 h14 v14 h-14 Z M70,50 h14 v14 h-14 Z M30,70 h14 v14 h-14 Z M50,70 h14 v14 h-14 Z M70,70 h14 v14 h-14 Z" /></svg></button>'},thumbs:{autoStart:!1,hideOnClose:!0,parentEl:".fancybox-container",axis:"y"}},e.fancybox.defaults);var n=function(t){this.init(t)};e.extend(n.prototype,{$button:null,$grid:null,$list:null,isVisible:!1,isActive:!1,init:function(t){var e=this;e.instance=t,t.Thumbs=e;var n=t.group[0],o=t.group[1];e.opts=t.group[t.currIndex].opts.thumbs,e.$button=t.$refs.toolbar.find("[data-fancybox-thumbs]"),e.opts&&n&&o&&("image"==n.type||n.opts.thumb||n.opts.$thumb)&&("image"==o.type||o.opts.thumb||o.opts.$thumb)?(e.$button.show().on("click",function(){e.toggle()}),e.isActive=!0):e.$button.hide()},create:function(){var t,n,o=this,i=o.instance,a=o.opts.parentEl;o.$grid=e('<div class="fancybox-thumbs fancybox-thumbs-'+o.opts.axis+'"></div>').appendTo(i.$refs.container.find(a).addBack().filter(a)),t="<ul>",e.each(i.group,function(e,o){n=o.opts.thumb||(o.opts.$thumb?o.opts.$thumb.attr("src"):null),n||"image"!==o.type||(n=o.src),n&&n.length&&(t+='<li data-index="'+e+'" tabindex="0" class="fancybox-thumbs-loading"><img data-src="'+n+'" /></li>')}),t+="</ul>",o.$list=e(t).appendTo(o.$grid).on("click","li",function(){i.jumpTo(e(this).data("index"))}),o.$list.find("img").hide().one("load",function(){var t,n,o,i,a=e(this).parent().removeClass("fancybox-thumbs-loading"),s=a.outerWidth(),r=a.outerHeight();t=this.naturalWidth||this.width,n=this.naturalHeight||this.height,o=t/s,i=n/r,o>=1&&i>=1&&(o>i?(t/=i,n=r):(t=s,n/=o)),e(this).css({width:Math.floor(t),height:Math.floor(n),"margin-top":n>r?Math.floor(.3*r-.3*n):Math.floor(.5*r-.5*n),"margin-left":Math.floor(.5*s-.5*t)}).show()}).each(function(){this.src=e(this).data("src")}),"x"===o.opts.axis&&o.$list.width(parseInt(o.$grid.css("padding-right"))+i.group.length*o.$list.children().eq(0).outerWidth(!0)+"px")},focus:function(t){var e,n,o=this,i=o.$list;o.instance.current&&(e=i.children().removeClass("fancybox-thumbs-active").filter('[data-index="'+o.instance.current.index+'"]').addClass("fancybox-thumbs-active"),n=e.position(),"y"===o.opts.axis&&(n.top<0||n.top>i.height()-e.outerHeight())?i.stop().animate({scrollTop:i.scrollTop()+n.top},t):"x"===o.opts.axis&&(n.left<i.parent().scrollLeft()||n.left>i.parent().scrollLeft()+(i.parent().width()-e.outerWidth()))&&i.parent().stop().animate({scrollLeft:n.left},t))},update:function(){this.instance.$refs.container.toggleClass("fancybox-show-thumbs",this.isVisible),this.isVisible?(this.$grid||this.create(),this.instance.trigger("onThumbsShow"),this.focus(0)):this.$grid&&this.instance.trigger("onThumbsHide"),this.instance.update()},hide:function(){this.isVisible=!1,this.update()},show:function(){this.isVisible=!0,this.update()},toggle:function(){this.isVisible=!this.isVisible,this.update()}}),e(t).on({"onInit.fb":function(t,e){var o;e&&!e.Thumbs&&(o=new n(e),o.isActive&&o.opts.autoStart===!0&&o.show())},"beforeShow.fb":function(t,e,n,o){var i=e&&e.Thumbs;i&&i.isVisible&&i.focus(o?0:250)},"afterKeydown.fb":function(t,e,n,o,i){var a=e&&e.Thumbs;a&&a.isActive&&71===i&&(o.preventDefault(),a.toggle())},"beforeClose.fb":function(t,e){var n=e&&e.Thumbs;n&&n.isVisible&&n.opts.hideOnClose!==!1&&n.$grid.hide()}})}(document,window.jQuery),function(t,e){"use strict";function n(t){var e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};return String(t).replace(/[&<>"'`=\/]/g,function(t){return e[t]})}e.extend(!0,e.fancybox.defaults,{btnTpl:{share:'<button data-fancybox-share class="fancybox-button fancybox-button--share" title="{{SHARE}}"><svg viewBox="0 0 40 40"><path d="M6,30 C8,18 19,16 23,16 L23,16 L23,10 L33,20 L23,29 L23,24 C19,24 8,27 6,30 Z"></svg></button>'},share:{tpl:'<div class="fancybox-share"><h1>{{SHARE}}</h1><p class="fancybox-share__links"><a class="fancybox-share__button fancybox-share__button--fb" href="https://www.facebook.com/sharer/sharer.php?u={{url}}"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m287 456v-299c0-21 6-35 35-35h38v-63c-7-1-29-3-55-3-54 0-91 33-91 94v306m143-254h-205v72h196" /></svg><span>Facebook</span></a><a class="fancybox-share__button fancybox-share__button--pt" href="https://www.pinterest.com/pin/create/button/?url={{url}}&description={{descr}}&media={{media}}"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m265 56c-109 0-164 78-164 144 0 39 15 74 47 87 5 2 10 0 12-5l4-19c2-6 1-8-3-13-9-11-15-25-15-45 0-58 43-110 113-110 62 0 96 38 96 88 0 67-30 122-73 122-24 0-42-19-36-44 6-29 20-60 20-81 0-19-10-35-31-35-25 0-44 26-44 60 0 21 7 36 7 36l-30 125c-8 37-1 83 0 87 0 3 4 4 5 2 2-3 32-39 42-75l16-64c8 16 31 29 56 29 74 0 124-67 124-157 0-69-58-132-146-132z" fill="#fff"/></svg><span>Pinterest</span></a><a class="fancybox-share__button fancybox-share__button--tw" href="https://twitter.com/intent/tweet?url={{url}}&text={{descr}}"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m456 133c-14 7-31 11-47 13 17-10 30-27 37-46-15 10-34 16-52 20-61-62-157-7-141 75-68-3-129-35-169-85-22 37-11 86 26 109-13 0-26-4-37-9 0 39 28 72 65 80-12 3-25 4-37 2 10 33 41 57 77 57-42 30-77 38-122 34 170 111 378-32 359-208 16-11 30-25 41-42z" /></svg><span>Twitter</span></a></p><p><input class="fancybox-share__input" type="text" value="{{url_raw}}" /></p></div>'}}),e(t).on("click","[data-fancybox-share]",function(){var t,o,i=e.fancybox.getInstance();i&&(t=i.current.opts.hash===!1?i.current.src:window.location,o=i.current.opts.share.tpl.replace(/\{\{media\}\}/g,"image"===i.current.type?encodeURIComponent(i.current.src):"").replace(/\{\{url\}\}/g,encodeURIComponent(t)).replace(/\{\{url_raw\}\}/g,n(t)).replace(/\{\{descr\}\}/g,i.$caption?encodeURIComponent(i.$caption.text()):""),e.fancybox.open({src:i.translate(i,o),type:"html",opts:{animationEffect:"fade",animationDuration:250,afterLoad:function(t,e){e.$content.find(".fancybox-share__links a").click(function(){return window.open(this.href,"Share","width=550, height=450"),!1})}}}))})}(document,window.jQuery||jQuery),function(t,e,n){"use strict";function o(){var t=e.location.hash.substr(1),n=t.split("-"),o=n.length>1&&/^\+?\d+$/.test(n[n.length-1])?parseInt(n.pop(-1),10)||1:1,i=n.join("-");return o<1&&(o=1),{hash:t,index:o,gallery:i}}function i(t){var e;""!==t.gallery&&(e=n("[data-fancybox='"+n.escapeSelector(t.gallery)+"']").eq(t.index-1),e.length||(e=n("#"+n.escapeSelector(t.gallery))),e.length&&(s=!1,e.trigger("click")))}function a(t){var e;return!!t&&(e=t.current?t.current.opts:t.opts,e.hash||(e.$orig?e.$orig.data("fancybox"):""))}n.escapeSelector||(n.escapeSelector=function(t){var e=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,n=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t};return(t+"").replace(e,n)});var s=!0,r=null,c=null;n(function(){n.fancybox.defaults.hash!==!1&&(n(t).on({"onInit.fb":function(t,e){var n,i;e.group[e.currIndex].opts.hash!==!1&&(n=o(),i=a(e),i&&n.gallery&&i==n.gallery&&(e.currIndex=n.index-1))},"beforeShow.fb":function(n,o,i){var l;i&&i.opts.hash!==!1&&(l=a(o),l&&""!==l&&(e.location.hash.indexOf(l)<0&&(o.opts.origHash=e.location.hash),r=l+(o.group.length>1?"-"+(i.index+1):""),"replaceState"in e.history?(c&&clearTimeout(c),c=setTimeout(function(){e.history[s?"pushState":"replaceState"]({},t.title,e.location.pathname+e.location.search+"#"+r),c=null,s=!1},300)):e.location.hash=r))},"beforeClose.fb":function(o,i,s){var l,u;c&&clearTimeout(c),s.opts.hash!==!1&&(l=a(i),u=i&&i.opts.origHash?i.opts.origHash:"",l&&""!==l&&("replaceState"in history?e.history.replaceState({},t.title,e.location.pathname+e.location.search+u):(e.location.hash=u,n(e).scrollTop(i.scrollTop).scrollLeft(i.scrollLeft))),r=null)}}),n(e).on("hashchange.fb",function(){var t=o();n.fancybox.getInstance()?!r||r===t.gallery+"-"+t.index||1===t.index&&r==t.gallery||(r=null,n.fancybox.close()):""!==t.gallery&&i(t)}),setTimeout(function(){i(o())},50))})}(document,window,window.jQuery||jQuery),function(t,e){"use strict";var n=(new Date).getTime();e(t).on({"onInit.fb":function(t,e,o){e.$refs.stage.on("mousewheel DOMMouseScroll wheel MozMousePixelScroll",function(t){var o=e.current,i=(new Date).getTime();e.group.length<1||o.opts.wheel===!1||"auto"===o.opts.wheel&&"image"!==o.type||(t.preventDefault(),t.stopPropagation(),o.$slide.hasClass("fancybox-animated")||(t=t.originalEvent||t,i-n<250||(n=i,e[(-t.deltaY||-t.deltaX||t.wheelDelta||-t.detail)<0?"next":"previous"]())))})}})}(document,window.jQuery||jQuery);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/js/jquery.steps.min.js
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
/*!
|
2 |
-
* jQuery Steps v1.1.0 - 09/04/2014
|
3 |
-
* Copyright (c) 2014 Rafael Staib (http://www.jquery-steps.com)
|
4 |
-
* Licensed under MIT http://www.opensource.org/licenses/MIT
|
5 |
-
*/
|
6 |
-
!function(a,b){function c(a,b){o(a).push(b)}function d(d,e,f){var g=d.children(e.headerTag),h=d.children(e.bodyTag);g.length>h.length?R(Z,"contents"):g.length<h.length&&R(Z,"titles");var i=e.startIndex;if(f.stepCount=g.length,e.saveState&&a.cookie){var j=a.cookie(U+q(d)),k=parseInt(j,0);!isNaN(k)&&k<f.stepCount&&(i=k)}f.currentIndex=i,g.each(function(e){var f=a(this),g=h.eq(e),i=g.data("mode"),j=null==i?$.html:r($,/^\s*$/.test(i)||isNaN(i)?i:parseInt(i,0)),k=j===$.html||g.data("url")===b?"":g.data("url"),l=j!==$.html&&"1"===g.data("loaded"),m=a.extend({},bb,{title:f.html(),content:j===$.html?g.html():"",contentUrl:k,contentMode:j,contentLoaded:l});c(d,m)})}function e(a){a.triggerHandler("canceled")}function f(a,b){return a.currentIndex-b}function g(b,c){var d=i(b);b.unbind(d).removeData("uid").removeData("options").removeData("state").removeData("steps").removeData("eventNamespace").find(".actions a").unbind(d),b.removeClass(c.clearFixCssClass+" vertical");var e=b.find(".content > *");e.removeData("loaded").removeData("mode").removeData("url"),e.removeAttr("id").removeAttr("role").removeAttr("tabindex").removeAttr("class").removeAttr("style")._removeAria("labelledby")._removeAria("hidden"),b.find(".content > [data-mode='async'],.content > [data-mode='iframe']").empty();var f=a('<{0} class="{1}"></{0}>'.format(b.get(0).tagName,b.attr("class"))),g=b._id();return null!=g&&""!==g&&f._id(g),f.html(b.find(".content").html()),b.after(f),b.remove(),f}function h(a,b){var c=a.find(".steps li").eq(b.currentIndex);a.triggerHandler("finishing",[b.currentIndex])?(c.addClass("done").removeClass("error"),a.triggerHandler("finished",[b.currentIndex])):c.addClass("error")}function i(a){var b=a.data("eventNamespace");return null==b&&(b="."+q(a),a.data("eventNamespace",b)),b}function j(a,b){var c=q(a);return a.find("#"+c+V+b)}function k(a,b){var c=q(a);return a.find("#"+c+W+b)}function l(a,b){var c=q(a);return a.find("#"+c+X+b)}function m(a){return a.data("options")}function n(a){return a.data("state")}function o(a){return a.data("steps")}function p(a,b){var c=o(a);return(0>b||b>=c.length)&&R(Y),c[b]}function q(a){var b=a.data("uid");return null==b&&(b=a._id(),null==b&&(b="steps-uid-".concat(T),a._id(b)),T++,a.data("uid",b)),b}function r(a,c){if(S("enumType",a),S("keyOrValue",c),"string"==typeof c){var d=a[c];return d===b&&R("The enum key '{0}' does not exist.",c),d}if("number"==typeof c){for(var e in a)if(a[e]===c)return c;R("Invalid enum value '{0}'.",c)}else R("Invalid key or value type.")}function s(a,b,c){return B(a,b,c,v(c,1))}function t(a,b,c){return B(a,b,c,f(c,1))}function u(a,b,c,d){if((0>d||d>=c.stepCount)&&R(Y),!(b.forceMoveForward&&d<c.currentIndex)){var e=c.currentIndex;return a.triggerHandler("stepChanging",[c.currentIndex,d])?(c.currentIndex=d,O(a,b,c),E(a,b,c,e),D(a,b,c),A(a,b,c),P(a,b,c,d,e,function(){a.triggerHandler("stepChanged",[d,e])})):a.find(".steps li").eq(e).addClass("error"),!0}}function v(a,b){return a.currentIndex+b}function w(b){var c=a.extend(!0,{},cb,b);return this.each(function(){var b=a(this),e={currentIndex:c.startIndex,currentStep:null,stepCount:0,transitionElement:null};b.data("options",c),b.data("state",e),b.data("steps",[]),d(b,c,e),J(b,c,e),G(b,c),c.autoFocus&&0===T&&j(b,c.startIndex).focus(),b.triggerHandler("init",[c.startIndex])})}function x(b,c,d,e,f){(0>e||e>d.stepCount)&&R(Y),f=a.extend({},bb,f),y(b,e,f),d.currentIndex!==d.stepCount&&d.currentIndex>=e&&(d.currentIndex++,O(b,c,d)),d.stepCount++;var g=b.find(".content"),h=a("<{0}>{1}</{0}>".format(c.headerTag,f.title)),i=a("<{0}></{0}>".format(c.bodyTag));return(null==f.contentMode||f.contentMode===$.html)&&i.html(f.content),0===e?g.prepend(i).prepend(h):k(b,e-1).after(i).after(h),K(b,d,i,e),N(b,c,d,h,e),F(b,c,d,e),e===d.currentIndex&&E(b,c,d),D(b,c,d),b}function y(a,b,c){o(a).splice(b,0,c)}function z(b){var c=a(this),d=m(c),e=n(c);if(d.suppressPaginationOnFocus&&c.find(":focus").is(":input"))return b.preventDefault(),!1;var f={left:37,right:39};b.keyCode===f.left?(b.preventDefault(),t(c,d,e)):b.keyCode===f.right&&(b.preventDefault(),s(c,d,e))}function A(b,c,d){if(d.stepCount>0){var e=d.currentIndex,f=p(b,e);if(!c.enableContentCache||!f.contentLoaded)switch(r($,f.contentMode)){case $.iframe:b.find(".content > .body").eq(d.currentIndex).empty().html('<iframe src="'+f.contentUrl+'" frameborder="0" scrolling="no" />').data("loaded","1");break;case $.async:var g=k(b,e)._aria("busy","true").empty().append(M(c.loadingTemplate,{text:c.labels.loading}));a.ajax({url:f.contentUrl,cache:!1}).done(function(a){g.empty().html(a)._aria("busy","false").data("loaded","1"),b.triggerHandler("contentLoaded",[e])})}}}function B(a,b,c,d){var e=c.currentIndex;if(d>=0&&d<c.stepCount&&!(b.forceMoveForward&&d<c.currentIndex)){var f=j(a,d),g=f.parent(),h=g.hasClass("disabled");return g._enableAria(),f.click(),e===c.currentIndex&&h?(g._enableAria(!1),!1):!0}return!1}function C(b){b.preventDefault();var c=a(this),d=c.parent().parent().parent().parent(),f=m(d),g=n(d),i=c.attr("href");switch(i.substring(i.lastIndexOf("#")+1)){case"cancel":e(d);break;case"finish":h(d,g);break;case"next":s(d,f,g);break;case"previous":t(d,f,g)}}function D(a,b,c){if(b.enablePagination){var d=a.find(".actions a[href$='#finish']").parent(),e=a.find(".actions a[href$='#next']").parent();if(!b.forceMoveForward){var f=a.find(".actions a[href$='#previous']").parent();f._enableAria(c.currentIndex>0)}b.enableFinishButton&&b.showFinishButtonAlways?(d._enableAria(c.stepCount>0),e._enableAria(c.stepCount>1&&c.stepCount>c.currentIndex+1)):(d._showAria(b.enableFinishButton&&c.stepCount===c.currentIndex+1),e._showAria(0===c.stepCount||c.stepCount>c.currentIndex+1)._enableAria(c.stepCount>c.currentIndex+1||!b.enableFinishButton))}}function E(b,c,d,e){var f=j(b,d.currentIndex),g=a('<span class="current-info audible">'+c.labels.current+" </span>"),h=b.find(".content > .title");if(null!=e){var i=j(b,e);i.parent().addClass("done").removeClass("error")._selectAria(!1),h.eq(e).removeClass("current").next(".body").removeClass("current"),g=i.find(".current-info"),f.focus()}f.prepend(g).parent()._selectAria().removeClass("done")._enableAria(),h.eq(d.currentIndex).addClass("current").next(".body").addClass("current")}function F(a,b,c,d){for(var e=q(a),f=d;f<c.stepCount;f++){var g=e+V+f,h=e+W+f,i=e+X+f,j=a.find(".title").eq(f)._id(i);a.find(".steps a").eq(f)._id(g)._aria("controls",h).attr("href","#"+i).html(M(b.titleTemplate,{index:f+1,title:j.html()})),a.find(".body").eq(f)._id(h)._aria("labelledby",i)}}function G(a,b){var c=i(a);a.bind("canceled"+c,b.onCanceled),a.bind("contentLoaded"+c,b.onContentLoaded),a.bind("finishing"+c,b.onFinishing),a.bind("finished"+c,b.onFinished),a.bind("init"+c,b.onInit),a.bind("stepChanging"+c,b.onStepChanging),a.bind("stepChanged"+c,b.onStepChanged),b.enableKeyNavigation&&a.bind("keyup"+c,z),a.find(".actions a").bind("click"+c,C)}function H(a,b,c,d){return 0>d||d>=c.stepCount||c.currentIndex===d?!1:(I(a,d),c.currentIndex>d&&(c.currentIndex--,O(a,b,c)),c.stepCount--,l(a,d).remove(),k(a,d).remove(),j(a,d).parent().remove(),0===d&&a.find(".steps li").first().addClass("first"),d===c.stepCount&&a.find(".steps li").eq(d).addClass("last"),F(a,b,c,d),D(a,b,c),!0)}function I(a,b){o(a).splice(b,1)}function J(b,c,d){var e='<{0} class="{1}">{2}</{0}>',f=r(_,c.stepsOrientation),g=f===_.vertical?" vertical":"",h=a(e.format(c.contentContainerTag,"content "+c.clearFixCssClass,b.html())),i=a(e.format(c.stepsContainerTag,"steps "+c.clearFixCssClass,'<ul role="tablist"></ul>')),j=h.children(c.headerTag),k=h.children(c.bodyTag);b.attr("role","application").empty().append(i).append(h).addClass(c.cssClass+" "+c.clearFixCssClass+g),k.each(function(c){K(b,d,a(this),c)}),j.each(function(e){N(b,c,d,a(this),e)}),E(b,c,d),L(b,c,d)}function K(a,b,c,d){var e=q(a),f=e+W+d,g=e+X+d;c._id(f).attr("role","tabpanel")._aria("labelledby",g).addClass("body")._showAria(b.currentIndex===d)}function L(a,b,c){if(b.enablePagination){var d='<{0} class="actions {1}"><ul role="menu" aria-label="{2}">{3}</ul></{0}>',e='<li><a href="#{0}" role="menuitem">{1}</a></li>',f="";b.forceMoveForward||(f+=e.format("previous",b.labels.previous)),f+=e.format("next",b.labels.next),b.enableFinishButton&&(f+=e.format("finish",b.labels.finish)),b.enableCancelButton&&(f+=e.format("cancel",b.labels.cancel)),a.append(d.format(b.actionContainerTag,b.clearFixCssClass,b.labels.pagination,f)),D(a,b,c),A(a,b,c)}}function M(a,c){for(var d=a.match(/#([a-z]*)#/gi),e=0;e<d.length;e++){var f=d[e],g=f.substring(1,f.length-1);c[g]===b&&R("The key '{0}' does not exist in the substitute collection!",g),a=a.replace(f,c[g])}return a}function N(b,c,d,e,f){var g=q(b),h=g+V+f,j=g+W+f,k=g+X+f,l=b.find(".steps > ul"),m=M(c.titleTemplate,{index:f+1,title:e.html()}),n=a('<li role="tab"><a id="'+h+'" href="#'+k+'" aria-controls="'+j+'">'+m+"</a></li>");n._enableAria(c.enableAllSteps||d.currentIndex>f),d.currentIndex>f&&n.addClass("done"),e._id(k).attr("tabindex","-1").addClass("title"),0===f?l.prepend(n):l.find("li").eq(f-1).after(n),0===f&&l.find("li").removeClass("first").eq(f).addClass("first"),f===d.stepCount-1&&l.find("li").removeClass("last").eq(f).addClass("last"),n.children("a").bind("click"+i(b),Q)}function O(b,c,d){c.saveState&&a.cookie&&a.cookie(U+q(b),d.currentIndex)}function P(b,c,d,e,f,g){var h=b.find(".content > .body"),i=r(ab,c.transitionEffect),j=c.transitionEffectSpeed,k=h.eq(e),l=h.eq(f);switch(i){case ab.fade:case ab.slide:var m=i===ab.fade?"fadeOut":"slideUp",o=i===ab.fade?"fadeIn":"slideDown";d.transitionElement=k,l[m](j,function(){var b=a(this)._showAria(!1).parent().parent(),c=n(b);c.transitionElement&&(c.transitionElement[o](j,function(){a(this)._showAria()}).promise().done(g),c.transitionElement=null)});break;case ab.slideLeft:var p=l.outerWidth(!0),q=e>f?-p:p,s=e>f?p:-p;a.when(l.animate({left:q},j,function(){a(this)._showAria(!1)}),k.css("left",s+"px")._showAria().animate({left:0},j)).done(g);break;default:a.when(l._showAria(!1),k._showAria()).done(g)}}function Q(b){b.preventDefault();var c=a(this),d=c.parent().parent().parent().parent(),e=m(d),f=n(d),g=f.currentIndex;if(c.parent().is(":not(.disabled):not(.current)")){var h=c.attr("href"),i=parseInt(h.substring(h.lastIndexOf("-")+1),0);u(d,e,f,i)}return g===f.currentIndex?(j(d,g).focus(),!1):void 0}function R(a){throw arguments.length>1&&(a=a.format(Array.prototype.slice.call(arguments,1))),new Error(a)}function S(a,b){null==b&&R("The argument '{0}' is null or undefined.",a)}a.fn.extend({_aria:function(a,b){return this.attr("aria-"+a,b)},_removeAria:function(a){return this.removeAttr("aria-"+a)},_enableAria:function(a){return null==a||a?this.removeClass("disabled")._aria("disabled","false"):this.addClass("disabled")._aria("disabled","true")},_showAria:function(a){return null==a||a?this.show()._aria("hidden","false"):this.hide()._aria("hidden","true")},_selectAria:function(a){return null==a||a?this.addClass("current")._aria("selected","true"):this.removeClass("current")._aria("selected","false")},_id:function(a){return a?this.attr("id",a):this.attr("id")}}),String.prototype.format||(String.prototype.format=function(){for(var b=1===arguments.length&&a.isArray(arguments[0])?arguments[0]:arguments,c=this,d=0;d<b.length;d++){var e=new RegExp("\\{"+d+"\\}","gm");c=c.replace(e,b[d])}return c});var T=0,U="jQu3ry_5teps_St@te_",V="-t-",W="-p-",X="-h-",Y="Index out of range.",Z="One or more corresponding step {0} are missing.";a.fn.steps=function(b){return a.fn.steps[b]?a.fn.steps[b].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof b&&b?void a.error("Method "+b+" does not exist on jQuery.steps"):w.apply(this,arguments)},a.fn.steps.add=function(a){var b=n(this);return x(this,m(this),b,b.stepCount,a)},a.fn.steps.destroy=function(){return g(this,m(this))},a.fn.steps.finish=function(){h(this,n(this))},a.fn.steps.getCurrentIndex=function(){return n(this).currentIndex},a.fn.steps.getCurrentStep=function(){return p(this,n(this).currentIndex)},a.fn.steps.getStep=function(a){return p(this,a)},a.fn.steps.insert=function(a,b){return x(this,m(this),n(this),a,b)},a.fn.steps.next=function(){return s(this,m(this),n(this))},a.fn.steps.previous=function(){return t(this,m(this),n(this))},a.fn.steps.remove=function(a){return H(this,m(this),n(this),a)},a.fn.steps.setStep=function(){throw new Error("Not yet implemented!")},a.fn.steps.skip=function(){throw new Error("Not yet implemented!")};var $=a.fn.steps.contentMode={html:0,iframe:1,async:2},_=a.fn.steps.stepsOrientation={horizontal:0,vertical:1},ab=a.fn.steps.transitionEffect={none:0,fade:1,slide:2,slideLeft:3},bb=a.fn.steps.stepModel={title:"",content:"",contentUrl:"",contentMode:$.html,contentLoaded:!1},cb=a.fn.steps.defaults={headerTag:"h1",bodyTag:"div",contentContainerTag:"div",actionContainerTag:"div",stepsContainerTag:"div",cssClass:"wizard",clearFixCssClass:"clearfix",stepsOrientation:_.horizontal,titleTemplate:'<span class="number">#index#.</span> #title#',loadingTemplate:'<span class="spinner"></span> #text#',autoFocus:!1,enableAllSteps:!1,enableKeyNavigation:!0,enablePagination:!0,suppressPaginationOnFocus:!0,enableContentCache:!0,enableCancelButton:!1,enableFinishButton:!0,preloadContent:!1,showFinishButtonAlways:!1,forceMoveForward:!1,saveState:!1,startIndex:0,transitionEffect:ab.none,transitionEffectSpeed:200,onStepChanging:function(){return!0},onStepChanged:function(){},onCanceled:function(){},onFinishing:function(){return!0},onFinished:function(){},onContentLoaded:function(){},onInit:function(){},labels:{cancel:"Cancel",current:"current step:",pagination:"Pagination",finish:"Finish",next:"Next",previous:"Previous",loading:"Loading ..."}}}(jQuery);
|
|
|
|
|
|
|
|
|
|
|
|
resources/js/jquery/fancybox.min.js
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// ==================================================
|
2 |
+
// fancyBox v3.5.7
|
3 |
+
//
|
4 |
+
// Licensed GPLv3 for open source use
|
5 |
+
// or fancyBox Commercial License for commercial use
|
6 |
+
//
|
7 |
+
// http://fancyapps.com/fancybox/
|
8 |
+
// Copyright 2019 fancyApps
|
9 |
+
//
|
10 |
+
// ==================================================
|
11 |
+
!function(t,e,n,o){"use strict";function i(t,e){var o,i,a,s=[],r=0;t&&t.isDefaultPrevented()||(t.preventDefault(),e=e||{},t&&t.data&&(e=h(t.data.options,e)),o=e.$target||n(t.currentTarget).trigger("blur"),(a=n.fancybox.getInstance())&&a.$trigger&&a.$trigger.is(o)||(e.selector?s=n(e.selector):(i=o.attr("data-fancybox")||"",i?(s=t.data?t.data.items:[],s=s.length?s.filter('[data-fancybox="'+i+'"]'):n('[data-fancybox="'+i+'"]')):s=[o]),r=n(s).index(o),r<0&&(r=0),a=n.fancybox.open(s,e,r),a.$trigger=o))}if(t.console=t.console||{info:function(t){}},n){if(n.fn.fancybox)return void console.info("fancyBox already initialized");var a={closeExisting:!1,loop:!1,gutter:50,keyboard:!0,preventCaptionOverlap:!0,arrows:!0,infobar:!0,smallBtn:"auto",toolbar:"auto",buttons:["zoom","slideShow","thumbs","close"],idleTime:3,protect:!1,modal:!1,image:{preload:!1},ajax:{settings:{data:{fancybox:!0}}},iframe:{tpl:'<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" allowfullscreen="allowfullscreen" allow="autoplay; fullscreen" src=""></iframe>',preload:!0,css:{},attr:{scrolling:"auto"}},video:{tpl:'<video class="fancybox-video" controls controlsList="nodownload" poster="{{poster}}"><source src="{{src}}" type="{{format}}" />Sorry, your browser doesn\'t support embedded videos, <a href="{{src}}">download</a> and watch with your favorite video player!</video>',format:"",autoStart:!0},defaultType:"image",animationEffect:"zoom",animationDuration:366,zoomOpacity:"auto",transitionEffect:"fade",transitionDuration:366,slideClass:"",baseClass:"",baseTpl:'<div class="fancybox-container" role="dialog" tabindex="-1"><div class="fancybox-bg"></div><div class="fancybox-inner"><div class="fancybox-infobar"><span data-fancybox-index></span> / <span data-fancybox-count></span></div><div class="fancybox-toolbar">{{buttons}}</div><div class="fancybox-navigation">{{arrows}}</div><div class="fancybox-stage"></div><div class="fancybox-caption"><div class="fancybox-caption__body"></div></div></div></div>',spinnerTpl:'<div class="fancybox-loading"></div>',errorTpl:'<div class="fancybox-error"><p>{{ERROR}}</p></div>',btnTpl:{download:'<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}" href="javascript:;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.62 17.09V19H5.38v-1.91zm-2.97-6.96L17 11.45l-5 4.87-5-4.87 1.36-1.32 2.68 2.64V5h1.92v7.77z"/></svg></a>',zoom:'<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.7 17.3l-3-3a5.9 5.9 0 0 0-.6-7.6 5.9 5.9 0 0 0-8.4 0 5.9 5.9 0 0 0 0 8.4 5.9 5.9 0 0 0 7.7.7l3 3a1 1 0 0 0 1.3 0c.4-.5.4-1 0-1.5zM8.1 13.8a4 4 0 0 1 0-5.7 4 4 0 0 1 5.7 0 4 4 0 0 1 0 5.7 4 4 0 0 1-5.7 0z"/></svg></button>',close:'<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 10.6L6.6 5.2 5.2 6.6l5.4 5.4-5.4 5.4 1.4 1.4 5.4-5.4 5.4 5.4 1.4-1.4-5.4-5.4 5.4-5.4-1.4-1.4-5.4 5.4z"/></svg></button>',arrowLeft:'<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}"><div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.28 15.7l-1.34 1.37L5 12l4.94-5.07 1.34 1.38-2.68 2.72H19v1.94H8.6z"/></svg></div></button>',arrowRight:'<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}"><div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.4 12.97l-2.68 2.72 1.34 1.38L19 12l-4.94-5.07-1.34 1.38 2.68 2.72H5v1.94z"/></svg></div></button>',smallBtn:'<button type="button" data-fancybox-close class="fancybox-button fancybox-close-small" title="{{CLOSE}}"><svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 24 24"><path d="M13 12l5-5-1-1-5 5-5-5-1 1 5 5-5 5 1 1 5-5 5 5 1-1z"/></svg></button>'},parentEl:"body",hideScrollbar:!0,autoFocus:!0,backFocus:!0,trapFocus:!0,fullScreen:{autoStart:!1},touch:{vertical:!0,momentum:!0},hash:null,media:{},slideShow:{autoStart:!1,speed:3e3},thumbs:{autoStart:!1,hideOnClose:!0,parentEl:".fancybox-container",axis:"y"},wheel:"auto",onInit:n.noop,beforeLoad:n.noop,afterLoad:n.noop,beforeShow:n.noop,afterShow:n.noop,beforeClose:n.noop,afterClose:n.noop,onActivate:n.noop,onDeactivate:n.noop,clickContent:function(t,e){return"image"===t.type&&"zoom"},clickSlide:"close",clickOutside:"close",dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1,mobile:{preventCaptionOverlap:!1,idleTime:!1,clickContent:function(t,e){return"image"===t.type&&"toggleControls"},clickSlide:function(t,e){return"image"===t.type?"toggleControls":"close"},dblclickContent:function(t,e){return"image"===t.type&&"zoom"},dblclickSlide:function(t,e){return"image"===t.type&&"zoom"}},lang:"en",i18n:{en:{CLOSE:"Close",NEXT:"Next",PREV:"Previous",ERROR:"The requested content cannot be loaded. <br/> Please try again later.",PLAY_START:"Start slideshow",PLAY_STOP:"Pause slideshow",FULL_SCREEN:"Full screen",THUMBS:"Thumbnails",DOWNLOAD:"Download",SHARE:"Share",ZOOM:"Zoom"},de:{CLOSE:"Schließen",NEXT:"Weiter",PREV:"Zurück",ERROR:"Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.",PLAY_START:"Diaschau starten",PLAY_STOP:"Diaschau beenden",FULL_SCREEN:"Vollbild",THUMBS:"Vorschaubilder",DOWNLOAD:"Herunterladen",SHARE:"Teilen",ZOOM:"Vergrößern"}}},s=n(t),r=n(e),c=0,l=function(t){return t&&t.hasOwnProperty&&t instanceof n},d=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),u=function(){return t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.mozCancelAnimationFrame||t.oCancelAnimationFrame||function(e){t.clearTimeout(e)}}(),f=function(){var t,n=e.createElement("fakeelement"),o={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in o)if(void 0!==n.style[t])return o[t];return"transitionend"}(),p=function(t){return t&&t.length&&t[0].offsetHeight},h=function(t,e){var o=n.extend(!0,{},t,e);return n.each(e,function(t,e){n.isArray(e)&&(o[t]=e)}),o},g=function(t){var o,i;return!(!t||t.ownerDocument!==e)&&(n(".fancybox-container").css("pointer-events","none"),o={x:t.getBoundingClientRect().left+t.offsetWidth/2,y:t.getBoundingClientRect().top+t.offsetHeight/2},i=e.elementFromPoint(o.x,o.y)===t,n(".fancybox-container").css("pointer-events",""),i)},b=function(t,e,o){var i=this;i.opts=h({index:o},n.fancybox.defaults),n.isPlainObject(e)&&(i.opts=h(i.opts,e)),n.fancybox.isMobile&&(i.opts=h(i.opts,i.opts.mobile)),i.id=i.opts.id||++c,i.currIndex=parseInt(i.opts.index,10)||0,i.prevIndex=null,i.prevPos=null,i.currPos=0,i.firstRun=!0,i.group=[],i.slides={},i.addContent(t),i.group.length&&i.init()};n.extend(b.prototype,{init:function(){var o,i,a=this,s=a.group[a.currIndex],r=s.opts;r.closeExisting&&n.fancybox.close(!0),n("body").addClass("fancybox-active"),!n.fancybox.getInstance()&&!1!==r.hideScrollbar&&!n.fancybox.isMobile&&e.body.scrollHeight>t.innerHeight&&(n("head").append('<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar{margin-right:'+(t.innerWidth-e.documentElement.clientWidth)+"px;}</style>"),n("body").addClass("compensate-for-scrollbar")),i="",n.each(r.buttons,function(t,e){i+=r.btnTpl[e]||""}),o=n(a.translate(a,r.baseTpl.replace("{{buttons}}",i).replace("{{arrows}}",r.btnTpl.arrowLeft+r.btnTpl.arrowRight))).attr("id","fancybox-container-"+a.id).addClass(r.baseClass).data("FancyBox",a).appendTo(r.parentEl),a.$refs={container:o},["bg","inner","infobar","toolbar","stage","caption","navigation"].forEach(function(t){a.$refs[t]=o.find(".fancybox-"+t)}),a.trigger("onInit"),a.activate(),a.jumpTo(a.currIndex)},translate:function(t,e){var n=t.opts.i18n[t.opts.lang]||t.opts.i18n.en;return e.replace(/\{\{(\w+)\}\}/g,function(t,e){return void 0===n[e]?t:n[e]})},addContent:function(t){var e,o=this,i=n.makeArray(t);n.each(i,function(t,e){var i,a,s,r,c,l={},d={};n.isPlainObject(e)?(l=e,d=e.opts||e):"object"===n.type(e)&&n(e).length?(i=n(e),d=i.data()||{},d=n.extend(!0,{},d,d.options),d.$orig=i,l.src=o.opts.src||d.src||i.attr("href"),l.type||l.src||(l.type="inline",l.src=e)):l={type:"html",src:e+""},l.opts=n.extend(!0,{},o.opts,d),n.isArray(d.buttons)&&(l.opts.buttons=d.buttons),n.fancybox.isMobile&&l.opts.mobile&&(l.opts=h(l.opts,l.opts.mobile)),a=l.type||l.opts.type,r=l.src||"",!a&&r&&((s=r.match(/\.(mp4|mov|ogv|webm)((\?|#).*)?$/i))?(a="video",l.opts.video.format||(l.opts.video.format="video/"+("ogv"===s[1]?"ogg":s[1]))):r.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)?a="image":r.match(/\.(pdf)((\?|#).*)?$/i)?(a="iframe",l=n.extend(!0,l,{contentType:"pdf",opts:{iframe:{preload:!1}}})):"#"===r.charAt(0)&&(a="inline")),a?l.type=a:o.trigger("objectNeedsType",l),l.contentType||(l.contentType=n.inArray(l.type,["html","inline","ajax"])>-1?"html":l.type),l.index=o.group.length,"auto"==l.opts.smallBtn&&(l.opts.smallBtn=n.inArray(l.type,["html","inline","ajax"])>-1),"auto"===l.opts.toolbar&&(l.opts.toolbar=!l.opts.smallBtn),l.$thumb=l.opts.$thumb||null,l.opts.$trigger&&l.index===o.opts.index&&(l.$thumb=l.opts.$trigger.find("img:first"),l.$thumb.length&&(l.opts.$orig=l.opts.$trigger)),l.$thumb&&l.$thumb.length||!l.opts.$orig||(l.$thumb=l.opts.$orig.find("img:first")),l.$thumb&&!l.$thumb.length&&(l.$thumb=null),l.thumb=l.opts.thumb||(l.$thumb?l.$thumb[0].src:null),"function"===n.type(l.opts.caption)&&(l.opts.caption=l.opts.caption.apply(e,[o,l])),"function"===n.type(o.opts.caption)&&(l.opts.caption=o.opts.caption.apply(e,[o,l])),l.opts.caption instanceof n||(l.opts.caption=void 0===l.opts.caption?"":l.opts.caption+""),"ajax"===l.type&&(c=r.split(/\s+/,2),c.length>1&&(l.src=c.shift(),l.opts.filter=c.shift())),l.opts.modal&&(l.opts=n.extend(!0,l.opts,{trapFocus:!0,infobar:0,toolbar:0,smallBtn:0,keyboard:0,slideShow:0,fullScreen:0,thumbs:0,touch:0,clickContent:!1,clickSlide:!1,clickOutside:!1,dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1})),o.group.push(l)}),Object.keys(o.slides).length&&(o.updateControls(),(e=o.Thumbs)&&e.isActive&&(e.create(),e.focus()))},addEvents:function(){var e=this;e.removeEvents(),e.$refs.container.on("click.fb-close","[data-fancybox-close]",function(t){t.stopPropagation(),t.preventDefault(),e.close(t)}).on("touchstart.fb-prev click.fb-prev","[data-fancybox-prev]",function(t){t.stopPropagation(),t.preventDefault(),e.previous()}).on("touchstart.fb-next click.fb-next","[data-fancybox-next]",function(t){t.stopPropagation(),t.preventDefault(),e.next()}).on("click.fb","[data-fancybox-zoom]",function(t){e[e.isScaledDown()?"scaleToActual":"scaleToFit"]()}),s.on("orientationchange.fb resize.fb",function(t){t&&t.originalEvent&&"resize"===t.originalEvent.type?(e.requestId&&u(e.requestId),e.requestId=d(function(){e.update(t)})):(e.current&&"iframe"===e.current.type&&e.$refs.stage.hide(),setTimeout(function(){e.$refs.stage.show(),e.update(t)},n.fancybox.isMobile?600:250))}),r.on("keydown.fb",function(t){var o=n.fancybox?n.fancybox.getInstance():null,i=o.current,a=t.keyCode||t.which;if(9==a)return void(i.opts.trapFocus&&e.focus(t));if(!(!i.opts.keyboard||t.ctrlKey||t.altKey||t.shiftKey||n(t.target).is("input,textarea,video,audio,select")))return 8===a||27===a?(t.preventDefault(),void e.close(t)):37===a||38===a?(t.preventDefault(),void e.previous()):39===a||40===a?(t.preventDefault(),void e.next()):void e.trigger("afterKeydown",t,a)}),e.group[e.currIndex].opts.idleTime&&(e.idleSecondsCounter=0,r.on("mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",function(t){e.idleSecondsCounter=0,e.isIdle&&e.showControls(),e.isIdle=!1}),e.idleInterval=t.setInterval(function(){++e.idleSecondsCounter>=e.group[e.currIndex].opts.idleTime&&!e.isDragging&&(e.isIdle=!0,e.idleSecondsCounter=0,e.hideControls())},1e3))},removeEvents:function(){var e=this;s.off("orientationchange.fb resize.fb"),r.off("keydown.fb .fb-idle"),this.$refs.container.off(".fb-close .fb-prev .fb-next"),e.idleInterval&&(t.clearInterval(e.idleInterval),e.idleInterval=null)},previous:function(t){return this.jumpTo(this.currPos-1,t)},next:function(t){return this.jumpTo(this.currPos+1,t)},jumpTo:function(t,e){var o,i,a,s,r,c,l,d,u,f=this,h=f.group.length;if(!(f.isDragging||f.isClosing||f.isAnimating&&f.firstRun)){if(t=parseInt(t,10),!(a=f.current?f.current.opts.loop:f.opts.loop)&&(t<0||t>=h))return!1;if(o=f.firstRun=!Object.keys(f.slides).length,r=f.current,f.prevIndex=f.currIndex,f.prevPos=f.currPos,s=f.createSlide(t),h>1&&((a||s.index<h-1)&&f.createSlide(t+1),(a||s.index>0)&&f.createSlide(t-1)),f.current=s,f.currIndex=s.index,f.currPos=s.pos,f.trigger("beforeShow",o),f.updateControls(),s.forcedDuration=void 0,n.isNumeric(e)?s.forcedDuration=e:e=s.opts[o?"animationDuration":"transitionDuration"],e=parseInt(e,10),i=f.isMoved(s),s.$slide.addClass("fancybox-slide--current"),o)return s.opts.animationEffect&&e&&f.$refs.container.css("transition-duration",e+"ms"),f.$refs.container.addClass("fancybox-is-open").trigger("focus"),f.loadSlide(s),void f.preload("image");c=n.fancybox.getTranslate(r.$slide),l=n.fancybox.getTranslate(f.$refs.stage),n.each(f.slides,function(t,e){n.fancybox.stop(e.$slide,!0)}),r.pos!==s.pos&&(r.isComplete=!1),r.$slide.removeClass("fancybox-slide--complete fancybox-slide--current"),i?(u=c.left-(r.pos*c.width+r.pos*r.opts.gutter),n.each(f.slides,function(t,o){o.$slide.removeClass("fancybox-animated").removeClass(function(t,e){return(e.match(/(^|\s)fancybox-fx-\S+/g)||[]).join(" ")});var i=o.pos*c.width+o.pos*o.opts.gutter;n.fancybox.setTranslate(o.$slide,{top:0,left:i-l.left+u}),o.pos!==s.pos&&o.$slide.addClass("fancybox-slide--"+(o.pos>s.pos?"next":"previous")),p(o.$slide),n.fancybox.animate(o.$slide,{top:0,left:(o.pos-s.pos)*c.width+(o.pos-s.pos)*o.opts.gutter},e,function(){o.$slide.css({transform:"",opacity:""}).removeClass("fancybox-slide--next fancybox-slide--previous"),o.pos===f.currPos&&f.complete()})})):e&&s.opts.transitionEffect&&(d="fancybox-animated fancybox-fx-"+s.opts.transitionEffect,r.$slide.addClass("fancybox-slide--"+(r.pos>s.pos?"next":"previous")),n.fancybox.animate(r.$slide,d,e,function(){r.$slide.removeClass(d).removeClass("fancybox-slide--next fancybox-slide--previous")},!1)),s.isLoaded?f.revealContent(s):f.loadSlide(s),f.preload("image")}},createSlide:function(t){var e,o,i=this;return o=t%i.group.length,o=o<0?i.group.length+o:o,!i.slides[t]&&i.group[o]&&(e=n('<div class="fancybox-slide"></div>').appendTo(i.$refs.stage),i.slides[t]=n.extend(!0,{},i.group[o],{pos:t,$slide:e,isLoaded:!1}),i.updateSlide(i.slides[t])),i.slides[t]},scaleToActual:function(t,e,o){var i,a,s,r,c,l=this,d=l.current,u=d.$content,f=n.fancybox.getTranslate(d.$slide).width,p=n.fancybox.getTranslate(d.$slide).height,h=d.width,g=d.height;l.isAnimating||l.isMoved()||!u||"image"!=d.type||!d.isLoaded||d.hasError||(l.isAnimating=!0,n.fancybox.stop(u),t=void 0===t?.5*f:t,e=void 0===e?.5*p:e,i=n.fancybox.getTranslate(u),i.top-=n.fancybox.getTranslate(d.$slide).top,i.left-=n.fancybox.getTranslate(d.$slide).left,r=h/i.width,c=g/i.height,a=.5*f-.5*h,s=.5*p-.5*g,h>f&&(a=i.left*r-(t*r-t),a>0&&(a=0),a<f-h&&(a=f-h)),g>p&&(s=i.top*c-(e*c-e),s>0&&(s=0),s<p-g&&(s=p-g)),l.updateCursor(h,g),n.fancybox.animate(u,{top:s,left:a,scaleX:r,scaleY:c},o||366,function(){l.isAnimating=!1}),l.SlideShow&&l.SlideShow.isActive&&l.SlideShow.stop())},scaleToFit:function(t){var e,o=this,i=o.current,a=i.$content;o.isAnimating||o.isMoved()||!a||"image"!=i.type||!i.isLoaded||i.hasError||(o.isAnimating=!0,n.fancybox.stop(a),e=o.getFitPos(i),o.updateCursor(e.width,e.height),n.fancybox.animate(a,{top:e.top,left:e.left,scaleX:e.width/a.width(),scaleY:e.height/a.height()},t||366,function(){o.isAnimating=!1}))},getFitPos:function(t){var e,o,i,a,s=this,r=t.$content,c=t.$slide,l=t.width||t.opts.width,d=t.height||t.opts.height,u={};return!!(t.isLoaded&&r&&r.length)&&(e=n.fancybox.getTranslate(s.$refs.stage).width,o=n.fancybox.getTranslate(s.$refs.stage).height,e-=parseFloat(c.css("paddingLeft"))+parseFloat(c.css("paddingRight"))+parseFloat(r.css("marginLeft"))+parseFloat(r.css("marginRight")),o-=parseFloat(c.css("paddingTop"))+parseFloat(c.css("paddingBottom"))+parseFloat(r.css("marginTop"))+parseFloat(r.css("marginBottom")),l&&d||(l=e,d=o),i=Math.min(1,e/l,o/d),l*=i,d*=i,l>e-.5&&(l=e),d>o-.5&&(d=o),"image"===t.type?(u.top=Math.floor(.5*(o-d))+parseFloat(c.css("paddingTop")),u.left=Math.floor(.5*(e-l))+parseFloat(c.css("paddingLeft"))):"video"===t.contentType&&(a=t.opts.width&&t.opts.height?l/d:t.opts.ratio||16/9,d>l/a?d=l/a:l>d*a&&(l=d*a)),u.width=l,u.height=d,u)},update:function(t){var e=this;n.each(e.slides,function(n,o){e.updateSlide(o,t)})},updateSlide:function(t,e){var o=this,i=t&&t.$content,a=t.width||t.opts.width,s=t.height||t.opts.height,r=t.$slide;o.adjustCaption(t),i&&(a||s||"video"===t.contentType)&&!t.hasError&&(n.fancybox.stop(i),n.fancybox.setTranslate(i,o.getFitPos(t)),t.pos===o.currPos&&(o.isAnimating=!1,o.updateCursor())),o.adjustLayout(t),r.length&&(r.trigger("refresh"),t.pos===o.currPos&&o.$refs.toolbar.add(o.$refs.navigation.find(".fancybox-button--arrow_right")).toggleClass("compensate-for-scrollbar",r.get(0).scrollHeight>r.get(0).clientHeight)),o.trigger("onUpdate",t,e)},centerSlide:function(t){var e=this,o=e.current,i=o.$slide;!e.isClosing&&o&&(i.siblings().css({transform:"",opacity:""}),i.parent().children().removeClass("fancybox-slide--previous fancybox-slide--next"),n.fancybox.animate(i,{top:0,left:0,opacity:1},void 0===t?0:t,function(){i.css({transform:"",opacity:""}),o.isComplete||e.complete()},!1))},isMoved:function(t){var e,o,i=t||this.current;return!!i&&(o=n.fancybox.getTranslate(this.$refs.stage),e=n.fancybox.getTranslate(i.$slide),!i.$slide.hasClass("fancybox-animated")&&(Math.abs(e.top-o.top)>.5||Math.abs(e.left-o.left)>.5))},updateCursor:function(t,e){var o,i,a=this,s=a.current,r=a.$refs.container;s&&!a.isClosing&&a.Guestures&&(r.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan"),o=a.canPan(t,e),i=!!o||a.isZoomable(),r.toggleClass("fancybox-is-zoomable",i),n("[data-fancybox-zoom]").prop("disabled",!i),o?r.addClass("fancybox-can-pan"):i&&("zoom"===s.opts.clickContent||n.isFunction(s.opts.clickContent)&&"zoom"==s.opts.clickContent(s))?r.addClass("fancybox-can-zoomIn"):s.opts.touch&&(s.opts.touch.vertical||a.group.length>1)&&"video"!==s.contentType&&r.addClass("fancybox-can-swipe"))},isZoomable:function(){var t,e=this,n=e.current;if(n&&!e.isClosing&&"image"===n.type&&!n.hasError){if(!n.isLoaded)return!0;if((t=e.getFitPos(n))&&(n.width>t.width||n.height>t.height))return!0}return!1},isScaledDown:function(t,e){var o=this,i=!1,a=o.current,s=a.$content;return void 0!==t&&void 0!==e?i=t<a.width&&e<a.height:s&&(i=n.fancybox.getTranslate(s),i=i.width<a.width&&i.height<a.height),i},canPan:function(t,e){var o=this,i=o.current,a=null,s=!1;return"image"===i.type&&(i.isComplete||t&&e)&&!i.hasError&&(s=o.getFitPos(i),void 0!==t&&void 0!==e?a={width:t,height:e}:i.isComplete&&(a=n.fancybox.getTranslate(i.$content)),a&&s&&(s=Math.abs(a.width-s.width)>1.5||Math.abs(a.height-s.height)>1.5)),s},loadSlide:function(t){var e,o,i,a=this;if(!t.isLoading&&!t.isLoaded){if(t.isLoading=!0,!1===a.trigger("beforeLoad",t))return t.isLoading=!1,!1;switch(e=t.type,o=t.$slide,o.off("refresh").trigger("onReset").addClass(t.opts.slideClass),e){case"image":a.setImage(t);break;case"iframe":a.setIframe(t);break;case"html":a.setContent(t,t.src||t.content);break;case"video":a.setContent(t,t.opts.video.tpl.replace(/\{\{src\}\}/gi,t.src).replace("{{format}}",t.opts.videoFormat||t.opts.video.format||"").replace("{{poster}}",t.thumb||""));break;case"inline":n(t.src).length?a.setContent(t,n(t.src)):a.setError(t);break;case"ajax":a.showLoading(t),i=n.ajax(n.extend({},t.opts.ajax.settings,{url:t.src,success:function(e,n){"success"===n&&a.setContent(t,e)},error:function(e,n){e&&"abort"!==n&&a.setError(t)}})),o.one("onReset",function(){i.abort()});break;default:a.setError(t)}return!0}},setImage:function(t){var o,i=this;setTimeout(function(){var e=t.$image;i.isClosing||!t.isLoading||e&&e.length&&e[0].complete||t.hasError||i.showLoading(t)},50),i.checkSrcset(t),t.$content=n('<div class="fancybox-content"></div>').addClass("fancybox-is-hidden").appendTo(t.$slide.addClass("fancybox-slide--image")),!1!==t.opts.preload&&t.opts.width&&t.opts.height&&t.thumb&&(t.width=t.opts.width,t.height=t.opts.height,o=e.createElement("img"),o.onerror=function(){n(this).remove(),t.$ghost=null},o.onload=function(){i.afterLoad(t)},t.$ghost=n(o).addClass("fancybox-image").appendTo(t.$content).attr("src",t.thumb)),i.setBigImage(t)},checkSrcset:function(e){var n,o,i,a,s=e.opts.srcset||e.opts.image.srcset;if(s){i=t.devicePixelRatio||1,a=t.innerWidth*i,o=s.split(",").map(function(t){var e={};return t.trim().split(/\s+/).forEach(function(t,n){var o=parseInt(t.substring(0,t.length-1),10);if(0===n)return e.url=t;o&&(e.value=o,e.postfix=t[t.length-1])}),e}),o.sort(function(t,e){return t.value-e.value});for(var r=0;r<o.length;r++){var c=o[r];if("w"===c.postfix&&c.value>=a||"x"===c.postfix&&c.value>=i){n=c;break}}!n&&o.length&&(n=o[o.length-1]),n&&(e.src=n.url,e.width&&e.height&&"w"==n.postfix&&(e.height=e.width/e.height*n.value,e.width=n.value),e.opts.srcset=s)}},setBigImage:function(t){var o=this,i=e.createElement("img"),a=n(i);t.$image=a.one("error",function(){o.setError(t)}).one("load",function(){var e;t.$ghost||(o.resolveImageSlideSize(t,this.naturalWidth,this.naturalHeight),o.afterLoad(t)),o.isClosing||(t.opts.srcset&&(e=t.opts.sizes,e&&"auto"!==e||(e=(t.width/t.height>1&&s.width()/s.height()>1?"100":Math.round(t.width/t.height*100))+"vw"),a.attr("sizes",e).attr("srcset",t.opts.srcset)),t.$ghost&&setTimeout(function(){t.$ghost&&!o.isClosing&&t.$ghost.hide()},Math.min(300,Math.max(1e3,t.height/1600))),o.hideLoading(t))}).addClass("fancybox-image").attr("src",t.src).appendTo(t.$content),(i.complete||"complete"==i.readyState)&&a.naturalWidth&&a.naturalHeight?a.trigger("load"):i.error&&a.trigger("error")},resolveImageSlideSize:function(t,e,n){var o=parseInt(t.opts.width,10),i=parseInt(t.opts.height,10);t.width=e,t.height=n,o>0&&(t.width=o,t.height=Math.floor(o*n/e)),i>0&&(t.width=Math.floor(i*e/n),t.height=i)},setIframe:function(t){var e,o=this,i=t.opts.iframe,a=t.$slide;t.$content=n('<div class="fancybox-content'+(i.preload?" fancybox-is-hidden":"")+'"></div>').css(i.css).appendTo(a),a.addClass("fancybox-slide--"+t.contentType),t.$iframe=e=n(i.tpl.replace(/\{rnd\}/g,(new Date).getTime())).attr(i.attr).appendTo(t.$content),i.preload?(o.showLoading(t),e.on("load.fb error.fb",function(e){this.isReady=1,t.$slide.trigger("refresh"),o.afterLoad(t)}),a.on("refresh.fb",function(){var n,o,s=t.$content,r=i.css.width,c=i.css.height;if(1===e[0].isReady){try{n=e.contents(),o=n.find("body")}catch(t){}o&&o.length&&o.children().length&&(a.css("overflow","visible"),s.css({width:"100%","max-width":"100%",height:"9999px"}),void 0===r&&(r=Math.ceil(Math.max(o[0].clientWidth,o.outerWidth(!0)))),s.css("width",r||"").css("max-width",""),void 0===c&&(c=Math.ceil(Math.max(o[0].clientHeight,o.outerHeight(!0)))),s.css("height",c||""),a.css("overflow","auto")),s.removeClass("fancybox-is-hidden")}})):o.afterLoad(t),e.attr("src",t.src),a.one("onReset",function(){try{n(this).find("iframe").hide().unbind().attr("src","//about:blank")}catch(t){}n(this).off("refresh.fb").empty(),t.isLoaded=!1,t.isRevealed=!1})},setContent:function(t,e){var o=this;o.isClosing||(o.hideLoading(t),t.$content&&n.fancybox.stop(t.$content),t.$slide.empty(),l(e)&&e.parent().length?((e.hasClass("fancybox-content")||e.parent().hasClass("fancybox-content"))&&e.parents(".fancybox-slide").trigger("onReset"),t.$placeholder=n("<div>").hide().insertAfter(e),e.css("display","inline-block")):t.hasError||("string"===n.type(e)&&(e=n("<div>").append(n.trim(e)).contents()),t.opts.filter&&(e=n("<div>").html(e).find(t.opts.filter))),t.$slide.one("onReset",function(){n(this).find("video,audio").trigger("pause"),t.$placeholder&&(t.$placeholder.after(e.removeClass("fancybox-content").hide()).remove(),t.$placeholder=null),t.$smallBtn&&(t.$smallBtn.remove(),t.$smallBtn=null),t.hasError||(n(this).empty(),t.isLoaded=!1,t.isRevealed=!1)}),n(e).appendTo(t.$slide),n(e).is("video,audio")&&(n(e).addClass("fancybox-video"),n(e).wrap("<div></div>"),t.contentType="video",t.opts.width=t.opts.width||n(e).attr("width"),t.opts.height=t.opts.height||n(e).attr("height")),t.$content=t.$slide.children().filter("div,form,main,video,audio,article,.fancybox-content").first(),t.$content.siblings().hide(),t.$content.length||(t.$content=t.$slide.wrapInner("<div></div>").children().first()),t.$content.addClass("fancybox-content"),t.$slide.addClass("fancybox-slide--"+t.contentType),o.afterLoad(t))},setError:function(t){t.hasError=!0,t.$slide.trigger("onReset").removeClass("fancybox-slide--"+t.contentType).addClass("fancybox-slide--error"),t.contentType="html",this.setContent(t,this.translate(t,t.opts.errorTpl)),t.pos===this.currPos&&(this.isAnimating=!1)},showLoading:function(t){var e=this;(t=t||e.current)&&!t.$spinner&&(t.$spinner=n(e.translate(e,e.opts.spinnerTpl)).appendTo(t.$slide).hide().fadeIn("fast"))},hideLoading:function(t){var e=this;(t=t||e.current)&&t.$spinner&&(t.$spinner.stop().remove(),delete t.$spinner)},afterLoad:function(t){var e=this;e.isClosing||(t.isLoading=!1,t.isLoaded=!0,e.trigger("afterLoad",t),e.hideLoading(t),!t.opts.smallBtn||t.$smallBtn&&t.$smallBtn.length||(t.$smallBtn=n(e.translate(t,t.opts.btnTpl.smallBtn)).appendTo(t.$content)),t.opts.protect&&t.$content&&!t.hasError&&(t.$content.on("contextmenu.fb",function(t){return 2==t.button&&t.preventDefault(),!0}),"image"===t.type&&n('<div class="fancybox-spaceball"></div>').appendTo(t.$content)),e.adjustCaption(t),e.adjustLayout(t),t.pos===e.currPos&&e.updateCursor(),e.revealContent(t))},adjustCaption:function(t){var e,n=this,o=t||n.current,i=o.opts.caption,a=o.opts.preventCaptionOverlap,s=n.$refs.caption,r=!1;s.toggleClass("fancybox-caption--separate",a),a&&i&&i.length&&(o.pos!==n.currPos?(e=s.clone().appendTo(s.parent()),e.children().eq(0).empty().html(i),r=e.outerHeight(!0),e.empty().remove()):n.$caption&&(r=n.$caption.outerHeight(!0)),o.$slide.css("padding-bottom",r||""))},adjustLayout:function(t){var e,n,o,i,a=this,s=t||a.current;s.isLoaded&&!0!==s.opts.disableLayoutFix&&(s.$content.css("margin-bottom",""),s.$content.outerHeight()>s.$slide.height()+.5&&(o=s.$slide[0].style["padding-bottom"],i=s.$slide.css("padding-bottom"),parseFloat(i)>0&&(e=s.$slide[0].scrollHeight,s.$slide.css("padding-bottom",0),Math.abs(e-s.$slide[0].scrollHeight)<1&&(n=i),s.$slide.css("padding-bottom",o))),s.$content.css("margin-bottom",n))},revealContent:function(t){var e,o,i,a,s=this,r=t.$slide,c=!1,l=!1,d=s.isMoved(t),u=t.isRevealed;return t.isRevealed=!0,e=t.opts[s.firstRun?"animationEffect":"transitionEffect"],i=t.opts[s.firstRun?"animationDuration":"transitionDuration"],i=parseInt(void 0===t.forcedDuration?i:t.forcedDuration,10),!d&&t.pos===s.currPos&&i||(e=!1),"zoom"===e&&(t.pos===s.currPos&&i&&"image"===t.type&&!t.hasError&&(l=s.getThumbPos(t))?c=s.getFitPos(t):e="fade"),"zoom"===e?(s.isAnimating=!0,c.scaleX=c.width/l.width,c.scaleY=c.height/l.height,a=t.opts.zoomOpacity,"auto"==a&&(a=Math.abs(t.width/t.height-l.width/l.height)>.1),a&&(l.opacity=.1,c.opacity=1),n.fancybox.setTranslate(t.$content.removeClass("fancybox-is-hidden"),l),p(t.$content),void n.fancybox.animate(t.$content,c,i,function(){s.isAnimating=!1,s.complete()})):(s.updateSlide(t),e?(n.fancybox.stop(r),o="fancybox-slide--"+(t.pos>=s.prevPos?"next":"previous")+" fancybox-animated fancybox-fx-"+e,r.addClass(o).removeClass("fancybox-slide--current"),t.$content.removeClass("fancybox-is-hidden"),p(r),"image"!==t.type&&t.$content.hide().show(0),void n.fancybox.animate(r,"fancybox-slide--current",i,function(){r.removeClass(o).css({transform:"",opacity:""}),t.pos===s.currPos&&s.complete()},!0)):(t.$content.removeClass("fancybox-is-hidden"),u||!d||"image"!==t.type||t.hasError||t.$content.hide().fadeIn("fast"),void(t.pos===s.currPos&&s.complete())))},getThumbPos:function(t){var e,o,i,a,s,r=!1,c=t.$thumb;return!(!c||!g(c[0]))&&(e=n.fancybox.getTranslate(c),o=parseFloat(c.css("border-top-width")||0),i=parseFloat(c.css("border-right-width")||0),a=parseFloat(c.css("border-bottom-width")||0),s=parseFloat(c.css("border-left-width")||0),r={top:e.top+o,left:e.left+s,width:e.width-i-s,height:e.height-o-a,scaleX:1,scaleY:1},e.width>0&&e.height>0&&r)},complete:function(){var t,e=this,o=e.current,i={};!e.isMoved()&&o.isLoaded&&(o.isComplete||(o.isComplete=!0,o.$slide.siblings().trigger("onReset"),e.preload("inline"),p(o.$slide),o.$slide.addClass("fancybox-slide--complete"),n.each(e.slides,function(t,o){o.pos>=e.currPos-1&&o.pos<=e.currPos+1?i[o.pos]=o:o&&(n.fancybox.stop(o.$slide),o.$slide.off().remove())}),e.slides=i),e.isAnimating=!1,e.updateCursor(),e.trigger("afterShow"),o.opts.video.autoStart&&o.$slide.find("video,audio").filter(":visible:first").trigger("play").one("ended",function(){Document.exitFullscreen?Document.exitFullscreen():this.webkitExitFullscreen&&this.webkitExitFullscreen(),e.next()}),o.opts.autoFocus&&"html"===o.contentType&&(t=o.$content.find("input[autofocus]:enabled:visible:first"),t.length?t.trigger("focus"):e.focus(null,!0)),o.$slide.scrollTop(0).scrollLeft(0))},preload:function(t){var e,n,o=this;o.group.length<2||(n=o.slides[o.currPos+1],e=o.slides[o.currPos-1],e&&e.type===t&&o.loadSlide(e),n&&n.type===t&&o.loadSlide(n))},focus:function(t,o){var i,a,s=this,r=["a[href]","area[href]",'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',"select:not([disabled]):not([aria-hidden])","textarea:not([disabled]):not([aria-hidden])","button:not([disabled]):not([aria-hidden])","iframe","object","embed","video","audio","[contenteditable]",'[tabindex]:not([tabindex^="-"])'].join(",");s.isClosing||(i=!t&&s.current&&s.current.isComplete?s.current.$slide.find("*:visible"+(o?":not(.fancybox-close-small)":"")):s.$refs.container.find("*:visible"),i=i.filter(r).filter(function(){return"hidden"!==n(this).css("visibility")&&!n(this).hasClass("disabled")}),i.length?(a=i.index(e.activeElement),t&&t.shiftKey?(a<0||0==a)&&(t.preventDefault(),i.eq(i.length-1).trigger("focus")):(a<0||a==i.length-1)&&(t&&t.preventDefault(),i.eq(0).trigger("focus"))):s.$refs.container.trigger("focus"))},activate:function(){var t=this;n(".fancybox-container").each(function(){var e=n(this).data("FancyBox");e&&e.id!==t.id&&!e.isClosing&&(e.trigger("onDeactivate"),e.removeEvents(),e.isVisible=!1)}),t.isVisible=!0,(t.current||t.isIdle)&&(t.update(),t.updateControls()),t.trigger("onActivate"),t.addEvents()},close:function(t,e){var o,i,a,s,r,c,l,u=this,f=u.current,h=function(){u.cleanUp(t)};return!u.isClosing&&(u.isClosing=!0,!1===u.trigger("beforeClose",t)?(u.isClosing=!1,d(function(){u.update()}),!1):(u.removeEvents(),a=f.$content,o=f.opts.animationEffect,i=n.isNumeric(e)?e:o?f.opts.animationDuration:0,f.$slide.removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated"),!0!==t?n.fancybox.stop(f.$slide):o=!1,f.$slide.siblings().trigger("onReset").remove(),i&&u.$refs.container.removeClass("fancybox-is-open").addClass("fancybox-is-closing").css("transition-duration",i+"ms"),u.hideLoading(f),u.hideControls(!0),u.updateCursor(),"zoom"!==o||a&&i&&"image"===f.type&&!u.isMoved()&&!f.hasError&&(l=u.getThumbPos(f))||(o="fade"),"zoom"===o?(n.fancybox.stop(a),s=n.fancybox.getTranslate(a),c={top:s.top,left:s.left,scaleX:s.width/l.width,scaleY:s.height/l.height,width:l.width,height:l.height},r=f.opts.zoomOpacity,
|
12 |
+
"auto"==r&&(r=Math.abs(f.width/f.height-l.width/l.height)>.1),r&&(l.opacity=0),n.fancybox.setTranslate(a,c),p(a),n.fancybox.animate(a,l,i,h),!0):(o&&i?n.fancybox.animate(f.$slide.addClass("fancybox-slide--previous").removeClass("fancybox-slide--current"),"fancybox-animated fancybox-fx-"+o,i,h):!0===t?setTimeout(h,i):h(),!0)))},cleanUp:function(e){var o,i,a,s=this,r=s.current.opts.$orig;s.current.$slide.trigger("onReset"),s.$refs.container.empty().remove(),s.trigger("afterClose",e),s.current.opts.backFocus&&(r&&r.length&&r.is(":visible")||(r=s.$trigger),r&&r.length&&(i=t.scrollX,a=t.scrollY,r.trigger("focus"),n("html, body").scrollTop(a).scrollLeft(i))),s.current=null,o=n.fancybox.getInstance(),o?o.activate():(n("body").removeClass("fancybox-active compensate-for-scrollbar"),n("#fancybox-style-noscroll").remove())},trigger:function(t,e){var o,i=Array.prototype.slice.call(arguments,1),a=this,s=e&&e.opts?e:a.current;if(s?i.unshift(s):s=a,i.unshift(a),n.isFunction(s.opts[t])&&(o=s.opts[t].apply(s,i)),!1===o)return o;"afterClose"!==t&&a.$refs?a.$refs.container.trigger(t+".fb",i):r.trigger(t+".fb",i)},updateControls:function(){var t=this,o=t.current,i=o.index,a=t.$refs.container,s=t.$refs.caption,r=o.opts.caption;o.$slide.trigger("refresh"),r&&r.length?(t.$caption=s,s.children().eq(0).html(r)):t.$caption=null,t.hasHiddenControls||t.isIdle||t.showControls(),a.find("[data-fancybox-count]").html(t.group.length),a.find("[data-fancybox-index]").html(i+1),a.find("[data-fancybox-prev]").prop("disabled",!o.opts.loop&&i<=0),a.find("[data-fancybox-next]").prop("disabled",!o.opts.loop&&i>=t.group.length-1),"image"===o.type?a.find("[data-fancybox-zoom]").show().end().find("[data-fancybox-download]").attr("href",o.opts.image.src||o.src).show():o.opts.toolbar&&a.find("[data-fancybox-download],[data-fancybox-zoom]").hide(),n(e.activeElement).is(":hidden,[disabled]")&&t.$refs.container.trigger("focus")},hideControls:function(t){var e=this,n=["infobar","toolbar","nav"];!t&&e.current.opts.preventCaptionOverlap||n.push("caption"),this.$refs.container.removeClass(n.map(function(t){return"fancybox-show-"+t}).join(" ")),this.hasHiddenControls=!0},showControls:function(){var t=this,e=t.current?t.current.opts:t.opts,n=t.$refs.container;t.hasHiddenControls=!1,t.idleSecondsCounter=0,n.toggleClass("fancybox-show-toolbar",!(!e.toolbar||!e.buttons)).toggleClass("fancybox-show-infobar",!!(e.infobar&&t.group.length>1)).toggleClass("fancybox-show-caption",!!t.$caption).toggleClass("fancybox-show-nav",!!(e.arrows&&t.group.length>1)).toggleClass("fancybox-is-modal",!!e.modal)},toggleControls:function(){this.hasHiddenControls?this.showControls():this.hideControls()}}),n.fancybox={version:"3.5.7",defaults:a,getInstance:function(t){var e=n('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"),o=Array.prototype.slice.call(arguments,1);return e instanceof b&&("string"===n.type(t)?e[t].apply(e,o):"function"===n.type(t)&&t.apply(e,o),e)},open:function(t,e,n){return new b(t,e,n)},close:function(t){var e=this.getInstance();e&&(e.close(),!0===t&&this.close(t))},destroy:function(){this.close(!0),r.add("body").off("click.fb-start","**")},isMobile:/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),use3d:function(){var n=e.createElement("div");return t.getComputedStyle&&t.getComputedStyle(n)&&t.getComputedStyle(n).getPropertyValue("transform")&&!(e.documentMode&&e.documentMode<11)}(),getTranslate:function(t){var e;return!(!t||!t.length)&&(e=t[0].getBoundingClientRect(),{top:e.top||0,left:e.left||0,width:e.width,height:e.height,opacity:parseFloat(t.css("opacity"))})},setTranslate:function(t,e){var n="",o={};if(t&&e)return void 0===e.left&&void 0===e.top||(n=(void 0===e.left?t.position().left:e.left)+"px, "+(void 0===e.top?t.position().top:e.top)+"px",n=this.use3d?"translate3d("+n+", 0px)":"translate("+n+")"),void 0!==e.scaleX&&void 0!==e.scaleY?n+=" scale("+e.scaleX+", "+e.scaleY+")":void 0!==e.scaleX&&(n+=" scaleX("+e.scaleX+")"),n.length&&(o.transform=n),void 0!==e.opacity&&(o.opacity=e.opacity),void 0!==e.width&&(o.width=e.width),void 0!==e.height&&(o.height=e.height),t.css(o)},animate:function(t,e,o,i,a){var s,r=this;n.isFunction(o)&&(i=o,o=null),r.stop(t),s=r.getTranslate(t),t.on(f,function(c){(!c||!c.originalEvent||t.is(c.originalEvent.target)&&"z-index"!=c.originalEvent.propertyName)&&(r.stop(t),n.isNumeric(o)&&t.css("transition-duration",""),n.isPlainObject(e)?void 0!==e.scaleX&&void 0!==e.scaleY&&r.setTranslate(t,{top:e.top,left:e.left,width:s.width*e.scaleX,height:s.height*e.scaleY,scaleX:1,scaleY:1}):!0!==a&&t.removeClass(e),n.isFunction(i)&&i(c))}),n.isNumeric(o)&&t.css("transition-duration",o+"ms"),n.isPlainObject(e)?(void 0!==e.scaleX&&void 0!==e.scaleY&&(delete e.width,delete e.height,t.parent().hasClass("fancybox-slide--image")&&t.parent().addClass("fancybox-is-scaling")),n.fancybox.setTranslate(t,e)):t.addClass(e),t.data("timer",setTimeout(function(){t.trigger(f)},o+33))},stop:function(t,e){t&&t.length&&(clearTimeout(t.data("timer")),e&&t.trigger(f),t.off(f).css("transition-duration",""),t.parent().removeClass("fancybox-is-scaling"))}},n.fn.fancybox=function(t){var e;return t=t||{},e=t.selector||!1,e?n("body").off("click.fb-start",e).on("click.fb-start",e,{options:t},i):this.off("click.fb-start").on("click.fb-start",{items:this,options:t},i),this},r.on("click.fb-start","[data-fancybox]",i),r.on("click.fb-start","[data-fancybox-trigger]",function(t){n('[data-fancybox="'+n(this).attr("data-fancybox-trigger")+'"]').eq(n(this).attr("data-fancybox-index")||0).trigger("click.fb-start",{$trigger:n(this)})}),function(){var t=null;r.on("mousedown mouseup focus blur",".fancybox-button",function(e){switch(e.type){case"mousedown":t=n(this);break;case"mouseup":t=null;break;case"focusin":n(".fancybox-button").removeClass("fancybox-focus"),n(this).is(t)||n(this).is("[disabled]")||n(this).addClass("fancybox-focus");break;case"focusout":n(".fancybox-button").removeClass("fancybox-focus")}})}()}}(window,document,jQuery),function(t){"use strict";var e={youtube:{matcher:/(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,params:{autoplay:1,autohide:1,fs:1,rel:0,hd:1,wmode:"transparent",enablejsapi:1,html5:1},paramPlace:8,type:"iframe",url:"https://www.youtube-nocookie.com/embed/$4",thumb:"https://img.youtube.com/vi/$4/hqdefault.jpg"},vimeo:{matcher:/^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,params:{autoplay:1,hd:1,show_title:1,show_byline:1,show_portrait:0,fullscreen:1},paramPlace:3,type:"iframe",url:"//player.vimeo.com/video/$2"},instagram:{matcher:/(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,type:"image",url:"//$1/p/$2/media/?size=l"},gmap_place:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/?ll="+(t[9]?t[9]+"&z="+Math.floor(t[10])+(t[12]?t[12].replace(/^\//,"&"):""):t[12]+"").replace(/\?/,"&")+"&output="+(t[12]&&t[12].indexOf("layer=c")>0?"svembed":"embed")}},gmap_search:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/maps?q="+t[5].replace("query=","q=").replace("api=1","")+"&output=embed"}}},n=function(e,n,o){if(e)return o=o||"","object"===t.type(o)&&(o=t.param(o,!0)),t.each(n,function(t,n){e=e.replace("$"+t,n||"")}),o.length&&(e+=(e.indexOf("?")>0?"&":"?")+o),e};t(document).on("objectNeedsType.fb",function(o,i,a){var s,r,c,l,d,u,f,p=a.src||"",h=!1;s=t.extend(!0,{},e,a.opts.media),t.each(s,function(e,o){if(c=p.match(o.matcher)){if(h=o.type,f=e,u={},o.paramPlace&&c[o.paramPlace]){d=c[o.paramPlace],"?"==d[0]&&(d=d.substring(1)),d=d.split("&");for(var i=0;i<d.length;++i){var s=d[i].split("=",2);2==s.length&&(u[s[0]]=decodeURIComponent(s[1].replace(/\+/g," ")))}}return l=t.extend(!0,{},o.params,a.opts[e],u),p="function"===t.type(o.url)?o.url.call(this,c,l,a):n(o.url,c,l),r="function"===t.type(o.thumb)?o.thumb.call(this,c,l,a):n(o.thumb,c),"youtube"===e?p=p.replace(/&t=((\d+)m)?(\d+)s/,function(t,e,n,o){return"&start="+((n?60*parseInt(n,10):0)+parseInt(o,10))}):"vimeo"===e&&(p=p.replace("&%23","#")),!1}}),h?(a.opts.thumb||a.opts.$thumb&&a.opts.$thumb.length||(a.opts.thumb=r),"iframe"===h&&(a.opts=t.extend(!0,a.opts,{iframe:{preload:!1,attr:{scrolling:"no"}}})),t.extend(a,{type:h,src:p,origSrc:a.src,contentSource:f,contentType:"image"===h?"image":"gmap_place"==f||"gmap_search"==f?"map":"video"})):p&&(a.type=a.opts.defaultType)});var o={youtube:{src:"https://www.youtube.com/iframe_api",class:"YT",loading:!1,loaded:!1},vimeo:{src:"https://player.vimeo.com/api/player.js",class:"Vimeo",loading:!1,loaded:!1},load:function(t){var e,n=this;if(this[t].loaded)return void setTimeout(function(){n.done(t)});this[t].loading||(this[t].loading=!0,e=document.createElement("script"),e.type="text/javascript",e.src=this[t].src,"youtube"===t?window.onYouTubeIframeAPIReady=function(){n[t].loaded=!0,n.done(t)}:e.onload=function(){n[t].loaded=!0,n.done(t)},document.body.appendChild(e))},done:function(e){var n,o,i;"youtube"===e&&delete window.onYouTubeIframeAPIReady,(n=t.fancybox.getInstance())&&(o=n.current.$content.find("iframe"),"youtube"===e&&void 0!==YT&&YT?i=new YT.Player(o.attr("id"),{events:{onStateChange:function(t){0==t.data&&n.next()}}}):"vimeo"===e&&void 0!==Vimeo&&Vimeo&&(i=new Vimeo.Player(o),i.on("ended",function(){n.next()})))}};t(document).on({"afterShow.fb":function(t,e,n){e.group.length>1&&("youtube"===n.contentSource||"vimeo"===n.contentSource)&&o.load(n.contentSource)}})}(jQuery),function(t,e,n){"use strict";var o=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),i=function(){return t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.mozCancelAnimationFrame||t.oCancelAnimationFrame||function(e){t.clearTimeout(e)}}(),a=function(e){var n=[];e=e.originalEvent||e||t.e,e=e.touches&&e.touches.length?e.touches:e.changedTouches&&e.changedTouches.length?e.changedTouches:[e];for(var o in e)e[o].pageX?n.push({x:e[o].pageX,y:e[o].pageY}):e[o].clientX&&n.push({x:e[o].clientX,y:e[o].clientY});return n},s=function(t,e,n){return e&&t?"x"===n?t.x-e.x:"y"===n?t.y-e.y:Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)):0},r=function(t){if(t.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio,iframe')||n.isFunction(t.get(0).onclick)||t.data("selectable"))return!0;for(var e=0,o=t[0].attributes,i=o.length;e<i;e++)if("data-fancybox-"===o[e].nodeName.substr(0,14))return!0;return!1},c=function(e){var n=t.getComputedStyle(e)["overflow-y"],o=t.getComputedStyle(e)["overflow-x"],i=("scroll"===n||"auto"===n)&&e.scrollHeight>e.clientHeight,a=("scroll"===o||"auto"===o)&&e.scrollWidth>e.clientWidth;return i||a},l=function(t){for(var e=!1;;){if(e=c(t.get(0)))break;if(t=t.parent(),!t.length||t.hasClass("fancybox-stage")||t.is("body"))break}return e},d=function(t){var e=this;e.instance=t,e.$bg=t.$refs.bg,e.$stage=t.$refs.stage,e.$container=t.$refs.container,e.destroy(),e.$container.on("touchstart.fb.touch mousedown.fb.touch",n.proxy(e,"ontouchstart"))};d.prototype.destroy=function(){var t=this;t.$container.off(".fb.touch"),n(e).off(".fb.touch"),t.requestId&&(i(t.requestId),t.requestId=null),t.tapped&&(clearTimeout(t.tapped),t.tapped=null)},d.prototype.ontouchstart=function(o){var i=this,c=n(o.target),d=i.instance,u=d.current,f=u.$slide,p=u.$content,h="touchstart"==o.type;if(h&&i.$container.off("mousedown.fb.touch"),(!o.originalEvent||2!=o.originalEvent.button)&&f.length&&c.length&&!r(c)&&!r(c.parent())&&(c.is("img")||!(o.originalEvent.clientX>c[0].clientWidth+c.offset().left))){if(!u||d.isAnimating||u.$slide.hasClass("fancybox-animated"))return o.stopPropagation(),void o.preventDefault();i.realPoints=i.startPoints=a(o),i.startPoints.length&&(u.touch&&o.stopPropagation(),i.startEvent=o,i.canTap=!0,i.$target=c,i.$content=p,i.opts=u.opts.touch,i.isPanning=!1,i.isSwiping=!1,i.isZooming=!1,i.isScrolling=!1,i.canPan=d.canPan(),i.startTime=(new Date).getTime(),i.distanceX=i.distanceY=i.distance=0,i.canvasWidth=Math.round(f[0].clientWidth),i.canvasHeight=Math.round(f[0].clientHeight),i.contentLastPos=null,i.contentStartPos=n.fancybox.getTranslate(i.$content)||{top:0,left:0},i.sliderStartPos=n.fancybox.getTranslate(f),i.stagePos=n.fancybox.getTranslate(d.$refs.stage),i.sliderStartPos.top-=i.stagePos.top,i.sliderStartPos.left-=i.stagePos.left,i.contentStartPos.top-=i.stagePos.top,i.contentStartPos.left-=i.stagePos.left,n(e).off(".fb.touch").on(h?"touchend.fb.touch touchcancel.fb.touch":"mouseup.fb.touch mouseleave.fb.touch",n.proxy(i,"ontouchend")).on(h?"touchmove.fb.touch":"mousemove.fb.touch",n.proxy(i,"ontouchmove")),n.fancybox.isMobile&&e.addEventListener("scroll",i.onscroll,!0),((i.opts||i.canPan)&&(c.is(i.$stage)||i.$stage.find(c).length)||(c.is(".fancybox-image")&&o.preventDefault(),n.fancybox.isMobile&&c.parents(".fancybox-caption").length))&&(i.isScrollable=l(c)||l(c.parent()),n.fancybox.isMobile&&i.isScrollable||o.preventDefault(),(1===i.startPoints.length||u.hasError)&&(i.canPan?(n.fancybox.stop(i.$content),i.isPanning=!0):i.isSwiping=!0,i.$container.addClass("fancybox-is-grabbing")),2===i.startPoints.length&&"image"===u.type&&(u.isLoaded||u.$ghost)&&(i.canTap=!1,i.isSwiping=!1,i.isPanning=!1,i.isZooming=!0,n.fancybox.stop(i.$content),i.centerPointStartX=.5*(i.startPoints[0].x+i.startPoints[1].x)-n(t).scrollLeft(),i.centerPointStartY=.5*(i.startPoints[0].y+i.startPoints[1].y)-n(t).scrollTop(),i.percentageOfImageAtPinchPointX=(i.centerPointStartX-i.contentStartPos.left)/i.contentStartPos.width,i.percentageOfImageAtPinchPointY=(i.centerPointStartY-i.contentStartPos.top)/i.contentStartPos.height,i.startDistanceBetweenFingers=s(i.startPoints[0],i.startPoints[1]))))}},d.prototype.onscroll=function(t){var n=this;n.isScrolling=!0,e.removeEventListener("scroll",n.onscroll,!0)},d.prototype.ontouchmove=function(t){var e=this;return void 0!==t.originalEvent.buttons&&0===t.originalEvent.buttons?void e.ontouchend(t):e.isScrolling?void(e.canTap=!1):(e.newPoints=a(t),void((e.opts||e.canPan)&&e.newPoints.length&&e.newPoints.length&&(e.isSwiping&&!0===e.isSwiping||t.preventDefault(),e.distanceX=s(e.newPoints[0],e.startPoints[0],"x"),e.distanceY=s(e.newPoints[0],e.startPoints[0],"y"),e.distance=s(e.newPoints[0],e.startPoints[0]),e.distance>0&&(e.isSwiping?e.onSwipe(t):e.isPanning?e.onPan():e.isZooming&&e.onZoom()))))},d.prototype.onSwipe=function(e){var a,s=this,r=s.instance,c=s.isSwiping,l=s.sliderStartPos.left||0;if(!0!==c)"x"==c&&(s.distanceX>0&&(s.instance.group.length<2||0===s.instance.current.index&&!s.instance.current.opts.loop)?l+=Math.pow(s.distanceX,.8):s.distanceX<0&&(s.instance.group.length<2||s.instance.current.index===s.instance.group.length-1&&!s.instance.current.opts.loop)?l-=Math.pow(-s.distanceX,.8):l+=s.distanceX),s.sliderLastPos={top:"x"==c?0:s.sliderStartPos.top+s.distanceY,left:l},s.requestId&&(i(s.requestId),s.requestId=null),s.requestId=o(function(){s.sliderLastPos&&(n.each(s.instance.slides,function(t,e){var o=e.pos-s.instance.currPos;n.fancybox.setTranslate(e.$slide,{top:s.sliderLastPos.top,left:s.sliderLastPos.left+o*s.canvasWidth+o*e.opts.gutter})}),s.$container.addClass("fancybox-is-sliding"))});else if(Math.abs(s.distance)>10){if(s.canTap=!1,r.group.length<2&&s.opts.vertical?s.isSwiping="y":r.isDragging||!1===s.opts.vertical||"auto"===s.opts.vertical&&n(t).width()>800?s.isSwiping="x":(a=Math.abs(180*Math.atan2(s.distanceY,s.distanceX)/Math.PI),s.isSwiping=a>45&&a<135?"y":"x"),"y"===s.isSwiping&&n.fancybox.isMobile&&s.isScrollable)return void(s.isScrolling=!0);r.isDragging=s.isSwiping,s.startPoints=s.newPoints,n.each(r.slides,function(t,e){var o,i;n.fancybox.stop(e.$slide),o=n.fancybox.getTranslate(e.$slide),i=n.fancybox.getTranslate(r.$refs.stage),e.$slide.css({transform:"",opacity:"","transition-duration":""}).removeClass("fancybox-animated").removeClass(function(t,e){return(e.match(/(^|\s)fancybox-fx-\S+/g)||[]).join(" ")}),e.pos===r.current.pos&&(s.sliderStartPos.top=o.top-i.top,s.sliderStartPos.left=o.left-i.left),n.fancybox.setTranslate(e.$slide,{top:o.top-i.top,left:o.left-i.left})}),r.SlideShow&&r.SlideShow.isActive&&r.SlideShow.stop()}},d.prototype.onPan=function(){var t=this;if(s(t.newPoints[0],t.realPoints[0])<(n.fancybox.isMobile?10:5))return void(t.startPoints=t.newPoints);t.canTap=!1,t.contentLastPos=t.limitMovement(),t.requestId&&i(t.requestId),t.requestId=o(function(){n.fancybox.setTranslate(t.$content,t.contentLastPos)})},d.prototype.limitMovement=function(){var t,e,n,o,i,a,s=this,r=s.canvasWidth,c=s.canvasHeight,l=s.distanceX,d=s.distanceY,u=s.contentStartPos,f=u.left,p=u.top,h=u.width,g=u.height;return i=h>r?f+l:f,a=p+d,t=Math.max(0,.5*r-.5*h),e=Math.max(0,.5*c-.5*g),n=Math.min(r-h,.5*r-.5*h),o=Math.min(c-g,.5*c-.5*g),l>0&&i>t&&(i=t-1+Math.pow(-t+f+l,.8)||0),l<0&&i<n&&(i=n+1-Math.pow(n-f-l,.8)||0),d>0&&a>e&&(a=e-1+Math.pow(-e+p+d,.8)||0),d<0&&a<o&&(a=o+1-Math.pow(o-p-d,.8)||0),{top:a,left:i}},d.prototype.limitPosition=function(t,e,n,o){var i=this,a=i.canvasWidth,s=i.canvasHeight;return n>a?(t=t>0?0:t,t=t<a-n?a-n:t):t=Math.max(0,a/2-n/2),o>s?(e=e>0?0:e,e=e<s-o?s-o:e):e=Math.max(0,s/2-o/2),{top:e,left:t}},d.prototype.onZoom=function(){var e=this,a=e.contentStartPos,r=a.width,c=a.height,l=a.left,d=a.top,u=s(e.newPoints[0],e.newPoints[1]),f=u/e.startDistanceBetweenFingers,p=Math.floor(r*f),h=Math.floor(c*f),g=(r-p)*e.percentageOfImageAtPinchPointX,b=(c-h)*e.percentageOfImageAtPinchPointY,m=(e.newPoints[0].x+e.newPoints[1].x)/2-n(t).scrollLeft(),v=(e.newPoints[0].y+e.newPoints[1].y)/2-n(t).scrollTop(),y=m-e.centerPointStartX,x=v-e.centerPointStartY,w=l+(g+y),$=d+(b+x),S={top:$,left:w,scaleX:f,scaleY:f};e.canTap=!1,e.newWidth=p,e.newHeight=h,e.contentLastPos=S,e.requestId&&i(e.requestId),e.requestId=o(function(){n.fancybox.setTranslate(e.$content,e.contentLastPos)})},d.prototype.ontouchend=function(t){var o=this,s=o.isSwiping,r=o.isPanning,c=o.isZooming,l=o.isScrolling;if(o.endPoints=a(t),o.dMs=Math.max((new Date).getTime()-o.startTime,1),o.$container.removeClass("fancybox-is-grabbing"),n(e).off(".fb.touch"),e.removeEventListener("scroll",o.onscroll,!0),o.requestId&&(i(o.requestId),o.requestId=null),o.isSwiping=!1,o.isPanning=!1,o.isZooming=!1,o.isScrolling=!1,o.instance.isDragging=!1,o.canTap)return o.onTap(t);o.speed=100,o.velocityX=o.distanceX/o.dMs*.5,o.velocityY=o.distanceY/o.dMs*.5,r?o.endPanning():c?o.endZooming():o.endSwiping(s,l)},d.prototype.endSwiping=function(t,e){var o=this,i=!1,a=o.instance.group.length,s=Math.abs(o.distanceX),r="x"==t&&a>1&&(o.dMs>130&&s>10||s>50);o.sliderLastPos=null,"y"==t&&!e&&Math.abs(o.distanceY)>50?(n.fancybox.animate(o.instance.current.$slide,{top:o.sliderStartPos.top+o.distanceY+150*o.velocityY,opacity:0},200),i=o.instance.close(!0,250)):r&&o.distanceX>0?i=o.instance.previous(300):r&&o.distanceX<0&&(i=o.instance.next(300)),!1!==i||"x"!=t&&"y"!=t||o.instance.centerSlide(200),o.$container.removeClass("fancybox-is-sliding")},d.prototype.endPanning=function(){var t,e,o,i=this;i.contentLastPos&&(!1===i.opts.momentum||i.dMs>350?(t=i.contentLastPos.left,e=i.contentLastPos.top):(t=i.contentLastPos.left+500*i.velocityX,e=i.contentLastPos.top+500*i.velocityY),o=i.limitPosition(t,e,i.contentStartPos.width,i.contentStartPos.height),o.width=i.contentStartPos.width,o.height=i.contentStartPos.height,n.fancybox.animate(i.$content,o,366))},d.prototype.endZooming=function(){var t,e,o,i,a=this,s=a.instance.current,r=a.newWidth,c=a.newHeight;a.contentLastPos&&(t=a.contentLastPos.left,e=a.contentLastPos.top,i={top:e,left:t,width:r,height:c,scaleX:1,scaleY:1},n.fancybox.setTranslate(a.$content,i),r<a.canvasWidth&&c<a.canvasHeight?a.instance.scaleToFit(150):r>s.width||c>s.height?a.instance.scaleToActual(a.centerPointStartX,a.centerPointStartY,150):(o=a.limitPosition(t,e,r,c),n.fancybox.animate(a.$content,o,150)))},d.prototype.onTap=function(e){var o,i=this,s=n(e.target),r=i.instance,c=r.current,l=e&&a(e)||i.startPoints,d=l[0]?l[0].x-n(t).scrollLeft()-i.stagePos.left:0,u=l[0]?l[0].y-n(t).scrollTop()-i.stagePos.top:0,f=function(t){var o=c.opts[t];if(n.isFunction(o)&&(o=o.apply(r,[c,e])),o)switch(o){case"close":r.close(i.startEvent);break;case"toggleControls":r.toggleControls();break;case"next":r.next();break;case"nextOrClose":r.group.length>1?r.next():r.close(i.startEvent);break;case"zoom":"image"==c.type&&(c.isLoaded||c.$ghost)&&(r.canPan()?r.scaleToFit():r.isScaledDown()?r.scaleToActual(d,u):r.group.length<2&&r.close(i.startEvent))}};if((!e.originalEvent||2!=e.originalEvent.button)&&(s.is("img")||!(d>s[0].clientWidth+s.offset().left))){if(s.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container"))o="Outside";else if(s.is(".fancybox-slide"))o="Slide";else{if(!r.current.$content||!r.current.$content.find(s).addBack().filter(s).length)return;o="Content"}if(i.tapped){if(clearTimeout(i.tapped),i.tapped=null,Math.abs(d-i.tapX)>50||Math.abs(u-i.tapY)>50)return this;f("dblclick"+o)}else i.tapX=d,i.tapY=u,c.opts["dblclick"+o]&&c.opts["dblclick"+o]!==c.opts["click"+o]?i.tapped=setTimeout(function(){i.tapped=null,r.isAnimating||f("click"+o)},500):f("click"+o);return this}},n(e).on("onActivate.fb",function(t,e){e&&!e.Guestures&&(e.Guestures=new d(e))}).on("beforeClose.fb",function(t,e){e&&e.Guestures&&e.Guestures.destroy()})}(window,document,jQuery),function(t,e){"use strict";e.extend(!0,e.fancybox.defaults,{btnTpl:{slideShow:'<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 5.4v13.2l11-6.6z"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.33 5.75h2.2v12.5h-2.2V5.75zm5.15 0h2.2v12.5h-2.2V5.75z"/></svg></button>'},slideShow:{autoStart:!1,speed:3e3,progress:!0}});var n=function(t){this.instance=t,this.init()};e.extend(n.prototype,{timer:null,isActive:!1,$button:null,init:function(){var t=this,n=t.instance,o=n.group[n.currIndex].opts.slideShow;t.$button=n.$refs.toolbar.find("[data-fancybox-play]").on("click",function(){t.toggle()}),n.group.length<2||!o?t.$button.hide():o.progress&&(t.$progress=e('<div class="fancybox-progress"></div>').appendTo(n.$refs.inner))},set:function(t){var n=this,o=n.instance,i=o.current;i&&(!0===t||i.opts.loop||o.currIndex<o.group.length-1)?n.isActive&&"video"!==i.contentType&&(n.$progress&&e.fancybox.animate(n.$progress.show(),{scaleX:1},i.opts.slideShow.speed),n.timer=setTimeout(function(){o.current.opts.loop||o.current.index!=o.group.length-1?o.next():o.jumpTo(0)},i.opts.slideShow.speed)):(n.stop(),o.idleSecondsCounter=0,o.showControls())},clear:function(){var t=this;clearTimeout(t.timer),t.timer=null,t.$progress&&t.$progress.removeAttr("style").hide()},start:function(){var t=this,e=t.instance.current;e&&(t.$button.attr("title",(e.opts.i18n[e.opts.lang]||e.opts.i18n.en).PLAY_STOP).removeClass("fancybox-button--play").addClass("fancybox-button--pause"),t.isActive=!0,e.isComplete&&t.set(!0),t.instance.trigger("onSlideShowChange",!0))},stop:function(){var t=this,e=t.instance.current;t.clear(),t.$button.attr("title",(e.opts.i18n[e.opts.lang]||e.opts.i18n.en).PLAY_START).removeClass("fancybox-button--pause").addClass("fancybox-button--play"),t.isActive=!1,t.instance.trigger("onSlideShowChange",!1),t.$progress&&t.$progress.removeAttr("style").hide()},toggle:function(){var t=this;t.isActive?t.stop():t.start()}}),e(t).on({"onInit.fb":function(t,e){e&&!e.SlideShow&&(e.SlideShow=new n(e))},"beforeShow.fb":function(t,e,n,o){var i=e&&e.SlideShow;o?i&&n.opts.slideShow.autoStart&&i.start():i&&i.isActive&&i.clear()},"afterShow.fb":function(t,e,n){var o=e&&e.SlideShow;o&&o.isActive&&o.set()},"afterKeydown.fb":function(n,o,i,a,s){var r=o&&o.SlideShow;!r||!i.opts.slideShow||80!==s&&32!==s||e(t.activeElement).is("button,a,input")||(a.preventDefault(),r.toggle())},"beforeClose.fb onDeactivate.fb":function(t,e){var n=e&&e.SlideShow;n&&n.stop()}}),e(t).on("visibilitychange",function(){var n=e.fancybox.getInstance(),o=n&&n.SlideShow;o&&o.isActive&&(t.hidden?o.clear():o.set())})}(document,jQuery),function(t,e){"use strict";var n=function(){for(var e=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],n={},o=0;o<e.length;o++){var i=e[o];if(i&&i[1]in t){for(var a=0;a<i.length;a++)n[e[0][a]]=i[a];return n}}return!1}();if(n){var o={request:function(e){e=e||t.documentElement,e[n.requestFullscreen](e.ALLOW_KEYBOARD_INPUT)},exit:function(){t[n.exitFullscreen]()},toggle:function(e){e=e||t.documentElement,this.isFullscreen()?this.exit():this.request(e)},isFullscreen:function(){return Boolean(t[n.fullscreenElement])},enabled:function(){return Boolean(t[n.fullscreenEnabled])}};e.extend(!0,e.fancybox.defaults,{btnTpl:{fullScreen:'<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fsenter" title="{{FULL_SCREEN}}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z"/></svg></button>'},fullScreen:{autoStart:!1}}),e(t).on(n.fullscreenchange,function(){var t=o.isFullscreen(),n=e.fancybox.getInstance();n&&(n.current&&"image"===n.current.type&&n.isAnimating&&(n.isAnimating=!1,n.update(!0,!0,0),n.isComplete||n.complete()),n.trigger("onFullscreenChange",t),n.$refs.container.toggleClass("fancybox-is-fullscreen",t),n.$refs.toolbar.find("[data-fancybox-fullscreen]").toggleClass("fancybox-button--fsenter",!t).toggleClass("fancybox-button--fsexit",t))})}e(t).on({"onInit.fb":function(t,e){var i;if(!n)return void e.$refs.toolbar.find("[data-fancybox-fullscreen]").remove();e&&e.group[e.currIndex].opts.fullScreen?(i=e.$refs.container,i.on("click.fb-fullscreen","[data-fancybox-fullscreen]",function(t){t.stopPropagation(),t.preventDefault(),o.toggle()}),e.opts.fullScreen&&!0===e.opts.fullScreen.autoStart&&o.request(),e.FullScreen=o):e&&e.$refs.toolbar.find("[data-fancybox-fullscreen]").hide()},"afterKeydown.fb":function(t,e,n,o,i){e&&e.FullScreen&&70===i&&(o.preventDefault(),e.FullScreen.toggle())},"beforeClose.fb":function(t,e){e&&e.FullScreen&&e.$refs.container.hasClass("fancybox-is-fullscreen")&&o.exit()}})}(document,jQuery),function(t,e){"use strict";var n="fancybox-thumbs";e.fancybox.defaults=e.extend(!0,{btnTpl:{thumbs:'<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.59 14.59h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76H5.65V5.65z"/></svg></button>'},thumbs:{autoStart:!1,hideOnClose:!0,parentEl:".fancybox-container",axis:"y"}},e.fancybox.defaults);var o=function(t){this.init(t)};e.extend(o.prototype,{$button:null,$grid:null,$list:null,isVisible:!1,isActive:!1,init:function(t){var e=this,n=t.group,o=0;e.instance=t,e.opts=n[t.currIndex].opts.thumbs,t.Thumbs=e,e.$button=t.$refs.toolbar.find("[data-fancybox-thumbs]");for(var i=0,a=n.length;i<a&&(n[i].thumb&&o++,!(o>1));i++);o>1&&e.opts?(e.$button.removeAttr("style").on("click",function(){e.toggle()}),e.isActive=!0):e.$button.hide()},create:function(){var t,o=this,i=o.instance,a=o.opts.parentEl,s=[];o.$grid||(o.$grid=e('<div class="'+n+" "+n+"-"+o.opts.axis+'"></div>').appendTo(i.$refs.container.find(a).addBack().filter(a)),o.$grid.on("click","a",function(){i.jumpTo(e(this).attr("data-index"))})),o.$list||(o.$list=e('<div class="'+n+'__list">').appendTo(o.$grid)),e.each(i.group,function(e,n){t=n.thumb,t||"image"!==n.type||(t=n.src),s.push('<a href="javascript:;" tabindex="0" data-index="'+e+'"'+(t&&t.length?' style="background-image:url('+t+')"':'class="fancybox-thumbs-missing"')+"></a>")}),o.$list[0].innerHTML=s.join(""),"x"===o.opts.axis&&o.$list.width(parseInt(o.$grid.css("padding-right"),10)+i.group.length*o.$list.children().eq(0).outerWidth(!0))},focus:function(t){var e,n,o=this,i=o.$list,a=o.$grid;o.instance.current&&(e=i.children().removeClass("fancybox-thumbs-active").filter('[data-index="'+o.instance.current.index+'"]').addClass("fancybox-thumbs-active"),n=e.position(),"y"===o.opts.axis&&(n.top<0||n.top>i.height()-e.outerHeight())?i.stop().animate({scrollTop:i.scrollTop()+n.top},t):"x"===o.opts.axis&&(n.left<a.scrollLeft()||n.left>a.scrollLeft()+(a.width()-e.outerWidth()))&&i.parent().stop().animate({scrollLeft:n.left},t))},update:function(){var t=this;t.instance.$refs.container.toggleClass("fancybox-show-thumbs",this.isVisible),t.isVisible?(t.$grid||t.create(),t.instance.trigger("onThumbsShow"),t.focus(0)):t.$grid&&t.instance.trigger("onThumbsHide"),t.instance.update()},hide:function(){this.isVisible=!1,this.update()},show:function(){this.isVisible=!0,this.update()},toggle:function(){this.isVisible=!this.isVisible,this.update()}}),e(t).on({"onInit.fb":function(t,e){var n;e&&!e.Thumbs&&(n=new o(e),n.isActive&&!0===n.opts.autoStart&&n.show())},"beforeShow.fb":function(t,e,n,o){var i=e&&e.Thumbs;i&&i.isVisible&&i.focus(o?0:250)},"afterKeydown.fb":function(t,e,n,o,i){var a=e&&e.Thumbs;a&&a.isActive&&71===i&&(o.preventDefault(),a.toggle())},"beforeClose.fb":function(t,e){var n=e&&e.Thumbs;n&&n.isVisible&&!1!==n.opts.hideOnClose&&n.$grid.hide()}})}(document,jQuery),function(t,e){"use strict";function n(t){var e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};return String(t).replace(/[&<>"'`=\/]/g,function(t){return e[t]})}e.extend(!0,e.fancybox.defaults,{btnTpl:{share:'<button data-fancybox-share class="fancybox-button fancybox-button--share" title="{{SHARE}}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2.55 19c1.4-8.4 9.1-9.8 11.9-9.8V5l7 7-7 6.3v-3.5c-2.8 0-10.5 2.1-11.9 4.2z"/></svg></button>'},share:{url:function(t,e){return!t.currentHash&&"inline"!==e.type&&"html"!==e.type&&(e.origSrc||e.src)||window.location},
|
13 |
+
tpl:'<div class="fancybox-share"><h1>{{SHARE}}</h1><p><a class="fancybox-share__button fancybox-share__button--fb" href="https://www.facebook.com/sharer/sharer.php?u={{url}}"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m287 456v-299c0-21 6-35 35-35h38v-63c-7-1-29-3-55-3-54 0-91 33-91 94v306m143-254h-205v72h196" /></svg><span>Facebook</span></a><a class="fancybox-share__button fancybox-share__button--tw" href="https://twitter.com/intent/tweet?url={{url}}&text={{descr}}"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m456 133c-14 7-31 11-47 13 17-10 30-27 37-46-15 10-34 16-52 20-61-62-157-7-141 75-68-3-129-35-169-85-22 37-11 86 26 109-13 0-26-4-37-9 0 39 28 72 65 80-12 3-25 4-37 2 10 33 41 57 77 57-42 30-77 38-122 34 170 111 378-32 359-208 16-11 30-25 41-42z" /></svg><span>Twitter</span></a><a class="fancybox-share__button fancybox-share__button--pt" href="https://www.pinterest.com/pin/create/button/?url={{url}}&description={{descr}}&media={{media}}"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m265 56c-109 0-164 78-164 144 0 39 15 74 47 87 5 2 10 0 12-5l4-19c2-6 1-8-3-13-9-11-15-25-15-45 0-58 43-110 113-110 62 0 96 38 96 88 0 67-30 122-73 122-24 0-42-19-36-44 6-29 20-60 20-81 0-19-10-35-31-35-25 0-44 26-44 60 0 21 7 36 7 36l-30 125c-8 37-1 83 0 87 0 3 4 4 5 2 2-3 32-39 42-75l16-64c8 16 31 29 56 29 74 0 124-67 124-157 0-69-58-132-146-132z" fill="#fff"/></svg><span>Pinterest</span></a></p><p><input class="fancybox-share__input" type="text" value="{{url_raw}}" onclick="select()" /></p></div>'}}),e(t).on("click","[data-fancybox-share]",function(){var t,o,i=e.fancybox.getInstance(),a=i.current||null;a&&("function"===e.type(a.opts.share.url)&&(t=a.opts.share.url.apply(a,[i,a])),o=a.opts.share.tpl.replace(/\{\{media\}\}/g,"image"===a.type?encodeURIComponent(a.src):"").replace(/\{\{url\}\}/g,encodeURIComponent(t)).replace(/\{\{url_raw\}\}/g,n(t)).replace(/\{\{descr\}\}/g,i.$caption?encodeURIComponent(i.$caption.text()):""),e.fancybox.open({src:i.translate(i,o),type:"html",opts:{touch:!1,animationEffect:!1,afterLoad:function(t,e){i.$refs.container.one("beforeClose.fb",function(){t.close(null,0)}),e.$content.find(".fancybox-share__button").click(function(){return window.open(this.href,"Share","width=550, height=450"),!1})},mobile:{autoFocus:!1}}}))})}(document,jQuery),function(t,e,n){"use strict";function o(){var e=t.location.hash.substr(1),n=e.split("-"),o=n.length>1&&/^\+?\d+$/.test(n[n.length-1])?parseInt(n.pop(-1),10)||1:1,i=n.join("-");return{hash:e,index:o<1?1:o,gallery:i}}function i(t){""!==t.gallery&&n("[data-fancybox='"+n.escapeSelector(t.gallery)+"']").eq(t.index-1).focus().trigger("click.fb-start")}function a(t){var e,n;return!!t&&(e=t.current?t.current.opts:t.opts,""!==(n=e.hash||(e.$orig?e.$orig.data("fancybox")||e.$orig.data("fancybox-trigger"):""))&&n)}n.escapeSelector||(n.escapeSelector=function(t){return(t+"").replace(/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t})}),n(function(){!1!==n.fancybox.defaults.hash&&(n(e).on({"onInit.fb":function(t,e){var n,i;!1!==e.group[e.currIndex].opts.hash&&(n=o(),(i=a(e))&&n.gallery&&i==n.gallery&&(e.currIndex=n.index-1))},"beforeShow.fb":function(n,o,i,s){var r;i&&!1!==i.opts.hash&&(r=a(o))&&(o.currentHash=r+(o.group.length>1?"-"+(i.index+1):""),t.location.hash!=="#"+o.currentHash&&(s&&!o.origHash&&(o.origHash=t.location.hash),o.hashTimer&&clearTimeout(o.hashTimer),o.hashTimer=setTimeout(function(){"replaceState"in t.history?(t.history[s?"pushState":"replaceState"]({},e.title,t.location.pathname+t.location.search+"#"+o.currentHash),s&&(o.hasCreatedHistory=!0)):t.location.hash=o.currentHash,o.hashTimer=null},300)))},"beforeClose.fb":function(n,o,i){i&&!1!==i.opts.hash&&(clearTimeout(o.hashTimer),o.currentHash&&o.hasCreatedHistory?t.history.back():o.currentHash&&("replaceState"in t.history?t.history.replaceState({},e.title,t.location.pathname+t.location.search+(o.origHash||"")):t.location.hash=o.origHash),o.currentHash=null)}}),n(t).on("hashchange.fb",function(){var t=o(),e=null;n.each(n(".fancybox-container").get().reverse(),function(t,o){var i=n(o).data("FancyBox");if(i&&i.currentHash)return e=i,!1}),e?e.currentHash===t.gallery+"-"+t.index||1===t.index&&e.currentHash==t.gallery||(e.currentHash=null,e.close()):""!==t.gallery&&i(t)}),setTimeout(function(){n.fancybox.getInstance()||i(o())},50))})}(window,document,jQuery),function(t,e){"use strict";var n=(new Date).getTime();e(t).on({"onInit.fb":function(t,e,o){e.$refs.stage.on("mousewheel DOMMouseScroll wheel MozMousePixelScroll",function(t){var o=e.current,i=(new Date).getTime();e.group.length<2||!1===o.opts.wheel||"auto"===o.opts.wheel&&"image"!==o.type||(t.preventDefault(),t.stopPropagation(),o.$slide.hasClass("fancybox-animated")||(t=t.originalEvent||t,i-n<250||(n=i,e[(-t.deltaY||-t.deltaX||t.wheelDelta||-t.detail)<0?"next":"previous"]())))})}})}(document,jQuery);
|
resources/js/{jquery.fileDownload.js → jquery/fileDownload.js}
RENAMED
File without changes
|
resources/js/{u2f-frontend.js → login/u2f.js}
RENAMED
File without changes
|
resources/js/plugin.js
CHANGED
@@ -332,7 +332,7 @@ jQuery.fn.icwpWpsfAjaxTable = function ( aOptions ) {
|
|
332 |
if ( typeof icwp_wpsf_vars_plugin !== 'undefined' ) {
|
333 |
|
334 |
jQuery( document ).ready( function () {
|
335 |
-
jQuery( document ).on( 'click', 'a.shield_file_download,
|
336 |
evt.preventDefault();
|
337 |
/** Cache busting **/
|
338 |
let url = jQuery( this ).attr( 'href' ) + '&rand='
|
332 |
if ( typeof icwp_wpsf_vars_plugin !== 'undefined' ) {
|
333 |
|
334 |
jQuery( document ).ready( function () {
|
335 |
+
jQuery( document ).on( 'click', 'a.shield_file_download, a.shield_file_download ', function ( evt ) {
|
336 |
evt.preventDefault();
|
337 |
/** Cache busting **/
|
338 |
let url = jQuery( this ).attr( 'href' ) + '&rand='
|
resources/js/shield/antibot.js
CHANGED
@@ -20,8 +20,21 @@ if ( typeof Shield_Antibot === typeof undefined && typeof shield_vars_antibotjs
|
|
20 |
}
|
21 |
|
22 |
this.initialise = function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
domReady( function () {
|
24 |
-
fire();
|
25 |
} );
|
26 |
};
|
27 |
|
@@ -58,5 +71,6 @@ if ( typeof Shield_Antibot === typeof undefined && typeof shield_vars_antibotjs
|
|
58 |
if ( parts.length === 2 ) return parts.pop().split( ";" ).shift();
|
59 |
};
|
60 |
}();
|
|
|
61 |
Shield_Antibot.initialise();
|
62 |
}
|
20 |
}
|
21 |
|
22 |
this.initialise = function () {
|
23 |
+
/**
|
24 |
+
* @since 11.2 we no longer wait until DOM is ready.
|
25 |
+
* This is mainly AJAX so it's asynchronous and wont hold up any other part of the page load.
|
26 |
+
* Early execution also helps mitigate the case where login requests are
|
27 |
+
* sent quickly, before browser has fired NotBot request.
|
28 |
+
*/
|
29 |
+
if ( shield_vars_antibotjs.flags.run ) {
|
30 |
+
sendReq();
|
31 |
+
}
|
32 |
+
/**
|
33 |
+
* @since 11.2 this script is only loaded if a not bot signal doesn't exist for this IP.
|
34 |
+
* This removes the need for cookies - as used by fire()
|
35 |
+
*/
|
36 |
domReady( function () {
|
37 |
+
// fire();
|
38 |
} );
|
39 |
};
|
40 |
|
71 |
if ( parts.length === 2 ) return parts.pop().split( ";" ).shift();
|
72 |
};
|
73 |
}();
|
74 |
+
|
75 |
Shield_Antibot.initialise();
|
76 |
}
|
resources/js/shield/dialog.js
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var Shield_Dialogs = new function () {
|
2 |
+
|
3 |
+
this.show = function ( $dialog, options ) {
|
4 |
+
$dialog.dialog( jQuery.extend( {
|
5 |
+
classes: {
|
6 |
+
'ui-dialog': 'shield_dialog'
|
7 |
+
}
|
8 |
+
}, options ) );
|
9 |
+
};
|
10 |
+
}();
|
resources/js/shield/navigation.js
CHANGED
@@ -43,7 +43,7 @@ jQuery.fn.icwpWpsfPluginNavigation = function ( options ) {
|
|
43 |
|
44 |
jQuery( document ).ready( function () {
|
45 |
|
46 |
-
jQuery( document ).on( 'click', '
|
47 |
evt.preventDefault();
|
48 |
currentMenuClickTarget = evt.currentTarget;
|
49 |
renderDynamicPageLoad( jQuery( currentMenuClickTarget ).data() );
|
43 |
|
44 |
jQuery( document ).ready( function () {
|
45 |
|
46 |
+
jQuery( document ).on( 'click', 'a.dynamic_body_load', function ( evt ) {
|
47 |
evt.preventDefault();
|
48 |
currentMenuClickTarget = evt.currentTarget;
|
49 |
renderDynamicPageLoad( jQuery( currentMenuClickTarget ).data() );
|
resources/js/shield/tours.js
CHANGED
@@ -8,16 +8,33 @@ jQuery.fn.icwpWpsfTours = function ( options ) {
|
|
8 |
} );
|
9 |
}
|
10 |
|
11 |
-
var setupTour = function (
|
12 |
-
introJs().setOptions( getTourSettings(
|
13 |
.onexit( function () {
|
14 |
-
markTourFinished(
|
15 |
} )
|
16 |
.start();
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
var getTourSettings = function ( tourKey ) {
|
20 |
return {
|
|
|
21 |
overlayOpacity: 0.7,
|
22 |
highlightClass: "tour-" + tourKey,
|
23 |
tooltipClass: "shield_tour_tooltip",
|
8 |
} );
|
9 |
}
|
10 |
|
11 |
+
var setupTour = function ( tourKey ) {
|
12 |
+
introJs().setOptions( getTourSettings( tourKey ) )
|
13 |
.onexit( function () {
|
14 |
+
markTourFinished( tourKey );
|
15 |
} )
|
16 |
.start();
|
17 |
}
|
18 |
|
19 |
+
var buildStepsForTour = function ( tourKey ) {
|
20 |
+
let steps = [];
|
21 |
+
let tourItems = document.querySelectorAll( '.tour-' + tourKey );
|
22 |
+
for ( var i = 0; i < tourItems.length; i++ ) {
|
23 |
+
let step = {
|
24 |
+
element: tourItems[ i ],
|
25 |
+
intro: tourItems[ i ].dataset.intro
|
26 |
+
};
|
27 |
+
if ( typeof tourItems[ i ].dataset.introtitle !== typeof undefined ) {
|
28 |
+
step.title = tourItems[ i ].dataset.introtitle;
|
29 |
+
}
|
30 |
+
steps.push(step);
|
31 |
+
}
|
32 |
+
return steps;
|
33 |
+
}
|
34 |
+
|
35 |
var getTourSettings = function ( tourKey ) {
|
36 |
return {
|
37 |
+
steps: buildStepsForTour( tourKey ),
|
38 |
overlayOpacity: 0.7,
|
39 |
highlightClass: "tour-" + tourKey,
|
40 |
tooltipClass: "shield_tour_tooltip",
|
resources/js/shield/u2f-admin.js
DELETED
@@ -1,64 +0,0 @@
|
|
1 |
-
if ( typeof icwp_wpsf_vars_u2f !== 'undefined' ) {
|
2 |
-
jQuery( document ).ready( function () {
|
3 |
-
|
4 |
-
let $oBtnReg = jQuery( 'button#icwp_u2f_key_reg' );
|
5 |
-
let $oU2fStatus = jQuery( '#icwp_u2f_section p.description' );
|
6 |
-
let oLabelRegEx = new RegExp( "^[a-zA-Z0-9_-]{1,16}$" );
|
7 |
-
|
8 |
-
u2fApi.isSupported()
|
9 |
-
.then( function ( supported ) {
|
10 |
-
if ( supported ) {
|
11 |
-
$oBtnReg.prop( 'disabled', false );
|
12 |
-
$oBtnReg.on( 'click', function () {
|
13 |
-
let label = prompt( icwp_wpsf_vars_u2f.strings.prompt_dialog, "<Insert Label>" );
|
14 |
-
if ( typeof label === 'undefined' || label === null ) {
|
15 |
-
alert( icwp_wpsf_vars_u2f.strings.err_no_label )
|
16 |
-
}
|
17 |
-
else if ( !oLabelRegEx.test( label ) ) {
|
18 |
-
alert( icwp_wpsf_vars_u2f.strings.err_invalid_label )
|
19 |
-
}
|
20 |
-
else {
|
21 |
-
u2fApi.register( icwp_wpsf_vars_u2f.reg_request, icwp_wpsf_vars_u2f.signs )
|
22 |
-
.then( function ( response ) {
|
23 |
-
response.label = label;
|
24 |
-
jQuery( '#icwp_wpsf_new_u2f_response' ).val( JSON.stringify( response ) )
|
25 |
-
$oU2fStatus.text( icwp_wpsf_vars_u2f.strings.do_save );
|
26 |
-
$oU2fStatus.css( 'font-weight', 'bolder' )
|
27 |
-
.css( 'color', 'green' );
|
28 |
-
} )
|
29 |
-
.catch( function ( response ) {
|
30 |
-
$oU2fStatus.text( icwp_wpsf_vars_u2f.strings.failed );
|
31 |
-
$oU2fStatus.css( 'font-weight', 'bolder' )
|
32 |
-
.css( 'color', 'red' );
|
33 |
-
} );
|
34 |
-
}
|
35 |
-
} );
|
36 |
-
}
|
37 |
-
else {
|
38 |
-
$oBtnReg.prop( 'disabled', true );
|
39 |
-
$oU2fStatus.text( icwp_wpsf_vars_u2f.strings.not_supported );
|
40 |
-
}
|
41 |
-
} )
|
42 |
-
.catch();
|
43 |
-
|
44 |
-
} );
|
45 |
-
|
46 |
-
jQuery.fn.icwpWpsfProfileU2f = function () {
|
47 |
-
|
48 |
-
var initialise = function () {
|
49 |
-
jQuery( document ).ready( function () {
|
50 |
-
jQuery( 'a.icwpWpsf-U2FRemove' ).on( 'click', function ( evt ) {
|
51 |
-
evt.preventDefault();
|
52 |
-
icwp_wpsf_vars_u2f.ajax.u2f_remove.u2fid = jQuery( evt.currentTarget ).data( 'u2fid' );
|
53 |
-
iCWP_WPSF_StandardAjax.send_ajax_req( icwp_wpsf_vars_u2f.ajax.u2f_remove );
|
54 |
-
return false;
|
55 |
-
} )
|
56 |
-
} );
|
57 |
-
};
|
58 |
-
|
59 |
-
initialise();
|
60 |
-
return this;
|
61 |
-
};
|
62 |
-
|
63 |
-
jQuery( document ).icwpWpsfProfileU2f();
|
64 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resources/js/shield/userprofile.js
CHANGED
@@ -1,21 +1,186 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
} );
|
14 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
};
|
19 |
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/** @var object shield_vars_userprofile */
|
2 |
+
jQuery.fn.ShieldUserProfile = function ( options ) {
|
3 |
+
|
4 |
+
let $emailCheckbox = jQuery( 'input[type=checkbox]#shield_enable_mfaemail' );
|
5 |
+
let $dialog = jQuery( '#ShieldMfaDialog' );
|
6 |
+
let $emailStartState;
|
7 |
+
|
8 |
+
let initGA = function ( shield_vars ) {
|
9 |
+
let $gaCode = jQuery( 'input[type=text]#shield_gacode' );
|
10 |
+
if ( $gaCode.length > 0 ) {
|
11 |
+
jQuery( document ).on( 'change, keyup', $gaCode, function ( evt ) {
|
12 |
+
$gaCode.val( $gaCode.val()
|
13 |
+
.replace( /[^A-F0-9]/gi, '' )
|
14 |
+
.toUpperCase()
|
15 |
+
.substring( 0, 6 )
|
16 |
+
);
|
17 |
+
if ( $gaCode.val().length === 6 ) {
|
18 |
+
$gaCode.prop( 'disabled', 'disabled' );
|
19 |
+
shield_vars.ajax.user_ga_toggle.ga_otp = $gaCode.val();
|
20 |
+
sendReq( shield_vars.ajax.user_ga_toggle );
|
21 |
+
}
|
22 |
} );
|
23 |
+
}
|
24 |
+
|
25 |
+
jQuery( document ).on( 'click', '#shield_ga_remove', function ( evt ) {
|
26 |
+
sendReq( shield_vars.ajax.user_ga_toggle );
|
27 |
+
} );
|
28 |
+
}
|
29 |
+
|
30 |
+
let initMfaRemoveAll = function () {
|
31 |
+
jQuery( document ).on( 'click', 'button#ShieldMfaRemoveAll', function ( evt ) {
|
32 |
+
if ( confirm( shield_vars_userprofile.strings.are_you_sure ) ) {
|
33 |
+
shield_vars_userprofile.ajax.mfa_remove_all.user_id = jQuery( evt.currentTarget ).data( 'user_id' );
|
34 |
+
sendReq( shield_vars_userprofile.ajax.mfa_remove_all );
|
35 |
+
}
|
36 |
+
} );
|
37 |
+
};
|
38 |
+
|
39 |
+
let initBackupcodes = function ( shield_vars ) {
|
40 |
+
jQuery( document ).on( 'click', '#IcwpWpsfGenBackupLoginCode', function ( evt ) {
|
41 |
+
sendReq( shield_vars.ajax.gen_backup_codes );
|
42 |
+
} );
|
43 |
+
jQuery( document ).on( 'click', '#IcwpWpsfDelBackupLoginCode', function ( evt ) {
|
44 |
+
sendReq( shield_vars.ajax.del_backup_codes );
|
45 |
+
} );
|
46 |
+
};
|
47 |
+
|
48 |
+
let initYubi = function ( shield_vars ) {
|
49 |
+
let $yubiText = jQuery( 'input[type=text]#shield_yubi' );
|
50 |
+
jQuery( document ).on( 'keyup', $yubiText, function ( evt ) {
|
51 |
+
if ( evt.key === 'Enter' || evt.keyCode === 13 ) {
|
52 |
+
shield_vars.ajax.user_yubikey_toggle.otp = $yubiText.val();
|
53 |
+
sendReq( shield_vars.ajax.user_yubikey_toggle );
|
54 |
+
}
|
55 |
+
} );
|
56 |
+
|
57 |
+
jQuery( 'a.shield_yubi_remove' ).on( 'click', function ( evt ) {
|
58 |
+
evt.preventDefault();
|
59 |
+
shield_vars.ajax.user_yubikey_toggle.otp = jQuery( evt.currentTarget ).data( 'yubikeyid' );
|
60 |
+
sendReq( shield_vars.ajax.user_yubikey_toggle );
|
61 |
+
return false;
|
62 |
+
} )
|
63 |
+
};
|
64 |
+
|
65 |
+
let initEmail = function ( shield_vars ) {
|
66 |
+
$emailStartState = $emailCheckbox.is( ':checked' );
|
67 |
+
jQuery( document ).on( 'change', $emailCheckbox, function ( evt ) {
|
68 |
+
if ( $emailStartState !== $emailCheckbox.is( ':checked' ) ) {
|
69 |
+
$emailCheckbox.prop( 'disabled', true );
|
70 |
+
shield_vars.ajax.user_email2fa_toggle.direction = $emailCheckbox.is( ':checked' ) ? 'on' : 'off';
|
71 |
+
sendReq( shield_vars.ajax.user_email2fa_toggle );
|
72 |
+
}
|
73 |
+
} );
|
74 |
+
}
|
75 |
+
|
76 |
+
let initU2f = function ( shield_vars ) {
|
77 |
|
78 |
+
let $registerButton = jQuery( 'button#icwp_u2f_key_reg' );
|
79 |
+
let $oU2fStatus = jQuery( '#icwp_u2f_section p.description' );
|
80 |
+
let oLabelRegEx = new RegExp( "^[a-zA-Z0-9_-]{1,16}$" );
|
81 |
+
|
82 |
+
u2fApi.isSupported()
|
83 |
+
.then( function ( supported ) {
|
84 |
+
if ( supported ) {
|
85 |
+
$registerButton.prop( 'disabled', false );
|
86 |
+
$registerButton.on( 'click', function () {
|
87 |
+
let label = prompt( shield_vars.strings.prompt_dialog, "<Insert Label>" );
|
88 |
+
if ( typeof label === 'undefined' || label === null ) {
|
89 |
+
alert( shield_vars.strings.err_no_label )
|
90 |
+
}
|
91 |
+
else if ( !oLabelRegEx.test( label ) ) {
|
92 |
+
alert( shield_vars.strings.err_invalid_label )
|
93 |
+
}
|
94 |
+
else {
|
95 |
+
u2fApi.register( shield_vars.reg_request, shield_vars.signs )
|
96 |
+
.then( function ( u2fResponse ) {
|
97 |
+
u2fResponse.label = label;
|
98 |
+
shield_vars.ajax.u2f_add.icwp_wpsf_new_u2f_response = u2fResponse;
|
99 |
+
sendReq( shield_vars.ajax.u2f_add );
|
100 |
+
} )
|
101 |
+
.catch( function ( response ) {
|
102 |
+
$oU2fStatus.text( shield_vars.strings.failed );
|
103 |
+
$oU2fStatus.css( 'font-weight', 'bolder' )
|
104 |
+
.css( 'color', 'red' );
|
105 |
+
} );
|
106 |
+
}
|
107 |
+
} );
|
108 |
+
}
|
109 |
+
else {
|
110 |
+
$registerButton.prop( 'disabled', true );
|
111 |
+
$oU2fStatus.text( shield_vars.strings.not_supported );
|
112 |
+
}
|
113 |
+
} )
|
114 |
+
.catch();
|
115 |
+
|
116 |
+
jQuery( 'a.icwpWpsf-U2FRemove' ).on( 'click', function ( evt ) {
|
117 |
+
evt.preventDefault();
|
118 |
+
shield_vars.ajax.u2f_remove.u2fid = jQuery( evt.currentTarget ).data( 'u2fid' );
|
119 |
+
sendReq( shield_vars.ajax.u2f_remove );
|
120 |
+
return false;
|
121 |
+
} );
|
122 |
+
};
|
123 |
+
|
124 |
+
var sendReq = function ( reqParams ) {
|
125 |
+
let ajaxurl = reqParams.ajaxurl;
|
126 |
+
delete reqParams.ajaxurl;
|
127 |
+
|
128 |
+
jQuery( 'body' ).css( 'cursor', 'progress' );
|
129 |
+
jQuery.post( ajaxurl, reqParams, function ( response ) {
|
130 |
+
|
131 |
+
let msg = 'Communications error with site.';
|
132 |
+
if ( response.data.message !== undefined ) {
|
133 |
+
msg = response.data.message;
|
134 |
+
}
|
135 |
+
|
136 |
+
showDialog( response.data.success, msg )
|
137 |
+
}
|
138 |
+
).always( function () {
|
139 |
+
}
|
140 |
+
);
|
141 |
+
};
|
142 |
+
|
143 |
+
var showDialog = function ( success, msg ) {
|
144 |
+
jQuery( '.dialog-content', $dialog ).html( msg );
|
145 |
+
Shield_Dialogs.show($dialog, {
|
146 |
+
title: success ? 'Success' : 'Failure',
|
147 |
+
buttons: [
|
148 |
+
{
|
149 |
+
text: 'OK',
|
150 |
+
click: function () {
|
151 |
+
jQuery( this ).dialog( 'close' );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
],
|
155 |
+
close: function ( event, ui ) {
|
156 |
+
location.reload();
|
157 |
+
}
|
158 |
+
});
|
159 |
};
|
160 |
|
161 |
+
var initialise = function () {
|
162 |
+
jQuery( document ).ready( function () {
|
163 |
+
if ( typeof shield_vars_userprofile.vars.providers.u2f !== typeof undefined ) {
|
164 |
+
initU2f( shield_vars_userprofile.vars.providers.u2f );
|
165 |
+
}
|
166 |
+
if ( typeof shield_vars_userprofile.vars.providers.ga !== typeof undefined ) {
|
167 |
+
initGA( shield_vars_userprofile.vars.providers.ga );
|
168 |
+
}
|
169 |
+
if ( typeof shield_vars_userprofile.vars.providers.email !== typeof undefined ) {
|
170 |
+
initEmail( shield_vars_userprofile.vars.providers.email );
|
171 |
+
}
|
172 |
+
if ( typeof shield_vars_userprofile.vars.providers.yubi !== typeof undefined ) {
|
173 |
+
initYubi( shield_vars_userprofile.vars.providers.yubi );
|
174 |
+
}
|
175 |
+
if ( typeof shield_vars_userprofile.vars.providers.backupcode !== typeof undefined ) {
|
176 |
+
initBackupcodes( shield_vars_userprofile.vars.providers.backupcode );
|
177 |
+
}
|
178 |
+
initMfaRemoveAll();
|
179 |
+
} );
|
180 |
+
};
|
181 |
+
|
182 |
+
initialise();
|
183 |
+
|
184 |
+
return this;
|
185 |
+
};
|
186 |
+
jQuery( document ).ShieldUserProfile();
|
resources/js/shield/wizard.js
ADDED
File without changes
|
src/config/feature-autoupdates.php
CHANGED
@@ -67,7 +67,7 @@
|
|
67 |
"default": "N",
|
68 |
"type": "checkbox",
|
69 |
"link_info": "https://shsec.io/3v",
|
70 |
-
"link_blog": "",
|
71 |
"name": "Disable All",
|
72 |
"summary": "Completely Disable WordPress Automatic Updates",
|
73 |
"description": "When selected, regardless of any other settings, all WordPress automatic updates on this site will be completely disabled!"
|
@@ -91,7 +91,7 @@
|
|
91 |
"text": "Major and Minor Versions"
|
92 |
}
|
93 |
],
|
94 |
-
"link_info": "https://shsec.io/
|
95 |
"link_blog": "",
|
96 |
"name": "WordPress Core Updates",
|
97 |
"summary": "Decide how the WordPress Core will automatically update, if at all",
|
67 |
"default": "N",
|
68 |
"type": "checkbox",
|
69 |
"link_info": "https://shsec.io/3v",
|
70 |
+
"link_blog": "https://shsec.io/k6",
|
71 |
"name": "Disable All",
|
72 |
"summary": "Completely Disable WordPress Automatic Updates",
|
73 |
"description": "When selected, regardless of any other settings, all WordPress automatic updates on this site will be completely disabled!"
|
91 |
"text": "Major and Minor Versions"
|
92 |
}
|
93 |
],
|
94 |
+
"link_info": "https://shsec.io/k5",
|
95 |
"link_blog": "",
|
96 |
"name": "WordPress Core Updates",
|
97 |
"summary": "Decide how the WordPress Core will automatically update, if at all",
|
src/config/feature-comments_filter.php
CHANGED
@@ -124,7 +124,7 @@
|
|
124 |
"section": "section_bot_comment_spam_protection_filter",
|
125 |
"default": "N",
|
126 |
"type": "checkbox",
|
127 |
-
"link_info": "https://shsec.io/
|
128 |
"link_blog": "https://shsec.io/jo",
|
129 |
"name": "AntiBot Detection Engine",
|
130 |
"summary": "Use Experimental AntiBot Detection Engine",
|
124 |
"section": "section_bot_comment_spam_protection_filter",
|
125 |
"default": "N",
|
126 |
"type": "checkbox",
|
127 |
+
"link_info": "https://shsec.io/k1",
|
128 |
"link_blog": "https://shsec.io/jo",
|
129 |
"name": "AntiBot Detection Engine",
|
130 |
"summary": "Use Experimental AntiBot Detection Engine",
|
src/config/feature-integrations.php
CHANGED
@@ -5,6 +5,7 @@
|
|
5 |
"storage_key": "integrations",
|
6 |
"name": "Integrations",
|
7 |
"menu_title": "Integrations",
|
|
|
8 |
"show_module_options": true,
|
9 |
"show_module_menu_item": false,
|
10 |
"auto_enabled": true,
|
@@ -32,6 +33,11 @@
|
|
32 |
"title": "SPAM Detection",
|
33 |
"title_short": "SPAM Detection"
|
34 |
},
|
|
|
|
|
|
|
|
|
|
|
35 |
{
|
36 |
"slug": "section_non_ui",
|
37 |
"hidden": true
|
@@ -49,18 +55,6 @@
|
|
49 |
"summary": "Enable The Built-In MainWP Extension",
|
50 |
"description": "This option will enable Shield's built-in MainWP extension for both server and client."
|
51 |
},
|
52 |
-
{
|
53 |
-
"key": "enable_spam_antibot",
|
54 |
-
"section": "section_spam",
|
55 |
-
"premium": true,
|
56 |
-
"default": "N",
|
57 |
-
"type": "checkbox",
|
58 |
-
"link_info": "",
|
59 |
-
"link_blog": "",
|
60 |
-
"name": "AntiBot SPAM Detection",
|
61 |
-
"summary": "Enable The AntiBot SPAM Detection",
|
62 |
-
"description": "Use Shield's built-in AntiBot Detection Engine to identify contact form SPAM."
|
63 |
-
},
|
64 |
{
|
65 |
"key": "form_spam_providers",
|
66 |
"section": "section_spam",
|
@@ -93,6 +87,10 @@
|
|
93 |
"value_key": "gravityforms",
|
94 |
"text": "Gravity Forms"
|
95 |
},
|
|
|
|
|
|
|
|
|
96 |
{
|
97 |
"value_key": "kaliforms",
|
98 |
"text": "Kali Forms"
|
@@ -110,11 +108,70 @@
|
|
110 |
"text": "WPForms"
|
111 |
}
|
112 |
],
|
113 |
-
"link_info": "",
|
114 |
-
"link_blog": "",
|
115 |
"name": "SPAM Form Checking",
|
116 |
"summary": "Select The Form Providers That Should Be Checked For SPAM",
|
117 |
"description": "Select The Form Providers That Should Be Checked For SPAM."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
}
|
119 |
],
|
120 |
"definitions": {
|
@@ -128,6 +185,16 @@
|
|
128 |
"stat": true,
|
129 |
"audit": true,
|
130 |
"offense": false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
}
|
133 |
}
|
5 |
"storage_key": "integrations",
|
6 |
"name": "Integrations",
|
7 |
"menu_title": "Integrations",
|
8 |
+
"sidebar_name": "3rd Party Integrations",
|
9 |
"show_module_options": true,
|
10 |
"show_module_menu_item": false,
|
11 |
"auto_enabled": true,
|
33 |
"title": "SPAM Detection",
|
34 |
"title_short": "SPAM Detection"
|
35 |
},
|
36 |
+
{
|
37 |
+
"slug": "section_user_forms",
|
38 |
+
"title": "User Forms Bot Detection",
|
39 |
+
"title_short": "User Forms Bot Detection"
|
40 |
+
},
|
41 |
{
|
42 |
"slug": "section_non_ui",
|
43 |
"hidden": true
|
55 |
"summary": "Enable The Built-In MainWP Extension",
|
56 |
"description": "This option will enable Shield's built-in MainWP extension for both server and client."
|
57 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
{
|
59 |
"key": "form_spam_providers",
|
60 |
"section": "section_spam",
|
87 |
"value_key": "gravityforms",
|
88 |
"text": "Gravity Forms"
|
89 |
},
|
90 |
+
{
|
91 |
+
"value_key": "groundhogg",
|
92 |
+
"text": "Groundhogg"
|
93 |
+
},
|
94 |
{
|
95 |
"value_key": "kaliforms",
|
96 |
"text": "Kali Forms"
|
108 |
"text": "WPForms"
|
109 |
}
|
110 |
],
|
111 |
+
"link_info": "https://shsec.io/k2",
|
112 |
+
"link_blog": "https://shsec.io/k3",
|
113 |
"name": "SPAM Form Checking",
|
114 |
"summary": "Select The Form Providers That Should Be Checked For SPAM",
|
115 |
"description": "Select The Form Providers That Should Be Checked For SPAM."
|
116 |
+
},
|
117 |
+
{
|
118 |
+
"key": "user_form_providers",
|
119 |
+
"section": "section_user_forms",
|
120 |
+
"premium": true,
|
121 |
+
"advanced": true,
|
122 |
+
"type": "multiple_select",
|
123 |
+
"default": [ "wordpress" ],
|
124 |
+
"value_options": [
|
125 |
+
{
|
126 |
+
"value_key": "buddypress",
|
127 |
+
"text": "BuddyPress"
|
128 |
+
},
|
129 |
+
{
|
130 |
+
"value_key": "easydigitaldownloads",
|
131 |
+
"text": "Easy Digital Downloads"
|
132 |
+
},
|
133 |
+
{
|
134 |
+
"value_key": "learnpress",
|
135 |
+
"text": "LearnPress"
|
136 |
+
},
|
137 |
+
{
|
138 |
+
"value_key": "lifterlms",
|
139 |
+
"text": "LifterLMS"
|
140 |
+
},
|
141 |
+
{
|
142 |
+
"value_key": "memberpress",
|
143 |
+
"text": "MemberPress"
|
144 |
+
},
|
145 |
+
{
|
146 |
+
"value_key": "paidmembersubscriptions",
|
147 |
+
"text": "Paid Member Subscriptions"
|
148 |
+
},
|
149 |
+
{
|
150 |
+
"value_key": "profilebuilder",
|
151 |
+
"text": "Profile Builder"
|
152 |
+
},
|
153 |
+
{
|
154 |
+
"value_key": "ultimatemember",
|
155 |
+
"text": "Ultimate Member"
|
156 |
+
},
|
157 |
+
{
|
158 |
+
"value_key": "woocommerce",
|
159 |
+
"text": "WooCommerce"
|
160 |
+
},
|
161 |
+
{
|
162 |
+
"value_key": "wordpress",
|
163 |
+
"text": "WordPress"
|
164 |
+
},
|
165 |
+
{
|
166 |
+
"value_key": "wpmembers",
|
167 |
+
"text": "WP Members"
|
168 |
+
}
|
169 |
+
],
|
170 |
+
"link_info": "https://shsec.io/k4",
|
171 |
+
"link_blog": "https://shsec.io/k3",
|
172 |
+
"name": "User Form Checking",
|
173 |
+
"summary": "Select The User Form Providers That Should Be Checked For SPAM Registrations and Logins",
|
174 |
+
"description": "Select The User Form Providers That Should Be Checked For SPAM Registrations and Logins"
|
175 |
}
|
176 |
],
|
177 |
"definitions": {
|
185 |
"stat": true,
|
186 |
"audit": true,
|
187 |
"offense": false
|
188 |
+
},
|
189 |
+
"user_form_bot_pass": {
|
190 |
+
"stat": true,
|
191 |
+
"audit": true,
|
192 |
+
"offense": false
|
193 |
+
},
|
194 |
+
"user_form_bot_fail": {
|
195 |
+
"stat": true,
|
196 |
+
"audit": true,
|
197 |
+
"offense": true
|
198 |
}
|
199 |
}
|
200 |
}
|
src/config/feature-ips.php
CHANGED
@@ -18,7 +18,7 @@
|
|
18 |
},
|
19 |
"menu_items": [
|
20 |
{
|
21 |
-
"title": "IP
|
22 |
"slug": "ips-redirect"
|
23 |
}
|
24 |
],
|
@@ -149,8 +149,8 @@
|
|
149 |
"type": "integer",
|
150 |
"min": 1,
|
151 |
"max": 99,
|
152 |
-
"link_info": "",
|
153 |
-
"link_blog": "",
|
154 |
"name": "AntiBot Threshold",
|
155 |
"summary": "AntiBot Testing Threshold (Percentage)",
|
156 |
"description": "When using Shield's AntiBot system, this is the threshold used for testing (between 1 and 99)."
|
@@ -580,6 +580,7 @@
|
|
580 |
"cols_timestamps": {
|
581 |
"notbot_at": "NotBot",
|
582 |
"frontpage_at": "Front Page Loaded",
|
|
|
583 |
"bt404_at": "BotTrack 404",
|
584 |
"btfake_at": "BotTrack FakeWebCrawler",
|
585 |
"btcheese_at": "BotTrack LinkCheese",
|
18 |
},
|
19 |
"menu_items": [
|
20 |
{
|
21 |
+
"title": "IP Manager",
|
22 |
"slug": "ips-redirect"
|
23 |
}
|
24 |
],
|
149 |
"type": "integer",
|
150 |
"min": 1,
|
151 |
"max": 99,
|
152 |
+
"link_info": "https://shsec.io/jy",
|
153 |
+
"link_blog": "https://shsec.io/jz",
|
154 |
"name": "AntiBot Threshold",
|
155 |
"summary": "AntiBot Testing Threshold (Percentage)",
|
156 |
"description": "When using Shield's AntiBot system, this is the threshold used for testing (between 1 and 99)."
|
580 |
"cols_timestamps": {
|
581 |
"notbot_at": "NotBot",
|
582 |
"frontpage_at": "Front Page Loaded",
|
583 |
+
"loginpage_at": "Login Page Loaded",
|
584 |
"bt404_at": "BotTrack 404",
|
585 |
"btfake_at": "BotTrack FakeWebCrawler",
|
586 |
"btcheese_at": "BotTrack LinkCheese",
|
src/config/feature-login_protect.php
CHANGED
@@ -265,6 +265,17 @@
|
|
265 |
"summary": "Allow Any User To Turn-On Two-Factor Authentication By Email",
|
266 |
"description": "Allow Any User To Turn-On Two-Factor Authentication By Email."
|
267 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
{
|
269 |
"key": "bot_protection_locations",
|
270 |
"section": "section_brute_force_login_protection",
|
@@ -299,7 +310,7 @@
|
|
299 |
{
|
300 |
"key": "login_limit_interval",
|
301 |
"section": "section_brute_force_login_protection",
|
302 |
-
"default": "
|
303 |
"min": 0,
|
304 |
"type": "integer",
|
305 |
"link_info": "https://shsec.io/3q",
|
@@ -308,17 +319,6 @@
|
|
308 |
"summary": "Limit login attempts to every X seconds",
|
309 |
"description": "WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off."
|
310 |
},
|
311 |
-
{
|
312 |
-
"key": "enable_antibot_check",
|
313 |
-
"section": "section_brute_force_login_protection",
|
314 |
-
"default": "N",
|
315 |
-
"type": "checkbox",
|
316 |
-
"link_info": "https://shsec.io/jn",
|
317 |
-
"link_blog": "https://shsec.io/jo",
|
318 |
-
"name": "AntiBot",
|
319 |
-
"summary": "Use Experimental AntiBot Detection Engine",
|
320 |
-
"description": "Use Shield's AntiBot Detection Engine In-Place of GASP/CAPTCHA Bot checking."
|
321 |
-
},
|
322 |
{
|
323 |
"key": "enable_login_gasp_check",
|
324 |
"section": "section_brute_force_login_protection",
|
265 |
"summary": "Allow Any User To Turn-On Two-Factor Authentication By Email",
|
266 |
"description": "Allow Any User To Turn-On Two-Factor Authentication By Email."
|
267 |
},
|
268 |
+
{
|
269 |
+
"key": "enable_antibot_check",
|
270 |
+
"section": "section_brute_force_login_protection",
|
271 |
+
"default": "N",
|
272 |
+
"type": "checkbox",
|
273 |
+
"link_info": "https://shsec.io/k0",
|
274 |
+
"link_blog": "https://shsec.io/jo",
|
275 |
+
"name": "AntiBot",
|
276 |
+
"summary": "Use Experimental AntiBot Detection Engine",
|
277 |
+
"description": "Use Shield's AntiBot Detection Engine In-Place of GASP/CAPTCHA Bot checking."
|
278 |
+
},
|
279 |
{
|
280 |
"key": "bot_protection_locations",
|
281 |
"section": "section_brute_force_login_protection",
|
310 |
{
|
311 |
"key": "login_limit_interval",
|
312 |
"section": "section_brute_force_login_protection",
|
313 |
+
"default": "5",
|
314 |
"min": 0,
|
315 |
"type": "integer",
|
316 |
"link_info": "https://shsec.io/3q",
|
319 |
"summary": "Limit login attempts to every X seconds",
|
320 |
"description": "WordPress will process only ONE login attempt for every number of seconds specified. Zero (0) turns this off."
|
321 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
{
|
323 |
"key": "enable_login_gasp_check",
|
324 |
"section": "section_brute_force_login_protection",
|
src/config/feature-plugin.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
"slug": "plugin",
|
4 |
"name": "General Settings",
|
5 |
"sidebar_name": "General",
|
6 |
-
"menu_title": "
|
7 |
"show_module_menu_item": true,
|
8 |
"show_module_options": true,
|
9 |
"storage_key": "plugin",
|
@@ -267,7 +267,7 @@
|
|
267 |
"link_info": "https://shsec.io/5v",
|
268 |
"link_blog": "https://shsec.io/wpsf20",
|
269 |
"name": "Show Plugin Badge",
|
270 |
-
"summary": "Display Plugin Badge On Your Site",
|
271 |
"description": "Enabling this option helps support the plugin by spreading the word about it on your website. The plugin badge also demonstrates to visitors that you take your website security seriously."
|
272 |
},
|
273 |
{
|
@@ -529,32 +529,32 @@
|
|
529 |
}
|
530 |
],
|
531 |
"definitions": {
|
532 |
-
"help_video_id":
|
533 |
-
"tracking_cron_handle":
|
534 |
-
"tracking_post_url":
|
535 |
-
"importexport_cron_name":
|
536 |
-
"href_privacy_policy":
|
537 |
-
"db_classes":
|
538 |
"geoip": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\GeoIp\\Handler",
|
539 |
"notes": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Handler"
|
540 |
},
|
541 |
-
"db_table_notes":
|
542 |
-
"slug":
|
543 |
-
"has_updated_at":
|
544 |
-
"cols_custom":
|
545 |
"wp_username": "varchar(255) NOT NULL DEFAULT 'unknown'",
|
546 |
"note": "TEXT"
|
547 |
}
|
548 |
},
|
549 |
-
"db_table_geoip":
|
550 |
-
"autoexpire":
|
551 |
-
"slug":
|
552 |
-
"cols_custom":
|
553 |
"ip": "varbinary(16) DEFAULT NULL COMMENT 'IP Address'",
|
554 |
"meta": "TEXT"
|
555 |
}
|
556 |
},
|
557 |
-
"active_plugin_features":
|
558 |
{
|
559 |
"slug": "insights",
|
560 |
"load_priority": 1,
|
@@ -635,7 +635,7 @@
|
|
635 |
"slug": "email"
|
636 |
}
|
637 |
],
|
638 |
-
"events":
|
639 |
"test_cron_run": {
|
640 |
"audit": false,
|
641 |
"recent": true
|
@@ -681,9 +681,14 @@
|
|
681 |
"offense": false,
|
682 |
"stat": false,
|
683 |
"audit": false
|
|
|
|
|
|
|
|
|
|
|
684 |
}
|
685 |
},
|
686 |
-
"wizards":
|
687 |
"welcome": {
|
688 |
"title": "Getting Started Setup Wizard",
|
689 |
"desc": "An introduction to this security plugin, helping you get setup and started quickly with the core features.",
|
@@ -711,8 +716,14 @@
|
|
711 |
"comments_filter": {
|
712 |
"title": "Comment SPAM"
|
713 |
},
|
714 |
-
"
|
715 |
-
"title": "
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
},
|
717 |
"optin": {
|
718 |
"title": "Join Us!"
|
3 |
"slug": "plugin",
|
4 |
"name": "General Settings",
|
5 |
"sidebar_name": "General",
|
6 |
+
"menu_title": "Configuration",
|
7 |
"show_module_menu_item": true,
|
8 |
"show_module_options": true,
|
9 |
"storage_key": "plugin",
|
267 |
"link_info": "https://shsec.io/5v",
|
268 |
"link_blog": "https://shsec.io/wpsf20",
|
269 |
"name": "Show Plugin Badge",
|
270 |
+
"summary": "Display Plugin Security Badge On Your Site",
|
271 |
"description": "Enabling this option helps support the plugin by spreading the word about it on your website. The plugin badge also demonstrates to visitors that you take your website security seriously."
|
272 |
},
|
273 |
{
|
529 |
}
|
530 |
],
|
531 |
"definitions": {
|
532 |
+
"help_video_id": "",
|
533 |
+
"tracking_cron_handle": "plugin_tracking_cron",
|
534 |
+
"tracking_post_url": "https://tracking.icontrolwp.com/track/plugin/shield",
|
535 |
+
"importexport_cron_name": "autoimport",
|
536 |
+
"href_privacy_policy": "https://shsec.io/wpshieldprivacypolicy",
|
537 |
+
"db_classes": {
|
538 |
"geoip": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\GeoIp\\Handler",
|
539 |
"notes": "\\FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Handler"
|
540 |
},
|
541 |
+
"db_table_notes": {
|
542 |
+
"slug": "notes",
|
543 |
+
"has_updated_at": true,
|
544 |
+
"cols_custom": {
|
545 |
"wp_username": "varchar(255) NOT NULL DEFAULT 'unknown'",
|
546 |
"note": "TEXT"
|
547 |
}
|
548 |
},
|
549 |
+
"db_table_geoip": {
|
550 |
+
"autoexpire": 30,
|
551 |
+
"slug": "geoip",
|
552 |
+
"cols_custom": {
|
553 |
"ip": "varbinary(16) DEFAULT NULL COMMENT 'IP Address'",
|
554 |
"meta": "TEXT"
|
555 |
}
|
556 |
},
|
557 |
+
"active_plugin_features": [
|
558 |
{
|
559 |
"slug": "insights",
|
560 |
"load_priority": 1,
|
635 |
"slug": "email"
|
636 |
}
|
637 |
],
|
638 |
+
"events": {
|
639 |
"test_cron_run": {
|
640 |
"audit": false,
|
641 |
"recent": true
|
681 |
"offense": false,
|
682 |
"stat": false,
|
683 |
"audit": false
|
684 |
+
},
|
685 |
+
"loginpage_load": {
|
686 |
+
"offense": false,
|
687 |
+
"stat": false,
|
688 |
+
"audit": false
|
689 |
}
|
690 |
},
|
691 |
+
"wizards": {
|
692 |
"welcome": {
|
693 |
"title": "Getting Started Setup Wizard",
|
694 |
"desc": "An introduction to this security plugin, helping you get setup and started quickly with the core features.",
|
716 |
"comments_filter": {
|
717 |
"title": "Comment SPAM"
|
718 |
},
|
719 |
+
"plugin_badge": {
|
720 |
+
"title": "Security Badge"
|
721 |
+
},
|
722 |
+
"plugin_telemetry": {
|
723 |
+
"title": "Plugin Telemetry"
|
724 |
+
},
|
725 |
+
"free_trial": {
|
726 |
+
"title": "Free Trial"
|
727 |
},
|
728 |
"optin": {
|
729 |
"title": "Join Us!"
|
src/lib/src/Controller/Admin/MainAdminMenu.php
CHANGED
@@ -27,7 +27,6 @@ class MainAdminMenu {
|
|
27 |
|
28 |
private function createAdminMenu() {
|
29 |
$con = $this->getCon();
|
30 |
-
|
31 |
$menu = $con->cfg->menu;
|
32 |
if ( $menu[ 'top_level' ] ) {
|
33 |
|
@@ -51,23 +50,8 @@ class MainAdminMenu {
|
|
51 |
);
|
52 |
|
53 |
if ( $menu[ 'has_submenu' ] ) {
|
54 |
-
|
55 |
-
$menuItems = apply_filters( $con->prefix( 'submenu_items' ), [] );
|
56 |
-
if ( !empty( $menuItems ) ) {
|
57 |
-
foreach ( $menuItems as $menuTitle => $menuItem ) {
|
58 |
-
list( $sMenuItemText, $sMenuItemId, $aMenuCallBack, $bShowItem ) = $menuItem;
|
59 |
-
add_submenu_page(
|
60 |
-
$bShowItem ? $parentMenuID : null,
|
61 |
-
$menuTitle,
|
62 |
-
$sMenuItemText,
|
63 |
-
$con->getBasePermissions(),
|
64 |
-
$sMenuItemId,
|
65 |
-
$aMenuCallBack
|
66 |
-
);
|
67 |
-
}
|
68 |
-
}
|
69 |
}
|
70 |
-
|
71 |
if ( $menu[ 'do_submenu_fix' ] ) {
|
72 |
$this->fixSubmenu();
|
73 |
}
|
27 |
|
28 |
private function createAdminMenu() {
|
29 |
$con = $this->getCon();
|
|
|
30 |
$menu = $con->cfg->menu;
|
31 |
if ( $menu[ 'top_level' ] ) {
|
32 |
|
50 |
);
|
51 |
|
52 |
if ( $menu[ 'has_submenu' ] ) {
|
53 |
+
do_action( $con->prefix( 'admin_submenu' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
}
|
|
|
55 |
if ( $menu[ 'do_submenu_fix' ] ) {
|
56 |
$this->fixSubmenu();
|
57 |
}
|
src/lib/src/Controller/Ajax/Response.php
CHANGED
@@ -7,7 +7,7 @@ use FernleafSystems\Wordpress\Services\Services;
|
|
7 |
class Response {
|
8 |
|
9 |
public function issue( array $response, $wrap = false ) {
|
10 |
-
$wrap = $wrap ||
|
11 |
|
12 |
if ( !headers_sent() ) {
|
13 |
header( 'Content-Type: application/json; charset='.get_option( 'blog_charset' ) );
|
7 |
class Response {
|
8 |
|
9 |
public function issue( array $response, $wrap = false ) {
|
10 |
+
$wrap = $wrap || Services::Request()->request( 'apto_wrap_response' );
|
11 |
|
12 |
if ( !headers_sent() ) {
|
13 |
header( 'Content-Type: application/json; charset='.get_option( 'blog_charset' ) );
|
src/lib/src/Controller/Assets/Enqueue.php
CHANGED
@@ -23,18 +23,43 @@ class Enqueue {
|
|
23 |
}
|
24 |
|
25 |
protected function run() {
|
|
|
26 |
add_action( 'login_enqueue_scripts', function () {
|
27 |
$this->enqueue();
|
|
|
|
|
|
|
28 |
}, 1000 );
|
|
|
29 |
add_action( 'wp_enqueue_scripts', function () {
|
30 |
$this->enqueue();
|
|
|
|
|
|
|
31 |
}, 1000 );
|
|
|
32 |
add_action( 'admin_enqueue_scripts', function ( $hook_suffix ) {
|
33 |
$this->adminHookSuffix = $hook_suffix;
|
34 |
$this->enqueue();
|
|
|
|
|
|
|
35 |
}, 1000 );
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
protected function enqueue() {
|
39 |
|
40 |
// Register all plugin assets
|
@@ -104,20 +129,26 @@ class Enqueue {
|
|
104 |
foreach ( $incl[ $type ] as $key => $spec ) {
|
105 |
if ( !in_array( $key, $assetKeys[ $type ] ) ) {
|
106 |
|
|
|
|
|
107 |
$handle = $this->normaliseHandle( $key );
|
108 |
if ( $type === self::CSS ) {
|
109 |
$reg = wp_register_style(
|
110 |
$handle,
|
111 |
$con->urls->forCss( $key ),
|
112 |
-
$this->prefixKeys( $
|
113 |
$con->getVersion()
|
114 |
);
|
115 |
}
|
116 |
else {
|
|
|
|
|
|
|
|
|
117 |
$reg = wp_register_script(
|
118 |
$handle,
|
119 |
$con->urls->forJs( $key ),
|
120 |
-
$this->prefixKeys( $
|
121 |
$con->getVersion(),
|
122 |
$spec[ 'footer' ] ?? false
|
123 |
);
|
23 |
}
|
24 |
|
25 |
protected function run() {
|
26 |
+
|
27 |
add_action( 'login_enqueue_scripts', function () {
|
28 |
$this->enqueue();
|
29 |
+
add_action( 'login_footer', function () {
|
30 |
+
$this->dequeue();
|
31 |
+
}, -1000 );
|
32 |
}, 1000 );
|
33 |
+
|
34 |
add_action( 'wp_enqueue_scripts', function () {
|
35 |
$this->enqueue();
|
36 |
+
add_action( 'wp_footer', function () {
|
37 |
+
$this->dequeue();
|
38 |
+
}, -1000 );
|
39 |
}, 1000 );
|
40 |
+
|
41 |
add_action( 'admin_enqueue_scripts', function ( $hook_suffix ) {
|
42 |
$this->adminHookSuffix = $hook_suffix;
|
43 |
$this->enqueue();
|
44 |
+
add_action( 'admin_footer', function () {
|
45 |
+
$this->dequeue();
|
46 |
+
}, -1000 );
|
47 |
}, 1000 );
|
48 |
}
|
49 |
|
50 |
+
protected function dequeue() {
|
51 |
+
$customDequeues = apply_filters( 'shield/custom_dequeues', [
|
52 |
+
self::CSS => [],
|
53 |
+
self::JS => [],
|
54 |
+
] );
|
55 |
+
foreach ( $customDequeues as $type => $assets ) {
|
56 |
+
foreach ( $assets as $asset ) {
|
57 |
+
$handle = $this->normaliseHandle( $asset );
|
58 |
+
$type == self::CSS ? wp_dequeue_style( $handle ) : wp_dequeue_script( $handle );
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
protected function enqueue() {
|
64 |
|
65 |
// Register all plugin assets
|
129 |
foreach ( $incl[ $type ] as $key => $spec ) {
|
130 |
if ( !in_array( $key, $assetKeys[ $type ] ) ) {
|
131 |
|
132 |
+
$deps = $spec[ 'deps' ] ?? [];
|
133 |
+
|
134 |
$handle = $this->normaliseHandle( $key );
|
135 |
if ( $type === self::CSS ) {
|
136 |
$reg = wp_register_style(
|
137 |
$handle,
|
138 |
$con->urls->forCss( $key ),
|
139 |
+
$this->prefixKeys( $deps ),
|
140 |
$con->getVersion()
|
141 |
);
|
142 |
}
|
143 |
else {
|
144 |
+
if ( strpos( $key, 'jquery/' ) ) {
|
145 |
+
array_unshift( $deps, 'wp-jquery' );
|
146 |
+
}
|
147 |
+
|
148 |
$reg = wp_register_script(
|
149 |
$handle,
|
150 |
$con->urls->forJs( $key ),
|
151 |
+
$this->prefixKeys( $deps ),
|
152 |
$con->getVersion(),
|
153 |
$spec[ 'footer' ] ?? false
|
154 |
);
|
src/lib/src/Controller/Assets/Svgs.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
|
8 |
+
class Svgs {
|
9 |
+
|
10 |
+
use PluginControllerConsumer;
|
11 |
+
|
12 |
+
public function raw( string $image ) :string {
|
13 |
+
return Services::WpFs()->getFileContent( $this->getCon()->paths->forImage( $image ) );
|
14 |
+
}
|
15 |
+
|
16 |
+
public function url( string $image ) :string {
|
17 |
+
return $this->getCon()->urls->forImage( $image );
|
18 |
+
}
|
19 |
+
}
|
src/lib/src/Controller/Controller.php
CHANGED
@@ -13,6 +13,7 @@ use FernleafSystems\Wordpress\Services\Utilities\Options\Transient;
|
|
13 |
* @property Config\ConfigVO $cfg
|
14 |
* @property Shield\Controller\Assets\Urls $urls
|
15 |
* @property Shield\Controller\Assets\Paths $paths
|
|
|
16 |
* @property bool $is_activating
|
17 |
* @property bool $is_debug
|
18 |
* @property bool $modules_loaded
|
@@ -163,6 +164,12 @@ class Controller extends DynPropertiesClass {
|
|
163 |
}
|
164 |
break;
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
case 'paths':
|
167 |
if ( !$val instanceof Shield\Controller\Assets\Paths ) {
|
168 |
$val = ( new Shield\Controller\Assets\Paths() )->setCon( $this );
|
@@ -530,12 +537,15 @@ class Controller extends DynPropertiesClass {
|
|
530 |
( new Shield\Controller\Assets\Enqueue() )
|
531 |
->setCon( $this )
|
532 |
->execute();
|
533 |
-
( new Admin\MainAdminMenu() )
|
534 |
-
->setCon( $this )
|
535 |
-
->execute();
|
536 |
( new Utilities\CaptureMyUpgrade() )
|
537 |
->setCon( $this )
|
538 |
->execute();
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
}
|
540 |
|
541 |
protected function initCrons() {
|
@@ -1372,6 +1382,10 @@ class Controller extends DynPropertiesClass {
|
|
1372 |
return $this->getModule( 'events' );
|
1373 |
}
|
1374 |
|
|
|
|
|
|
|
|
|
1375 |
public function getModule_HackGuard() :Shield\Modules\HackGuard\ModCon {
|
1376 |
return $this->getModule( 'hack_protect' );
|
1377 |
}
|
@@ -1591,7 +1605,7 @@ class Controller extends DynPropertiesClass {
|
|
1591 |
*/
|
1592 |
private function buildPrivacyPolicyContent() {
|
1593 |
try {
|
1594 |
-
if ( $this->getModule_SecAdmin()->
|
1595 |
$name = $this->getHumanName();
|
1596 |
$href = $this->getLabels()[ 'PluginURI' ];
|
1597 |
}
|
13 |
* @property Config\ConfigVO $cfg
|
14 |
* @property Shield\Controller\Assets\Urls $urls
|
15 |
* @property Shield\Controller\Assets\Paths $paths
|
16 |
+
* @property Shield\Controller\Assets\Svgs $svgs
|
17 |
* @property bool $is_activating
|
18 |
* @property bool $is_debug
|
19 |
* @property bool $modules_loaded
|
164 |
}
|
165 |
break;
|
166 |
|
167 |
+
case 'svgs':
|
168 |
+
if ( !$val instanceof Shield\Controller\Assets\Svgs ) {
|
169 |
+
$val = ( new Shield\Controller\Assets\Svgs() )->setCon( $this );
|
170 |
+
}
|
171 |
+
break;
|
172 |
+
|
173 |
case 'paths':
|
174 |
if ( !$val instanceof Shield\Controller\Assets\Paths ) {
|
175 |
$val = ( new Shield\Controller\Assets\Paths() )->setCon( $this );
|
537 |
( new Shield\Controller\Assets\Enqueue() )
|
538 |
->setCon( $this )
|
539 |
->execute();
|
|
|
|
|
|
|
540 |
( new Utilities\CaptureMyUpgrade() )
|
541 |
->setCon( $this )
|
542 |
->execute();
|
543 |
+
|
544 |
+
if ( is_admin() || is_network_admin() ) {
|
545 |
+
( new Admin\MainAdminMenu() )
|
546 |
+
->setCon( $this )
|
547 |
+
->execute();
|
548 |
+
}
|
549 |
}
|
550 |
|
551 |
protected function initCrons() {
|
1382 |
return $this->getModule( 'events' );
|
1383 |
}
|
1384 |
|
1385 |
+
public function getModule_Firewall() :Shield\Modules\Firewall\ModCon {
|
1386 |
+
return $this->getModule( 'firewall' );
|
1387 |
+
}
|
1388 |
+
|
1389 |
public function getModule_HackGuard() :Shield\Modules\HackGuard\ModCon {
|
1390 |
return $this->getModule( 'hack_protect' );
|
1391 |
}
|
1605 |
*/
|
1606 |
private function buildPrivacyPolicyContent() {
|
1607 |
try {
|
1608 |
+
if ( $this->getModule_SecAdmin()->getWhiteLabelController()->isEnabled() ) {
|
1609 |
$name = $this->getHumanName();
|
1610 |
$href = $this->getLabels()[ 'PluginURI' ];
|
1611 |
}
|
src/lib/src/Databases/AuditTrail/Handler.php
CHANGED
@@ -13,12 +13,4 @@ class Handler extends Base\Handler {
|
|
13 |
$this->tableCleanExpired( $opts->getAutoCleanDays() );
|
14 |
$this->tableTrimExcess( $opts->getMaxEntries() );
|
15 |
}
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @return string
|
19 |
-
* @deprecated 11.1
|
20 |
-
*/
|
21 |
-
protected function getDefaultTableName() :string {
|
22 |
-
return $this->getOptions()->getDef( 'audit_trail_table_name' );
|
23 |
-
}
|
24 |
}
|
13 |
$this->tableCleanExpired( $opts->getAutoCleanDays() );
|
14 |
$this->tableTrimExcess( $opts->getMaxEntries() );
|
15 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
src/lib/src/Databases/Base/BaseQuery.php
CHANGED
@@ -18,9 +18,11 @@ abstract class BaseQuery {
|
|
18 |
protected $aWheres;
|
19 |
|
20 |
/**
|
21 |
-
* @var
|
22 |
*/
|
23 |
-
protected $
|
|
|
|
|
24 |
|
25 |
/**
|
26 |
* @var int
|
@@ -54,83 +56,86 @@ abstract class BaseQuery {
|
|
54 |
|
55 |
/**
|
56 |
* @param string $column
|
57 |
-
* @param string|array $
|
58 |
* @param string $operator
|
59 |
* @return $this
|
60 |
*/
|
61 |
-
public function addWhere( $column, $
|
62 |
if ( !$this->isValidComparisonOperator( $operator ) ) {
|
63 |
return $this; // Exception?
|
64 |
}
|
65 |
|
66 |
-
if ( is_array( $
|
67 |
-
$
|
68 |
-
$
|
69 |
}
|
70 |
else {
|
71 |
-
|
72 |
-
|
73 |
-
if ( strcasecmp( $operator, 'LIKE' ) === 0 ) {
|
74 |
-
$mValue = sprintf( '%%%s%%', $mValue );
|
75 |
}
|
76 |
-
if (
|
77 |
-
$
|
78 |
}
|
79 |
}
|
80 |
|
81 |
-
$
|
82 |
-
$
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
84 |
}
|
85 |
|
86 |
/**
|
87 |
-
* @param string $
|
88 |
* @param mixed $mValue
|
89 |
* @return $this
|
90 |
*/
|
91 |
-
public function addWhereEquals( $
|
92 |
-
return $this->addWhere( $
|
93 |
}
|
94 |
|
95 |
/**
|
96 |
-
* @param string $
|
97 |
-
* @param array $
|
98 |
* @return $this
|
99 |
*/
|
100 |
-
public function addWhereIn( $
|
101 |
-
if ( !empty( $
|
102 |
-
$this->addWhere( $
|
103 |
}
|
104 |
return $this;
|
105 |
}
|
106 |
|
107 |
/**
|
108 |
-
* @param string $
|
109 |
-
* @param string $
|
110 |
-
* @param string $
|
111 |
-
* @param string $
|
112 |
* @return $this
|
113 |
*/
|
114 |
-
public function addWhereLike( $
|
115 |
-
return $this->addWhere( $
|
116 |
}
|
117 |
|
118 |
/**
|
119 |
* @param int $nNewerThanTimeStamp
|
120 |
-
* @param string $
|
121 |
* @return $this
|
122 |
*/
|
123 |
-
public function addWhereNewerThan( $nNewerThanTimeStamp, $
|
124 |
-
return $this->addWhere( $
|
125 |
}
|
126 |
|
127 |
/**
|
128 |
* @param int $nOlderThanTimeStamp
|
129 |
-
* @param string $
|
130 |
* @return $this
|
131 |
*/
|
132 |
-
public function addWhereOlderThan( $nOlderThanTimeStamp, $
|
133 |
-
return $this->addWhere( $
|
134 |
}
|
135 |
|
136 |
/**
|
@@ -175,7 +180,7 @@ abstract class BaseQuery {
|
|
175 |
* @return $this
|
176 |
*/
|
177 |
public function clearWheres() {
|
178 |
-
return $this->
|
179 |
}
|
180 |
|
181 |
/**
|
@@ -190,12 +195,23 @@ abstract class BaseQuery {
|
|
190 |
*/
|
191 |
public function buildWhere() {
|
192 |
|
193 |
-
|
194 |
-
|
195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
}
|
197 |
|
198 |
-
return implode( ' AND ', $
|
199 |
}
|
200 |
|
201 |
/**
|
@@ -312,10 +328,11 @@ abstract class BaseQuery {
|
|
312 |
}
|
313 |
|
314 |
public function getWheres() :array {
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
|
|
319 |
}
|
320 |
|
321 |
/**
|
@@ -358,18 +375,16 @@ abstract class BaseQuery {
|
|
358 |
return $this->getLimit() > 0;
|
359 |
}
|
360 |
|
361 |
-
|
362 |
-
* @return bool
|
363 |
-
*/
|
364 |
-
public function hasWheres() {
|
365 |
return count( $this->getWheres() ) > 0;
|
366 |
}
|
367 |
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
|
|
373 |
}
|
374 |
|
375 |
/**
|
@@ -377,17 +392,17 @@ abstract class BaseQuery {
|
|
377 |
*/
|
378 |
public function reset() {
|
379 |
return $this->setLimit( 0 )
|
380 |
-
->
|
381 |
->setPage( 1 )
|
382 |
->setOrderBy( null );
|
383 |
}
|
384 |
|
385 |
/**
|
386 |
-
* @param
|
387 |
* @return $this
|
388 |
*/
|
389 |
-
public function
|
390 |
-
$this->
|
391 |
return $this;
|
392 |
}
|
393 |
|
@@ -443,11 +458,24 @@ abstract class BaseQuery {
|
|
443 |
}
|
444 |
|
445 |
/**
|
446 |
-
* @param array $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
* @return $this
|
448 |
*/
|
449 |
-
public function setWheres( $
|
450 |
-
$this->aWheres = $
|
451 |
return $this;
|
452 |
}
|
453 |
|
18 |
protected $aWheres;
|
19 |
|
20 |
/**
|
21 |
+
* @var array
|
22 |
*/
|
23 |
+
protected $rawWheres;
|
24 |
+
|
25 |
+
protected $includeSoftDeleted;
|
26 |
|
27 |
/**
|
28 |
* @var int
|
56 |
|
57 |
/**
|
58 |
* @param string $column
|
59 |
+
* @param string|array $value
|
60 |
* @param string $operator
|
61 |
* @return $this
|
62 |
*/
|
63 |
+
public function addWhere( $column, $value, $operator = '=' ) {
|
64 |
if ( !$this->isValidComparisonOperator( $operator ) ) {
|
65 |
return $this; // Exception?
|
66 |
}
|
67 |
|
68 |
+
if ( is_array( $value ) ) {
|
69 |
+
$value = array_map( 'esc_sql', $value );
|
70 |
+
$value = "('".implode( "','", $value )."')";
|
71 |
}
|
72 |
else {
|
73 |
+
if ( strtoupper( $operator ) === 'LIKE' ) {
|
74 |
+
$value = sprintf( '%%%s%%', $value );
|
|
|
|
|
75 |
}
|
76 |
+
if ( !is_int( $value ) ) {
|
77 |
+
$value = sprintf( '"%s"', esc_sql( $value ) );
|
78 |
}
|
79 |
}
|
80 |
|
81 |
+
$rawWheres = $this->getRawWheres();
|
82 |
+
$rawWheres[] = [
|
83 |
+
esc_sql( $column ),
|
84 |
+
$operator,
|
85 |
+
$value
|
86 |
+
];
|
87 |
+
|
88 |
+
return $this->setRawWheres( $rawWheres );
|
89 |
}
|
90 |
|
91 |
/**
|
92 |
+
* @param string $column
|
93 |
* @param mixed $mValue
|
94 |
* @return $this
|
95 |
*/
|
96 |
+
public function addWhereEquals( string $column, $mValue ) {
|
97 |
+
return $this->addWhere( $column, $mValue, '=' );
|
98 |
}
|
99 |
|
100 |
/**
|
101 |
+
* @param string $column
|
102 |
+
* @param array $values
|
103 |
* @return $this
|
104 |
*/
|
105 |
+
public function addWhereIn( string $column, $values ) {
|
106 |
+
if ( !empty( $values ) && is_array( $values ) ) {
|
107 |
+
$this->addWhere( $column, $values, 'IN' );
|
108 |
}
|
109 |
return $this;
|
110 |
}
|
111 |
|
112 |
/**
|
113 |
+
* @param string $column
|
114 |
+
* @param string $like
|
115 |
+
* @param string $left
|
116 |
+
* @param string $right
|
117 |
* @return $this
|
118 |
*/
|
119 |
+
public function addWhereLike( string $column, $like, $left = '%', $right = '%' ) {
|
120 |
+
return $this->addWhere( $column, $left.$like.$right, 'LIKE' );
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
* @param int $nNewerThanTimeStamp
|
125 |
+
* @param string $column
|
126 |
* @return $this
|
127 |
*/
|
128 |
+
public function addWhereNewerThan( $nNewerThanTimeStamp, $column = 'created_at' ) {
|
129 |
+
return $this->addWhere( $column, $nNewerThanTimeStamp, '>' );
|
130 |
}
|
131 |
|
132 |
/**
|
133 |
* @param int $nOlderThanTimeStamp
|
134 |
+
* @param string $column
|
135 |
* @return $this
|
136 |
*/
|
137 |
+
public function addWhereOlderThan( $nOlderThanTimeStamp, $column = 'created_at' ) {
|
138 |
+
return $this->addWhere( $column, $nOlderThanTimeStamp, '<' );
|
139 |
}
|
140 |
|
141 |
/**
|
180 |
* @return $this
|
181 |
*/
|
182 |
public function clearWheres() {
|
183 |
+
return $this->setRawWheres( [] );
|
184 |
}
|
185 |
|
186 |
/**
|
195 |
*/
|
196 |
public function buildWhere() {
|
197 |
|
198 |
+
if ( method_exists( $this, 'getRawWheres' ) ) {
|
199 |
+
$wheres = $this->getRawWheres();
|
200 |
+
if ( !$this->isIncludeSoftDeletedRows() ) {
|
201 |
+
$wheres[] = [ 'deleted_at', '=', 0 ];
|
202 |
+
}
|
203 |
+
$wheres = array_map( function ( array $where ) {
|
204 |
+
return $this->rawWhereToString( $where );
|
205 |
+
}, $wheres );
|
206 |
+
}
|
207 |
+
else { // TODO: @deprecated 11.2
|
208 |
+
$wheres = $this->getWheres();
|
209 |
+
if ( !$this->isIncludeSoftDeletedRows() ) {
|
210 |
+
$wheres[] = '`deleted_at`=0';
|
211 |
+
}
|
212 |
}
|
213 |
|
214 |
+
return implode( ' AND ', $wheres );
|
215 |
}
|
216 |
|
217 |
/**
|
328 |
}
|
329 |
|
330 |
public function getWheres() :array {
|
331 |
+
return is_array( $this->aWheres ) ? $this->aWheres : [];
|
332 |
+
}
|
333 |
+
|
334 |
+
public function getRawWheres() :array {
|
335 |
+
return is_array( $this->rawWheres ) ? $this->rawWheres : [];
|
336 |
}
|
337 |
|
338 |
/**
|
375 |
return $this->getLimit() > 0;
|
376 |
}
|
377 |
|
378 |
+
public function hasWheres() :bool {
|
|
|
|
|
|
|
379 |
return count( $this->getWheres() ) > 0;
|
380 |
}
|
381 |
|
382 |
+
public function isIncludeSoftDeletedRows() :bool {
|
383 |
+
return $this->includeSoftDeleted ?? false;
|
384 |
+
}
|
385 |
+
|
386 |
+
protected function rawWhereToString( array $rawWhere ) :string {
|
387 |
+
return vsprintf( '`%s` %s %s', $rawWhere );
|
388 |
}
|
389 |
|
390 |
/**
|
392 |
*/
|
393 |
public function reset() {
|
394 |
return $this->setLimit( 0 )
|
395 |
+
->setRawWheres( [] )
|
396 |
->setPage( 1 )
|
397 |
->setOrderBy( null );
|
398 |
}
|
399 |
|
400 |
/**
|
401 |
+
* @param bool $includeSoftDeleted
|
402 |
* @return $this
|
403 |
*/
|
404 |
+
public function setIncludeSoftDeleted( bool $includeSoftDeleted ) {
|
405 |
+
$this->includeSoftDeleted = $includeSoftDeleted;
|
406 |
return $this;
|
407 |
}
|
408 |
|
458 |
}
|
459 |
|
460 |
/**
|
461 |
+
* @param array[] $wheres
|
462 |
+
* @return $this
|
463 |
+
*/
|
464 |
+
public function setRawWheres( array $wheres ) {
|
465 |
+
$this->rawWheres = $wheres;
|
466 |
+
return $this->setWheres(
|
467 |
+
array_map( function ( array $where ) {
|
468 |
+
return $this->rawWhereToString( $where );
|
469 |
+
}, $this->rawWheres )
|
470 |
+
);
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* @param array $wheres
|
475 |
* @return $this
|
476 |
*/
|
477 |
+
public function setWheres( array $wheres ) {
|
478 |
+
$this->aWheres = $wheres;
|
479 |
return $this;
|
480 |
}
|
481 |
|
src/lib/src/Databases/Base/Delete.php
CHANGED
@@ -2,8 +2,35 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
4 |
|
|
|
|
|
5 |
class Delete extends BaseQuery {
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
/**
|
8 |
* @return bool
|
9 |
*/
|
@@ -12,13 +39,12 @@ class Delete extends BaseQuery {
|
|
12 |
}
|
13 |
|
14 |
/**
|
15 |
-
* @param int $
|
16 |
* @return bool
|
17 |
*/
|
18 |
-
public function deleteById( $
|
19 |
return $this->reset()
|
20 |
-
->addWhereEquals( 'id', (int)$
|
21 |
-
->setLimit( 1 )//perhaps an unnecessary precaution
|
22 |
->query();
|
23 |
}
|
24 |
|
@@ -48,7 +74,7 @@ class Delete extends BaseQuery {
|
|
48 |
// The same WHEREs should apply
|
49 |
$nTotal = $this->getDbH()
|
50 |
->getQuerySelector()
|
51 |
-
->
|
52 |
->count();
|
53 |
$nToDelete = $nTotal - $maxEntries;
|
54 |
|
@@ -72,4 +98,14 @@ class Delete extends BaseQuery {
|
|
72 |
protected function buildOffsetPhrase() {
|
73 |
return '';
|
74 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Services\Services;
|
6 |
+
|
7 |
class Delete extends BaseQuery {
|
8 |
|
9 |
+
private $isSoftDelete = false;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @return bool
|
13 |
+
*/
|
14 |
+
public function query() {
|
15 |
+
if ( $this->isSoftDelete && $this->getDbH()->getTableSchema()->hasColumn( 'deleted_at' ) ) {
|
16 |
+
|
17 |
+
$updateWheres = [];
|
18 |
+
foreach ( $this->getRawWheres() as $where ) {
|
19 |
+
$updateWheres[ $where[ 0 ] ] = $where[ 2 ];
|
20 |
+
}
|
21 |
+
|
22 |
+
$success = $this->getDbH()
|
23 |
+
->getQueryUpdater()
|
24 |
+
->setUpdateWheres( $updateWheres )
|
25 |
+
->setUpdateData( [ 'deleted_at' => Services::Request()->ts(), ] )
|
26 |
+
->query();
|
27 |
+
}
|
28 |
+
else {
|
29 |
+
$success = parent::query();
|
30 |
+
}
|
31 |
+
return $success;
|
32 |
+
}
|
33 |
+
|
34 |
/**
|
35 |
* @return bool
|
36 |
*/
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
+
* @param int $id
|
43 |
* @return bool
|
44 |
*/
|
45 |
+
public function deleteById( $id ) {
|
46 |
return $this->reset()
|
47 |
+
->addWhereEquals( 'id', (int)$id )
|
|
|
48 |
->query();
|
49 |
}
|
50 |
|
74 |
// The same WHEREs should apply
|
75 |
$nTotal = $this->getDbH()
|
76 |
->getQuerySelector()
|
77 |
+
->setRawWheres( $this->getRawWheres() )
|
78 |
->count();
|
79 |
$nToDelete = $nTotal - $maxEntries;
|
80 |
|
98 |
protected function buildOffsetPhrase() {
|
99 |
return '';
|
100 |
}
|
101 |
+
|
102 |
+
public function setIsHardDelete() {
|
103 |
+
$this->isSoftDelete = false;
|
104 |
+
return $this;
|
105 |
+
}
|
106 |
+
|
107 |
+
public function setIsSoftDelete() {
|
108 |
+
$this->isSoftDelete = true;
|
109 |
+
return $this;
|
110 |
+
}
|
111 |
}
|
src/lib/src/Databases/Base/EntryVO.php
CHANGED
@@ -45,7 +45,7 @@ class EntryVO extends DynPropertiesClass {
|
|
45 |
break;
|
46 |
}
|
47 |
|
48 |
-
if ( preg_match( '#^.*_at$#i', $key ) ) {
|
49 |
$value = (int)$value;
|
50 |
}
|
51 |
|
45 |
break;
|
46 |
}
|
47 |
|
48 |
+
if ( $key === 'id' || preg_match( '#^.*_at$#i', $key ) ) {
|
49 |
$value = (int)$value;
|
50 |
}
|
51 |
|
src/lib/src/Databases/Base/Handler.php
CHANGED
@@ -2,20 +2,12 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Common\AlignTableWithSchema;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Common\TableSchema;
|
8 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
-
|
12 |
-
* Class Handler
|
13 |
-
* @package FernleafSystems\Wordpress\Plugin\Shield\Databases\Base
|
14 |
-
*/
|
15 |
-
abstract class Handler {
|
16 |
-
|
17 |
-
use ModConsumer;
|
18 |
-
use ExecOnce;
|
19 |
|
20 |
/**
|
21 |
* @var string
|
@@ -234,14 +226,6 @@ abstract class Handler {
|
|
234 |
return $this->bIsReady;
|
235 |
}
|
236 |
|
237 |
-
/**
|
238 |
-
* @return string
|
239 |
-
* @deprecated 11.1
|
240 |
-
*/
|
241 |
-
protected function getDefaultTableName() :string {
|
242 |
-
return $this->getTableSchema()->slug;
|
243 |
-
}
|
244 |
-
|
245 |
public function getTableSchema() :TableSchema {
|
246 |
return $this->schema;
|
247 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Common\AlignTableWithSchema;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Common\TableSchema;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
+
abstract class Handler extends ExecOnceModConsumer {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
/**
|
13 |
* @var string
|
226 |
return $this->bIsReady;
|
227 |
}
|
228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
public function getTableSchema() :TableSchema {
|
230 |
return $this->schema;
|
231 |
}
|
src/lib/src/Databases/Base/Update.php
CHANGED
@@ -95,16 +95,13 @@ class Update extends Insert {
|
|
95 |
if ( !empty( $updateData ) ) {
|
96 |
$success = $this->setUpdateId( $id )
|
97 |
->setUpdateData( $updateData )
|
98 |
-
->query()
|
99 |
}
|
100 |
return $success;
|
101 |
}
|
102 |
|
103 |
-
/**
|
104 |
-
* @return int|false
|
105 |
-
*/
|
106 |
public function query() {
|
107 |
-
return Services::WpDb()
|
108 |
->updateRowsFromTableWhere(
|
109 |
$this->getDbH()->getTable(),
|
110 |
$this->getUpdateData(),
|
95 |
if ( !empty( $updateData ) ) {
|
96 |
$success = $this->setUpdateId( $id )
|
97 |
->setUpdateData( $updateData )
|
98 |
+
->query();
|
99 |
}
|
100 |
return $success;
|
101 |
}
|
102 |
|
|
|
|
|
|
|
103 |
public function query() {
|
104 |
+
return (bool)Services::WpDb()
|
105 |
->updateRowsFromTableWhere(
|
106 |
$this->getDbH()->getTable(),
|
107 |
$this->getUpdateData(),
|
src/lib/src/Databases/BotSignals/EntryVO.php
CHANGED
@@ -7,6 +7,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals;
|
|
7 |
* @property string $ip
|
8 |
* @property int $notbot_at
|
9 |
* @property int $frontpage_at
|
|
|
10 |
* @property int $bt404_at
|
11 |
* @property int $btcheese_at
|
12 |
* @property int $btfake_at
|
7 |
* @property string $ip
|
8 |
* @property int $notbot_at
|
9 |
* @property int $frontpage_at
|
10 |
+
* @property int $loginpage_at
|
11 |
* @property int $bt404_at
|
12 |
* @property int $btcheese_at
|
13 |
* @property int $btfake_at
|
src/lib/src/Databases/Events/Handler.php
CHANGED
@@ -36,12 +36,4 @@ class Handler extends Base\Handler {
|
|
36 |
$QI = $this->getQueryInserter();
|
37 |
return $QI->insert( $oEvt );
|
38 |
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* @return string
|
42 |
-
* @deprecated 11.1
|
43 |
-
*/
|
44 |
-
protected function getDefaultTableName() :string {
|
45 |
-
return $this->getOptions()->getDef( 'events_table_name' );
|
46 |
-
}
|
47 |
}
|
36 |
$QI = $this->getQueryInserter();
|
37 |
return $QI->insert( $oEvt );
|
38 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
src/lib/src/Databases/Events/Select.php
CHANGED
@@ -40,16 +40,15 @@ class Select extends Base\Select {
|
|
40 |
* @return int[]
|
41 |
*/
|
42 |
public function sumAllEvents() {
|
43 |
-
$
|
44 |
|
45 |
-
$
|
46 |
-
$aAllEvents = $oNewMe->reset()->getAllEvents();
|
47 |
|
48 |
-
natsort( $
|
49 |
-
foreach ( $
|
50 |
-
$
|
51 |
}
|
52 |
-
return $
|
53 |
}
|
54 |
|
55 |
/**
|
40 |
* @return int[]
|
41 |
*/
|
42 |
public function sumAllEvents() {
|
43 |
+
$sums = [];
|
44 |
|
45 |
+
$allEvents = ( clone $this )->reset()->getAllEvents();
|
|
|
46 |
|
47 |
+
natsort( $allEvents );
|
48 |
+
foreach ( $allEvents as $event ) {
|
49 |
+
$sums[ $event ] = $this->clearWheres()->sumEvent( $event );
|
50 |
}
|
51 |
+
return $sums;
|
52 |
}
|
53 |
|
54 |
/**
|
src/lib/src/Databases/FileLocker/Handler.php
CHANGED
@@ -6,11 +6,4 @@ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
|
6 |
|
7 |
class Handler extends Base\Handler {
|
8 |
|
9 |
-
/**
|
10 |
-
* @return string
|
11 |
-
* @deprecated 11.1
|
12 |
-
*/
|
13 |
-
protected function getDefaultTableName() :string {
|
14 |
-
return $this->getOptions()->getDef( 'table_name_filelocker' );
|
15 |
-
}
|
16 |
}
|
6 |
|
7 |
class Handler extends Base\Handler {
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
}
|
src/lib/src/Databases/IPs/Handler.php
CHANGED
@@ -29,12 +29,4 @@ class Handler extends Base\Handler {
|
|
29 |
->addWhere( 'list', ModCon::LIST_MANUAL_WHITE, '!=' )
|
30 |
->query();
|
31 |
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @return string
|
35 |
-
* @deprecated 11.1
|
36 |
-
*/
|
37 |
-
protected function getDefaultTableName() :string {
|
38 |
-
return $this->getOptions()->getDef( 'ip_lists_table_name' );
|
39 |
-
}
|
40 |
}
|
29 |
->addWhere( 'list', ModCon::LIST_MANUAL_WHITE, '!=' )
|
30 |
->query();
|
31 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
src/lib/src/Databases/ScanQueue/Common.php
CHANGED
@@ -48,12 +48,12 @@ trait Common {
|
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
-
* @param string $
|
52 |
* @return bool
|
53 |
*/
|
54 |
-
public function forScan( $
|
55 |
$this->reset();
|
56 |
-
return $this->filterByScan( $
|
57 |
->query();
|
58 |
}
|
59 |
}
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
+
* @param string $scan
|
52 |
* @return bool
|
53 |
*/
|
54 |
+
public function forScan( $scan ) {
|
55 |
$this->reset();
|
56 |
+
return $this->filterByScan( $scan )
|
57 |
->query();
|
58 |
}
|
59 |
}
|
src/lib/src/Databases/Scanner/Update.php
CHANGED
@@ -8,40 +8,36 @@ use FernleafSystems\Wordpress\Services\Services;
|
|
8 |
class Update extends Base\Update {
|
9 |
|
10 |
/**
|
11 |
-
* @param string $
|
12 |
* @return bool
|
13 |
*/
|
14 |
-
public function clearIgnoredAtForScan( $
|
15 |
-
return $this->setUpdateWheres( [ 'scan' => $
|
16 |
->setUpdateData( [ 'ignored_at' => 0 ] )
|
17 |
->query() !== false;
|
18 |
}
|
19 |
|
20 |
/**
|
21 |
-
* @param string $
|
22 |
* @return bool
|
23 |
*/
|
24 |
-
public function clearNotifiedAtForScan( $
|
25 |
-
return $this->setUpdateWheres( [ 'scan' => $
|
26 |
->setUpdateData( [ 'notified_at' => 0 ] )
|
27 |
->query() !== false;
|
28 |
}
|
29 |
|
30 |
/**
|
31 |
-
* @param string $
|
32 |
* @return bool
|
33 |
*/
|
34 |
-
public function setAllNotifiedForScan( $
|
35 |
return $this
|
36 |
-
->setUpdateWheres(
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
)
|
42 |
-
->setUpdateData(
|
43 |
-
[ 'notified_at' => Services::Request()->ts() ]
|
44 |
-
)
|
45 |
->query() !== false;
|
46 |
}
|
47 |
|
8 |
class Update extends Base\Update {
|
9 |
|
10 |
/**
|
11 |
+
* @param string $scan
|
12 |
* @return bool
|
13 |
*/
|
14 |
+
public function clearIgnoredAtForScan( $scan ) {
|
15 |
+
return $this->setUpdateWheres( [ 'scan' => $scan ] )
|
16 |
->setUpdateData( [ 'ignored_at' => 0 ] )
|
17 |
->query() !== false;
|
18 |
}
|
19 |
|
20 |
/**
|
21 |
+
* @param string $scan
|
22 |
* @return bool
|
23 |
*/
|
24 |
+
public function clearNotifiedAtForScan( $scan ) {
|
25 |
+
return $this->setUpdateWheres( [ 'scan' => $scan ] )
|
26 |
->setUpdateData( [ 'notified_at' => 0 ] )
|
27 |
->query() !== false;
|
28 |
}
|
29 |
|
30 |
/**
|
31 |
+
* @param string $scan
|
32 |
* @return bool
|
33 |
*/
|
34 |
+
public function setAllNotifiedForScan( $scan ) {
|
35 |
return $this
|
36 |
+
->setUpdateWheres( [
|
37 |
+
'scan' => $scan,
|
38 |
+
'ignored_at' => 0,
|
39 |
+
] )
|
40 |
+
->setUpdateData( [ 'notified_at' => Services::Request()->ts() ] )
|
|
|
|
|
|
|
|
|
41 |
->query() !== false;
|
42 |
}
|
43 |
|
src/lib/src/Databases/Session/Handler.php
CHANGED
@@ -3,18 +3,16 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Session;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
|
|
6 |
|
7 |
class Handler extends Base\Handler {
|
8 |
|
9 |
public function autoCleanDb() {
|
10 |
$this->tableCleanExpired( 30 );
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
*/
|
17 |
-
protected function getDefaultTableName() :string {
|
18 |
-
return $this->getOptions()->getDef( 'sessions_table_name' );
|
19 |
}
|
20 |
}
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\Session;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
class Handler extends Base\Handler {
|
9 |
|
10 |
public function autoCleanDb() {
|
11 |
$this->tableCleanExpired( 30 );
|
12 |
+
// Remove soft-deleted sessions after 3 days
|
13 |
+
$this->getQueryDeleter()
|
14 |
+
->addWhereNewerThan( 0, 'deleted_at' )
|
15 |
+
->addWhereOlderThan( Services::Request()->carbon()->subDays( 5 )->timestamp, 'deleted_at' )
|
16 |
+
->query();
|
|
|
|
|
|
|
17 |
}
|
18 |
}
|
src/lib/src/Databases/Traffic/Handler.php
CHANGED
@@ -13,12 +13,4 @@ class Handler extends Base\Handler {
|
|
13 |
$this->tableCleanExpired( $opts->getAutoCleanDays() );
|
14 |
$this->tableTrimExcess( $opts->getMaxEntries() );
|
15 |
}
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @return string
|
19 |
-
* @deprecated 11.1
|
20 |
-
*/
|
21 |
-
protected function getDefaultTableName() :string {
|
22 |
-
return $this->getOptions()->getDef( 'traffic_table_name' );
|
23 |
-
}
|
24 |
}
|
13 |
$this->tableCleanExpired( $opts->getAutoCleanDays() );
|
14 |
$this->tableTrimExcess( $opts->getMaxEntries() );
|
15 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
src/lib/src/License/EddLicenseVO.php
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\License;
|
4 |
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\License;
|
4 |
|
src/lib/src/Modules/AuditTrail/Insights/OverviewCards.php
CHANGED
@@ -7,24 +7,15 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail;
|
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
-
|
11 |
/** @var AuditTrail\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var AuditTrail\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
16 |
-
$cardSection = [
|
17 |
-
'title' => __( 'Activity Audit Log', 'wp-simple-firewall' ),
|
18 |
-
'subtitle' => $mod->getStrings()->getModTagLine(),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage(),
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
-
if (
|
25 |
-
$data[ 'key_opts' ][ 'mod' ] = $this->getModDisabledCard();
|
26 |
-
}
|
27 |
-
else {
|
28 |
$cards[ 'audit' ] = [
|
29 |
'name' => __( 'Audit Areas', 'wp-simple-firewall' ),
|
30 |
'state' => 1,
|
@@ -40,7 +31,10 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
40 |
];
|
41 |
}
|
42 |
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
45 |
}
|
46 |
}
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
+
protected function buildModCards() :array {
|
11 |
/** @var AuditTrail\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var AuditTrail\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
$cards = [];
|
17 |
|
18 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
19 |
$cards[ 'audit' ] = [
|
20 |
'name' => __( 'Audit Areas', 'wp-simple-firewall' ),
|
21 |
'state' => 1,
|
31 |
];
|
32 |
}
|
33 |
|
34 |
+
return $cards;
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function getSectionTitle() :string {
|
38 |
+
return __( 'Activity Audit Log', 'wp-simple-firewall' );
|
39 |
}
|
40 |
}
|
src/lib/src/Modules/AuditTrail/Lib/AuditWriter.php
CHANGED
@@ -23,7 +23,7 @@ class AuditWriter extends EventsListener {
|
|
23 |
*/
|
24 |
protected function captureEvent( string $evt, $meta = [], $def = [] ) {
|
25 |
$con = $this->getCon();
|
26 |
-
if ( empty( $def ) ) { // TODO: @deprecated 11.
|
27 |
$def = $con->loadEventsService()->getEventDef( $evt );
|
28 |
}
|
29 |
if ( $def[ 'audit' ] && empty( $meta[ 'suppress_audit' ] ) ) { // only audit if it's an auditable event
|
23 |
*/
|
24 |
protected function captureEvent( string $evt, $meta = [], $def = [] ) {
|
25 |
$con = $this->getCon();
|
26 |
+
if ( empty( $def ) ) { // TODO: @deprecated 11.2 - remove this if
|
27 |
$def = $con->loadEventsService()->getEventDef( $evt );
|
28 |
}
|
29 |
if ( $def[ 'audit' ] && empty( $meta[ 'suppress_audit' ] ) ) { // only audit if it's an auditable event
|
src/lib/src/Modules/Autoupdates/Insights/OverviewCards.php
CHANGED
@@ -8,51 +8,42 @@ use FernleafSystems\Wordpress\Services\Services;
|
|
8 |
|
9 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
10 |
|
11 |
-
|
12 |
/** @var Autoupdates\ModCon $mod */
|
13 |
$mod = $this->getMod();
|
14 |
/** @var Autoupdates\Options $opts */
|
15 |
$opts = $this->getOptions();
|
16 |
$WP = Services::WpGeneral();
|
17 |
|
18 |
-
$cardSection = [
|
19 |
-
'title' => __( 'Automatic Updates', 'wp-simple-firewall' ),
|
20 |
-
'subtitle' => __( 'Controlling WordPress Automatic Updates', 'wp-simple-firewall' ),
|
21 |
-
'href_options' => $mod->getUrl_AdminPage()
|
22 |
-
];
|
23 |
-
|
24 |
$cards = [];
|
25 |
|
26 |
-
if (
|
27 |
-
$
|
28 |
-
}
|
29 |
-
else {
|
30 |
-
$bHasUpdate = $WP->hasCoreUpdate();
|
31 |
$cards[ 'core_update' ] = [
|
32 |
'name' => __( 'Core Update', 'wp-simple-firewall' ),
|
33 |
-
'state' => $
|
34 |
-
'summary' => $
|
35 |
__( 'WordPress Core is up-to-date', 'wp-simple-firewall' )
|
36 |
: __( "No WordPress Core upgrades waiting to be applied", 'wp-simple-firewall' ),
|
37 |
'href' => $WP->getAdminUrl_Updates( true ),
|
38 |
'help' => __( 'Core upgrades should be applied as early as possible.', 'wp-simple-firewall' )
|
39 |
];
|
40 |
|
41 |
-
$
|
42 |
$cards[ 'core_minor' ] = [
|
43 |
'name' => __( 'Auto Core Updates', 'wp-simple-firewall' ),
|
44 |
-
'state' => $
|
45 |
-
'summary' => $
|
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 |
'href' => $mod->getUrl_DirectLinkToOption( 'autoupdate_core' ),
|
49 |
];
|
50 |
|
51 |
-
$
|
52 |
$cards[ 'delay' ] = [
|
53 |
'name' => __( 'Update Delay', 'wp-simple-firewall' ),
|
54 |
-
'state' => $
|
55 |
-
'summary' => $
|
56 |
__( 'Automatic updates are applied after a short delay', 'wp-simple-firewall' )
|
57 |
: __( 'Automatic updates are applied immediately', 'wp-simple-firewall' ),
|
58 |
'href' => $mod->getUrl_DirectLinkToOption( 'update_delay' ),
|
@@ -74,7 +65,7 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
74 |
//really disabled?
|
75 |
if ( $mod->isModOptEnabled()
|
76 |
&& $opts->isDisableAllAutoUpdates() && !$WP->getWpAutomaticUpdater()->is_disabled() ) {
|
77 |
-
$
|
78 |
'name' => 'Auto Updates Not Really Disabled',
|
79 |
'summary' => __( 'Automatic Updates Are Not Disabled As Expected.', 'wp-simple-firewall' ),
|
80 |
'href' => $mod->getUrl_DirectLinkToOption( 'enable_autoupdate_disable_all' ),
|
@@ -85,21 +76,26 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
85 |
];
|
86 |
}
|
87 |
|
88 |
-
|
89 |
$cards,
|
90 |
$this->getCardsForPlugins(),
|
91 |
$this->getCardsForThemes()
|
92 |
);
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
-
|
95 |
-
return
|
96 |
}
|
97 |
|
98 |
private function getCardsForPlugins() :array {
|
99 |
$cards = [];
|
100 |
|
101 |
-
$
|
102 |
-
$nCount = count( $
|
103 |
$cards[ 'plugins_inactive' ] = [
|
104 |
'name' => __( 'Inactive Plugins', 'wp-simple-firewall' ),
|
105 |
'state' => $nCount > 0 ? -1 : 1,
|
@@ -110,7 +106,7 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
110 |
'help' => __( 'Unused plugins should be removed.', 'wp-simple-firewall' )
|
111 |
];
|
112 |
|
113 |
-
$nCount = count( $
|
114 |
$cards[ 'plugin_updates' ] = [
|
115 |
'name' => __( 'Plugin Updates', 'wp-simple-firewall' ),
|
116 |
'state' => $nCount > 0 ? -1 : 1,
|
8 |
|
9 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
10 |
|
11 |
+
protected function buildModCards() :array {
|
12 |
/** @var Autoupdates\ModCon $mod */
|
13 |
$mod = $this->getMod();
|
14 |
/** @var Autoupdates\Options $opts */
|
15 |
$opts = $this->getOptions();
|
16 |
$WP = Services::WpGeneral();
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
$cards = [];
|
19 |
|
20 |
+
if ( $mod->isModOptEnabled() ) {
|
21 |
+
$hasUpdate = $WP->hasCoreUpdate();
|
|
|
|
|
|
|
22 |
$cards[ 'core_update' ] = [
|
23 |
'name' => __( 'Core Update', 'wp-simple-firewall' ),
|
24 |
+
'state' => $hasUpdate ? -1 : 1,
|
25 |
+
'summary' => $hasUpdate ?
|
26 |
__( 'WordPress Core is up-to-date', 'wp-simple-firewall' )
|
27 |
: __( "No WordPress Core upgrades waiting to be applied", 'wp-simple-firewall' ),
|
28 |
'href' => $WP->getAdminUrl_Updates( true ),
|
29 |
'help' => __( 'Core upgrades should be applied as early as possible.', 'wp-simple-firewall' )
|
30 |
];
|
31 |
|
32 |
+
$canCore = Services::WpGeneral()->canCoreUpdateAutomatically();
|
33 |
$cards[ 'core_minor' ] = [
|
34 |
'name' => __( 'Auto Core Updates', 'wp-simple-firewall' ),
|
35 |
+
'state' => $canCore ? 1 : -1,
|
36 |
+
'summary' => $canCore ?
|
37 |
__( 'Minor WP Core updates will be installed automatically', 'wp-simple-firewall' )
|
38 |
: __( 'Minor WP Core updates will not be installed automatically', 'wp-simple-firewall' ),
|
39 |
'href' => $mod->getUrl_DirectLinkToOption( 'autoupdate_core' ),
|
40 |
];
|
41 |
|
42 |
+
$hasDelay = $mod->isModOptEnabled() && $opts->getDelayUpdatesPeriod();
|
43 |
$cards[ 'delay' ] = [
|
44 |
'name' => __( 'Update Delay', 'wp-simple-firewall' ),
|
45 |
+
'state' => $hasDelay ? 1 : -1,
|
46 |
+
'summary' => $hasDelay ?
|
47 |
__( 'Automatic updates are applied after a short delay', 'wp-simple-firewall' )
|
48 |
: __( 'Automatic updates are applied immediately', 'wp-simple-firewall' ),
|
49 |
'href' => $mod->getUrl_DirectLinkToOption( 'update_delay' ),
|
65 |
//really disabled?
|
66 |
if ( $mod->isModOptEnabled()
|
67 |
&& $opts->isDisableAllAutoUpdates() && !$WP->getWpAutomaticUpdater()->is_disabled() ) {
|
68 |
+
$cards[ 'messages' ][ 'disabled_auto' ] = [
|
69 |
'name' => 'Auto Updates Not Really Disabled',
|
70 |
'summary' => __( 'Automatic Updates Are Not Disabled As Expected.', 'wp-simple-firewall' ),
|
71 |
'href' => $mod->getUrl_DirectLinkToOption( 'enable_autoupdate_disable_all' ),
|
76 |
];
|
77 |
}
|
78 |
|
79 |
+
return array_merge(
|
80 |
$cards,
|
81 |
$this->getCardsForPlugins(),
|
82 |
$this->getCardsForThemes()
|
83 |
);
|
84 |
+
}
|
85 |
+
|
86 |
+
protected function getSectionTitle() :string {
|
87 |
+
return __( 'Automatic Updates', 'wp-simple-firewall' );
|
88 |
+
}
|
89 |
|
90 |
+
protected function getSectionSubTitle() :string {
|
91 |
+
return __( 'Controlling WordPress Automatic Updates', 'wp-simple-firewall' );
|
92 |
}
|
93 |
|
94 |
private function getCardsForPlugins() :array {
|
95 |
$cards = [];
|
96 |
|
97 |
+
$WPP = Services::WpPlugins();
|
98 |
+
$nCount = count( $WPP->getPlugins() ) - count( $WPP->getActivePlugins() );
|
99 |
$cards[ 'plugins_inactive' ] = [
|
100 |
'name' => __( 'Inactive Plugins', 'wp-simple-firewall' ),
|
101 |
'state' => $nCount > 0 ? -1 : 1,
|
106 |
'help' => __( 'Unused plugins should be removed.', 'wp-simple-firewall' )
|
107 |
];
|
108 |
|
109 |
+
$nCount = count( $WPP->getUpdates() );
|
110 |
$cards[ 'plugin_updates' ] = [
|
111 |
'name' => __( 'Plugin Updates', 'wp-simple-firewall' ),
|
112 |
'state' => $nCount > 0 ? -1 : 1,
|
src/lib/src/Modules/Base/AdminPage.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
|
8 |
+
class AdminPage extends ExecOnceModConsumer {
|
9 |
+
|
10 |
+
protected $screenID;
|
11 |
+
|
12 |
+
protected function canRun() :bool {
|
13 |
+
return !Services::WpGeneral()->isAjax() && ( is_admin() || is_network_admin() );
|
14 |
+
}
|
15 |
+
|
16 |
+
protected function run() {
|
17 |
+
$con = $this->getCon();
|
18 |
+
add_action( $con->prefix( 'admin_submenu' ), function () {
|
19 |
+
$this->addSubMenuItem();
|
20 |
+
}, $this->getMenuPriority() );
|
21 |
+
}
|
22 |
+
|
23 |
+
protected function addSubMenuItem() {
|
24 |
+
$this->screenID = add_submenu_page(
|
25 |
+
$this->isShowMenu() ? $this->getCon()->prefix() : null,
|
26 |
+
$this->getPageTitle(),
|
27 |
+
$this->getMenuTitle(),
|
28 |
+
$this->getCap(),
|
29 |
+
$this->getMod()->getModSlug(),
|
30 |
+
[ $this, 'displayModuleAdminPage' ]
|
31 |
+
);
|
32 |
+
|
33 |
+
foreach ( $this->getAdditionalMenuItems() as $additionalMenuItem ) {
|
34 |
+
list( $itemText, $itemID, $itemCallback, $showItem ) = $additionalMenuItem;
|
35 |
+
add_submenu_page(
|
36 |
+
$showItem ? $this->getCon()->prefix() : null,
|
37 |
+
$itemText,
|
38 |
+
$itemText,
|
39 |
+
$this->getCap(),
|
40 |
+
$itemID,
|
41 |
+
$itemCallback
|
42 |
+
);
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @uses echo()
|
48 |
+
*/
|
49 |
+
public function displayModuleAdminPage() {
|
50 |
+
echo $this->renderModulePage();
|
51 |
+
}
|
52 |
+
|
53 |
+
public function getScreenID() :string {
|
54 |
+
return (string)$this->screenID;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Override this to customize anything with the display of the page
|
59 |
+
* @param array $data
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
protected function renderModulePage( array $data = [] ) :string {
|
63 |
+
return $this->getMod()->renderTemplate(
|
64 |
+
'index.php',
|
65 |
+
Services::DataManipulation()->mergeArraysRecursive( $this->getMod()->getUIHandler()
|
66 |
+
->getBaseDisplayData(), $data )
|
67 |
+
);
|
68 |
+
}
|
69 |
+
|
70 |
+
protected function getMenuPriority() :int {
|
71 |
+
$pri = $this->getOptions()->getFeatureProperty( 'menu_priority' );
|
72 |
+
return is_null( $pri ) ? 100 : (int)$pri;
|
73 |
+
}
|
74 |
+
|
75 |
+
public function getCap() :string {
|
76 |
+
return $this->getCon()->getBasePermissions();
|
77 |
+
}
|
78 |
+
|
79 |
+
public function isShowMenu() :bool {
|
80 |
+
return (bool)$this->getOptions()->getFeatureProperty( 'show_module_menu_item' );
|
81 |
+
}
|
82 |
+
|
83 |
+
public function getMenuTitle( bool $markup = true ) :string {
|
84 |
+
$mod = $this->getMod();
|
85 |
+
$title = $this->getOptions()->getFeatureProperty( 'menu_title' );
|
86 |
+
$title = empty( $title ) ? $mod->getMainFeatureName() : __( $title, 'wp-simple-firewall' );
|
87 |
+
if ( $markup && $this->getOptions()->getFeatureProperty( 'highlight_menu_item' ) ) {
|
88 |
+
$title = sprintf( '<span class="shield_highlighted_menu">%s</span>', $title );
|
89 |
+
}
|
90 |
+
return $title;
|
91 |
+
}
|
92 |
+
|
93 |
+
public function getPageTitle() :string {
|
94 |
+
return sprintf( '%s - %s', $this->getMenuTitle( false ), $this->getCon()->getHumanName() );
|
95 |
+
}
|
96 |
+
|
97 |
+
public function getAdditionalMenuItems() :array {
|
98 |
+
$items = [];
|
99 |
+
|
100 |
+
$con = $this->getCon();
|
101 |
+
$mod = $this->getMod();
|
102 |
+
foreach ( $this->getOptions()->getAdditionalMenuItems() as $menuItem ) {
|
103 |
+
|
104 |
+
// special case: don't show go pro if you're pro.
|
105 |
+
if ( $menuItem[ 'slug' ] !== 'pro-redirect' || !$mod->isPremium() ) {
|
106 |
+
|
107 |
+
$title = __( $menuItem[ 'title' ], 'wp-simple-firewall' );
|
108 |
+
$menuPageTitle = $con->getHumanName().' - '.$title;
|
109 |
+
$isHighlighted = $menuItem[ 'highlight' ] ?? false;
|
110 |
+
$items[ $menuPageTitle ] = [
|
111 |
+
$isHighlighted ? sprintf( '<span class="shield_highlighted_menu">%s</span>', $title ) : $title,
|
112 |
+
$mod->prefix( $menuItem[ 'slug' ] ),
|
113 |
+
[ $this, $menuItem[ 'callback' ] ?? '' ],
|
114 |
+
true
|
115 |
+
];
|
116 |
+
}
|
117 |
+
}
|
118 |
+
return $items;
|
119 |
+
}
|
120 |
+
}
|
src/lib/src/Modules/Base/Common/ExecOnceModConsumer.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common;
|
4 |
+
|
5 |
+
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
+
|
8 |
+
class ExecOnceModConsumer {
|
9 |
+
|
10 |
+
use ModConsumer;
|
11 |
+
use ExecOnce;
|
12 |
+
}
|
src/lib/src/Modules/Base/Insights/OverviewCards.php
CHANGED
@@ -9,16 +9,51 @@ class OverviewCards {
|
|
9 |
use Shield\Modules\ModConsumer;
|
10 |
|
11 |
public function build() :array {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
return [];
|
13 |
}
|
14 |
|
15 |
-
protected function
|
16 |
-
$mod = $this->getMod();
|
17 |
return [
|
18 |
-
'
|
19 |
-
'summary' => __( 'All features of this module are completely disabled', 'wp-simple-firewall' ),
|
20 |
-
'state' => -2,
|
21 |
-
'href' => $mod->getUrl_DirectLinkToOption( $mod->getEnableModOptKey() ),
|
22 |
];
|
23 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
}
|
9 |
use Shield\Modules\ModConsumer;
|
10 |
|
11 |
public function build() :array {
|
12 |
+
$mod = $this->getMod();
|
13 |
+
return [
|
14 |
+
$this->getMod()->getModSlug( false ) => [
|
15 |
+
'title' => $this->getSectionTitle(),
|
16 |
+
'subtitle' => $mod->getStrings()->getModTagLine(),
|
17 |
+
'href_options' => $mod->getUrl_AdminPage(),
|
18 |
+
'cards' => $this->buildCards()
|
19 |
+
]
|
20 |
+
];
|
21 |
+
}
|
22 |
+
|
23 |
+
protected function buildCards() :array {
|
24 |
+
return array_filter( array_merge( $this->buildCommonCards(), $this->buildModCards() ) );
|
25 |
+
}
|
26 |
+
|
27 |
+
protected function buildModCards() :array {
|
28 |
return [];
|
29 |
}
|
30 |
|
31 |
+
protected function buildCommonCards() :array {
|
|
|
32 |
return [
|
33 |
+
'mod' => $this->getModDisabledCard()
|
|
|
|
|
|
|
34 |
];
|
35 |
}
|
36 |
+
|
37 |
+
protected function getSectionTitle() :string {
|
38 |
+
return $this->getMod()->getMainFeatureName();
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function getSectionSubTitle() :string {
|
42 |
+
return $this->getMod()->getStrings()->getModTagLine();
|
43 |
+
}
|
44 |
+
|
45 |
+
protected function getModDisabledCard() :array {
|
46 |
+
$mod = $this->getMod();
|
47 |
+
$card = [];
|
48 |
+
if ( $mod->getOptions()->optExists( $mod->getEnableModOptKey() ) && !$mod->isModOptEnabled() ) {
|
49 |
+
$card = [
|
50 |
+
'name' => sprintf( '%s: %s',
|
51 |
+
$this->getMod()->getMainFeatureName(), __( 'Disabled', 'wp-simple-firewall' ) ),
|
52 |
+
'summary' => __( 'All features of this module are completely disabled', 'wp-simple-firewall' ),
|
53 |
+
'state' => -2,
|
54 |
+
'href' => $mod->getUrl_DirectLinkToOption( $mod->getEnableModOptKey() ),
|
55 |
+
];
|
56 |
+
}
|
57 |
+
return $card;
|
58 |
+
}
|
59 |
}
|
src/lib/src/Modules/Base/Lib/Rest/Request/Process.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Request;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
+
use FernleafSystems\Wordpress\Services\Services;
|
9 |
+
use FernleafSystems\Wordpress\Services\Utilities\File\Cache;
|
10 |
+
|
11 |
+
abstract class Process {
|
12 |
+
|
13 |
+
use ModConsumer;
|
14 |
+
use Rest\Route\RestRouteConsumer;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var RequestVO
|
18 |
+
*/
|
19 |
+
private $reqVO;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var \WP_REST_Request
|
23 |
+
*/
|
24 |
+
protected $wpRestRequest;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Process constructor.
|
28 |
+
* @param Rest\Route\RouteBase|mixed $route
|
29 |
+
* @param \WP_REST_Request $restRequest
|
30 |
+
*/
|
31 |
+
public function __construct( $route, \WP_REST_Request $restRequest ) {
|
32 |
+
$this->setRestRoute( $route );
|
33 |
+
$this->wpRestRequest = $restRequest;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @return array
|
38 |
+
*/
|
39 |
+
public function run() :array {
|
40 |
+
$route = $this->getRestRoute();
|
41 |
+
|
42 |
+
$apiResponse = [
|
43 |
+
'meta' => [
|
44 |
+
'ts' => Services::Request()->ts(),
|
45 |
+
'api_version' => $this->getCon()->getVersion(),
|
46 |
+
'from_cache' => false
|
47 |
+
],
|
48 |
+
];
|
49 |
+
|
50 |
+
$locked = false;
|
51 |
+
try {
|
52 |
+
if ( $route->bypass_lock !== true ) {
|
53 |
+
$locker = ( new Base\Lib\Rest\Utility\RestLocker() )->setRestRoute( $route );
|
54 |
+
$locked = $locker->start();
|
55 |
+
}
|
56 |
+
|
57 |
+
// Ensure only valid parameters are supplied
|
58 |
+
$permittedParams = array_keys( $this->wpRestRequest->get_attributes()[ 'args' ] );
|
59 |
+
if ( count( array_diff_key(
|
60 |
+
$this->wpRestRequest->get_params(),
|
61 |
+
array_flip( $permittedParams )
|
62 |
+
) ) > 0 ) {
|
63 |
+
throw new \Exception(
|
64 |
+
sprintf( 'Please only supply parameters that are permitted: %s',
|
65 |
+
implode( ', ', $permittedParams ) ), 500 );
|
66 |
+
}
|
67 |
+
|
68 |
+
// Is the site ready?
|
69 |
+
( new Base\Lib\Rest\Utility\PreChecks() )
|
70 |
+
->setMod( $this->getMod() )
|
71 |
+
->run();
|
72 |
+
|
73 |
+
// Begin processing.
|
74 |
+
|
75 |
+
$cacher = $route->getCacheHandler();
|
76 |
+
$cacher->request_file = $this->getCacheFileFragment();
|
77 |
+
$cacheDef = $cacher->getCacheDefinition();
|
78 |
+
if ( $cacher->can_cache ) {
|
79 |
+
( new Cache\LoadFromCache() )
|
80 |
+
->setCacheDef( $cacheDef )
|
81 |
+
->load();
|
82 |
+
if ( is_array( $cacheDef->data ) ) {
|
83 |
+
$apiResponse[ 'meta' ][ 'from_cache' ] = true;
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
if ( !is_array( $cacheDef->data ) ) {
|
88 |
+
$cacheDef->data = $this->process();
|
89 |
+
if ( $cacher->can_cache ) {
|
90 |
+
( new Cache\StoreToCache() )
|
91 |
+
->setCacheDef( $cacheDef )
|
92 |
+
->store();
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
$apiResponse[ 'error' ] = false;
|
97 |
+
$apiResponse[ $this->getResponseResultsDataKey() ] = $cacheDef->data;
|
98 |
+
}
|
99 |
+
catch ( \Exception $e ) {
|
100 |
+
$apiResponse[ 'error' ] = true;
|
101 |
+
$apiResponse[ 'code' ] = $e->getCode();
|
102 |
+
$apiResponse[ 'message' ] = $e->getMessage();
|
103 |
+
$apiResponse[ $this->getResponseResultsDataKey() ] = [];
|
104 |
+
}
|
105 |
+
|
106 |
+
if ( $locked && !empty( $locker ) ) {
|
107 |
+
$locker->end();
|
108 |
+
}
|
109 |
+
|
110 |
+
return $apiResponse;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* @return array
|
115 |
+
* @throws \Exception
|
116 |
+
*/
|
117 |
+
abstract protected function process() :array;
|
118 |
+
|
119 |
+
protected function getResponseResultsDataKey() :string {
|
120 |
+
return $this->getMod()->getModSlug( false );
|
121 |
+
}
|
122 |
+
|
123 |
+
protected function getWpRestRequest() :\WP_REST_Request {
|
124 |
+
return $this->wpRestRequest;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* @return RequestVO|mixed
|
129 |
+
*/
|
130 |
+
protected function getRequestVO() {
|
131 |
+
if ( !isset( $this->reqVO ) ) {
|
132 |
+
$this->reqVO = $this->getRestRoute()
|
133 |
+
->getNewReqVO()
|
134 |
+
->applyFromArray( $this->wpRestRequest->get_params() );
|
135 |
+
}
|
136 |
+
return $this->reqVO;
|
137 |
+
}
|
138 |
+
|
139 |
+
protected function getCacheFileFragment() :string {
|
140 |
+
$d = $this->getWpRestRequest()->get_params();
|
141 |
+
ksort( $d );
|
142 |
+
return md5( serialize( $d ) );
|
143 |
+
}
|
144 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/Request/RequestVO.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Request;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class RequestVO
|
7 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Request
|
8 |
+
* @property string $action
|
9 |
+
* @property string $type
|
10 |
+
*/
|
11 |
+
class RequestVO extends \FernleafSystems\Utilities\Data\Adapter\DynPropertiesClass {
|
12 |
+
|
13 |
+
public function getCacheFileSlug() :string {
|
14 |
+
$aD = $this->getRawData();
|
15 |
+
ksort( $aD );
|
16 |
+
return md5( serialize( $aD ) );
|
17 |
+
}
|
18 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/RequestVoConsumer.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Request\RequestVO;
|
6 |
+
|
7 |
+
trait RequestVoConsumer {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @var RequestVO
|
11 |
+
*/
|
12 |
+
private $requestVO;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @return RequestVO|mixed
|
16 |
+
*/
|
17 |
+
public function getRequestVO() {
|
18 |
+
return $this->requestVO;
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param RequestVO|mixed $reqVO
|
23 |
+
* @return $this
|
24 |
+
*/
|
25 |
+
public function setRequestVO( $reqVO ) {
|
26 |
+
$this->requestVO = $reqVO;
|
27 |
+
return $this;
|
28 |
+
}
|
29 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/Route/RestRouteConsumer.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Route;
|
4 |
+
|
5 |
+
trait RestRouteConsumer {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @var RouteBase|mixed
|
9 |
+
*/
|
10 |
+
private $restRoute;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @return RouteBase|mixed
|
14 |
+
*/
|
15 |
+
public function getRestRoute() {
|
16 |
+
return $this->restRoute;
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param RouteBase|mixed $route
|
21 |
+
* @return $this
|
22 |
+
*/
|
23 |
+
public function setRestRoute( $route ) {
|
24 |
+
$this->restRoute = $route;
|
25 |
+
return $this;
|
26 |
+
}
|
27 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/Route/RouteBase.php
ADDED
@@ -0,0 +1,256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Route;
|
4 |
+
|
5 |
+
use FernleafSystems\Utilities\Data\Adapter\DynProperties;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
+
use FernleafSystems\Wordpress\Services\Services;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class RouteBase
|
12 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Route
|
13 |
+
* @property bool $bypass_lock
|
14 |
+
*/
|
15 |
+
abstract class RouteBase extends \WP_REST_Controller {
|
16 |
+
|
17 |
+
use ModConsumer;
|
18 |
+
use DynProperties;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var bool
|
22 |
+
*/
|
23 |
+
private $registered;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/#examples
|
27 |
+
*/
|
28 |
+
public function register_routes() {
|
29 |
+
if ( empty( $this->registered ) ) {
|
30 |
+
$this->registered = true;
|
31 |
+
if ( $this->isReady() ) {
|
32 |
+
register_rest_route( $this->getNamespace(),
|
33 |
+
$this->getRoutePath(),
|
34 |
+
[ $this->buildRouteDefs() ]
|
35 |
+
);
|
36 |
+
}
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @return Base\Lib\Rest\Request\RequestVO
|
42 |
+
*/
|
43 |
+
public function getNewReqVO() {
|
44 |
+
return new Base\Lib\Rest\Request\RequestVO();
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @param array[] $aArgs
|
49 |
+
* @return array[]
|
50 |
+
*/
|
51 |
+
protected function applyArgsDefaults( $aArgs ) {
|
52 |
+
return array_map(
|
53 |
+
function ( $args ) {
|
54 |
+
|
55 |
+
$args[ 'validate_callback' ] = function ( $value, $wpRequest, $reqArgKey ) {
|
56 |
+
return $this->validateRequestArg( $value, $wpRequest, $reqArgKey );
|
57 |
+
};
|
58 |
+
|
59 |
+
$args[ 'sanitize_callback' ] = function ( $value, $wpRequest, $reqArgKey ) {
|
60 |
+
return $this->sanitizeRequestArg( $value, $wpRequest, $reqArgKey );
|
61 |
+
};
|
62 |
+
|
63 |
+
return $args;
|
64 |
+
},
|
65 |
+
$aArgs
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
public function buildRouteDefs() :array {
|
70 |
+
return [
|
71 |
+
'methods' => $this->getArgMethods(),
|
72 |
+
'callback' => function ( \WP_REST_Request $req ) {
|
73 |
+
return $this->executeApiRequest( $req );
|
74 |
+
},
|
75 |
+
'permission_callback' => function ( \WP_REST_Request $req ) {
|
76 |
+
return $this->verifyPermission( $req );
|
77 |
+
},
|
78 |
+
'args' => $this->applyArgsDefaults( $this->getRouteArgs() ),
|
79 |
+
];
|
80 |
+
}
|
81 |
+
|
82 |
+
public function getCacheHandler() :RouteCache {
|
83 |
+
return new RouteCache( $this );
|
84 |
+
}
|
85 |
+
|
86 |
+
protected function getNamespace() :string {
|
87 |
+
$version = $this->getMod()
|
88 |
+
->getOptions()
|
89 |
+
->getDef( 'rest_version' );
|
90 |
+
return sprintf( '%s/v%s',
|
91 |
+
$this->getCon()->prefix(),
|
92 |
+
is_numeric( $version ) ? $version : '1'
|
93 |
+
);
|
94 |
+
}
|
95 |
+
|
96 |
+
abstract public function getRoutePath() :string;
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @return array[]
|
100 |
+
*/
|
101 |
+
protected function getRouteArgs() :array {
|
102 |
+
return array_merge( $this->getRouteArgsDefaults(), $this->getRouteArgsCustom() );
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @return array[]
|
107 |
+
*/
|
108 |
+
protected function getRouteArgsCustom() :array {
|
109 |
+
return [];
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* @return array[][]
|
114 |
+
*/
|
115 |
+
protected function getRouteArgsDefaults() :array {
|
116 |
+
return [];
|
117 |
+
}
|
118 |
+
|
119 |
+
protected function getRouteSlug() :string {
|
120 |
+
try {
|
121 |
+
return strtolower( ( new \ReflectionClass( $this ) )->getShortName() );
|
122 |
+
}
|
123 |
+
catch ( \ReflectionException $e ) {
|
124 |
+
return substr( md5( get_class( $this ) ), 0, 6 );
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
public function getArgMethods() :array {
|
129 |
+
return [ \WP_REST_Server::READABLE ];
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @return string
|
134 |
+
* @throws \Exception
|
135 |
+
*/
|
136 |
+
public function getWorkingDir() :string {
|
137 |
+
$base = $this->getMod()->getRestHandler()->getWorkingDir();
|
138 |
+
if ( !empty( $base ) ) {
|
139 |
+
$dir = path_join( $base, 'r-'.$this->getRouteSlug() );
|
140 |
+
Services::WpFs()->mkdir( $dir );
|
141 |
+
if ( !empty( realpath( $dir ) ) ) {
|
142 |
+
return $dir;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
throw new \Exception( 'Working directory not available' );
|
146 |
+
}
|
147 |
+
|
148 |
+
protected function isReady() :bool {
|
149 |
+
try {
|
150 |
+
$ready = $this->getWorkingDir() !== false;
|
151 |
+
}
|
152 |
+
catch ( \Exception $e ) {
|
153 |
+
$ready = false;
|
154 |
+
}
|
155 |
+
return $ready;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* @param \WP_REST_Request $wpReq
|
160 |
+
* @return \WP_REST_Response
|
161 |
+
*/
|
162 |
+
protected function executeApiRequest( \WP_REST_Request $wpReq ) :\WP_REST_Response {
|
163 |
+
|
164 |
+
$apiResponse = $this->processRequest( $wpReq );
|
165 |
+
$apiResponse[ 'meta' ][ 'params' ] = $wpReq->get_params();
|
166 |
+
$apiResponse = $this->adjustApiResponse( $apiResponse, $wpReq );
|
167 |
+
|
168 |
+
$response = new \WP_REST_Response();
|
169 |
+
$response->set_data( $apiResponse );
|
170 |
+
|
171 |
+
if ( $apiResponse[ 'error' ] ) {
|
172 |
+
$response->set_status( empty( $apiResponse[ 'code' ] ) ? 500 : $apiResponse[ 'code' ] );
|
173 |
+
$response->header( 'Cache-Control', 'no-cache, must-revalidate' );
|
174 |
+
}
|
175 |
+
else {
|
176 |
+
$response->header( 'Cache-Control', 'public, max-age='.$this->getCacheHandler()->expiration );
|
177 |
+
$response->set_status( 200 );
|
178 |
+
}
|
179 |
+
|
180 |
+
return $response;
|
181 |
+
}
|
182 |
+
|
183 |
+
protected function adjustApiResponse( array $response, \WP_REST_Request $wpReq ) :array {
|
184 |
+
return $response;
|
185 |
+
}
|
186 |
+
|
187 |
+
abstract protected function processRequest( \WP_REST_Request $wpReq ) :array;
|
188 |
+
|
189 |
+
/**
|
190 |
+
* @param string|mixed $value
|
191 |
+
* @param \WP_REST_Request $wpRequest
|
192 |
+
* @param string $reqArgKey
|
193 |
+
* @return \WP_Error|mixed
|
194 |
+
*/
|
195 |
+
public function sanitizeRequestArg( $value, \WP_REST_Request $wpRequest, string $reqArgKey ) {
|
196 |
+
try {
|
197 |
+
$value = rest_sanitize_request_arg( $value, $wpRequest, $reqArgKey );
|
198 |
+
if ( !is_wp_error( $value ) ) {
|
199 |
+
$value = $this->customSanitizeRequestArg( $value, $wpRequest, $reqArgKey );
|
200 |
+
}
|
201 |
+
}
|
202 |
+
catch ( \Exception $e ) {
|
203 |
+
$value = new \WP_Error( 400, $e->getMessage() );
|
204 |
+
}
|
205 |
+
return $value;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* @param string|mixed $value
|
210 |
+
* @param \WP_REST_Request $wpRequest
|
211 |
+
* @param string $reqArgKey
|
212 |
+
* @return \WP_Error|bool
|
213 |
+
*/
|
214 |
+
public function validateRequestArg( $value, \WP_REST_Request $wpRequest, string $reqArgKey ) {
|
215 |
+
try {
|
216 |
+
$valid = rest_validate_request_arg( $value, $wpRequest, $reqArgKey );
|
217 |
+
if ( $valid === true ) { // retain WP_ERROR info
|
218 |
+
$valid = $this->customValidateRequestArg( $value, $wpRequest, $reqArgKey );
|
219 |
+
}
|
220 |
+
}
|
221 |
+
catch ( \Exception $e ) {
|
222 |
+
$valid = new \WP_Error( 400, $e->getMessage() );
|
223 |
+
}
|
224 |
+
return $valid;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* @param mixed $value
|
229 |
+
* @param \WP_REST_Request $wpRequest
|
230 |
+
* @param string $reqArgKey
|
231 |
+
* @return \WP_Error|mixed
|
232 |
+
* @throws \Exception
|
233 |
+
*/
|
234 |
+
protected function customSanitizeRequestArg( $value, \WP_REST_Request $wpRequest, string $reqArgKey ) {
|
235 |
+
return $value;
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* @param string|mixed $value
|
240 |
+
* @param \WP_REST_Request $wpRequest
|
241 |
+
* @param string $reqArgKey
|
242 |
+
* @return true
|
243 |
+
* @throws \Exception
|
244 |
+
*/
|
245 |
+
protected function customValidateRequestArg( $value, $wpRequest, $reqArgKey ) :bool {
|
246 |
+
return true;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* @param \WP_REST_Request $req
|
251 |
+
* @return \WP_Error|true
|
252 |
+
*/
|
253 |
+
protected function verifyPermission( \WP_REST_Request $req ) {
|
254 |
+
return true;
|
255 |
+
}
|
256 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/Route/RouteCache.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Route;
|
4 |
+
|
5 |
+
use FernleafSystems\Utilities\Data\Adapter\DynProperties;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
use FernleafSystems\Wordpress\Services\Utilities\File\Cache\CacheDefVO;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class RouteCache
|
11 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Route
|
12 |
+
* @property bool $can_cache
|
13 |
+
* @property string $request_file
|
14 |
+
* @property bool $is_touch
|
15 |
+
* @property int $expiration
|
16 |
+
* @property RouteBase|mixed $oRoute
|
17 |
+
*/
|
18 |
+
class RouteCache {
|
19 |
+
|
20 |
+
use DynProperties;
|
21 |
+
use RestRouteConsumer;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* RouteCache constructor.
|
25 |
+
* @param RouteBase|mixed $route
|
26 |
+
*/
|
27 |
+
public function __construct( $route ) {
|
28 |
+
$this->setRestRoute( $route );
|
29 |
+
}
|
30 |
+
|
31 |
+
public function getCacheDefinition() :CacheDefVO {
|
32 |
+
$def = new CacheDefVO();
|
33 |
+
try {
|
34 |
+
$def->dir = path_join( $this->oRoute->getWorkingDir(), 'cache' );
|
35 |
+
$def->expiration = (int)$this->expiration;
|
36 |
+
$def->touch_on_load = (bool)$this->is_touch;
|
37 |
+
if ( !empty( $this->request_file ) ) {
|
38 |
+
$def->file_fragment = Services::Data()->addExtensionToFilePath(
|
39 |
+
$this->request_file, 'json'
|
40 |
+
);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
catch ( \Exception $e ) {
|
44 |
+
}
|
45 |
+
return $def;
|
46 |
+
}
|
47 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/Utility/PreChecks.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Utility;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
6 |
+
|
7 |
+
class PreChecks {
|
8 |
+
|
9 |
+
use ModConsumer;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @throws \Exception
|
13 |
+
*/
|
14 |
+
public function run() {
|
15 |
+
try {
|
16 |
+
$this->testFileSystem();
|
17 |
+
}
|
18 |
+
catch ( \Exception $e ) {
|
19 |
+
throw new \Exception( 'Service is temporarily unavailable. Report Code: '.$e->getCode() );
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @throws \Exception
|
25 |
+
*/
|
26 |
+
private function testFileSystem() {
|
27 |
+
$dir = $this->getMod()->getWorkingDir();
|
28 |
+
$space = disk_free_space( $dir );
|
29 |
+
if ( $space === false || $space < 2000000 ) {
|
30 |
+
throw new \Exception( 'Not enough disk space: '.$space, 402 );
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
src/lib/src/Modules/Base/Lib/Rest/Utility/RestLocker.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Lib\Rest\Utility;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
|
8 |
+
class RestLocker {
|
9 |
+
|
10 |
+
use Modules\Base\Lib\Rest\Route\RestRouteConsumer;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @return bool
|
14 |
+
* @throws \Exception
|
15 |
+
*/
|
16 |
+
public function start() :bool {
|
17 |
+
$count = 0;
|
18 |
+
$max = 20;
|
19 |
+
while ( $this->isLocked() ) {
|
20 |
+
if ( $count++ > $max ) {
|
21 |
+
throw new \Exception( 'Could not get a lock - there are too many requests processing. Please try again a bit later.', 403 );
|
22 |
+
}
|
23 |
+
usleep( 50000 );
|
24 |
+
}
|
25 |
+
return $this->writeLock();
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @return bool
|
30 |
+
* @throws \Exception
|
31 |
+
*/
|
32 |
+
private function isLocked() :bool {
|
33 |
+
clearstatcache();
|
34 |
+
$FS = Services::WpFs();
|
35 |
+
$file = $this->getLockFile();
|
36 |
+
return !empty( $file ) &&
|
37 |
+
$FS->exists( $file ) && ( Services::Request()->ts() - (int)$FS->getModifiedTime( $file ) < 10 );
|
38 |
+
}
|
39 |
+
|
40 |
+
private function writeLock() :bool {
|
41 |
+
return (bool)Services::WpFs()->touch( $this->getLockFile() );
|
42 |
+
}
|
43 |
+
|
44 |
+
public function end() {
|
45 |
+
$FS = Services::WpFs();
|
46 |
+
$file = $this->getLockFile();
|
47 |
+
if ( $FS->exists( $file ) ) {
|
48 |
+
Services::WpFs()->deleteFile( $file );
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* @return string|bool
|
54 |
+
*/
|
55 |
+
private function getLockFile() {
|
56 |
+
try {
|
57 |
+
$sBase = $this->getRestRoute()->getWorkingDir();
|
58 |
+
$file = path_join( $sBase, 'rest_process.lock' );
|
59 |
+
}
|
60 |
+
catch ( \Exception $e ) {
|
61 |
+
$file = false;
|
62 |
+
}
|
63 |
+
return $file;
|
64 |
+
}
|
65 |
+
}
|
src/lib/src/Modules/Base/ModCon.php
CHANGED
@@ -51,6 +51,11 @@ abstract class ModCon {
|
|
51 |
*/
|
52 |
private $oUI;
|
53 |
|
|
|
|
|
|
|
|
|
|
|
54 |
/**
|
55 |
* @var Shield\Modules\Base\Options
|
56 |
*/
|
@@ -61,6 +66,11 @@ abstract class ModCon {
|
|
61 |
*/
|
62 |
private $oWpCli;
|
63 |
|
|
|
|
|
|
|
|
|
|
|
64 |
/**
|
65 |
* @var Shield\Databases\Base\Handler[]
|
66 |
*/
|
@@ -93,18 +103,18 @@ abstract class ModCon {
|
|
93 |
}
|
94 |
}
|
95 |
|
96 |
-
protected function setupHooks( array $
|
97 |
$con = $this->getCon();
|
98 |
-
$nRunPriority =
|
99 |
|
100 |
add_action( $con->prefix( 'modules_loaded' ), function () {
|
101 |
$this->onModulesLoaded();
|
102 |
}, $nRunPriority );
|
103 |
add_action( $con->prefix( 'run_processors' ), [ $this, 'onRunProcessors' ], $nRunPriority );
|
|
|
104 |
add_action( 'init', [ $this, 'onWpInit' ], 1 );
|
|
|
105 |
|
106 |
-
$nMenuPri = isset( $aModProps[ 'menu_priority' ] ) ? $aModProps[ 'menu_priority' ] : 100;
|
107 |
-
add_filter( $con->prefix( 'submenu_items' ), [ $this, 'supplySubMenuItem' ], $nMenuPri );
|
108 |
add_action( $con->prefix( 'plugin_shutdown' ), [ $this, 'onPluginShutdown' ] );
|
109 |
add_action( $con->prefix( 'deactivate_plugin' ), [ $this, 'onPluginDeactivate' ] );
|
110 |
add_action( $con->prefix( 'delete_plugin' ), [ $this, 'onPluginDelete' ] );
|
@@ -116,6 +126,16 @@ abstract class ModCon {
|
|
116 |
$this->loadAdminNotices();
|
117 |
}
|
118 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
// if ( $this->isAdminOptionsPage() ) {
|
120 |
// add_action( 'current_screen', array( $this, 'onSetCurrentScreen' ) );
|
121 |
// }
|
@@ -271,6 +291,12 @@ abstract class ModCon {
|
|
271 |
$this->getProcessor()->execute();
|
272 |
}
|
273 |
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
public function onWpInit() {
|
275 |
|
276 |
$shieldAction = $this->getCon()->getShieldAction();
|
@@ -542,6 +568,7 @@ abstract class ModCon {
|
|
542 |
/**
|
543 |
* @param array $items
|
544 |
* @return array
|
|
|
545 |
*/
|
546 |
public function supplySubMenuItem( $items ) {
|
547 |
|
@@ -549,7 +576,7 @@ abstract class ModCon {
|
|
549 |
$title = empty( $title ) ? $this->getMainFeatureName() : __( $title, 'wp-simple-firewall' );
|
550 |
|
551 |
if ( !empty( $title ) ) {
|
552 |
-
$highlightedTemplate = '<span class="
|
553 |
$humanName = $this->getCon()->getHumanName();
|
554 |
|
555 |
if ( $this->getOptions()->getFeatureProperty( 'highlight_menu_item' ) ) {
|
@@ -796,11 +823,11 @@ abstract class ModCon {
|
|
796 |
*/
|
797 |
public function getWizardHandler() {
|
798 |
if ( !isset( $this->oWizard ) ) {
|
799 |
-
$
|
800 |
-
if ( !class_exists( $
|
801 |
return null;
|
802 |
}
|
803 |
-
$this->oWizard = new $
|
804 |
$this->oWizard->setMod( $this );
|
805 |
}
|
806 |
return $this->oWizard;
|
@@ -948,14 +975,6 @@ abstract class ModCon {
|
|
948 |
&& Services::Request()->isGet() && $this->isThisModulePage();
|
949 |
}
|
950 |
|
951 |
-
/**
|
952 |
-
* @deprecated 11.1
|
953 |
-
*/
|
954 |
-
protected function isAdminOptionsPage() :bool {
|
955 |
-
return is_admin() && !Services::WpGeneral()->isAjax()
|
956 |
-
&& Services::Request()->isGet() && $this->isThisModulePage();
|
957 |
-
}
|
958 |
-
|
959 |
public function isPremium() :bool {
|
960 |
return $this->getCon()->isPremiumActive();
|
961 |
}
|
@@ -1136,7 +1155,8 @@ abstract class ModCon {
|
|
1136 |
|
1137 |
return add_query_arg(
|
1138 |
[
|
1139 |
-
'page' => $this->getModSlug(),
|
|
|
1140 |
'shield_action' => 'wizard',
|
1141 |
'wizard' => $wizardSlug,
|
1142 |
'nonwizard' => wp_create_nonce( 'wizard'.$wizardSlug )
|
@@ -1343,15 +1363,35 @@ abstract class ModCon {
|
|
1343 |
* @return null|Shield\Modules\Base\Options|mixed
|
1344 |
*/
|
1345 |
public function getOptions() {
|
1346 |
-
|
|
|
1347 |
$con = $this->getCon();
|
1348 |
-
$this->
|
1349 |
-
$this->
|
1350 |
-
|
1351 |
-
|
1352 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1353 |
}
|
1354 |
-
return $this->
|
1355 |
}
|
1356 |
|
1357 |
/**
|
@@ -1415,7 +1455,7 @@ abstract class ModCon {
|
|
1415 |
if ( $req->query( 'debug' ) && $req->query( 'mod' ) == $this->getModSlug()
|
1416 |
&& $this->getCon()->isPluginAdmin() ) {
|
1417 |
/** @var Shield\Modules\Base\Debug $debug */
|
1418 |
-
$debug = $this->loadModElement( 'Debug'
|
1419 |
$debug->run();
|
1420 |
}
|
1421 |
}
|
@@ -1424,21 +1464,20 @@ abstract class ModCon {
|
|
1424 |
* @return Shield\Modules\Base\Strings|mixed
|
1425 |
*/
|
1426 |
protected function loadStrings() {
|
1427 |
-
return $this->loadModElement( 'Strings'
|
1428 |
}
|
1429 |
|
1430 |
/**
|
1431 |
* @param string $class
|
1432 |
-
* @param false $injectMod
|
1433 |
* @return false|Shield\Modules\ModConsumer
|
1434 |
*/
|
1435 |
-
private function loadModElement( string $class
|
1436 |
$element = false;
|
1437 |
try {
|
1438 |
$C = $this->findElementClass( $class, true );
|
1439 |
/** @var Shield\Modules\ModConsumer $element */
|
1440 |
$element = @class_exists( $C ) ? new $C() : false;
|
1441 |
-
if (
|
1442 |
$element->setMod( $this );
|
1443 |
}
|
1444 |
}
|
51 |
*/
|
52 |
private $oUI;
|
53 |
|
54 |
+
/**
|
55 |
+
* @var Shield\Modules\Base\Options
|
56 |
+
*/
|
57 |
+
private $opts;
|
58 |
+
|
59 |
/**
|
60 |
* @var Shield\Modules\Base\Options
|
61 |
*/
|
66 |
*/
|
67 |
private $oWpCli;
|
68 |
|
69 |
+
/**
|
70 |
+
* @var Shield\Modules\Base\AdminPage
|
71 |
+
*/
|
72 |
+
private $adminPage;
|
73 |
+
|
74 |
/**
|
75 |
* @var Shield\Databases\Base\Handler[]
|
76 |
*/
|
103 |
}
|
104 |
}
|
105 |
|
106 |
+
protected function setupHooks( array $modProps ) {
|
107 |
$con = $this->getCon();
|
108 |
+
$nRunPriority = $modProps[ 'load_priority' ] ?? 100;
|
109 |
|
110 |
add_action( $con->prefix( 'modules_loaded' ), function () {
|
111 |
$this->onModulesLoaded();
|
112 |
}, $nRunPriority );
|
113 |
add_action( $con->prefix( 'run_processors' ), [ $this, 'onRunProcessors' ], $nRunPriority );
|
114 |
+
|
115 |
add_action( 'init', [ $this, 'onWpInit' ], 1 );
|
116 |
+
add_action( 'init', [ $this, 'onWpLoaded' ], 1 );
|
117 |
|
|
|
|
|
118 |
add_action( $con->prefix( 'plugin_shutdown' ), [ $this, 'onPluginShutdown' ] );
|
119 |
add_action( $con->prefix( 'deactivate_plugin' ), [ $this, 'onPluginDeactivate' ] );
|
120 |
add_action( $con->prefix( 'delete_plugin' ), [ $this, 'onPluginDelete' ] );
|
126 |
$this->loadAdminNotices();
|
127 |
}
|
128 |
|
129 |
+
if ( $this->getOptions()->getDef( 'rest_api' ) ) {
|
130 |
+
add_action( 'rest_api_init', function () {
|
131 |
+
try {
|
132 |
+
$this->getRestHandler()->init();
|
133 |
+
}
|
134 |
+
catch ( \Exception $e ) {
|
135 |
+
}
|
136 |
+
} );
|
137 |
+
}
|
138 |
+
|
139 |
// if ( $this->isAdminOptionsPage() ) {
|
140 |
// add_action( 'current_screen', array( $this, 'onSetCurrentScreen' ) );
|
141 |
// }
|
291 |
$this->getProcessor()->execute();
|
292 |
}
|
293 |
|
294 |
+
public function onWpLoaded() {
|
295 |
+
if ( is_admin() || is_network_admin() ) {
|
296 |
+
$this->getAdminPage()->execute();
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
public function onWpInit() {
|
301 |
|
302 |
$shieldAction = $this->getCon()->getShieldAction();
|
568 |
/**
|
569 |
* @param array $items
|
570 |
* @return array
|
571 |
+
* @deprecated 11.2
|
572 |
*/
|
573 |
public function supplySubMenuItem( $items ) {
|
574 |
|
576 |
$title = empty( $title ) ? $this->getMainFeatureName() : __( $title, 'wp-simple-firewall' );
|
577 |
|
578 |
if ( !empty( $title ) ) {
|
579 |
+
$highlightedTemplate = '<span class="shield_highlighted_menu">%s</span>';
|
580 |
$humanName = $this->getCon()->getHumanName();
|
581 |
|
582 |
if ( $this->getOptions()->getFeatureProperty( 'highlight_menu_item' ) ) {
|
823 |
*/
|
824 |
public function getWizardHandler() {
|
825 |
if ( !isset( $this->oWizard ) ) {
|
826 |
+
$class = $this->getWizardClassName();
|
827 |
+
if ( !class_exists( $class ) ) {
|
828 |
return null;
|
829 |
}
|
830 |
+
$this->oWizard = new $class();
|
831 |
$this->oWizard->setMod( $this );
|
832 |
}
|
833 |
return $this->oWizard;
|
975 |
&& Services::Request()->isGet() && $this->isThisModulePage();
|
976 |
}
|
977 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
978 |
public function isPremium() :bool {
|
979 |
return $this->getCon()->isPremiumActive();
|
980 |
}
|
1155 |
|
1156 |
return add_query_arg(
|
1157 |
[
|
1158 |
+
'page' => $this->getCon()->getModule_Insights()->getModSlug(),
|
1159 |
+
'inav' => 'wizard',
|
1160 |
'shield_action' => 'wizard',
|
1161 |
'wizard' => $wizardSlug,
|
1162 |
'nonwizard' => wp_create_nonce( 'wizard'.$wizardSlug )
|
1363 |
* @return null|Shield\Modules\Base\Options|mixed
|
1364 |
*/
|
1365 |
public function getOptions() {
|
1366 |
+
$opts = $this->opts ?? $this->oOpts;
|
1367 |
+
if ( !$opts instanceof Options ) {
|
1368 |
$con = $this->getCon();
|
1369 |
+
$this->opts = $this->loadModElement( 'Options' );
|
1370 |
+
$this->opts->setPathToConfig( $con->getPath_ConfigFile( $this->getSlug() ) )
|
1371 |
+
->setRebuildFromFile( $con->cfg->rebuilt )
|
1372 |
+
->setOptionsStorageKey( $this->getOptionsStorageKey() )
|
1373 |
+
->setIfLoadOptionsFromStorage( !$con->getIsResetPlugin() );
|
1374 |
+
$opts = $this->opts;
|
1375 |
+
/** @deprecated 11.2 */
|
1376 |
+
}
|
1377 |
+
return $opts;
|
1378 |
+
}
|
1379 |
+
|
1380 |
+
/**
|
1381 |
+
* @return RestHandler|mixed
|
1382 |
+
*/
|
1383 |
+
public function getRestHandler() {
|
1384 |
+
return $this->loadModElement( 'RestHandler' );
|
1385 |
+
}
|
1386 |
+
|
1387 |
+
/**
|
1388 |
+
* @return AdminPage
|
1389 |
+
*/
|
1390 |
+
public function getAdminPage() {
|
1391 |
+
if ( !isset( $this->adminPage ) ) {
|
1392 |
+
$this->adminPage = $this->loadModElement( 'AdminPage' );
|
1393 |
}
|
1394 |
+
return $this->adminPage;
|
1395 |
}
|
1396 |
|
1397 |
/**
|
1455 |
if ( $req->query( 'debug' ) && $req->query( 'mod' ) == $this->getModSlug()
|
1456 |
&& $this->getCon()->isPluginAdmin() ) {
|
1457 |
/** @var Shield\Modules\Base\Debug $debug */
|
1458 |
+
$debug = $this->loadModElement( 'Debug' );
|
1459 |
$debug->run();
|
1460 |
}
|
1461 |
}
|
1464 |
* @return Shield\Modules\Base\Strings|mixed
|
1465 |
*/
|
1466 |
protected function loadStrings() {
|
1467 |
+
return $this->loadModElement( 'Strings' );
|
1468 |
}
|
1469 |
|
1470 |
/**
|
1471 |
* @param string $class
|
|
|
1472 |
* @return false|Shield\Modules\ModConsumer
|
1473 |
*/
|
1474 |
+
private function loadModElement( string $class ) {
|
1475 |
$element = false;
|
1476 |
try {
|
1477 |
$C = $this->findElementClass( $class, true );
|
1478 |
/** @var Shield\Modules\ModConsumer $element */
|
1479 |
$element = @class_exists( $C ) ? new $C() : false;
|
1480 |
+
if ( method_exists( $element, 'setMod' ) ) {
|
1481 |
$element->setMod( $this );
|
1482 |
}
|
1483 |
}
|
src/lib/src/Modules/Base/Options.php
CHANGED
@@ -171,12 +171,12 @@ class Options {
|
|
171 |
}
|
172 |
|
173 |
/**
|
174 |
-
* @param $
|
175 |
* @return null|mixed
|
176 |
*/
|
177 |
-
public function getFeatureProperty( $
|
178 |
$raw = $this->getRawData_FullFeatureConfig();
|
179 |
-
return ( isset( $raw[ 'properties' ] ) && isset( $raw[ 'properties' ][ $
|
180 |
}
|
181 |
|
182 |
public function getWpCliCfg() :array {
|
@@ -648,6 +648,10 @@ class Options {
|
|
648 |
return (bool)$this->getOptProperty( $key, 'premium' );
|
649 |
}
|
650 |
|
|
|
|
|
|
|
|
|
651 |
public function resetOptToDefault( string $key ) :self {
|
652 |
return $this->setOpt( $key, $this->getOptDefault( $key ) );
|
653 |
}
|
171 |
}
|
172 |
|
173 |
/**
|
174 |
+
* @param $property
|
175 |
* @return null|mixed
|
176 |
*/
|
177 |
+
public function getFeatureProperty( $property ) {
|
178 |
$raw = $this->getRawData_FullFeatureConfig();
|
179 |
+
return ( isset( $raw[ 'properties' ] ) && isset( $raw[ 'properties' ][ $property ] ) ) ? $raw[ 'properties' ][ $property ] : null;
|
180 |
}
|
181 |
|
182 |
public function getWpCliCfg() :array {
|
648 |
return (bool)$this->getOptProperty( $key, 'premium' );
|
649 |
}
|
650 |
|
651 |
+
public function optExists( string $key ) :bool {
|
652 |
+
return !empty( $this->getRawData_SingleOption( $key ) );
|
653 |
+
}
|
654 |
+
|
655 |
public function resetOptToDefault( string $key ) :self {
|
656 |
return $this->setOpt( $key, $this->getOptDefault( $key ) );
|
657 |
}
|
src/lib/src/Modules/Base/RestHandler.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
|
8 |
+
abstract class RestHandler {
|
9 |
+
|
10 |
+
use ModConsumer;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var Lib\Rest\Route\RouteBase[]
|
14 |
+
*/
|
15 |
+
private $routes;
|
16 |
+
|
17 |
+
public function init() {
|
18 |
+
if ( $this->getIfPublishRoutes() ) {
|
19 |
+
foreach ( $this->getRoutes() as $route ) {
|
20 |
+
$route->register_routes();
|
21 |
+
}
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return Lib\Rest\Route\RouteBase[]
|
27 |
+
*/
|
28 |
+
protected function enumRoutes() :array {
|
29 |
+
return [];
|
30 |
+
}
|
31 |
+
|
32 |
+
protected function getIfPublishRoutes() :bool {
|
33 |
+
return true;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @return Lib\Rest\Route\RouteBase[]
|
38 |
+
*/
|
39 |
+
public function getRoutes() :array {
|
40 |
+
if ( !isset( $this->routes ) ) {
|
41 |
+
$this->routes = array_map(
|
42 |
+
function ( $route ) {
|
43 |
+
return $route->setMod( $this->getMod() );
|
44 |
+
},
|
45 |
+
$this->enumRoutes()
|
46 |
+
);
|
47 |
+
}
|
48 |
+
return $this->routes;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @return string
|
53 |
+
* @throws \Exception
|
54 |
+
*/
|
55 |
+
public function getWorkingDir() :string {
|
56 |
+
$base = $this->getMod()->getWorkingDir();
|
57 |
+
if ( !empty( $base ) ) {
|
58 |
+
$dir = path_join( $base, 'api' );
|
59 |
+
Services::WpFs()->mkdir( $dir );
|
60 |
+
if ( !empty( realpath( $dir ) ) ) {
|
61 |
+
return $dir;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
throw new \Exception( 'Working directory not available' );
|
65 |
+
}
|
66 |
+
}
|
src/lib/src/Modules/Base/Strings.php
CHANGED
@@ -10,7 +10,7 @@ class Strings {
|
|
10 |
use ModConsumer;
|
11 |
|
12 |
public function getModTagLine() :string {
|
13 |
-
return __( $this->getOptions()->getFeatureProperty( 'tagline' ), 'wp-simple-firewall' );
|
14 |
}
|
15 |
|
16 |
/**
|
@@ -42,7 +42,7 @@ class Strings {
|
|
42 |
'btn_options' => __( 'Options' ),
|
43 |
'btn_help' => __( 'Help' ),
|
44 |
'btn_wizards' => $this->getMod()->hasWizard() ? __( 'Wizards' ) : __( 'No Wizards' ),
|
45 |
-
'go_to_settings' => __( '
|
46 |
'on' => __( 'On', 'wp-simple-firewall' ),
|
47 |
'off' => __( 'Off', 'wp-simple-firewall' ),
|
48 |
'yes' => __( 'Yes' ),
|
10 |
use ModConsumer;
|
11 |
|
12 |
public function getModTagLine() :string {
|
13 |
+
return (string)__( $this->getOptions()->getFeatureProperty( 'tagline' ), 'wp-simple-firewall' );
|
14 |
}
|
15 |
|
16 |
/**
|
42 |
'btn_options' => __( 'Options' ),
|
43 |
'btn_help' => __( 'Help' ),
|
44 |
'btn_wizards' => $this->getMod()->hasWizard() ? __( 'Wizards' ) : __( 'No Wizards' ),
|
45 |
+
'go_to_settings' => __( 'Configuration', 'wp-simple-firewall' ),
|
46 |
'on' => __( 'On', 'wp-simple-firewall' ),
|
47 |
'off' => __( 'Off', 'wp-simple-firewall' ),
|
48 |
'yes' => __( 'Yes' ),
|
src/lib/src/Modules/Base/UI.php
CHANGED
@@ -247,7 +247,7 @@ class UI {
|
|
247 |
'js_bootstrap' => $urlBuilder->forJs( 'bootstrap' ),
|
248 |
'js_fancybox' => $urlBuilder->forJs( 'jquery.fancybox.min' ),
|
249 |
'js_globalplugin' => $urlBuilder->forJs( 'global-plugin' ),
|
250 |
-
'js_steps' =>
|
251 |
],
|
252 |
'imgs' => [
|
253 |
'favicon' => $urlBuilder->forImage( 'pluginlogo_24x24.png' ),
|
247 |
'js_bootstrap' => $urlBuilder->forJs( 'bootstrap' ),
|
248 |
'js_fancybox' => $urlBuilder->forJs( 'jquery.fancybox.min' ),
|
249 |
'js_globalplugin' => $urlBuilder->forJs( 'global-plugin' ),
|
250 |
+
'js_steps' => 'https://cdnjs.cloudflare.com/ajax/libs/jquery-steps/1.1.0/jquery.steps.min.js',
|
251 |
],
|
252 |
'imgs' => [
|
253 |
'favicon' => $urlBuilder->forImage( 'pluginlogo_24x24.png' ),
|
src/lib/src/Modules/Base/Upgrade.php
CHANGED
@@ -1,14 +1,10 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
|
8 |
-
class Upgrade {
|
9 |
-
|
10 |
-
use ModConsumer;
|
11 |
-
use ExecOnce;
|
12 |
|
13 |
protected function run() {
|
14 |
$this->upgradeModule();
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
|
7 |
+
class Upgrade extends ExecOnceModConsumer {
|
|
|
|
|
|
|
8 |
|
9 |
protected function run() {
|
10 |
$this->upgradeModule();
|
src/lib/src/Modules/Base/WpCli.php
CHANGED
@@ -1,20 +1,16 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\WpCli\ModuleStandard;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
|
9 |
-
class WpCli {
|
10 |
-
|
11 |
-
use ModConsumer;
|
12 |
-
use ExecOnce;
|
13 |
|
14 |
protected function run() {
|
15 |
try {
|
16 |
foreach ( $this->getAllCmdHandlers() as $handler ) {
|
17 |
-
$handler->
|
18 |
}
|
19 |
}
|
20 |
catch ( \Exception $e ) {
|
@@ -25,9 +21,14 @@ class WpCli {
|
|
25 |
* @return WpCli[]
|
26 |
*/
|
27 |
protected function getAllCmdHandlers() :array {
|
28 |
-
return
|
29 |
-
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
31 |
);
|
32 |
}
|
33 |
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\WpCli\ModuleStandard;
|
|
|
7 |
|
8 |
+
class WpCli extends ExecOnceModConsumer {
|
|
|
|
|
|
|
9 |
|
10 |
protected function run() {
|
11 |
try {
|
12 |
foreach ( $this->getAllCmdHandlers() as $handler ) {
|
13 |
+
$handler->execute();
|
14 |
}
|
15 |
}
|
16 |
catch ( \Exception $e ) {
|
21 |
* @return WpCli[]
|
22 |
*/
|
23 |
protected function getAllCmdHandlers() :array {
|
24 |
+
return array_map(
|
25 |
+
function ( $handler ) {
|
26 |
+
$handler->setMod( $this->getMod() );
|
27 |
+
},
|
28 |
+
array_merge(
|
29 |
+
[ new ModuleStandard() ],
|
30 |
+
$this->getCmdHandlers()
|
31 |
+
)
|
32 |
);
|
33 |
}
|
34 |
|
src/lib/src/Modules/BaseShield/AdminPage.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
|
4 |
+
|
5 |
+
class AdminPage extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\AdminPage {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* @uses echo()
|
9 |
+
*/
|
10 |
+
public function displayModuleAdminPage() {
|
11 |
+
if ( $this->getMod()->canDisplayOptionsForm() ) {
|
12 |
+
parent::displayModuleAdminPage();
|
13 |
+
}
|
14 |
+
else {
|
15 |
+
echo $this->getMod()->renderRestrictedPage();
|
16 |
+
}
|
17 |
+
}
|
18 |
+
}
|
src/lib/src/Modules/BaseShield/ModCon.php
CHANGED
@@ -87,27 +87,6 @@ class ModCon extends Base\ModCon {
|
|
87 |
return $cfg;
|
88 |
}
|
89 |
|
90 |
-
/**
|
91 |
-
* @deprecated 11.0
|
92 |
-
*/
|
93 |
-
public function getSecAdminLoginAjaxData() :array {
|
94 |
-
// We set a custom mod_slug so that this module handles the ajax request
|
95 |
-
$data = $this->getAjaxActionData( 'sec_admin_login' );
|
96 |
-
$data[ 'mod_slug' ] = $this->prefix( 'admin_access_restriction' );
|
97 |
-
return $data;
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* @return array
|
102 |
-
* @deprecated 11.1
|
103 |
-
*/
|
104 |
-
protected function getSecAdminCheckAjaxData() :array {
|
105 |
-
// We set a custom mod_slug so that this module handles the ajax request
|
106 |
-
$dat = $this->getAjaxActionData( 'sec_admin_check' );
|
107 |
-
$dat[ 'mod_slug' ] = $this->prefix( 'admin_access_restriction' );
|
108 |
-
return $dat;
|
109 |
-
}
|
110 |
-
|
111 |
public function getPluginReportEmail() :string {
|
112 |
return $this->getCon()
|
113 |
->getModule_Plugin()
|
@@ -126,11 +105,12 @@ class ModCon extends Base\ModCon {
|
|
126 |
}
|
127 |
}
|
128 |
|
129 |
-
|
130 |
/** @var Shield\Modules\SecurityAdmin\Options $secOpts */
|
131 |
$secOpts = $this->getCon()
|
132 |
->getModule_SecAdmin()
|
133 |
->getOptions();
|
|
|
134 |
return $this->renderTemplate(
|
135 |
'/wpadmin_pages/security_admin/index.twig',
|
136 |
Services::DataManipulation()
|
@@ -217,12 +197,6 @@ class ModCon extends Base\ModCon {
|
|
217 |
return self::$bIsVerifiedBot;
|
218 |
}
|
219 |
|
220 |
-
public function isEnabledWhitelabel() :bool {
|
221 |
-
/** @var SecurityAdmin\Options $opts */
|
222 |
-
$opts = $this->getCon()->getModule_SecAdmin()->getOptions();
|
223 |
-
return $opts->isEnabledWhitelabel();
|
224 |
-
}
|
225 |
-
|
226 |
public function isXmlrpcBypass() :bool {
|
227 |
return $this->getCon()
|
228 |
->getModule_Plugin()
|
@@ -257,4 +231,14 @@ class ModCon extends Base\ModCon {
|
|
257 |
$this->getBaseNamespace(),
|
258 |
];
|
259 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
260 |
}
|
87 |
return $cfg;
|
88 |
}
|
89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
public function getPluginReportEmail() :string {
|
91 |
return $this->getCon()
|
92 |
->getModule_Plugin()
|
105 |
}
|
106 |
}
|
107 |
|
108 |
+
public function renderRestrictedPage() :string {
|
109 |
/** @var Shield\Modules\SecurityAdmin\Options $secOpts */
|
110 |
$secOpts = $this->getCon()
|
111 |
->getModule_SecAdmin()
|
112 |
->getOptions();
|
113 |
+
|
114 |
return $this->renderTemplate(
|
115 |
'/wpadmin_pages/security_admin/index.twig',
|
116 |
Services::DataManipulation()
|
197 |
return self::$bIsVerifiedBot;
|
198 |
}
|
199 |
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
public function isXmlrpcBypass() :bool {
|
201 |
return $this->getCon()
|
202 |
->getModule_Plugin()
|
231 |
$this->getBaseNamespace(),
|
232 |
];
|
233 |
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* @return bool
|
237 |
+
* @deprecated 11.2
|
238 |
+
*/
|
239 |
+
public function isEnabledWhitelabel() :bool {
|
240 |
+
/** @var SecurityAdmin\Options $opts */
|
241 |
+
$opts = $this->getCon()->getModule_SecAdmin()->getOptions();
|
242 |
+
return $opts->isEnabledWhitelabel();
|
243 |
+
}
|
244 |
}
|
src/lib/src/Modules/BaseShield/UI.php
CHANGED
@@ -13,6 +13,9 @@ class UI extends Base\UI {
|
|
13 |
/** @var ModCon $mod */
|
14 |
$mod = $this->getMod();
|
15 |
|
|
|
|
|
|
|
16 |
return Services::DataManipulation()->mergeArraysRecursive(
|
17 |
parent::getBaseDisplayData(),
|
18 |
[
|
@@ -39,15 +42,20 @@ class UI extends Base\UI {
|
|
39 |
'sec_admin_login' => $con->getModule_SecAdmin()->getSecAdminLoginAjaxData(),
|
40 |
],
|
41 |
'flags' => [
|
42 |
-
'has_session'
|
43 |
-
|
44 |
-
|
45 |
-
'
|
46 |
],
|
47 |
'hrefs' => [
|
48 |
-
'aar_forget_key' => $
|
49 |
$this->getCon()->getLabels()[ 'AuthorURI' ] : 'https://shsec.io/gc'
|
50 |
],
|
|
|
|
|
|
|
|
|
|
|
51 |
'classes' => [
|
52 |
'top_container' => implode( ' ', array_filter( [
|
53 |
'odp-outercontainer',
|
13 |
/** @var ModCon $mod */
|
14 |
$mod = $this->getMod();
|
15 |
|
16 |
+
$isWhitelabelled = $con->getModule_SecAdmin()->getWhiteLabelController()->isEnabled();
|
17 |
+
$isPremium = $this->getCon()->isPremiumActive();
|
18 |
+
|
19 |
return Services::DataManipulation()->mergeArraysRecursive(
|
20 |
parent::getBaseDisplayData(),
|
21 |
[
|
42 |
'sec_admin_login' => $con->getModule_SecAdmin()->getSecAdminLoginAjaxData(),
|
43 |
],
|
44 |
'flags' => [
|
45 |
+
'has_session' => $con->getModule_Sessions()
|
46 |
+
->getSessionCon()
|
47 |
+
->hasSession(),
|
48 |
+
'display_helpdesk_widget' => !$isWhitelabelled
|
49 |
],
|
50 |
'hrefs' => [
|
51 |
+
'aar_forget_key' => $isWhitelabelled ?
|
52 |
$this->getCon()->getLabels()[ 'AuthorURI' ] : 'https://shsec.io/gc'
|
53 |
],
|
54 |
+
'vars' => [
|
55 |
+
'helpscout_beacon_id' => $isPremium ?
|
56 |
+
'db2ff886-2329-4029-9452-44587df92c8c'
|
57 |
+
: 'aded6929-af83-452d-993f-a60c03b46568'
|
58 |
+
],
|
59 |
'classes' => [
|
60 |
'top_container' => implode( ' ', array_filter( [
|
61 |
'odp-outercontainer',
|
src/lib/src/Modules/CommentsFilter/Forms/Gasp.php
CHANGED
@@ -2,16 +2,12 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Forms;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
|
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
8 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
-
class Gasp {
|
12 |
-
|
13 |
-
use ModConsumer;
|
14 |
-
use ExecOnce;
|
15 |
|
16 |
/**
|
17 |
* The unique comment token assigned to this page
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Forms;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
|
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
+
class Gasp extends ExecOnceModConsumer {
|
|
|
|
|
|
|
11 |
|
12 |
/**
|
13 |
* The unique comment token assigned to this page
|
src/lib/src/Modules/CommentsFilter/Forms/GoogleRecaptcha.php
CHANGED
@@ -2,15 +2,11 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Forms;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
-
class GoogleRecaptcha {
|
11 |
-
|
12 |
-
use ModConsumer;
|
13 |
-
use ExecOnce;
|
14 |
|
15 |
protected function canRun() :bool {
|
16 |
/** @var CommentsFilter\ModCon $mod */
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Forms;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
|
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
+
class GoogleRecaptcha extends ExecOnceModConsumer {
|
|
|
|
|
|
|
10 |
|
11 |
protected function canRun() :bool {
|
12 |
/** @var CommentsFilter\ModCon $mod */
|
src/lib/src/Modules/CommentsFilter/Insights/OverviewCards.php
CHANGED
@@ -7,24 +7,15 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
-
|
11 |
/** @var CommentsFilter\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var CommentsFilter\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
16 |
-
$cardSection = [
|
17 |
-
'title' => __( 'SPAM Blocking', 'wp-simple-firewall' ),
|
18 |
-
'subtitle' => __( 'Block Bot & Human Comment SPAM', 'wp-simple-firewall' ),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage()
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
-
if (
|
25 |
-
$cards[ 'mod' ] = $this->getModDisabledCard();
|
26 |
-
}
|
27 |
-
else {
|
28 |
$botSpamOn = $opts->isEnabledAntiBot() || $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha();
|
29 |
$cards[ 'bot' ] = [
|
30 |
'name' => __( 'Bot SPAM', 'wp-simple-firewall' ),
|
@@ -44,7 +35,14 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
44 |
];
|
45 |
}
|
46 |
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
}
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
+
protected function buildModCards() :array {
|
11 |
/** @var CommentsFilter\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var CommentsFilter\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
$cards = [];
|
17 |
|
18 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
19 |
$botSpamOn = $opts->isEnabledAntiBot() || $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha();
|
20 |
$cards[ 'bot' ] = [
|
21 |
'name' => __( 'Bot SPAM', 'wp-simple-firewall' ),
|
35 |
];
|
36 |
}
|
37 |
|
38 |
+
return $cards;
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function getSectionTitle() :string {
|
42 |
+
return __( 'SPAM Blocking', 'wp-simple-firewall' );
|
43 |
+
}
|
44 |
+
|
45 |
+
protected function getSectionSubTitle() :string {
|
46 |
+
return __( 'Block Bot & Human Comment SPAM', 'wp-simple-firewall' );
|
47 |
}
|
48 |
}
|
src/lib/src/Modules/CommentsFilter/ModCon.php
CHANGED
@@ -87,8 +87,8 @@ class ModCon extends BaseShield\ModCon {
|
|
87 |
&& $this->getCaptchaCfg()->ready;
|
88 |
}
|
89 |
|
90 |
-
public function
|
91 |
-
$this->getOptions()->setOpt( '
|
92 |
}
|
93 |
|
94 |
/**
|
87 |
&& $this->getCaptchaCfg()->ready;
|
88 |
}
|
89 |
|
90 |
+
public function setEnabledAntiBot( bool $enabled = true ) {
|
91 |
+
$this->getOptions()->setOpt( 'enable_antibot_check', $enabled ? 'Y' : 'N' );
|
92 |
}
|
93 |
|
94 |
/**
|
src/lib/src/Modules/CommentsFilter/Scan/CommentAdditiveCleaner.php
CHANGED
@@ -2,14 +2,10 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities;
|
8 |
|
9 |
-
class CommentAdditiveCleaner {
|
10 |
-
|
11 |
-
use ModConsumer;
|
12 |
-
use ExecOnce;
|
13 |
|
14 |
protected function run() {
|
15 |
add_action( 'wp_set_comment_status', function ( $commentID, $newStatus ) {
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities;
|
7 |
|
8 |
+
class CommentAdditiveCleaner extends ExecOnceModConsumer {
|
|
|
|
|
|
|
9 |
|
10 |
protected function run() {
|
11 |
add_action( 'wp_set_comment_status', function ( $commentID, $newStatus ) {
|
src/lib/src/Modules/CommentsFilter/Scan/Scanner.php
CHANGED
@@ -2,16 +2,12 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
-
class Scanner {
|
12 |
-
|
13 |
-
use ModConsumer;
|
14 |
-
use ExecOnce;
|
15 |
|
16 |
/**
|
17 |
* @var string|int|null
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter;
|
|
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
+
class Scanner extends ExecOnceModConsumer {
|
|
|
|
|
|
|
11 |
|
12 |
/**
|
13 |
* @var string|int|null
|
src/lib/src/Modules/CommentsFilter/Strings.php
CHANGED
@@ -118,8 +118,8 @@ class Strings extends Base\Strings {
|
|
118 |
break;
|
119 |
|
120 |
case 'enable_antibot_check' :
|
121 |
-
$name = __( 'AntiBot Detection Engine', 'wp-simple-firewall' );
|
122 |
-
$summary = __( "Use
|
123 |
$desc = [
|
124 |
sprintf( __( "AntiBot Detection Engine is %s's exclusive bot-detection technology that removes the needs for CAPTCHA and other challenges.", 'wp-simple-firewall' ),
|
125 |
$this->getCon()->getHumanName() ),
|
@@ -146,7 +146,10 @@ class Strings extends Base\Strings {
|
|
146 |
|
147 |
case 'enable_comments_gasp_protection' :
|
148 |
$name = __( 'SPAM Bot Protection', 'wp-simple-firewall' );
|
149 |
-
$summary =
|
|
|
|
|
|
|
150 |
$desc = [
|
151 |
sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
|
152 |
__( "Use the newer AntiBot Detection Engine to detect SPAM instead of CAPTCHAs.", 'wp-simple-firewall' ) ),
|
@@ -172,7 +175,10 @@ class Strings extends Base\Strings {
|
|
172 |
|
173 |
case 'google_recaptcha_style_comments' :
|
174 |
$name = __( 'CAPTCHA', 'wp-simple-firewall' );
|
175 |
-
$summary =
|
|
|
|
|
|
|
176 |
$desc = [
|
177 |
sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
|
178 |
__( "Use the newer AntiBot Detection Engine to detect SPAM instead of CAPTCHAs.", 'wp-simple-firewall' ) ),
|
118 |
break;
|
119 |
|
120 |
case 'enable_antibot_check' :
|
121 |
+
$name = __( 'AntiBot Detection Engine (ADE)', 'wp-simple-firewall' );
|
122 |
+
$summary = __( "Use ADE To Detect SPAM Bots And Block Comment SPAM", 'wp-simple-firewall' );
|
123 |
$desc = [
|
124 |
sprintf( __( "AntiBot Detection Engine is %s's exclusive bot-detection technology that removes the needs for CAPTCHA and other challenges.", 'wp-simple-firewall' ),
|
125 |
$this->getCon()->getHumanName() ),
|
146 |
|
147 |
case 'enable_comments_gasp_protection' :
|
148 |
$name = __( 'SPAM Bot Protection', 'wp-simple-firewall' );
|
149 |
+
$summary = sprintf( '[DEPRECATED - %s] %s',
|
150 |
+
'Please use the newer AntiBot setting above',
|
151 |
+
__( 'Block 100% Comment SPAM From Automated Bots', 'wp-simple-firewall' )
|
152 |
+
);
|
153 |
$desc = [
|
154 |
sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
|
155 |
__( "Use the newer AntiBot Detection Engine to detect SPAM instead of CAPTCHAs.", 'wp-simple-firewall' ) ),
|
175 |
|
176 |
case 'google_recaptcha_style_comments' :
|
177 |
$name = __( 'CAPTCHA', 'wp-simple-firewall' );
|
178 |
+
$summary = sprintf( '[DEPRECATED - %s] %s',
|
179 |
+
'Please use the newer AntiBot setting above',
|
180 |
+
__( 'Enable CAPTCHA To Protect Against SPAM Comments', 'wp-simple-firewall' )
|
181 |
+
);
|
182 |
$desc = [
|
183 |
sprintf( '%s - %s', __( 'Recommendation', 'wp-simple-firewall' ),
|
184 |
__( "Use the newer AntiBot Detection Engine to detect SPAM instead of CAPTCHAs.", 'wp-simple-firewall' ) ),
|
src/lib/src/Modules/Email/Processor.php
CHANGED
@@ -40,8 +40,7 @@ class Processor extends BaseShield\Processor {
|
|
40 |
shuffle( $benefits );
|
41 |
}
|
42 |
|
43 |
-
|
44 |
-
$secAdminOpts = $con->getModule_SecAdmin()->getOptions();
|
45 |
$footer = [
|
46 |
$this->getMod()
|
47 |
->renderTemplate( '/email/footer.twig', [
|
@@ -63,7 +62,7 @@ class Processor extends BaseShield\Processor {
|
|
63 |
],
|
64 |
'flags' => [
|
65 |
'is_pro' => $con->isPremiumActive(),
|
66 |
-
'is_whitelabelled' => $
|
67 |
]
|
68 |
] ),
|
69 |
];
|
40 |
shuffle( $benefits );
|
41 |
}
|
42 |
|
43 |
+
$isWhitelabelled = $con->getModule_SecAdmin()->getWhiteLabelController()->isEnabled();
|
|
|
44 |
$footer = [
|
45 |
$this->getMod()
|
46 |
->renderTemplate( '/email/footer.twig', [
|
62 |
],
|
63 |
'flags' => [
|
64 |
'is_pro' => $con->isPremiumActive(),
|
65 |
+
'is_whitelabelled' => $isWhitelabelled
|
66 |
]
|
67 |
] ),
|
68 |
];
|
src/lib/src/Modules/Events/Lib/EventsListener.php
CHANGED
@@ -23,9 +23,8 @@ abstract class EventsListener {
|
|
23 |
|
24 |
add_action( $con->prefix( 'event' ),
|
25 |
function ( $event, $meta = [], $def = [] ) use ( $con ) {
|
26 |
-
|
27 |
-
|
28 |
-
}, 10, 2 );
|
29 |
|
30 |
add_action( $con->prefix( 'plugin_shutdown' ), function () {
|
31 |
$this->onShutdown();
|
23 |
|
24 |
add_action( $con->prefix( 'event' ),
|
25 |
function ( $event, $meta = [], $def = [] ) use ( $con ) {
|
26 |
+
$this->captureEvent( $event, $meta, $def );
|
27 |
+
}, 10, 3 );
|
|
|
28 |
|
29 |
add_action( $con->prefix( 'plugin_shutdown' ), function () {
|
30 |
$this->onShutdown();
|
src/lib/src/Modules/Events/Lib/StatsWriter.php
CHANGED
@@ -21,7 +21,7 @@ class StatsWriter extends EventsListener {
|
|
21 |
* @param array $def
|
22 |
*/
|
23 |
protected function captureEvent( string $evt, $meta = [], $def = [] ) {
|
24 |
-
if ( empty( $def ) ) {
|
25 |
$def = $this->getCon()->loadEventsService()->getEventDef( $evt );
|
26 |
}
|
27 |
if ( !empty( $def[ 'stat' ] ) ) {
|
21 |
* @param array $def
|
22 |
*/
|
23 |
protected function captureEvent( string $evt, $meta = [], $def = [] ) {
|
24 |
+
if ( empty( $def ) ) { // TODO: @deprecated 11.2 - remove this if
|
25 |
$def = $this->getCon()->loadEventsService()->getEventDef( $evt );
|
26 |
}
|
27 |
if ( !empty( $def[ 'stat' ] ) ) {
|
src/lib/src/Modules/Firewall/Insights/OverviewCards.php
CHANGED
@@ -4,50 +4,53 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\Insights;
|
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\ModCon;
|
|
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
-
|
11 |
/** @var ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
-
/** @var
|
14 |
$opts = $this->getOptions();
|
15 |
|
16 |
-
$cardSection = [
|
17 |
-
'title' => __( 'Firewall', 'wp-simple-firewall' ),
|
18 |
-
'subtitle' => __( 'Block Malicious Requests', 'wp-simple-firewall' ),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage()
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
-
|
25 |
-
|
26 |
-
$cards[ 'mod' ] = [
|
27 |
-
'name' => __( 'Firewall', 'wp-simple-firewall' ),
|
28 |
-
'state' => $modEnabled ? 1 : 0,
|
29 |
-
'summary' => $modEnabled ?
|
30 |
-
__( 'Your site is protected against malicious requests', 'wp-simple-firewall' )
|
31 |
-
: __( 'Your site is not protected against malicious requests', 'wp-simple-firewall' ),
|
32 |
-
'href' => $mod->getUrl_DirectLinkToOption( $mod->getEnableModOptKey() ),
|
33 |
-
];
|
34 |
-
|
35 |
-
if ( $modEnabled ) {
|
36 |
//ignoring admin isn't a good idea
|
37 |
-
$
|
38 |
$cards[ 'admin' ] = [
|
39 |
-
'name' => $
|
40 |
__( "Include Admins", 'wp-simple-firewall' )
|
41 |
: __( "Ignore Admins", 'wp-simple-firewall' ),
|
42 |
-
'state' => $
|
43 |
-
'summary' => $
|
44 |
__( "Firewall rules are also applied to admins", 'wp-simple-firewall' )
|
45 |
: __( "Firewall rules aren't applied to admins", 'wp-simple-firewall' ),
|
46 |
'href' => $mod->getUrl_DirectLinkToOption( 'whitelist_admins' ),
|
47 |
];
|
48 |
}
|
49 |
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
}
|
53 |
}
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\ModCon;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\Options;
|
8 |
|
9 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
10 |
|
11 |
+
protected function buildModCards() :array {
|
12 |
/** @var ModCon $mod */
|
13 |
$mod = $this->getMod();
|
14 |
+
/** @var Options $opts */
|
15 |
$opts = $this->getOptions();
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
$cards = [];
|
18 |
|
19 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
//ignoring admin isn't a good idea
|
21 |
+
$includeAdmin = !$opts->isIgnoreAdmin();
|
22 |
$cards[ 'admin' ] = [
|
23 |
+
'name' => $includeAdmin ?
|
24 |
__( "Include Admins", 'wp-simple-firewall' )
|
25 |
: __( "Ignore Admins", 'wp-simple-firewall' ),
|
26 |
+
'state' => $includeAdmin ? 1 : 0,
|
27 |
+
'summary' => $includeAdmin ?
|
28 |
__( "Firewall rules are also applied to admins", 'wp-simple-firewall' )
|
29 |
: __( "Firewall rules aren't applied to admins", 'wp-simple-firewall' ),
|
30 |
'href' => $mod->getUrl_DirectLinkToOption( 'whitelist_admins' ),
|
31 |
];
|
32 |
}
|
33 |
|
34 |
+
return $cards;
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function getSectionTitle() :string {
|
38 |
+
return __( 'Firewall', 'wp-simple-firewall' );
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function getSectionSubTitle() :string {
|
42 |
+
return __( 'Block Malicious Requests', 'wp-simple-firewall' );
|
43 |
+
}
|
44 |
+
|
45 |
+
protected function getModDisabledCard() :array {
|
46 |
+
$mod = $this->getMod();
|
47 |
+
return [
|
48 |
+
'name' => __( 'Firewall', 'wp-simple-firewall' ),
|
49 |
+
'state' => $mod->isModOptEnabled() ? 1 : -2,
|
50 |
+
'summary' => $mod->isModOptEnabled() ?
|
51 |
+
__( "The Firewall is protecting your site against malicious requests", 'wp-simple-firewall' )
|
52 |
+
: __( "The Firewall is disabled so your site isn't protected against malicious requests", 'wp-simple-firewall' ),
|
53 |
+
'href' => $mod->getUrl_DirectLinkToOption( $mod->getEnableModOptKey() ),
|
54 |
+
];
|
55 |
}
|
56 |
}
|
src/lib/src/Modules/Firewall/Lib/Scan/PerformScan.php
CHANGED
@@ -3,12 +3,10 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\Lib\Scan;
|
4 |
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
|
8 |
-
class PerformScan {
|
9 |
-
|
10 |
-
use ModConsumer;
|
11 |
-
use ExecOnce;
|
12 |
|
13 |
/**
|
14 |
* @var false|\WP_Error
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Firewall\Lib\Scan;
|
4 |
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
|
9 |
+
class PerformScan extends ExecOnceModConsumer {
|
|
|
|
|
|
|
10 |
|
11 |
/**
|
12 |
* @var false|\WP_Error
|
src/lib/src/Modules/HackGuard/AjaxHandler.php
CHANGED
@@ -413,7 +413,7 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
413 |
foreach ( $selected as $slug ) {
|
414 |
try {
|
415 |
$thisScanCon = $mod->getScanCon( $slug );
|
416 |
-
if ( $thisScanCon->
|
417 |
|
418 |
$toScan[] = $slug;
|
419 |
|
413 |
foreach ( $selected as $slug ) {
|
414 |
try {
|
415 |
$thisScanCon = $mod->getScanCon( $slug );
|
416 |
+
if ( $thisScanCon->isReady() ) {
|
417 |
|
418 |
$toScan[] = $slug;
|
419 |
|
src/lib/src/Modules/HackGuard/Insights/OverviewCards.php
CHANGED
@@ -7,29 +7,20 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
-
|
11 |
/** @var HackGuard\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var HackGuard\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
16 |
-
$cardSection = [
|
17 |
-
'title' => __( 'Hack Guard', 'wp-simple-firewall' ),
|
18 |
-
'subtitle' => __( 'Threats/Intrusions Detection & Repair', 'wp-simple-firewall' ),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage()
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
-
if (
|
25 |
-
$
|
26 |
-
}
|
27 |
-
else {
|
28 |
-
$bGoodFrequency = $opts->getScanFrequency() > 1;
|
29 |
$cards[ 'frequency' ] = [
|
30 |
'name' => __( 'Scan Frequency', 'wp-simple-firewall' ),
|
31 |
-
'state' => $
|
32 |
-
'summary' => $
|
33 |
__( 'Automatic scanners run more than once per day', 'wp-simple-firewall' )
|
34 |
: __( "Automatic scanners only run once per day", 'wp-simple-firewall' ),
|
35 |
'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_options' ),
|
@@ -46,8 +37,15 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
46 |
);
|
47 |
}
|
48 |
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
|
53 |
private function getCardsForWcf() :array {
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
+
protected function buildModCards() :array {
|
11 |
/** @var HackGuard\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var HackGuard\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
$cards = [];
|
17 |
|
18 |
+
if ( $mod->isModOptEnabled() ) {
|
19 |
+
$goodFrequency = $opts->getScanFrequency() > 1;
|
|
|
|
|
|
|
20 |
$cards[ 'frequency' ] = [
|
21 |
'name' => __( 'Scan Frequency', 'wp-simple-firewall' ),
|
22 |
+
'state' => $goodFrequency ? 1 : 0,
|
23 |
+
'summary' => $goodFrequency ?
|
24 |
__( 'Automatic scanners run more than once per day', 'wp-simple-firewall' )
|
25 |
: __( "Automatic scanners only run once per day", 'wp-simple-firewall' ),
|
26 |
'href' => $mod->getUrl_DirectLinkToSection( 'section_scan_options' ),
|
37 |
);
|
38 |
}
|
39 |
|
40 |
+
return $cards;
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function getSectionTitle() :string {
|
44 |
+
return __( 'Hack Guard', 'wp-simple-firewall' );
|
45 |
+
}
|
46 |
+
|
47 |
+
protected function getSectionSubTitle() :string {
|
48 |
+
return __( 'Threats/Intrusions Detection & Repair', 'wp-simple-firewall' );
|
49 |
}
|
50 |
|
51 |
private function getCardsForWcf() :array {
|
src/lib/src/Modules/HackGuard/Lib/Reports/ScanAlerts.php
CHANGED
@@ -62,9 +62,9 @@ class ScanAlerts extends BaseReporter {
|
|
62 |
private function markAlertsAsNotified() {
|
63 |
/** @var HackGuard\ModCon $mod */
|
64 |
$mod = $this->getMod();
|
65 |
-
/** @var Scanner\Update $
|
66 |
-
$
|
67 |
-
$
|
68 |
->setUpdateWheres( [
|
69 |
'ignored_at' => 0,
|
70 |
'notified_at' => 0,
|
62 |
private function markAlertsAsNotified() {
|
63 |
/** @var HackGuard\ModCon $mod */
|
64 |
$mod = $this->getMod();
|
65 |
+
/** @var Scanner\Update $updater */
|
66 |
+
$updater = $mod->getDbHandler_ScanResults()->getQueryUpdater();
|
67 |
+
$updater
|
68 |
->setUpdateWheres( [
|
69 |
'ignored_at' => 0,
|
70 |
'notified_at' => 0,
|
src/lib/src/Modules/HackGuard/Scan/Controller/Base.php
CHANGED
@@ -2,11 +2,10 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases;
|
|
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
|
9 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
10 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans;
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseResultItem;
|
12 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseResultsSet;
|
@@ -14,10 +13,7 @@ use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseScanActionVO;
|
|
14 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Table\BaseEntryFormatter;
|
15 |
use FernleafSystems\Wordpress\Services\Services;
|
16 |
|
17 |
-
abstract class Base {
|
18 |
-
|
19 |
-
use ModConsumer;
|
20 |
-
use ExecOnce;
|
21 |
|
22 |
const SCAN_SLUG = '';
|
23 |
|
@@ -197,9 +193,19 @@ abstract class Base {
|
|
197 |
}
|
198 |
|
199 |
public function isReady() :bool {
|
200 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
}
|
202 |
|
|
|
|
|
|
|
|
|
203 |
public function isScanningAvailable() :bool {
|
204 |
/** @var ModCon $mod */
|
205 |
$mod = $this->getMod();
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\ModCon;
|
|
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans;
|
10 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseResultItem;
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\BaseResultsSet;
|
13 |
use FernleafSystems\Wordpress\Plugin\Shield\Scans\Base\Table\BaseEntryFormatter;
|
14 |
use FernleafSystems\Wordpress\Services\Services;
|
15 |
|
16 |
+
abstract class Base extends ExecOnceModConsumer {
|
|
|
|
|
|
|
17 |
|
18 |
const SCAN_SLUG = '';
|
19 |
|
193 |
}
|
194 |
|
195 |
public function isReady() :bool {
|
196 |
+
/** @var ModCon $mod */
|
197 |
+
$mod = $this->getMod();
|
198 |
+
return $mod->isModuleEnabled() && $this->isEnabled() && !$this->isRestricted();
|
199 |
+
}
|
200 |
+
|
201 |
+
public function isRestricted() :bool {
|
202 |
+
return $this->isPremiumOnly() && !$this->getCon()->isPremiumActive();
|
203 |
}
|
204 |
|
205 |
+
/**
|
206 |
+
* @return bool
|
207 |
+
* @deprecated 11.2
|
208 |
+
*/
|
209 |
public function isScanningAvailable() :bool {
|
210 |
/** @var ModCon $mod */
|
211 |
$mod = $this->getMod();
|
src/lib/src/Modules/HackGuard/Scan/Controller/Ptg.php
CHANGED
@@ -87,8 +87,8 @@ class Ptg extends BaseForAssets {
|
|
87 |
return $this->getOptions()->isOpt( 'ptg_enable', 'Y' ) && $this->getOptions()->isOptReqsMet( 'ptg_enable' );
|
88 |
}
|
89 |
|
90 |
-
public function
|
91 |
-
return parent::
|
92 |
&& $this->getOptions()->isOptReqsMet( 'ptg_enable' )
|
93 |
&& $this->getMod()->canCacheDirWrite();
|
94 |
}
|
87 |
return $this->getOptions()->isOpt( 'ptg_enable', 'Y' ) && $this->getOptions()->isOptReqsMet( 'ptg_enable' );
|
88 |
}
|
89 |
|
90 |
+
public function isReady() :bool {
|
91 |
+
return parent::isReady()
|
92 |
&& $this->getOptions()->isOptReqsMet( 'ptg_enable' )
|
93 |
&& $this->getMod()->canCacheDirWrite();
|
94 |
}
|
src/lib/src/Modules/HackGuard/Scan/Queue/CompleteQueue.php
CHANGED
@@ -52,8 +52,7 @@ class CompleteQueue {
|
|
52 |
|
53 |
/** @var Databases\ScanQueue\Delete $deleter */
|
54 |
$deleter = $dbh->getQueryDeleter();
|
55 |
-
$deleter->filterByScan( $scanSlug )
|
56 |
-
->query();
|
57 |
}
|
58 |
|
59 |
/** @var HackGuard\Options $opts */
|
52 |
|
53 |
/** @var Databases\ScanQueue\Delete $deleter */
|
54 |
$deleter = $dbh->getQueryDeleter();
|
55 |
+
$deleter->filterByScan( $scanSlug )->query();
|
|
|
56 |
}
|
57 |
|
58 |
/** @var HackGuard\Options $opts */
|
src/lib/src/Modules/HackGuard/Scan/ScansController.php
CHANGED
@@ -2,18 +2,15 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Crons\StandardCron;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases;
|
|
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
|
10 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
11 |
use FernleafSystems\Wordpress\Services\Services;
|
12 |
|
13 |
-
class ScansController {
|
14 |
|
15 |
-
use ModConsumer;
|
16 |
-
use ExecOnce;
|
17 |
use StandardCron;
|
18 |
|
19 |
private $scanCons;
|
@@ -123,7 +120,7 @@ class ScansController {
|
|
123 |
$scans = [];
|
124 |
foreach ( $opts->getScanSlugs() as $slug ) {
|
125 |
$scanCon = $mod->getScanCon( $slug );
|
126 |
-
if ( $scanCon->
|
127 |
$scans[] = $slug;
|
128 |
}
|
129 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Crons\StandardCron;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Options;
|
|
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
+
class ScansController extends ExecOnceModConsumer {
|
13 |
|
|
|
|
|
14 |
use StandardCron;
|
15 |
|
16 |
private $scanCons;
|
120 |
$scans = [];
|
121 |
foreach ( $opts->getScanSlugs() as $slug ) {
|
122 |
$scanCon = $mod->getScanCon( $slug );
|
123 |
+
if ( $scanCon->isReady() ) {
|
124 |
$scans[] = $slug;
|
125 |
}
|
126 |
}
|
src/lib/src/Modules/HackGuard/UI.php
CHANGED
@@ -38,8 +38,9 @@ class UI extends BaseShield\UI {
|
|
38 |
'item_action' => $mod->getAjaxActionData( 'item_action', true ),
|
39 |
],
|
40 |
'flags' => [
|
41 |
-
'is_premium'
|
42 |
-
'can_scan'
|
|
|
43 |
],
|
44 |
'strings' => [
|
45 |
'never' => __( 'Never', 'wp-simple-firewall' ),
|
@@ -65,15 +66,18 @@ class UI extends BaseShield\UI {
|
|
65 |
'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' ),
|
66 |
'scan_progress' => __( 'Scan Progress', 'wp-simple-firewall' ),
|
67 |
'reason_not_call_self' => __( "This site currently can't make HTTP requests to itself.", 'wp-simple-firewall' ),
|
|
|
|
|
68 |
],
|
69 |
'vars' => [
|
70 |
'initial_check' => $mod->getScanQueueController()->hasRunningScans(),
|
71 |
'cannot_scan_reasons' => $reasonsCantScan,
|
72 |
],
|
73 |
'hrefs' => [
|
74 |
-
'
|
75 |
-
|
76 |
-
|
|
|
77 |
],
|
78 |
'scan_results' => [
|
79 |
],
|
@@ -109,7 +113,7 @@ class UI extends BaseShield\UI {
|
|
109 |
__( 'The files listed below are WordPress Core files - official files that are installed with every WordPress website.', 'wp-simple-firewall' ),
|
110 |
__( 'However, they have either been deleted, or their contents have changed in some way.', 'wp-simple-firewall' ),
|
111 |
__( 'Under normal circumstances this should never happen.', 'wp-simple-firewall' ),
|
112 |
-
__( 'You should review each file below and repair them. Repair
|
113 |
__( "If you know why a file has been changed and you're happy to keep those changes, you can click to Ignore that file.", 'wp-simple-firewall' ),
|
114 |
],
|
115 |
],
|
@@ -175,11 +179,11 @@ class UI extends BaseShield\UI {
|
|
175 |
$lastScanAt = $scon->getLastScanAt();
|
176 |
$scData[ 'vars' ][ 'slug' ] = $slug;
|
177 |
$scData[ 'count' ] = $selector->countForScan( $slug );
|
178 |
-
$scData[ 'flags' ][ 'is_available' ] = $scon->
|
179 |
// $scData[ 'flags' ][ 'show_table' ] = $scData[ 'count' ] > 0;
|
180 |
-
$scData[ 'flags' ][ 'is_restricted' ] =
|
181 |
$scData[ 'flags' ][ 'is_enabled' ] = $scon->isEnabled();
|
182 |
-
$scData[ 'flags' ][ 'is_selected' ] = $scon->
|
183 |
$scData[ 'vars' ][ 'last_scan_at_ts' ] = $lastScanAt;
|
184 |
$scData[ 'flags' ][ 'has_last_scan' ] = $lastScanAt > 0;
|
185 |
$scData[ 'vars' ][ 'last_scan_at' ] = sprintf(
|
38 |
'item_action' => $mod->getAjaxActionData( 'item_action', true ),
|
39 |
],
|
40 |
'flags' => [
|
41 |
+
'is_premium' => $this->getCon()->isPremiumActive(),
|
42 |
+
'can_scan' => count( $reasonsCantScan ) === 0,
|
43 |
+
'module_disabled' => !$mod->isModOptEnabled(),
|
44 |
],
|
45 |
'strings' => [
|
46 |
'never' => __( 'Never', 'wp-simple-firewall' ),
|
66 |
'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' ),
|
67 |
'scan_progress' => __( 'Scan Progress', 'wp-simple-firewall' ),
|
68 |
'reason_not_call_self' => __( "This site currently can't make HTTP requests to itself.", 'wp-simple-firewall' ),
|
69 |
+
'module_disabled' => __( "Scans can't run because the module that controls them is currently disabled.", 'wp-simple-firewall' ),
|
70 |
+
'review_scanner_config' => __( "Review Scanner Module configuration", 'wp-simple-firewall' ),
|
71 |
],
|
72 |
'vars' => [
|
73 |
'initial_check' => $mod->getScanQueueController()->hasRunningScans(),
|
74 |
'cannot_scan_reasons' => $reasonsCantScan,
|
75 |
],
|
76 |
'hrefs' => [
|
77 |
+
'scanner_mod_config' => $mod->getUrl_DirectLinkToSection('section_enable_plugin_feature_hack_protection_tools'),
|
78 |
+
'scans_results' => $this->getCon()
|
79 |
+
->getModule_Insights()
|
80 |
+
->getUrl_ScansResults(),
|
81 |
],
|
82 |
'scan_results' => [
|
83 |
],
|
113 |
__( 'The files listed below are WordPress Core files - official files that are installed with every WordPress website.', 'wp-simple-firewall' ),
|
114 |
__( 'However, they have either been deleted, or their contents have changed in some way.', 'wp-simple-firewall' ),
|
115 |
__( 'Under normal circumstances this should never happen.', 'wp-simple-firewall' ),
|
116 |
+
__( 'You should review each file below and repair them. Repair means to replace file with the original.', 'wp-simple-firewall' ),
|
117 |
__( "If you know why a file has been changed and you're happy to keep those changes, you can click to Ignore that file.", 'wp-simple-firewall' ),
|
118 |
],
|
119 |
],
|
179 |
$lastScanAt = $scon->getLastScanAt();
|
180 |
$scData[ 'vars' ][ 'slug' ] = $slug;
|
181 |
$scData[ 'count' ] = $selector->countForScan( $slug );
|
182 |
+
$scData[ 'flags' ][ 'is_available' ] = $scon->isReady();
|
183 |
// $scData[ 'flags' ][ 'show_table' ] = $scData[ 'count' ] > 0;
|
184 |
+
$scData[ 'flags' ][ 'is_restricted' ] = $scon->isRestricted();
|
185 |
$scData[ 'flags' ][ 'is_enabled' ] = $scon->isEnabled();
|
186 |
+
$scData[ 'flags' ][ 'is_selected' ] = $scon->isReady() && in_array( $slug, $uiTrack[ 'selected_scans' ] );
|
187 |
$scData[ 'vars' ][ 'last_scan_at_ts' ] = $lastScanAt;
|
188 |
$scData[ 'flags' ][ 'has_last_scan' ] = $lastScanAt > 0;
|
189 |
$scData[ 'vars' ][ 'last_scan_at' ] = sprintf(
|
src/lib/src/Modules/Headers/Insights/OverviewCards.php
CHANGED
@@ -7,24 +7,15 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\Headers\Options;
|
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
-
|
11 |
/** @var Shield\Modules\Headers\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
16 |
-
$cardSection = [
|
17 |
-
'title' => __( 'HTTP Security Headers', 'wp-simple-firewall' ),
|
18 |
-
'subtitle' => __( 'Protect Visitors With Powerful HTTP Headers', 'wp-simple-firewall' ),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage()
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
-
if (
|
25 |
-
$cards[ 'mod' ] = $this->getModDisabledCard();
|
26 |
-
}
|
27 |
-
else {
|
28 |
$bAllEnabled = $opts->isEnabledXFrame() && $opts->isEnabledXssProtection()
|
29 |
&& $opts->isEnabledContentTypeHeader() && $opts->isReferrerPolicyEnabled();
|
30 |
$cards[ 'all' ] = [
|
@@ -46,7 +37,14 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
46 |
];
|
47 |
}
|
48 |
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
}
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
+
protected function buildModCards() :array {
|
11 |
/** @var Shield\Modules\Headers\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
$cards = [];
|
17 |
|
18 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
19 |
$bAllEnabled = $opts->isEnabledXFrame() && $opts->isEnabledXssProtection()
|
20 |
&& $opts->isEnabledContentTypeHeader() && $opts->isReferrerPolicyEnabled();
|
21 |
$cards[ 'all' ] = [
|
37 |
];
|
38 |
}
|
39 |
|
40 |
+
return $cards;
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function getSectionTitle() :string {
|
44 |
+
return __( 'HTTP Security Headers', 'wp-simple-firewall' );
|
45 |
+
}
|
46 |
+
|
47 |
+
protected function getSectionSubTitle() :string {
|
48 |
+
return __( 'Protect Visitors With Powerful HTTP Headers', 'wp-simple-firewall' );
|
49 |
}
|
50 |
}
|
src/lib/src/Modules/IPs/AjaxHandler.php
CHANGED
@@ -265,6 +265,10 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
265 |
break;
|
266 |
|
267 |
case 'delete_notbot':
|
|
|
|
|
|
|
|
|
268 |
$success = ( new Lib\Bots\BotSignalsRecord() )
|
269 |
->setMod( $this->getMod() )
|
270 |
->setIP( $ip )
|
265 |
break;
|
266 |
|
267 |
case 'delete_notbot':
|
268 |
+
( new Ops\DeleteIp() )
|
269 |
+
->setMod( $this->getMod() )
|
270 |
+
->setIP( $ip )
|
271 |
+
->fromBlacklist();
|
272 |
$success = ( new Lib\Bots\BotSignalsRecord() )
|
273 |
->setMod( $this->getMod() )
|
274 |
->setIP( $ip )
|
src/lib/src/Modules/IPs/Components/IpAddressConsumer.php
CHANGED
@@ -12,22 +12,29 @@ trait IpAddressConsumer {
|
|
12 |
|
13 |
/**
|
14 |
* @var string
|
|
|
15 |
*/
|
16 |
private $sIpAddress;
|
17 |
|
|
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* @return string
|
20 |
*/
|
21 |
public function getIP() {
|
22 |
-
return $this->sIpAddress;
|
23 |
}
|
24 |
|
25 |
/**
|
26 |
-
* @param string $
|
27 |
* @return $this
|
28 |
*/
|
29 |
-
public function setIP( $
|
30 |
-
$this->
|
|
|
31 |
return $this;
|
32 |
}
|
33 |
}
|
12 |
|
13 |
/**
|
14 |
* @var string
|
15 |
+
* @deprecated 11.2
|
16 |
*/
|
17 |
private $sIpAddress;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
private $ipAddress;
|
23 |
+
|
24 |
/**
|
25 |
* @return string
|
26 |
*/
|
27 |
public function getIP() {
|
28 |
+
return $this->ipAddress ?? $this->sIpAddress;
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
+
* @param string $IP
|
33 |
* @return $this
|
34 |
*/
|
35 |
+
public function setIP( $IP ) {
|
36 |
+
$this->ipAddress = $IP;
|
37 |
+
$this->sIpAddress = $IP;
|
38 |
return $this;
|
39 |
}
|
40 |
}
|
src/lib/src/Modules/IPs/Lib/AutoUnblock.php
CHANGED
@@ -2,7 +2,6 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
|
4 |
|
5 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\CommentsFilter\Scan\AntiBot;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
@@ -32,24 +31,6 @@ class AutoUnblock {
|
|
32 |
return $unblocked;
|
33 |
}
|
34 |
|
35 |
-
/**
|
36 |
-
* @deprecated 10.3 - temporary to ensure that service bots aren't blocked and reduce spurious Audit Trail
|
37 |
-
*/
|
38 |
-
private function checkForBlockedServiceBot() :bool {
|
39 |
-
/** @var IPs\ModCon $mod */
|
40 |
-
$mod = $this->getMod();
|
41 |
-
|
42 |
-
$unblocked = false;
|
43 |
-
if ( $mod->isVerifiedBot() ) {
|
44 |
-
( new IPs\Lib\Ops\DeleteIp() )
|
45 |
-
->setMod( $mod )
|
46 |
-
->setIP( Services::IP()->getRequestIp() )
|
47 |
-
->fromBlacklist();
|
48 |
-
$unblocked = true;
|
49 |
-
}
|
50 |
-
return $unblocked;
|
51 |
-
}
|
52 |
-
|
53 |
/**
|
54 |
* @return bool
|
55 |
* @throws \Exception
|
@@ -82,11 +63,6 @@ class AutoUnblock {
|
|
82 |
throw new \Exception( 'IP already processed in the last 1hr' );
|
83 |
}
|
84 |
|
85 |
-
// Perform the test
|
86 |
-
( new AntiBot() )
|
87 |
-
->setMod( $this->getMod() )
|
88 |
-
->scan();
|
89 |
-
|
90 |
{
|
91 |
$existing = $opts->getAutoUnblockIps();
|
92 |
$existing[ $ip ] = Services::Request()->ts();
|
@@ -103,6 +79,10 @@ class AutoUnblock {
|
|
103 |
->setMod( $mod )
|
104 |
->setIP( $ip )
|
105 |
->fromBlacklist();
|
|
|
|
|
|
|
|
|
106 |
$unblocked = true;
|
107 |
}
|
108 |
|
@@ -155,10 +135,10 @@ class AutoUnblock {
|
|
155 |
$existing = $opts->getAutoUnblockEmailIDs();
|
156 |
$existing[ $user->ID ] = Services::Request()->ts();
|
157 |
$opts->setOpt( 'autounblock_emailids',
|
158 |
-
array_filter( $existing, function ( $
|
159 |
return Services::Request()
|
160 |
->carbon()
|
161 |
-
->subHours( 1 )->timestamp < $
|
162 |
} )
|
163 |
);
|
164 |
}
|
@@ -169,6 +149,10 @@ class AutoUnblock {
|
|
169 |
->setMod( $mod )
|
170 |
->setIP( Services::IP()->getRequestIp() )
|
171 |
->fromBlacklist();
|
|
|
|
|
|
|
|
|
172 |
$unblocked = true;
|
173 |
}
|
174 |
else {
|
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;
|
31 |
return $unblocked;
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* @return bool
|
36 |
* @throws \Exception
|
63 |
throw new \Exception( 'IP already processed in the last 1hr' );
|
64 |
}
|
65 |
|
|
|
|
|
|
|
|
|
|
|
66 |
{
|
67 |
$existing = $opts->getAutoUnblockIps();
|
68 |
$existing[ $ip ] = Services::Request()->ts();
|
79 |
->setMod( $mod )
|
80 |
->setIP( $ip )
|
81 |
->fromBlacklist();
|
82 |
+
( new IPs\Lib\Bots\BotSignalsRecord() )
|
83 |
+
->setMod( $this->getMod() )
|
84 |
+
->setIP( $ip )
|
85 |
+
->delete();
|
86 |
$unblocked = true;
|
87 |
}
|
88 |
|
135 |
$existing = $opts->getAutoUnblockEmailIDs();
|
136 |
$existing[ $user->ID ] = Services::Request()->ts();
|
137 |
$opts->setOpt( 'autounblock_emailids',
|
138 |
+
array_filter( $existing, function ( $ts ) {
|
139 |
return Services::Request()
|
140 |
->carbon()
|
141 |
+
->subHours( 1 )->timestamp < $ts;
|
142 |
} )
|
143 |
);
|
144 |
}
|
149 |
->setMod( $mod )
|
150 |
->setIP( Services::IP()->getRequestIp() )
|
151 |
->fromBlacklist();
|
152 |
+
( new IPs\Lib\Bots\BotSignalsRecord() )
|
153 |
+
->setMod( $this->getMod() )
|
154 |
+
->setIP( Services::IP()->getRequestIp() )
|
155 |
+
->delete();
|
156 |
$unblocked = true;
|
157 |
}
|
158 |
else {
|
src/lib/src/Modules/IPs/Lib/BlockRequest.php
CHANGED
@@ -2,16 +2,12 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
use FernleafSystems\Wordpress\Services\Utilities\Obfuscate;
|
10 |
|
11 |
-
class BlockRequest {
|
12 |
-
|
13 |
-
use ModConsumer;
|
14 |
-
use ExecOnce;
|
15 |
|
16 |
protected function run() {
|
17 |
if ( $this->isBlocked() ) {
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
|
|
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
use FernleafSystems\Wordpress\Services\Utilities\Obfuscate;
|
9 |
|
10 |
+
class BlockRequest extends ExecOnceModConsumer {
|
|
|
|
|
|
|
11 |
|
12 |
protected function run() {
|
13 |
if ( $this->isBlocked() ) {
|
src/lib/src/Modules/IPs/Lib/Bots/BotEventListener.php
CHANGED
@@ -2,15 +2,10 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
-
class BotEventListener {
|
11 |
-
|
12 |
-
use ModConsumer;
|
13 |
-
use ExecOnce;
|
14 |
|
15 |
public function fireEventForIP( $ip, $event ) {
|
16 |
$events = $this->getEventsToColumn();
|
@@ -51,6 +46,7 @@ class BotEventListener {
|
|
51 |
[
|
52 |
'bottrack_notbot' => 'notbot',
|
53 |
'frontpage_load' => 'frontpage',
|
|
|
54 |
'bottrack_404' => 'bt404',
|
55 |
'bottrack_fakewebcrawler' => 'btfake',
|
56 |
'bottrack_linkcheese' => 'btcheese',
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
|
|
6 |
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
+
class BotEventListener extends ExecOnceModConsumer {
|
|
|
|
|
|
|
9 |
|
10 |
public function fireEventForIP( $ip, $event ) {
|
11 |
$events = $this->getEventsToColumn();
|
46 |
[
|
47 |
'bottrack_notbot' => 'notbot',
|
48 |
'frontpage_load' => 'frontpage',
|
49 |
+
'loginpage_load' => 'loginpage',
|
50 |
'bottrack_404' => 'bt404',
|
51 |
'bottrack_fakewebcrawler' => 'btfake',
|
52 |
'bottrack_linkcheese' => 'btcheese',
|
src/lib/src/Modules/IPs/Lib/Bots/BotSignalsController.php
CHANGED
@@ -2,15 +2,11 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\Calculator\CalculateVisitorBotScores;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
-
class BotSignalsController {
|
11 |
-
|
12 |
-
use ModConsumer;
|
13 |
-
use ExecOnce;
|
14 |
|
15 |
/**
|
16 |
* @var NotBot\NotBotHandler
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\Calculator\CalculateVisitorBotScores;
|
|
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
+
class BotSignalsController extends ExecOnceModConsumer {
|
|
|
|
|
|
|
10 |
|
11 |
/**
|
12 |
* @var NotBot\NotBotHandler
|
src/lib/src/Modules/IPs/Lib/Bots/BotSignalsRecord.php
CHANGED
@@ -4,10 +4,12 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots;
|
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals\EntryVO;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals\Select;
|
|
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\IpAddressConsumer;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
10 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
|
|
11 |
use FernleafSystems\Wordpress\Services\Services;
|
12 |
|
13 |
class BotSignalsRecord {
|
@@ -55,6 +57,18 @@ class BotSignalsRecord {
|
|
55 |
->hasCookie() ? Services::Request()->ts() : 0;
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
if ( $storeOnLoad ) {
|
59 |
$this->store( $e );
|
60 |
}
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals\EntryVO;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\BotSignals\Select;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\IpAddressConsumer;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
|
10 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
12 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops\Retrieve;
|
13 |
use FernleafSystems\Wordpress\Services\Services;
|
14 |
|
15 |
class BotSignalsRecord {
|
57 |
->hasCookie() ? Services::Request()->ts() : 0;
|
58 |
}
|
59 |
|
60 |
+
if ( empty( $e->auth_at ) ) {
|
61 |
+
$dbhSessions = $this->getCon()
|
62 |
+
->getModule_Sessions()
|
63 |
+
->getDbHandler_Sessions();
|
64 |
+
/** @var Session\Select $selector */
|
65 |
+
$selector = $dbhSessions->getQuerySelector();
|
66 |
+
$session = $selector->setIncludeSoftDeleted( true )
|
67 |
+
->filterByIp( $this->getIP() )
|
68 |
+
->first();
|
69 |
+
$e->auth_at = empty( $session ) ? 0 : $session->created_at;
|
70 |
+
}
|
71 |
+
|
72 |
if ( $storeOnLoad ) {
|
73 |
$this->store( $e );
|
74 |
}
|
src/lib/src/Modules/IPs/Lib/Bots/Calculator/BuildScores.php
CHANGED
@@ -17,6 +17,9 @@ class BuildScores {
|
|
17 |
$scores[ $field ] = $this->{'score_'.$field}();
|
18 |
}
|
19 |
$scores[ 'known' ] = $this->score_known();
|
|
|
|
|
|
|
20 |
return $scores;
|
21 |
}
|
22 |
|
@@ -36,7 +39,7 @@ class BuildScores {
|
|
36 |
$score = 0;
|
37 |
}
|
38 |
else {
|
39 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ?
|
40 |
}
|
41 |
return $score;
|
42 |
}
|
@@ -46,7 +49,7 @@ class BuildScores {
|
|
46 |
$score = 0;
|
47 |
}
|
48 |
else {
|
49 |
-
$score = $this->diffTs( __FUNCTION__ ) < HOUR_IN_SECONDS ? -
|
50 |
}
|
51 |
return $score;
|
52 |
}
|
@@ -56,7 +59,7 @@ class BuildScores {
|
|
56 |
$score = 0;
|
57 |
}
|
58 |
else {
|
59 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -
|
60 |
}
|
61 |
return $score;
|
62 |
}
|
@@ -66,7 +69,7 @@ class BuildScores {
|
|
66 |
$score = 0;
|
67 |
}
|
68 |
else {
|
69 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -
|
70 |
}
|
71 |
return $score;
|
72 |
}
|
@@ -76,7 +79,7 @@ class BuildScores {
|
|
76 |
$score = 0;
|
77 |
}
|
78 |
else {
|
79 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -
|
80 |
}
|
81 |
return $score;
|
82 |
}
|
@@ -86,7 +89,7 @@ class BuildScores {
|
|
86 |
$score = 0;
|
87 |
}
|
88 |
else {
|
89 |
-
$score = $this->diffTs( __FUNCTION__ ) < MINUTE_IN_SECONDS ? -
|
90 |
}
|
91 |
return $score;
|
92 |
}
|
@@ -96,7 +99,7 @@ class BuildScores {
|
|
96 |
$score = 0;
|
97 |
}
|
98 |
else {
|
99 |
-
$score = $this->diffTs( __FUNCTION__ ) <
|
100 |
}
|
101 |
return $score;
|
102 |
}
|
@@ -116,7 +119,7 @@ class BuildScores {
|
|
116 |
$score = 0;
|
117 |
}
|
118 |
else {
|
119 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -
|
120 |
}
|
121 |
return $score;
|
122 |
}
|
@@ -126,7 +129,7 @@ class BuildScores {
|
|
126 |
$score = 0;
|
127 |
}
|
128 |
else {
|
129 |
-
$score = $this->diffTs( __FUNCTION__ ) < MINUTE_IN_SECONDS ? -
|
130 |
}
|
131 |
return $score;
|
132 |
}
|
@@ -136,7 +139,7 @@ class BuildScores {
|
|
136 |
$score = 0;
|
137 |
}
|
138 |
else {
|
139 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -
|
140 |
}
|
141 |
return $score;
|
142 |
}
|
@@ -146,7 +149,7 @@ class BuildScores {
|
|
146 |
$score = 0;
|
147 |
}
|
148 |
else {
|
149 |
-
$score = $this->diffTs( __FUNCTION__ ) < MINUTE_IN_SECONDS ? -
|
150 |
}
|
151 |
return $score;
|
152 |
}
|
@@ -156,7 +159,7 @@ class BuildScores {
|
|
156 |
$score = 0;
|
157 |
}
|
158 |
else {
|
159 |
-
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -
|
160 |
}
|
161 |
return $score;
|
162 |
}
|
@@ -245,12 +248,16 @@ class BuildScores {
|
|
245 |
return $score;
|
246 |
}
|
247 |
|
|
|
|
|
|
|
|
|
248 |
private function score_notbot() :int {
|
249 |
if ( $this->lastAtTs( __FUNCTION__ ) === 0 ) {
|
250 |
-
$score = -
|
251 |
}
|
252 |
else {
|
253 |
-
$score = $this->diffTs( __FUNCTION__ ) < HOUR_IN_SECONDS ?
|
254 |
}
|
255 |
return $score;
|
256 |
}
|
17 |
$scores[ $field ] = $this->{'score_'.$field}();
|
18 |
}
|
19 |
$scores[ 'known' ] = $this->score_known();
|
20 |
+
if ( Services::Request()->ts() - $this->getRecord()->created_at < 30 ) {
|
21 |
+
$scores[ 'baseline' ] = 60;
|
22 |
+
}
|
23 |
return $scores;
|
24 |
}
|
25 |
|
39 |
$score = 0;
|
40 |
}
|
41 |
else {
|
42 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? 175 : 150;
|
43 |
}
|
44 |
return $score;
|
45 |
}
|
49 |
$score = 0;
|
50 |
}
|
51 |
else {
|
52 |
+
$score = $this->diffTs( __FUNCTION__ ) < HOUR_IN_SECONDS ? -15 : -5;
|
53 |
}
|
54 |
return $score;
|
55 |
}
|
59 |
$score = 0;
|
60 |
}
|
61 |
else {
|
62 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -65 : -45;
|
63 |
}
|
64 |
return $score;
|
65 |
}
|
69 |
$score = 0;
|
70 |
}
|
71 |
else {
|
72 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -75 : -45;
|
73 |
}
|
74 |
return $score;
|
75 |
}
|
79 |
$score = 0;
|
80 |
}
|
81 |
else {
|
82 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -25 : -15;
|
83 |
}
|
84 |
return $score;
|
85 |
}
|
89 |
$score = 0;
|
90 |
}
|
91 |
else {
|
92 |
+
$score = $this->diffTs( __FUNCTION__ ) < MINUTE_IN_SECONDS ? -35 : -15;
|
93 |
}
|
94 |
return $score;
|
95 |
}
|
99 |
$score = 0;
|
100 |
}
|
101 |
else {
|
102 |
+
$score = $this->diffTs( __FUNCTION__ ) < HOUR_IN_SECONDS ? -85 : -55;
|
103 |
}
|
104 |
return $score;
|
105 |
}
|
119 |
$score = 0;
|
120 |
}
|
121 |
else {
|
122 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -55 : -35;
|
123 |
}
|
124 |
return $score;
|
125 |
}
|
129 |
$score = 0;
|
130 |
}
|
131 |
else {
|
132 |
+
$score = $this->diffTs( __FUNCTION__ ) < MINUTE_IN_SECONDS ? -25 : -15;
|
133 |
}
|
134 |
return $score;
|
135 |
}
|
139 |
$score = 0;
|
140 |
}
|
141 |
else {
|
142 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -35 : -15;
|
143 |
}
|
144 |
return $score;
|
145 |
}
|
149 |
$score = 0;
|
150 |
}
|
151 |
else {
|
152 |
+
$score = $this->diffTs( __FUNCTION__ ) < MINUTE_IN_SECONDS ? -35 : -25;
|
153 |
}
|
154 |
return $score;
|
155 |
}
|
159 |
$score = 0;
|
160 |
}
|
161 |
else {
|
162 |
+
$score = $this->diffTs( __FUNCTION__ ) < DAY_IN_SECONDS ? -55 : -45;
|
163 |
}
|
164 |
return $score;
|
165 |
}
|
248 |
return $score;
|
249 |
}
|
250 |
|
251 |
+
private function score_loginpage() :int {
|
252 |
+
return $this->lastAtTs( __FUNCTION__ ) > 0 ? 15 : 0;
|
253 |
+
}
|
254 |
+
|
255 |
private function score_notbot() :int {
|
256 |
if ( $this->lastAtTs( __FUNCTION__ ) === 0 ) {
|
257 |
+
$score = -10;
|
258 |
}
|
259 |
else {
|
260 |
+
$score = $this->diffTs( __FUNCTION__ ) < HOUR_IN_SECONDS ? 150 : 75;
|
261 |
}
|
262 |
return $score;
|
263 |
}
|
src/lib/src/Modules/IPs/Lib/Bots/NotBot/InsertNotBotJs.php
CHANGED
@@ -3,13 +3,20 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\
|
|
|
|
|
7 |
|
8 |
-
class InsertNotBotJs {
|
9 |
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
|
13 |
$this->enqueueJS();
|
14 |
$this->nonceJs();
|
15 |
}
|
@@ -21,6 +28,9 @@ class InsertNotBotJs {
|
|
21 |
} );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
private function nonceJs() {
|
25 |
add_filter( 'shield/custom_localisations', function ( array $localz ) {
|
26 |
|
@@ -31,14 +41,17 @@ class InsertNotBotJs {
|
|
31 |
$localz[] = [
|
32 |
'shield/antibot',
|
33 |
'shield_vars_antibotjs',
|
34 |
-
[
|
35 |
'ajax' => [
|
36 |
'not_bot' => http_build_query( $ajaxData )
|
37 |
],
|
38 |
'hrefs' => [
|
39 |
'ajax' => $ajaxHref
|
40 |
],
|
41 |
-
|
|
|
|
|
|
|
42 |
];
|
43 |
return $localz;
|
44 |
} );
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\BotSignalsRecord;
|
8 |
+
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
+
class InsertNotBotJs extends ExecOnceModConsumer {
|
11 |
|
12 |
+
protected function canRun() :bool {
|
13 |
+
return ( Services::Request()->ts() - ( new BotSignalsRecord() )
|
14 |
+
->setMod( $this->getMod() )
|
15 |
+
->setIP( Services::IP()->getRequestIp() )
|
16 |
+
->retrieve()->notbot_at ) > MINUTE_IN_SECONDS*45;
|
17 |
+
}
|
18 |
|
19 |
+
protected function run() {
|
20 |
$this->enqueueJS();
|
21 |
$this->nonceJs();
|
22 |
}
|
28 |
} );
|
29 |
}
|
30 |
|
31 |
+
/**
|
32 |
+
* @since 11.2 - don't fire for GTMetrix page requests
|
33 |
+
*/
|
34 |
private function nonceJs() {
|
35 |
add_filter( 'shield/custom_localisations', function ( array $localz ) {
|
36 |
|
41 |
$localz[] = [
|
42 |
'shield/antibot',
|
43 |
'shield_vars_antibotjs',
|
44 |
+
apply_filters( 'shield/notbot_data_js', [
|
45 |
'ajax' => [
|
46 |
'not_bot' => http_build_query( $ajaxData )
|
47 |
],
|
48 |
'hrefs' => [
|
49 |
'ajax' => $ajaxHref
|
50 |
],
|
51 |
+
'flags' => [
|
52 |
+
'run' => !in_array( Services::IP()->getIpDetector()->getIPIdentity(), [ 'gtmetrix' ] ),
|
53 |
+
],
|
54 |
+
] )
|
55 |
];
|
56 |
return $localz;
|
57 |
} );
|
src/lib/src/Modules/IPs/Lib/Bots/NotBot/NotBotHandler.php
CHANGED
@@ -2,19 +2,20 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
-
class NotBotHandler {
|
11 |
|
12 |
const LIFETIME = 600;
|
13 |
const SLUG = 'notbot';
|
14 |
-
use ModConsumer;
|
15 |
-
use ExecOnce;
|
16 |
|
17 |
-
private $
|
|
|
|
|
|
|
|
|
18 |
|
19 |
protected function canRun() :bool {
|
20 |
return (bool)apply_filters( 'shield/can_run_antibot', true );
|
@@ -23,15 +24,16 @@ class NotBotHandler {
|
|
23 |
protected function run() {
|
24 |
( new InsertNotBotJs() )
|
25 |
->setMod( $this->getMod() )
|
26 |
-
->
|
27 |
$this->registerFrontPageLoad();
|
|
|
28 |
$this->maybeDeleteCookie();
|
29 |
}
|
30 |
|
31 |
private function registerFrontPageLoad() {
|
32 |
-
add_action( '
|
33 |
$req = Services::Request();
|
34 |
-
if ( $req->isGet() && is_front_page() ) {
|
35 |
/** @var ModCon $mod */
|
36 |
$mod = $this->getMod();
|
37 |
$mod->getBotSignalsController()
|
@@ -41,6 +43,19 @@ class NotBotHandler {
|
|
41 |
} );
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
private function maybeDeleteCookie() {
|
45 |
$cookie = $this->getCookieParts();
|
46 |
if ( !empty( $cookie ) && $cookie[ 'ts' ] - Services::Request()->ts() < 300 ) {
|
@@ -49,12 +64,14 @@ class NotBotHandler {
|
|
49 |
}
|
50 |
|
51 |
public function registerAsNotBot() :bool {
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
58 |
$this->getCon()->fireEvent( 'bottrack_notbot' );
|
59 |
return true;
|
60 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\NotBot;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
|
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
+
class NotBotHandler extends ExecOnceModConsumer {
|
10 |
|
11 |
const LIFETIME = 600;
|
12 |
const SLUG = 'notbot';
|
|
|
|
|
13 |
|
14 |
+
private $useCookies;
|
15 |
+
|
16 |
+
public function __construct( bool $useCookies = false ) {
|
17 |
+
$this->useCookies = $useCookies;
|
18 |
+
}
|
19 |
|
20 |
protected function canRun() :bool {
|
21 |
return (bool)apply_filters( 'shield/can_run_antibot', true );
|
24 |
protected function run() {
|
25 |
( new InsertNotBotJs() )
|
26 |
->setMod( $this->getMod() )
|
27 |
+
->execute();
|
28 |
$this->registerFrontPageLoad();
|
29 |
+
$this->registerLoginPageLoad();
|
30 |
$this->maybeDeleteCookie();
|
31 |
}
|
32 |
|
33 |
private function registerFrontPageLoad() {
|
34 |
+
add_action( $this->getCon()->prefix( 'pre_plugin_shutdown' ), function () {
|
35 |
$req = Services::Request();
|
36 |
+
if ( $req->isGet() && ( is_front_page() || is_home() ) ) {
|
37 |
/** @var ModCon $mod */
|
38 |
$mod = $this->getMod();
|
39 |
$mod->getBotSignalsController()
|
43 |
} );
|
44 |
}
|
45 |
|
46 |
+
private function registerLoginPageLoad() {
|
47 |
+
add_action( 'login_footer', function () {
|
48 |
+
$req = Services::Request();
|
49 |
+
if ( $req->isGet() ) {
|
50 |
+
/** @var ModCon $mod */
|
51 |
+
$mod = $this->getMod();
|
52 |
+
$mod->getBotSignalsController()
|
53 |
+
->getEventListener()
|
54 |
+
->fireEventForIP( Services::IP()->getRequestIp(), 'loginpage_load' );
|
55 |
+
}
|
56 |
+
} );
|
57 |
+
}
|
58 |
+
|
59 |
private function maybeDeleteCookie() {
|
60 |
$cookie = $this->getCookieParts();
|
61 |
if ( !empty( $cookie ) && $cookie[ 'ts' ] - Services::Request()->ts() < 300 ) {
|
64 |
}
|
65 |
|
66 |
public function registerAsNotBot() :bool {
|
67 |
+
if ( $this->useCookies ) {
|
68 |
+
$ts = Services::Request()->ts() + self::LIFETIME;
|
69 |
+
Services::Response()->cookieSet(
|
70 |
+
$this->getMod()->prefix( self::SLUG ),
|
71 |
+
sprintf( '%sz%s', $ts, $this->getHashForVisitorTS( $ts ) ),
|
72 |
+
self::LIFETIME
|
73 |
+
);
|
74 |
+
}
|
75 |
$this->getCon()->fireEvent( 'bottrack_notbot' );
|
76 |
return true;
|
77 |
}
|
src/lib/src/Modules/IPs/Lib/IpAnalyse/BuildDisplay.php
CHANGED
@@ -6,8 +6,8 @@ use FernleafSystems\Wordpress\Plugin\Shield\Databases;
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\AuditMessageBuilder;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\GeoIp\Lookup;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\IpAddressConsumer;
|
9 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\Calculator\CalculateVisitorBotScores;
|
10 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\BotSignalsRecord;
|
|
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\DeleteIp;
|
12 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
|
13 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
@@ -299,7 +299,7 @@ class BuildDisplay {
|
|
299 |
$column = $scoreKey.'_at';
|
300 |
if ( $scoreValue !== 0 ) {
|
301 |
if ( empty( $record ) || empty( $record->{$column} ) ) {
|
302 |
-
if ( in_array( $scoreKey, [ 'known' ] ) ) {
|
303 |
$signals[ $scoreKey ] = __( 'N/A', 'wp-simple-firewall' );
|
304 |
}
|
305 |
else {
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\AuditTrail\Lib\AuditMessageBuilder;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\GeoIp\Lookup;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Components\IpAddressConsumer;
|
|
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\BotSignalsRecord;
|
10 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Bots\Calculator\CalculateVisitorBotScores;
|
11 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\DeleteIp;
|
12 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib\Ops\LookupIpOnList;
|
13 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\ModCon;
|
299 |
$column = $scoreKey.'_at';
|
300 |
if ( $scoreValue !== 0 ) {
|
301 |
if ( empty( $record ) || empty( $record->{$column} ) ) {
|
302 |
+
if ( in_array( $scoreKey, [ 'known', 'baseline' ] ) ) {
|
303 |
$signals[ $scoreKey ] = __( 'N/A', 'wp-simple-firewall' );
|
304 |
}
|
305 |
else {
|
src/lib/src/Modules/IPs/Lib/OffenseTracker.php
CHANGED
@@ -22,10 +22,8 @@ class OffenseTracker extends EventsListener {
|
|
22 |
* @param array $def
|
23 |
*/
|
24 |
protected function captureEvent( string $evt, $meta = [], $def = [] ) {
|
25 |
-
if ( empty( $def ) ) {
|
26 |
-
$def = $this->getCon()
|
27 |
-
->loadEventsService()
|
28 |
-
->getEventDef( $evt );
|
29 |
}
|
30 |
|
31 |
if ( !empty( $def[ 'offense' ] ) && empty( $meta[ 'suppress_offense' ] ) ) {
|
22 |
* @param array $def
|
23 |
*/
|
24 |
protected function captureEvent( string $evt, $meta = [], $def = [] ) {
|
25 |
+
if ( empty( $def ) ) { // TODO: @deprecated 11.2 - remove this if
|
26 |
+
$def = $this->getCon()->loadEventsService()->getEventDef( $evt );
|
|
|
|
|
27 |
}
|
28 |
|
29 |
if ( !empty( $def[ 'offense' ] ) && empty( $meta[ 'suppress_offense' ] ) ) {
|
src/lib/src/Modules/IPs/Lib/Ops/LookupIpOnList.php
CHANGED
@@ -129,22 +129,4 @@ class LookupIpOnList {
|
|
129 |
$this->listType = 'white';
|
130 |
return $this;
|
131 |
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* @return $this
|
135 |
-
* @deprecated 11.1
|
136 |
-
*/
|
137 |
-
public function setListTypeBlack() {
|
138 |
-
$this->listType = 'black';
|
139 |
-
return $this;
|
140 |
-
}
|
141 |
-
|
142 |
-
/**
|
143 |
-
* @return $this
|
144 |
-
* @deprecated 11.1
|
145 |
-
*/
|
146 |
-
public function setListTypeWhite() {
|
147 |
-
$this->listType = 'white';
|
148 |
-
return $this;
|
149 |
-
}
|
150 |
}
|
129 |
$this->listType = 'white';
|
130 |
return $this;
|
131 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
}
|
src/lib/src/Modules/IPs/Lib/ProcessOffenses.php
CHANGED
@@ -2,15 +2,11 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
-
class ProcessOffenses {
|
11 |
-
|
12 |
-
use ModConsumer;
|
13 |
-
use ExecOnce;
|
14 |
|
15 |
protected function canRun() :bool {
|
16 |
return !$this->getMod()->isTrustedVerifiedBot();
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs\Lib;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\IPs;
|
|
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
+
class ProcessOffenses extends ExecOnceModConsumer {
|
|
|
|
|
|
|
10 |
|
11 |
protected function canRun() :bool {
|
12 |
return !$this->getMod()->isTrustedVerifiedBot();
|
src/lib/src/Modules/IPs/Options.php
CHANGED
@@ -14,20 +14,14 @@ class Options extends BaseShield\Options {
|
|
14 |
return constant( strtoupper( $this->getOpt( 'auto_expire' ).'_IN_SECONDS' ) );
|
15 |
}
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
public function getAutoUnblockIps() {
|
21 |
-
$aIps = $this->getOpt( 'autounblock_ips', [] );
|
22 |
-
return is_array( $aIps ) ? $aIps : [];
|
23 |
}
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
public function getAutoUnblockEmailIDs() {
|
29 |
-
$aIps = $this->getOpt( 'autounblock_emailids', [] );
|
30 |
-
return is_array( $aIps ) ? $aIps : [];
|
31 |
}
|
32 |
|
33 |
public function getCanIpRequestAutoUnblock( string $ip ) :bool {
|
@@ -36,20 +30,13 @@ class Options extends BaseShield\Options {
|
|
36 |
|| ( Services::Request()->carbon()->subHour( 1 )->timestamp > $existing[ $ip ] );
|
37 |
}
|
38 |
|
39 |
-
|
40 |
-
* @param \WP_User $user
|
41 |
-
* @return bool
|
42 |
-
*/
|
43 |
-
public function getCanRequestAutoUnblockEmailLink( \WP_User $user ) {
|
44 |
$existing = $this->getAutoUnblockEmailIDs();
|
45 |
return !array_key_exists( $user->ID, $existing )
|
46 |
|| ( Services::Request()->carbon()->subHour( 1 )->timestamp > $existing[ $user->ID ] );
|
47 |
}
|
48 |
|
49 |
-
|
50 |
-
* @return int
|
51 |
-
*/
|
52 |
-
public function getOffenseLimit() {
|
53 |
return (int)$this->getOpt( 'transgression_limit' );
|
54 |
}
|
55 |
|
@@ -58,8 +45,8 @@ class Options extends BaseShield\Options {
|
|
58 |
*/
|
59 |
public function getRequestWhitelistAsRegex() {
|
60 |
return array_map(
|
61 |
-
function ( $
|
62 |
-
return sprintf( '#^%s$#i', str_replace( 'STAR', '.*', preg_quote( str_replace( '*', 'STAR', $
|
63 |
},
|
64 |
$this->isPremium() ? $this->getOpt( 'request_whitelist', [] ) : []
|
65 |
);
|
14 |
return constant( strtoupper( $this->getOpt( 'auto_expire' ).'_IN_SECONDS' ) );
|
15 |
}
|
16 |
|
17 |
+
public function getAutoUnblockIps() :array {
|
18 |
+
$ips = $this->getOpt( 'autounblock_ips', [] );
|
19 |
+
return is_array( $ips ) ? $ips : [];
|
|
|
|
|
|
|
20 |
}
|
21 |
|
22 |
+
public function getAutoUnblockEmailIDs() :array {
|
23 |
+
$ips = $this->getOpt( 'autounblock_emailids', [] );
|
24 |
+
return is_array( $ips ) ? $ips : [];
|
|
|
|
|
|
|
25 |
}
|
26 |
|
27 |
public function getCanIpRequestAutoUnblock( string $ip ) :bool {
|
30 |
|| ( Services::Request()->carbon()->subHour( 1 )->timestamp > $existing[ $ip ] );
|
31 |
}
|
32 |
|
33 |
+
public function getCanRequestAutoUnblockEmailLink( \WP_User $user ) :bool {
|
|
|
|
|
|
|
|
|
34 |
$existing = $this->getAutoUnblockEmailIDs();
|
35 |
return !array_key_exists( $user->ID, $existing )
|
36 |
|| ( Services::Request()->carbon()->subHour( 1 )->timestamp > $existing[ $user->ID ] );
|
37 |
}
|
38 |
|
39 |
+
public function getOffenseLimit() :int {
|
|
|
|
|
|
|
40 |
return (int)$this->getOpt( 'transgression_limit' );
|
41 |
}
|
42 |
|
45 |
*/
|
46 |
public function getRequestWhitelistAsRegex() {
|
47 |
return array_map(
|
48 |
+
function ( $rule ) {
|
49 |
+
return sprintf( '#^%s$#i', str_replace( 'STAR', '.*', preg_quote( str_replace( '*', 'STAR', $rule ), '#' ) ) );
|
50 |
},
|
51 |
$this->isPremium() ? $this->getOpt( 'request_whitelist', [] ) : []
|
52 |
);
|
src/lib/src/Modules/IPs/Strings.php
CHANGED
@@ -270,9 +270,11 @@ class Strings extends Base\Strings {
|
|
270 |
*/
|
271 |
public function getBotSignalNames() :array {
|
272 |
return [
|
|
|
273 |
'known' => __( 'A Known Service Provider/Bot', 'wp-simple-firewall' ),
|
274 |
'notbot' => __( '"Not Bot" Registration', 'wp-simple-firewall' ),
|
275 |
-
'frontpage' => __( '
|
|
|
276 |
'bt404' => __( '404 Triggered', 'wp-simple-firewall' ),
|
277 |
'btfake' => __( 'Fake Web Crawler', 'wp-simple-firewall' ),
|
278 |
'btcheese' => __( 'Link Cheese', 'wp-simple-firewall' ),
|
270 |
*/
|
271 |
public function getBotSignalNames() :array {
|
272 |
return [
|
273 |
+
'baseline' => __( 'Baseline Starting Score', 'wp-simple-firewall' ),
|
274 |
'known' => __( 'A Known Service Provider/Bot', 'wp-simple-firewall' ),
|
275 |
'notbot' => __( '"Not Bot" Registration', 'wp-simple-firewall' ),
|
276 |
+
'frontpage' => __( 'Frontpage Visited', 'wp-simple-firewall' ),
|
277 |
+
'loginpage' => __( 'Login Page Visited', 'wp-simple-firewall' ),
|
278 |
'bt404' => __( '404 Triggered', 'wp-simple-firewall' ),
|
279 |
'btfake' => __( 'Fake Web Crawler', 'wp-simple-firewall' ),
|
280 |
'btcheese' => __( 'Link Cheese', 'wp-simple-firewall' ),
|
src/lib/src/Modules/IPs/UI.php
CHANGED
@@ -72,7 +72,7 @@ class UI extends BaseShield\UI {
|
|
72 |
}
|
73 |
|
74 |
protected function getSectionWarnings( string $section ) :array {
|
75 |
-
$
|
76 |
|
77 |
/** @var Options $opts */
|
78 |
$opts = $this->getOptions();
|
@@ -81,7 +81,7 @@ class UI extends BaseShield\UI {
|
|
81 |
|
82 |
case 'section_auto_black_list':
|
83 |
if ( !$opts->isEnabledAutoBlackList() ) {
|
84 |
-
$
|
85 |
}
|
86 |
break;
|
87 |
|
@@ -89,16 +89,16 @@ class UI extends BaseShield\UI {
|
|
89 |
case 'section_probes':
|
90 |
case 'section_logins':
|
91 |
if ( !$opts->isEnabledAutoBlackList() ) {
|
92 |
-
$
|
93 |
}
|
94 |
|
95 |
if ( $section == 'section_behaviours' && strlen( Services::Request()->getUserAgent() ) == 0 ) {
|
96 |
-
$
|
97 |
}
|
98 |
break;
|
99 |
}
|
100 |
|
101 |
-
return $
|
102 |
}
|
103 |
|
104 |
private function renderIpAnalyse() :string {
|
72 |
}
|
73 |
|
74 |
protected function getSectionWarnings( string $section ) :array {
|
75 |
+
$warnings = [];
|
76 |
|
77 |
/** @var Options $opts */
|
78 |
$opts = $this->getOptions();
|
81 |
|
82 |
case 'section_auto_black_list':
|
83 |
if ( !$opts->isEnabledAutoBlackList() ) {
|
84 |
+
$warnings[] = sprintf( '%s: %s', __( 'Note', 'wp-simple-firewall' ), __( "IP blocking is turned-off because the offenses limit is set to 0.", 'wp-simple-firewall' ) );
|
85 |
}
|
86 |
break;
|
87 |
|
89 |
case 'section_probes':
|
90 |
case 'section_logins':
|
91 |
if ( !$opts->isEnabledAutoBlackList() ) {
|
92 |
+
$warnings[] = __( "Since the offenses limit is set to 0, these options have no effect.", 'wp-simple-firewall' );
|
93 |
}
|
94 |
|
95 |
if ( $section == 'section_behaviours' && strlen( Services::Request()->getUserAgent() ) == 0 ) {
|
96 |
+
$warnings[] = __( "Your User Agent appears to be empty. We recommend not turning on this option.", 'wp-simple-firewall' );
|
97 |
}
|
98 |
break;
|
99 |
}
|
100 |
|
101 |
+
return $warnings;
|
102 |
}
|
103 |
|
104 |
private function renderIpAnalyse() :string {
|
src/lib/src/Modules/Insights/AdminPage.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights;
|
4 |
+
|
5 |
+
class AdminPage extends \FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield\AdminPage {
|
6 |
+
|
7 |
+
protected function renderModulePage( array $data = [] ) :string {
|
8 |
+
/** @var UI $UI */
|
9 |
+
$UI = $this->getMod()->getUIHandler();
|
10 |
+
return $UI->renderPages();
|
11 |
+
}
|
12 |
+
}
|
src/lib/src/Modules/Insights/Lib/Requests/DynamicPageLoader.php
CHANGED
@@ -28,6 +28,9 @@ class DynamicPageLoader extends DynPropertiesClass {
|
|
28 |
throw new \Exception( 'No dynamic page loading params' );
|
29 |
}
|
30 |
$this->applyFromArray( $params[ 'load_params' ] );
|
|
|
|
|
|
|
31 |
return [
|
32 |
'html' => $this->getContent(),
|
33 |
'page_url' => $this->getPageUrl(),
|
@@ -35,11 +38,20 @@ class DynamicPageLoader extends DynPropertiesClass {
|
|
35 |
];
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
private function getContent() :string {
|
39 |
|
40 |
switch ( $this->load_type ) {
|
41 |
-
case '
|
42 |
-
$content = $this->
|
43 |
break;
|
44 |
|
45 |
default:
|
@@ -53,7 +65,7 @@ class DynamicPageLoader extends DynPropertiesClass {
|
|
53 |
$con = $this->getCon();
|
54 |
|
55 |
switch ( $this->load_type ) {
|
56 |
-
case '
|
57 |
$url = $con->getModule( $this->load_variant )->getUrl_AdminPage();
|
58 |
break;
|
59 |
|
@@ -67,9 +79,9 @@ class DynamicPageLoader extends DynPropertiesClass {
|
|
67 |
$con = $this->getCon();
|
68 |
|
69 |
switch ( $this->load_type ) {
|
70 |
-
case '
|
71 |
$title = sprintf( '%s: %s',
|
72 |
-
__( '
|
73 |
$con->getModule( $this->load_variant )->getMainFeatureName()
|
74 |
);
|
75 |
break;
|
@@ -83,7 +95,7 @@ class DynamicPageLoader extends DynPropertiesClass {
|
|
83 |
/**
|
84 |
* @throws \Exception
|
85 |
*/
|
86 |
-
private function
|
87 |
|
88 |
$mod = $this->getCon()->getModule( $this->load_variant );
|
89 |
if ( !$mod instanceof ModCon ) {
|
28 |
throw new \Exception( 'No dynamic page loading params' );
|
29 |
}
|
30 |
$this->applyFromArray( $params[ 'load_params' ] );
|
31 |
+
|
32 |
+
$this->verifyLoadParams();
|
33 |
+
|
34 |
return [
|
35 |
'html' => $this->getContent(),
|
36 |
'page_url' => $this->getPageUrl(),
|
38 |
];
|
39 |
}
|
40 |
|
41 |
+
/**
|
42 |
+
* @throws \Exception
|
43 |
+
*/
|
44 |
+
private function verifyLoadParams() {
|
45 |
+
if ( !in_array( $this->load_type, [ 'configuration' ] ) ) {
|
46 |
+
throw new \Exception( 'Unsupported dynamic page load type' );
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
private function getContent() :string {
|
51 |
|
52 |
switch ( $this->load_type ) {
|
53 |
+
case 'configuration':
|
54 |
+
$content = $this->renderConfiguration();
|
55 |
break;
|
56 |
|
57 |
default:
|
65 |
$con = $this->getCon();
|
66 |
|
67 |
switch ( $this->load_type ) {
|
68 |
+
case 'configuration':
|
69 |
$url = $con->getModule( $this->load_variant )->getUrl_AdminPage();
|
70 |
break;
|
71 |
|
79 |
$con = $this->getCon();
|
80 |
|
81 |
switch ( $this->load_type ) {
|
82 |
+
case 'configuration':
|
83 |
$title = sprintf( '%s: %s',
|
84 |
+
__( 'Configuration', 'wp-simple-firewall' ),
|
85 |
$con->getModule( $this->load_variant )->getMainFeatureName()
|
86 |
);
|
87 |
break;
|
95 |
/**
|
96 |
* @throws \Exception
|
97 |
*/
|
98 |
+
private function renderConfiguration() :string {
|
99 |
|
100 |
$mod = $this->getCon()->getModule( $this->load_variant );
|
101 |
if ( !$mod instanceof ModCon ) {
|
src/lib/src/Modules/Insights/Lib/SideMenuBuilder.php
CHANGED
@@ -15,7 +15,7 @@ class SideMenuBuilder {
|
|
15 |
$this->search(),
|
16 |
$this->overview(),
|
17 |
$this->stats(),
|
18 |
-
$this->
|
19 |
$this->scans(),
|
20 |
$this->ips(),
|
21 |
$this->audit(),
|
@@ -39,12 +39,30 @@ class SideMenuBuilder {
|
|
39 |
'target' => '',
|
40 |
'data' => [],
|
41 |
'badge' => [],
|
|
|
42 |
], $item );
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
if ( !empty( $item[ 'sub_items' ] ) ) {
|
45 |
$item[ 'data' ][ 'toggle' ] = 'collapse';
|
46 |
$item[ 'href' ] = '#collapse-'.$item[ 'slug' ];
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
// Set parent active if any sub-items are active
|
49 |
if ( !$item[ 'active' ] ) {
|
50 |
$item[ 'active' ] = count( array_filter( $item[ 'sub_items' ], function ( $sub ) {
|
@@ -53,6 +71,10 @@ class SideMenuBuilder {
|
|
53 |
}
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
56 |
$menu[ $key ] = $item;
|
57 |
}
|
58 |
|
@@ -75,12 +97,12 @@ class SideMenuBuilder {
|
|
75 |
],
|
76 |
[
|
77 |
'slug' => $slug.'-blocksettings',
|
78 |
-
'title' => sprintf( '%s: %s', __( '
|
79 |
'href' => $con->getModule_IPs()->getUrl_AdminPage(),
|
80 |
],
|
81 |
[
|
82 |
'slug' => $slug.'-antibotsettings',
|
83 |
-
'title' => sprintf( '%s: %s', __( '
|
84 |
'href' => $con->getModule_IPs()->getUrl_DirectLinkToSection( 'section_antibot' ),
|
85 |
],
|
86 |
[
|
@@ -95,7 +117,9 @@ class SideMenuBuilder {
|
|
95 |
'slug' => $slug,
|
96 |
'title' => __( 'IPs and Bots', 'wp-simple-firewall' ),
|
97 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/diagram-3.svg' ),
|
98 |
-
'introjs' =>
|
|
|
|
|
99 |
'sub_items' => $subItems,
|
100 |
];
|
101 |
}
|
@@ -109,13 +133,13 @@ class SideMenuBuilder {
|
|
109 |
$subItems = [
|
110 |
[
|
111 |
'slug' => $slug.'-log',
|
112 |
-
'title' => __( 'View Log', 'wp-simple-firewall' ),
|
113 |
'href' => $mod->getUrl_SubInsightsPage( $slug ),
|
114 |
'active' => $this->getInav() === $slug,
|
115 |
],
|
116 |
[
|
117 |
'slug' => $slug.'-settings',
|
118 |
-
'title' => __( '
|
119 |
'href' => $con->getModule_AuditTrail()->getUrl_AdminPage(),
|
120 |
],
|
121 |
[
|
@@ -133,10 +157,12 @@ class SideMenuBuilder {
|
|
133 |
];
|
134 |
|
135 |
return [
|
136 |
-
'slug' =>
|
137 |
'title' => __( 'Audit Trail', 'wp-simple-firewall' ),
|
138 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/person-lines-fill.svg' ),
|
139 |
-
'introjs' =>
|
|
|
|
|
140 |
'sub_items' => $subItems,
|
141 |
];
|
142 |
}
|
@@ -163,7 +189,7 @@ class SideMenuBuilder {
|
|
163 |
],
|
164 |
[
|
165 |
'slug' => $slug.'-settings',
|
166 |
-
'title' => sprintf( '%s: %s', __( '
|
167 |
'href' => $con->getModule_HackGuard()->getUrl_AdminPage(),
|
168 |
],
|
169 |
];
|
@@ -172,8 +198,10 @@ class SideMenuBuilder {
|
|
172 |
'slug' => $slug,
|
173 |
'title' => __( 'Scans', 'wp-simple-firewall' ),
|
174 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/shield-shaded.svg' ),
|
175 |
-
'introjs' =>
|
176 |
-
|
|
|
|
|
177 |
'sub_items' => $subItems,
|
178 |
];
|
179 |
}
|
@@ -187,7 +215,9 @@ class SideMenuBuilder {
|
|
187 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/search.svg' ),
|
188 |
'id' => 'NavMenuSearch',
|
189 |
'href' => $mod->getUrl_SubInsightsPage( 'overview' ),
|
190 |
-
'introjs' =>
|
|
|
|
|
191 |
'data' => [
|
192 |
'toggle' => 'modal',
|
193 |
'target' => '#SearchDialog',
|
@@ -204,7 +234,9 @@ class SideMenuBuilder {
|
|
204 |
'title' => __( 'Reports', 'wp-simple-firewall' ),
|
205 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/graph-up.svg' ),
|
206 |
'href' => $mod->getUrl_SubInsightsPage( 'reports' ),
|
207 |
-
'introjs' =>
|
|
|
|
|
208 |
'sub_items' => [
|
209 |
[
|
210 |
'slug' => 'reports-stats',
|
@@ -230,15 +262,17 @@ class SideMenuBuilder {
|
|
230 |
'title' => __( 'Overview', 'wp-simple-firewall' ),
|
231 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/binoculars.svg' ),
|
232 |
'href' => $mod->getUrl_SubInsightsPage( 'overview' ),
|
233 |
-
'introjs' =>
|
234 |
-
|
|
|
|
|
235 |
];
|
236 |
}
|
237 |
|
238 |
-
private function
|
239 |
/** @var ModCon $mod */
|
240 |
$mod = $this->getMod();
|
241 |
-
$slug = '
|
242 |
|
243 |
$subItems = [];
|
244 |
foreach ( $mod->getModulesSummaryData() as $modData ) {
|
@@ -259,10 +293,12 @@ class SideMenuBuilder {
|
|
259 |
|
260 |
return [
|
261 |
'slug' => $slug,
|
262 |
-
'title' => __( '
|
263 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/sliders.svg' ),
|
264 |
-
'introjs' =>
|
265 |
-
|
|
|
|
|
266 |
'sub_items' => $subItems,
|
267 |
];
|
268 |
}
|
@@ -273,33 +309,24 @@ class SideMenuBuilder {
|
|
273 |
'slug' => 'integrations',
|
274 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/puzzle-fill.svg' ),
|
275 |
'title' => __( 'Integrations', 'wp-simple-firewall' ),
|
276 |
-
'introjs' =>
|
|
|
|
|
277 |
'sub_items' => [
|
278 |
[
|
279 |
-
'slug' => 'integrations-
|
280 |
-
'title' => __( 'Settings', 'wp-simple-firewall' ),
|
281 |
-
'href' => $con->getModule_Integrations()->getUrl_AdminPage(),
|
282 |
-
],
|
283 |
-
[
|
284 |
-
'slug' => 'integrations-spam',
|
285 |
'title' => __( 'Contact Form SPAM', 'wp-simple-firewall' ),
|
286 |
'href' => $con->getModule_Integrations()->getUrl_DirectLinkToSection( 'section_spam' ),
|
287 |
],
|
|
|
|
|
|
|
|
|
|
|
288 |
],
|
289 |
];
|
290 |
}
|
291 |
|
292 |
-
private function reports() :array {
|
293 |
-
/** @var ModCon $mod */
|
294 |
-
$mod = $this->getMod();
|
295 |
-
return [
|
296 |
-
'slug' => 'reports',
|
297 |
-
'title' => __( 'Reports', 'wp-simple-firewall' ),
|
298 |
-
'img' => $this->getCon()->urls->forImage( 'bootstrap/graph-up.svg' ),
|
299 |
-
'href' => $mod->getUrl_SubInsightsPage( 'reports' ),
|
300 |
-
];
|
301 |
-
}
|
302 |
-
|
303 |
private function docs() :array {
|
304 |
/** @var ModCon $mod */
|
305 |
$mod = $this->getMod();
|
@@ -331,8 +358,8 @@ class SideMenuBuilder {
|
|
331 |
[
|
332 |
'slug' => 'license-trial',
|
333 |
'title' => __( 'Free Trial', 'wp-simple-firewall' ),
|
334 |
-
'href' =>
|
335 |
-
'
|
336 |
],
|
337 |
[
|
338 |
'slug' => 'license-features',
|
@@ -388,7 +415,9 @@ class SideMenuBuilder {
|
|
388 |
'slug' => $slug,
|
389 |
'title' => __( 'Tools', 'wp-simple-firewall' ),
|
390 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/tools.svg' ),
|
391 |
-
'introjs' =>
|
|
|
|
|
392 |
'sub_items' => $subItems,
|
393 |
];
|
394 |
}
|
@@ -402,13 +431,13 @@ class SideMenuBuilder {
|
|
402 |
$subItems = [
|
403 |
[
|
404 |
'slug' => $slug.'-log',
|
405 |
-
'title' => __( 'View Log', 'wp-simple-firewall' ),
|
406 |
'href' => $mod->getUrl_SubInsightsPage( $slug ),
|
407 |
'active' => $this->getInav() === $slug,
|
408 |
],
|
409 |
[
|
410 |
'slug' => $slug.'-ratelimitsettings',
|
411 |
-
'title' => sprintf( '%s: %s', __( '
|
412 |
'href' => $con->getModule_Traffic()->getUrl_DirectLinkToSection( 'section_traffic_limiter' ),
|
413 |
],
|
414 |
[
|
@@ -423,7 +452,9 @@ class SideMenuBuilder {
|
|
423 |
'slug' => 'traffic',
|
424 |
'title' => __( 'Traffic', 'wp-simple-firewall' ),
|
425 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/stoplights.svg' ),
|
426 |
-
'introjs' =>
|
|
|
|
|
427 |
'sub_items' => $subItems,
|
428 |
];
|
429 |
}
|
@@ -441,23 +472,23 @@ class SideMenuBuilder {
|
|
441 |
],
|
442 |
[
|
443 |
'slug' => 'users-secadmin',
|
444 |
-
'title' => sprintf( '%s: %s', __( '
|
445 |
'href' => $con->getModule_SecAdmin()->getUrl_DirectLinkToSection( 'section_security_admin_settings' ),
|
446 |
],
|
447 |
[
|
448 |
'slug' => 'users-settings',
|
449 |
-
'title' => sprintf( '%s: %s', __( '
|
450 |
'href' => $con->getModule_UserManagement()
|
451 |
->getUrl_DirectLinkToSection( 'section_user_session_management' ),
|
452 |
],
|
453 |
[
|
454 |
'slug' => 'users-passwords',
|
455 |
-
'title' => sprintf( '%s: %s', __( '
|
456 |
'href' => $con->getModule_UserManagement()->getUrl_DirectLinkToSection( 'section_passwords' ),
|
457 |
],
|
458 |
[
|
459 |
'slug' => 'users-suspend',
|
460 |
-
'title' => sprintf( '%s: %s', __( '
|
461 |
'href' => $con->getModule_UserManagement()->getUrl_DirectLinkToSection( 'section_suspend' ),
|
462 |
],
|
463 |
];
|
@@ -466,11 +497,17 @@ class SideMenuBuilder {
|
|
466 |
'slug' => 'users',
|
467 |
'title' => __( 'Users', 'wp-simple-firewall' ),
|
468 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/person-badge.svg' ),
|
469 |
-
'introjs' =>
|
|
|
|
|
470 |
'sub_items' => $subItems,
|
471 |
];
|
472 |
}
|
473 |
|
|
|
|
|
|
|
|
|
474 |
private function getInav() :string {
|
475 |
return (string)Services::Request()->query( 'inav' );
|
476 |
}
|
15 |
$this->search(),
|
16 |
$this->overview(),
|
17 |
$this->stats(),
|
18 |
+
$this->configuration(),
|
19 |
$this->scans(),
|
20 |
$this->ips(),
|
21 |
$this->audit(),
|
39 |
'target' => '',
|
40 |
'data' => [],
|
41 |
'badge' => [],
|
42 |
+
'introjs' => [],
|
43 |
], $item );
|
44 |
|
45 |
+
if ( !empty( $item[ 'introjs' ] ) ) {
|
46 |
+
$item[ 'classes' ][] = 'tour-'.$this->getIntroJsTourID();
|
47 |
+
if ( empty( $item[ 'introjs' ][ 'title' ] ) ) {
|
48 |
+
$item[ 'introjs' ][ 'title' ] = $item[ 'title' ];
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
if ( !empty( $item[ 'sub_items' ] ) ) {
|
53 |
$item[ 'data' ][ 'toggle' ] = 'collapse';
|
54 |
$item[ 'href' ] = '#collapse-'.$item[ 'slug' ];
|
55 |
|
56 |
+
$item[ 'sub_items' ] = array_map( function ( $sub ) {
|
57 |
+
if ( empty( $sub[ 'classes' ] ) ) {
|
58 |
+
$sub[ 'classes' ] = [];
|
59 |
+
}
|
60 |
+
if ( $sub[ 'active' ] ?? false ) {
|
61 |
+
$sub[ 'classes' ][] = 'active';
|
62 |
+
}
|
63 |
+
return $sub;
|
64 |
+
}, $item[ 'sub_items' ] );
|
65 |
+
|
66 |
// Set parent active if any sub-items are active
|
67 |
if ( !$item[ 'active' ] ) {
|
68 |
$item[ 'active' ] = count( array_filter( $item[ 'sub_items' ], function ( $sub ) {
|
71 |
}
|
72 |
}
|
73 |
|
74 |
+
if ( $item[ 'active' ] ) {
|
75 |
+
$item[ 'classes' ][] = 'active';
|
76 |
+
}
|
77 |
+
|
78 |
$menu[ $key ] = $item;
|
79 |
}
|
80 |
|
97 |
],
|
98 |
[
|
99 |
'slug' => $slug.'-blocksettings',
|
100 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'IP Blocking', 'wp-simple-firewall' ) ),
|
101 |
'href' => $con->getModule_IPs()->getUrl_AdminPage(),
|
102 |
],
|
103 |
[
|
104 |
'slug' => $slug.'-antibotsettings',
|
105 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'AntiBot', 'wp-simple-firewall' ) ),
|
106 |
'href' => $con->getModule_IPs()->getUrl_DirectLinkToSection( 'section_antibot' ),
|
107 |
],
|
108 |
[
|
117 |
'slug' => $slug,
|
118 |
'title' => __( 'IPs and Bots', 'wp-simple-firewall' ),
|
119 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/diagram-3.svg' ),
|
120 |
+
'introjs' => [
|
121 |
+
'body' => __( "Protection begins by detecting bad bots - Review and Analyse all visitor IPs that have an impact on your site.", 'wp-simple-firewall' ),
|
122 |
+
],
|
123 |
'sub_items' => $subItems,
|
124 |
];
|
125 |
}
|
133 |
$subItems = [
|
134 |
[
|
135 |
'slug' => $slug.'-log',
|
136 |
+
'title' => __( 'View Audit Trail Log', 'wp-simple-firewall' ),
|
137 |
'href' => $mod->getUrl_SubInsightsPage( $slug ),
|
138 |
'active' => $this->getInav() === $slug,
|
139 |
],
|
140 |
[
|
141 |
'slug' => $slug.'-settings',
|
142 |
+
'title' => __( 'Configuration', 'wp-simple-firewall' ),
|
143 |
'href' => $con->getModule_AuditTrail()->getUrl_AdminPage(),
|
144 |
],
|
145 |
[
|
157 |
];
|
158 |
|
159 |
return [
|
160 |
+
'slug' => $slug,
|
161 |
'title' => __( 'Audit Trail', 'wp-simple-firewall' ),
|
162 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/person-lines-fill.svg' ),
|
163 |
+
'introjs' => [
|
164 |
+
'body' => __( "Track and review all important actions taken on your site - see the Who, What and When.", 'wp-simple-firewall' ),
|
165 |
+
],
|
166 |
'sub_items' => $subItems,
|
167 |
];
|
168 |
}
|
189 |
],
|
190 |
[
|
191 |
'slug' => $slug.'-settings',
|
192 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'Automatic Scans', 'wp-simple-firewall' ) ),
|
193 |
'href' => $con->getModule_HackGuard()->getUrl_AdminPage(),
|
194 |
],
|
195 |
];
|
198 |
'slug' => $slug,
|
199 |
'title' => __( 'Scans', 'wp-simple-firewall' ),
|
200 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/shield-shaded.svg' ),
|
201 |
+
'introjs' => [
|
202 |
+
'body' => sprintf( __( "Run a %s scan at any time, or view the results from the latest scan.", 'wp-simple-firewall' ),
|
203 |
+
$this->getCon()->getHumanName() ),
|
204 |
+
],
|
205 |
'sub_items' => $subItems,
|
206 |
];
|
207 |
}
|
215 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/search.svg' ),
|
216 |
'id' => 'NavMenuSearch',
|
217 |
'href' => $mod->getUrl_SubInsightsPage( 'overview' ),
|
218 |
+
'introjs' => [
|
219 |
+
'body' => __( 'Use Search to find any option within the entire plugin' ),
|
220 |
+
],
|
221 |
'data' => [
|
222 |
'toggle' => 'modal',
|
223 |
'target' => '#SearchDialog',
|
234 |
'title' => __( 'Reports', 'wp-simple-firewall' ),
|
235 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/graph-up.svg' ),
|
236 |
'href' => $mod->getUrl_SubInsightsPage( 'reports' ),
|
237 |
+
'introjs' => [
|
238 |
+
'body' => __( 'Reports use the built-in stats to show you how Shield is working to secure your site.' ),
|
239 |
+
],
|
240 |
'sub_items' => [
|
241 |
[
|
242 |
'slug' => 'reports-stats',
|
262 |
'title' => __( 'Overview', 'wp-simple-firewall' ),
|
263 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/binoculars.svg' ),
|
264 |
'href' => $mod->getUrl_SubInsightsPage( 'overview' ),
|
265 |
+
'introjs' => [
|
266 |
+
'body' => sprintf( __( "Review your entire %s configuration at a glance to see what's working and what's not.", 'wp-simple-firewall' ),
|
267 |
+
$this->getCon()->getHumanName() ),
|
268 |
+
],
|
269 |
];
|
270 |
}
|
271 |
|
272 |
+
private function configuration() :array {
|
273 |
/** @var ModCon $mod */
|
274 |
$mod = $this->getMod();
|
275 |
+
$slug = 'configuration';
|
276 |
|
277 |
$subItems = [];
|
278 |
foreach ( $mod->getModulesSummaryData() as $modData ) {
|
293 |
|
294 |
return [
|
295 |
'slug' => $slug,
|
296 |
+
'title' => __( 'Configuration', 'wp-simple-firewall' ),
|
297 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/sliders.svg' ),
|
298 |
+
'introjs' => [
|
299 |
+
'body' => sprintf( __( "%s is a big plugin split into modules, and each with their own options - use these jump-off points to find the specific option you need.", 'wp-simple-firewall' ),
|
300 |
+
$this->getCon()->getHumanName() ),
|
301 |
+
],
|
302 |
'sub_items' => $subItems,
|
303 |
];
|
304 |
}
|
309 |
'slug' => 'integrations',
|
310 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/puzzle-fill.svg' ),
|
311 |
'title' => __( 'Integrations', 'wp-simple-firewall' ),
|
312 |
+
'introjs' => [
|
313 |
+
'body' => __( "Integrate with your favourite plugins to block SPAM and manage Shield better.", 'wp-simple-firewall' ),
|
314 |
+
],
|
315 |
'sub_items' => [
|
316 |
[
|
317 |
+
'slug' => 'integrations-contact',
|
|
|
|
|
|
|
|
|
|
|
318 |
'title' => __( 'Contact Form SPAM', 'wp-simple-firewall' ),
|
319 |
'href' => $con->getModule_Integrations()->getUrl_DirectLinkToSection( 'section_spam' ),
|
320 |
],
|
321 |
+
[
|
322 |
+
'slug' => 'integrations-login',
|
323 |
+
'title' => __( 'Custom Login Forms', 'wp-simple-firewall' ),
|
324 |
+
'href' => $con->getModule_Integrations()->getUrl_DirectLinkToSection( 'section_user_forms' ),
|
325 |
+
],
|
326 |
],
|
327 |
];
|
328 |
}
|
329 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
330 |
private function docs() :array {
|
331 |
/** @var ModCon $mod */
|
332 |
$mod = $this->getMod();
|
358 |
[
|
359 |
'slug' => 'license-trial',
|
360 |
'title' => __( 'Free Trial', 'wp-simple-firewall' ),
|
361 |
+
'href' => 'https://shsec.io/shieldfreetrialinplugin',
|
362 |
+
'target' => '_blank',
|
363 |
],
|
364 |
[
|
365 |
'slug' => 'license-features',
|
415 |
'slug' => $slug,
|
416 |
'title' => __( 'Tools', 'wp-simple-firewall' ),
|
417 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/tools.svg' ),
|
418 |
+
'introjs' => [
|
419 |
+
'body' => __( "Important security tools, such a import/export, whitelabel and admin notes.", 'wp-simple-firewall' ),
|
420 |
+
],
|
421 |
'sub_items' => $subItems,
|
422 |
];
|
423 |
}
|
431 |
$subItems = [
|
432 |
[
|
433 |
'slug' => $slug.'-log',
|
434 |
+
'title' => __( 'View Traffic Log', 'wp-simple-firewall' ),
|
435 |
'href' => $mod->getUrl_SubInsightsPage( $slug ),
|
436 |
'active' => $this->getInav() === $slug,
|
437 |
],
|
438 |
[
|
439 |
'slug' => $slug.'-ratelimitsettings',
|
440 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'Rate Limiting', 'wp-simple-firewall' ) ),
|
441 |
'href' => $con->getModule_Traffic()->getUrl_DirectLinkToSection( 'section_traffic_limiter' ),
|
442 |
],
|
443 |
[
|
452 |
'slug' => 'traffic',
|
453 |
'title' => __( 'Traffic', 'wp-simple-firewall' ),
|
454 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/stoplights.svg' ),
|
455 |
+
'introjs' => [
|
456 |
+
'body' => __( "Monitor and watch traffic as it hits your site.", 'wp-simple-firewall' ),
|
457 |
+
],
|
458 |
'sub_items' => $subItems,
|
459 |
];
|
460 |
}
|
472 |
],
|
473 |
[
|
474 |
'slug' => 'users-secadmin',
|
475 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'Security Admin', 'wp-simple-firewall' ) ),
|
476 |
'href' => $con->getModule_SecAdmin()->getUrl_DirectLinkToSection( 'section_security_admin_settings' ),
|
477 |
],
|
478 |
[
|
479 |
'slug' => 'users-settings',
|
480 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'Sessions', 'wp-simple-firewall' ) ),
|
481 |
'href' => $con->getModule_UserManagement()
|
482 |
->getUrl_DirectLinkToSection( 'section_user_session_management' ),
|
483 |
],
|
484 |
[
|
485 |
'slug' => 'users-passwords',
|
486 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'Password Policies', 'wp-simple-firewall' ) ),
|
487 |
'href' => $con->getModule_UserManagement()->getUrl_DirectLinkToSection( 'section_passwords' ),
|
488 |
],
|
489 |
[
|
490 |
'slug' => 'users-suspend',
|
491 |
+
'title' => sprintf( '%s: %s', __( 'Configure', 'wp-simple-firewall' ), __( 'User Suspension', 'wp-simple-firewall' ) ),
|
492 |
'href' => $con->getModule_UserManagement()->getUrl_DirectLinkToSection( 'section_suspend' ),
|
493 |
],
|
494 |
];
|
497 |
'slug' => 'users',
|
498 |
'title' => __( 'Users', 'wp-simple-firewall' ),
|
499 |
'img' => $this->getCon()->urls->forImage( 'bootstrap/person-badge.svg' ),
|
500 |
+
'introjs' => [
|
501 |
+
'body' => __( 'View sessions, and configure session timeouts and passwords requirements.', 'wp-simple-firewall' ),
|
502 |
+
],
|
503 |
'sub_items' => $subItems,
|
504 |
];
|
505 |
}
|
506 |
|
507 |
+
private function getIntroJsTourID() :string {
|
508 |
+
return 'navigation_v1';
|
509 |
+
}
|
510 |
+
|
511 |
private function getInav() :string {
|
512 |
return (string)Services::Request()->query( 'inav' );
|
513 |
}
|
src/lib/src/Modules/Insights/Lib/SummaryCards.php
ADDED
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\HackGuard\Scan\Controller\{
|
7 |
+
Wcf
|
8 |
+
};
|
9 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
10 |
+
|
11 |
+
class SummaryCards {
|
12 |
+
|
13 |
+
use ModConsumer;
|
14 |
+
|
15 |
+
public function build() :array {
|
16 |
+
$cards = [];
|
17 |
+
$cards = array_merge(
|
18 |
+
$cards,
|
19 |
+
$this->getLoginSummary(),
|
20 |
+
$this->getFirewallSummary(),
|
21 |
+
$this->getIPBlockingSummary(),
|
22 |
+
$this->getSecurityAdminSummary(),
|
23 |
+
$this->getCommentSpamSummary(),
|
24 |
+
$this->getHackguardSummary(),
|
25 |
+
$this->getUserSummary(),
|
26 |
+
$this->getAuditTrailSummary(),
|
27 |
+
$this->getPluginSummary()
|
28 |
+
);
|
29 |
+
|
30 |
+
return array_map(
|
31 |
+
function ( $card ) {
|
32 |
+
$card = array_merge(
|
33 |
+
[
|
34 |
+
'enabled' => false
|
35 |
+
],
|
36 |
+
$card
|
37 |
+
);
|
38 |
+
|
39 |
+
if ( empty( $card[ 'icon' ] ) ) {
|
40 |
+
$card[ 'icon' ] = $card[ 'enabled' ] ?
|
41 |
+
$this->getCon()->svgs->raw( 'bootstrap/shield-fill-check.svg' )
|
42 |
+
: $this->getCon()->svgs->raw( 'bootstrap/shield-fill-exclamation.svg' );
|
43 |
+
}
|
44 |
+
|
45 |
+
return $card;
|
46 |
+
},
|
47 |
+
$cards
|
48 |
+
);
|
49 |
+
}
|
50 |
+
|
51 |
+
private function getPluginSummary() :array {
|
52 |
+
$mod = $this->getCon()->getModule_Plugin();
|
53 |
+
return [
|
54 |
+
$mod->getSlug() => [
|
55 |
+
'title' => 'Plugin',
|
56 |
+
'enabled' => $mod->isModuleEnabled(),
|
57 |
+
'href' => $mod->getUrl_DirectLinkToOption( 'global_enable_plugin_features' ),
|
58 |
+
]
|
59 |
+
];
|
60 |
+
}
|
61 |
+
|
62 |
+
private function getCommentSpamSummary() :array {
|
63 |
+
$mod = $this->getCon()->getModule_Comments();
|
64 |
+
/** @var Modules\CommentsFilter\Options $opts */
|
65 |
+
$opts = $mod->getOptions();
|
66 |
+
return [
|
67 |
+
$mod->getSlug() => [
|
68 |
+
'title' => 'Comment SPAM',
|
69 |
+
'enabled' => $mod->isModuleEnabled()
|
70 |
+
&& $opts->isEnabledAntiBot(),
|
71 |
+
'href' => $mod->getUrl_AdminPage(),
|
72 |
+
]
|
73 |
+
];
|
74 |
+
}
|
75 |
+
|
76 |
+
private function getAuditTrailSummary() :array {
|
77 |
+
$mod = $this->getCon()->getModule_AuditTrail();
|
78 |
+
return [
|
79 |
+
$mod->getSlug() => [
|
80 |
+
'title' => "Audit Trail",
|
81 |
+
'enabled' => $mod->isModuleEnabled(),
|
82 |
+
'href' => $mod->getUrl_AdminPage(),
|
83 |
+
]
|
84 |
+
];
|
85 |
+
}
|
86 |
+
|
87 |
+
private function getUserSummary() :array {
|
88 |
+
$mod = $this->getCon()->getModule_UserManagement();
|
89 |
+
/** @var Modules\UserManagement\Options $opts */
|
90 |
+
$opts = $mod->getOptions();
|
91 |
+
return [
|
92 |
+
$mod->getSlug() => [
|
93 |
+
'title' => "'Pwned' Passwords",
|
94 |
+
'enabled' => $mod->isModuleEnabled()
|
95 |
+
&& $opts->isPasswordPoliciesEnabled()
|
96 |
+
&& $opts->isPassPreventPwned(),
|
97 |
+
'href' => $mod->getUrl_DirectLinkToOption( 'enable_password_policies' ),
|
98 |
+
]
|
99 |
+
];
|
100 |
+
}
|
101 |
+
|
102 |
+
private function getHackguardSummary() :array {
|
103 |
+
$mod = $this->getCon()->getModule_HackGuard();
|
104 |
+
return [
|
105 |
+
$mod->getSlug() => [
|
106 |
+
'title' => 'Scanners',
|
107 |
+
'enabled' => $mod->isModuleEnabled(),
|
108 |
+
'href' => $mod->getUrl_DirectLinkToOption( 'enable_hack_protect' ),
|
109 |
+
],
|
110 |
+
'core_files' => [
|
111 |
+
'title' => 'Core File Scan',
|
112 |
+
'enabled' => $mod->isModuleEnabled()
|
113 |
+
&& $mod->getScanCon( Wcf::SCAN_SLUG )->isEnabled(),
|
114 |
+
'href' => $mod->getUrl_DirectLinkToOption( 'enable_core_file_integrity_scan' ),
|
115 |
+
]
|
116 |
+
];
|
117 |
+
}
|
118 |
+
|
119 |
+
private function getIPBlockingSummary() :array {
|
120 |
+
$mod = $this->getCon()->getModule_IPs();
|
121 |
+
/** @var Modules\IPs\Options $opts */
|
122 |
+
$opts = $mod->getOptions();
|
123 |
+
return [
|
124 |
+
$mod->getSlug() => [
|
125 |
+
'title' => 'Auto IP Block',
|
126 |
+
'enabled' => $mod->isModuleEnabled()
|
127 |
+
&& ( $opts->getOffenseLimit() > 0 ),
|
128 |
+
'href' => $mod->getUrl_AdminPage(),
|
129 |
+
]
|
130 |
+
];
|
131 |
+
}
|
132 |
+
|
133 |
+
private function getSecurityAdminSummary() :array {
|
134 |
+
$mod = $this->getCon()->getModule_SecAdmin();
|
135 |
+
return [
|
136 |
+
$mod->getSlug() => [
|
137 |
+
'title' => $mod->getMainFeatureName(),
|
138 |
+
'enabled' => $mod->isModuleEnabled()
|
139 |
+
&& $mod->getSecurityAdminController()->isEnabledSecAdmin(),
|
140 |
+
'href' => $mod->getUrl_AdminPage(),
|
141 |
+
]
|
142 |
+
];
|
143 |
+
}
|
144 |
+
|
145 |
+
private function getLoginSummary() :array {
|
146 |
+
$mod = $this->getCon()->getModule_LoginGuard();
|
147 |
+
/** @var Modules\LoginGuard\Options $opts */
|
148 |
+
$opts = $mod->getOptions();
|
149 |
+
return [
|
150 |
+
$mod->getSlug() => [
|
151 |
+
'title' => 'Login',
|
152 |
+
'enabled' => $mod->isModuleEnabled() && $opts->isEnabledAntiBot(),
|
153 |
+
'href' => $mod->getUrl_AdminPage(),
|
154 |
+
]
|
155 |
+
];
|
156 |
+
}
|
157 |
+
|
158 |
+
private function getFirewallSummary() :array {
|
159 |
+
$mod = $this->getCon()->getModule_Firewall();
|
160 |
+
/** @var Modules\LoginGuard\Options $opts */
|
161 |
+
$opts = $mod->getOptions();
|
162 |
+
return [
|
163 |
+
$mod->getSlug() => [
|
164 |
+
'title' => 'Firewall',
|
165 |
+
'enabled' => $mod->isModuleEnabled(),
|
166 |
+
'href' => $mod->getUrl_DirectLinkToOption( 'enable_firewall' ),
|
167 |
+
]
|
168 |
+
];
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* @param Modules\Base\ModCon $mod
|
173 |
+
* @return array[]
|
174 |
+
*/
|
175 |
+
private function getBasicModSummary( $mod ) :array {
|
176 |
+
return [
|
177 |
+
$mod->getSlug() => [
|
178 |
+
'title' => $mod->getMainFeatureName(),
|
179 |
+
'enabled' => $mod->isModuleEnabled(),
|
180 |
+
'href' => $mod->getUrl_AdminPage(),
|
181 |
+
]
|
182 |
+
];
|
183 |
+
}
|
184 |
+
}
|
src/lib/src/Modules/Insights/ModCon.php
CHANGED
@@ -17,21 +17,25 @@ class ModCon extends BaseShield\ModCon {
|
|
17 |
}
|
18 |
|
19 |
protected function onModulesLoaded() {
|
20 |
-
$this->
|
21 |
-
$this->maybeRedirectToOverview();
|
22 |
}
|
23 |
|
24 |
-
private function
|
25 |
-
$
|
26 |
-
if (
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
28 |
}
|
29 |
}
|
30 |
|
31 |
private function maybeRedirectToAdmin() {
|
32 |
$con = $this->getCon();
|
33 |
$activeFor = $con->getModule_Plugin()->getActivateLength();
|
34 |
-
if ( !Services::WpGeneral()->isAjax() &&
|
35 |
Services::Response()->redirect( $this->getCon()->getPluginUrl_DashboardHome() );
|
36 |
}
|
37 |
}
|
@@ -108,7 +112,7 @@ class ModCon extends BaseShield\ModCon {
|
|
108 |
$inav = 'overview';
|
109 |
}
|
110 |
|
111 |
-
if ( $con->getIsPage_PluginAdmin()
|
112 |
switch ( $inav ) {
|
113 |
|
114 |
case 'importexport':
|
@@ -136,6 +140,11 @@ class ModCon extends BaseShield\ModCon {
|
|
136 |
];
|
137 |
break;
|
138 |
|
|
|
|
|
|
|
|
|
|
|
139 |
case 'notes':
|
140 |
case 'scans_results':
|
141 |
case 'scans_run':
|
17 |
}
|
18 |
|
19 |
protected function onModulesLoaded() {
|
20 |
+
$this->handleCustomRedirection();
|
|
|
21 |
}
|
22 |
|
23 |
+
private function handleCustomRedirection() {
|
24 |
+
$con = $this->getCon();
|
25 |
+
if ( !Services::WpGeneral()->isAjax() && is_admin() && !$con->isModulePage() ) {
|
26 |
+
if ( $con->getModule_Plugin()->getActivateLength() < 5 ) {
|
27 |
+
Services::Response()->redirect( $con->getModule_Plugin()->getUrl_Wizard( 'welcome' ) );
|
28 |
+
}
|
29 |
+
elseif ( $this->isThisModAdminPage() && empty( Services::Request()->query( 'inav' ) ) ) {
|
30 |
+
Services::Response()->redirect( $con->getPluginUrl_DashboardHome() );
|
31 |
+
}
|
32 |
}
|
33 |
}
|
34 |
|
35 |
private function maybeRedirectToAdmin() {
|
36 |
$con = $this->getCon();
|
37 |
$activeFor = $con->getModule_Plugin()->getActivateLength();
|
38 |
+
if ( !Services::WpGeneral()->isAjax() && $activeFor < 4 ) {
|
39 |
Services::Response()->redirect( $this->getCon()->getPluginUrl_DashboardHome() );
|
40 |
}
|
41 |
}
|
112 |
$inav = 'overview';
|
113 |
}
|
114 |
|
115 |
+
if ( $con->getIsPage_PluginAdmin() ) {
|
116 |
switch ( $inav ) {
|
117 |
|
118 |
case 'importexport':
|
140 |
];
|
141 |
break;
|
142 |
|
143 |
+
case 'wizard':
|
144 |
+
$enq[ Enqueue::JS ][] = 'shield/wizard';
|
145 |
+
$enq[ Enqueue::CSS ][] = 'shield/wizard';
|
146 |
+
break;
|
147 |
+
|
148 |
case 'notes':
|
149 |
case 'scans_results':
|
150 |
case 'scans_run':
|
src/lib/src/Modules/Insights/UI.php
CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights;
|
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Insights\Lib\OverviewCards;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Insights\AdminNotes;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Changelog\Retrieve;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
@@ -15,12 +14,14 @@ class UI extends BaseShield\UI {
|
|
15 |
$con = $this->getCon();
|
16 |
return [
|
17 |
'content' => [
|
18 |
-
'tab_updates'
|
19 |
-
'tab_freetrial' => $this->renderFreeTrial(),
|
20 |
],
|
21 |
'flags' => [
|
22 |
'is_pro' => $con->isPremiumActive(),
|
23 |
],
|
|
|
|
|
|
|
24 |
'strings' => [
|
25 |
'tab_freetrial' => __( 'Free Trial', 'wp-simple-firewall' ),
|
26 |
'tab_updates' => __( 'Updates and Changes', 'wp-simple-firewall' ),
|
@@ -31,9 +32,12 @@ class UI extends BaseShield\UI {
|
|
31 |
private function buildInsightsVars_Overview() :array {
|
32 |
return [
|
33 |
'vars' => [
|
34 |
-
'overview_cards' => ( new OverviewCards() )
|
35 |
->setMod( $this->getMod() )
|
36 |
->buildForShuffle(),
|
|
|
|
|
|
|
37 |
],
|
38 |
'strings' => [
|
39 |
'click_clear_filter' => __( 'Click To Filter By Security Area or Status', 'wp-simple-firewall' ),
|
@@ -97,14 +101,6 @@ class UI extends BaseShield\UI {
|
|
97 |
$data = $this->buildInsightsVars_Docs();
|
98 |
break;
|
99 |
|
100 |
-
case 'free_trial':
|
101 |
-
$data = [
|
102 |
-
'content' => [
|
103 |
-
'free_trial' => $this->renderFreeTrial()
|
104 |
-
]
|
105 |
-
];
|
106 |
-
break;
|
107 |
-
|
108 |
case 'importexport':
|
109 |
$data = $modPlugin->getImpExpController()->buildInsightsVars();
|
110 |
break;
|
@@ -164,6 +160,21 @@ class UI extends BaseShield\UI {
|
|
164 |
case 'index':
|
165 |
$data = $this->buildInsightsVars_Overview();
|
166 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
default:
|
168 |
throw new \Exception( 'Not available' );
|
169 |
}
|
@@ -186,6 +197,7 @@ class UI extends BaseShield\UI {
|
|
186 |
'reports' => __( 'Reports', 'wp-simple-firewall' ),
|
187 |
'debug' => __( 'Debug', 'wp-simple-firewall' ),
|
188 |
'free_trial' => __( 'Free Trial', 'wp-simple-firewall' ),
|
|
|
189 |
];
|
190 |
|
191 |
$modsToSearch = array_filter(
|
@@ -198,12 +210,10 @@ class UI extends BaseShield\UI {
|
|
198 |
$pageTitle = $availablePages[ $inav ];
|
199 |
if ( !empty( $subNavSection ) ) {
|
200 |
$pageTitle = sprintf( '%s: %s',
|
201 |
-
__( '
|
202 |
}
|
203 |
|
204 |
-
|
205 |
-
$secAdminOpts = $this->getCon()->getModule_SecAdmin()->getOptions();
|
206 |
-
if ( $secAdminOpts->isEnabledWhitelabel() ) {
|
207 |
$dashboardLogo = ( new Shield\Modules\SecurityAdmin\Lib\WhiteLabel\BuildOptions() )
|
208 |
->setMod( $this->getCon()->getModule_SecAdmin() )
|
209 |
->build()[ 'url_login2fa_logourl' ];
|
@@ -255,6 +265,10 @@ class UI extends BaseShield\UI {
|
|
255 |
);
|
256 |
}
|
257 |
|
|
|
|
|
|
|
|
|
258 |
private function renderFreeTrial() :string {
|
259 |
$user = Services::WpUsers()->getCurrentWpUser();
|
260 |
return $this->getMod()
|
@@ -326,7 +340,7 @@ class UI extends BaseShield\UI {
|
|
326 |
'flags' => [
|
327 |
'show_promo' => $con->isModulePage()
|
328 |
&& !$con->isPremiumActive()
|
329 |
-
&& ( !in_array( $nav, [ 'scans_results', 'scans_run' ] ) ),
|
330 |
],
|
331 |
'hrefs' => [
|
332 |
'go_pro' => 'https://shsec.io/shieldgoprofeature',
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
|
|
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Insights\AdminNotes;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Changelog\Retrieve;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
14 |
$con = $this->getCon();
|
15 |
return [
|
16 |
'content' => [
|
17 |
+
'tab_updates' => $this->renderTabUpdates(),
|
|
|
18 |
],
|
19 |
'flags' => [
|
20 |
'is_pro' => $con->isPremiumActive(),
|
21 |
],
|
22 |
+
'hrefs' => [
|
23 |
+
'free_trial' => 'https://shsec.io/shieldfreetrialinplugin',
|
24 |
+
],
|
25 |
'strings' => [
|
26 |
'tab_freetrial' => __( 'Free Trial', 'wp-simple-firewall' ),
|
27 |
'tab_updates' => __( 'Updates and Changes', 'wp-simple-firewall' ),
|
32 |
private function buildInsightsVars_Overview() :array {
|
33 |
return [
|
34 |
'vars' => [
|
35 |
+
'overview_cards' => ( new Lib\OverviewCards() )
|
36 |
->setMod( $this->getMod() )
|
37 |
->buildForShuffle(),
|
38 |
+
'summary_cards' => ( new Lib\SummaryCards() )
|
39 |
+
->setMod( $this->getMod() )
|
40 |
+
->build(),
|
41 |
],
|
42 |
'strings' => [
|
43 |
'click_clear_filter' => __( 'Click To Filter By Security Area or Status', 'wp-simple-firewall' ),
|
101 |
$data = $this->buildInsightsVars_Docs();
|
102 |
break;
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
case 'importexport':
|
105 |
$data = $modPlugin->getImpExpController()->buildInsightsVars();
|
106 |
break;
|
160 |
case 'index':
|
161 |
$data = $this->buildInsightsVars_Overview();
|
162 |
break;
|
163 |
+
|
164 |
+
case 'wizard':
|
165 |
+
$wiz = $con->getModule_Plugin()->getWizardHandler();
|
166 |
+
if ( $wiz instanceof \ICWP_WPSF_Wizard_Base ) {
|
167 |
+
$data = [
|
168 |
+
'content' => [
|
169 |
+
'wizard' => $wiz->setCurrentWizard( $req->query( 'wizard' ) )
|
170 |
+
->renderWizard()
|
171 |
+
],
|
172 |
+
'flags' => [
|
173 |
+
'show_sidebar_nav' => 0
|
174 |
+
],
|
175 |
+
];
|
176 |
+
}
|
177 |
+
break;
|
178 |
default:
|
179 |
throw new \Exception( 'Not available' );
|
180 |
}
|
197 |
'reports' => __( 'Reports', 'wp-simple-firewall' ),
|
198 |
'debug' => __( 'Debug', 'wp-simple-firewall' ),
|
199 |
'free_trial' => __( 'Free Trial', 'wp-simple-firewall' ),
|
200 |
+
'wizard' => __( 'Wizard', 'wp-simple-firewall' ),
|
201 |
];
|
202 |
|
203 |
$modsToSearch = array_filter(
|
210 |
$pageTitle = $availablePages[ $inav ];
|
211 |
if ( !empty( $subNavSection ) ) {
|
212 |
$pageTitle = sprintf( '%s: %s',
|
213 |
+
__( 'Configuration', 'wp-simple-firewall' ), $modsToSearch[ $subNavSection ][ 'name' ] );
|
214 |
}
|
215 |
|
216 |
+
if ( $this->getCon()->getModule_SecAdmin()->getWhiteLabelController()->isEnabled() ) {
|
|
|
|
|
217 |
$dashboardLogo = ( new Shield\Modules\SecurityAdmin\Lib\WhiteLabel\BuildOptions() )
|
218 |
->setMod( $this->getCon()->getModule_SecAdmin() )
|
219 |
->build()[ 'url_login2fa_logourl' ];
|
265 |
);
|
266 |
}
|
267 |
|
268 |
+
/**
|
269 |
+
* @return string
|
270 |
+
* @deprecated 11.2
|
271 |
+
*/
|
272 |
private function renderFreeTrial() :string {
|
273 |
$user = Services::WpUsers()->getCurrentWpUser();
|
274 |
return $this->getMod()
|
340 |
'flags' => [
|
341 |
'show_promo' => $con->isModulePage()
|
342 |
&& !$con->isPremiumActive()
|
343 |
+
&& ( !in_array( $nav, [ 'scans_results', 'scans_run', 'wizard' ] ) ),
|
344 |
],
|
345 |
'hrefs' => [
|
346 |
'go_pro' => 'https://shsec.io/shieldgoprofeature',
|
src/lib/src/Modules/Integrations/Lib/Bots/Common/BaseBotDetectionController.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Common;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
+
|
7 |
+
abstract class BaseBotDetectionController extends ExecOnceModConsumer {
|
8 |
+
|
9 |
+
protected function canRun() :bool {
|
10 |
+
return $this->isEnabled();
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function run() {
|
14 |
+
array_map(
|
15 |
+
function ( $provider ) {
|
16 |
+
$provider->execute();
|
17 |
+
},
|
18 |
+
$this->getInstalledProviders()
|
19 |
+
);
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Inserts the ModCon;
|
24 |
+
* @return BaseHandler[]
|
25 |
+
*/
|
26 |
+
public function getInstalledProviders() :array {
|
27 |
+
return array_map(
|
28 |
+
function ( $provider ) {
|
29 |
+
return $provider->setMod( $this->getMod() );
|
30 |
+
},
|
31 |
+
array_filter(
|
32 |
+
$this->enumProviders(),
|
33 |
+
function ( $provider ) {
|
34 |
+
return $provider::IsProviderInstalled();
|
35 |
+
}
|
36 |
+
)
|
37 |
+
);
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @return BaseHandler[]
|
42 |
+
*/
|
43 |
+
public function enumProviders() :array {
|
44 |
+
return [];
|
45 |
+
}
|
46 |
+
|
47 |
+
protected function isEnabled() :bool {
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Common/BaseHandler.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Common;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
+
|
8 |
+
abstract class BaseHandler extends ExecOnceModConsumer {
|
9 |
+
|
10 |
+
const SLUG = '';
|
11 |
+
|
12 |
+
protected function canRun() :bool {
|
13 |
+
return ( $this->getCon()->isPremiumActive() || !$this->isProOnly() )
|
14 |
+
&& $this->isEnabled() && static::IsProviderInstalled();
|
15 |
+
}
|
16 |
+
|
17 |
+
protected function isBot() :bool {
|
18 |
+
return $this->getCon()
|
19 |
+
->getModule_IPs()
|
20 |
+
->getBotSignalsController()
|
21 |
+
->isBot( Services::IP()->getRequestIp() );
|
22 |
+
}
|
23 |
+
|
24 |
+
public function isEnabled() :bool {
|
25 |
+
return false;
|
26 |
+
}
|
27 |
+
|
28 |
+
public static function IsProviderInstalled() :bool {
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
|
32 |
+
protected function getProviderName() :string {
|
33 |
+
return '';
|
34 |
+
}
|
35 |
+
|
36 |
+
public function getHandlerSlug() :string {
|
37 |
+
try {
|
38 |
+
$slug = strtolower( ( new \ReflectionClass( $this ) )->getShortName() );
|
39 |
+
}
|
40 |
+
catch ( \Exception $e ) {
|
41 |
+
$slug = '';
|
42 |
+
}
|
43 |
+
return $slug;
|
44 |
+
}
|
45 |
+
|
46 |
+
protected function isProOnly() :bool {
|
47 |
+
return true;
|
48 |
+
}
|
49 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Base.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Common\BaseHandler;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
+
use FernleafSystems\Wordpress\Services\Services;
|
9 |
+
|
10 |
+
abstract class Base extends BaseHandler {
|
11 |
+
|
12 |
+
public function isSpam() :bool {
|
13 |
+
$isSpam = $this->isBot();
|
14 |
+
$this->getCon()->fireEvent(
|
15 |
+
sprintf( 'spam_form_%s', $isSpam ? 'fail' : 'pass' ),
|
16 |
+
[
|
17 |
+
'audit' => [
|
18 |
+
'form_provider' => $this->getProviderName(),
|
19 |
+
]
|
20 |
+
]
|
21 |
+
);
|
22 |
+
return $isSpam;
|
23 |
+
}
|
24 |
+
|
25 |
+
protected function isSpam_Human() :bool {
|
26 |
+
return false;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function isEnabled() :bool {
|
30 |
+
return in_array( $this->getHandlerSlug(), $this->getOptions()->getOpt( 'form_spam_providers', [] ) );
|
31 |
+
}
|
32 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ContactForm7.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class ContactForm7 extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_filter( 'wpcf7_spam', function ( $wasSpam, $submission ) {
|
9 |
+
return $wasSpam || $this->isSpam();
|
10 |
+
}, 1000, 2 );
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function getProviderName() :string {
|
14 |
+
return 'Contact Form 7';
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function IsProviderInstalled() :bool {
|
18 |
+
return defined( 'WPCF7_TEXT_DOMAIN' ) && WPCF7_TEXT_DOMAIN === 'contact-form-7';
|
19 |
+
}
|
20 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ElementorPro.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class ElementorPro extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_action( 'elementor_pro/forms/validation', function ( $form, $ajax_handler ) {
|
9 |
+
/** @var \ElementorPro\Modules\Forms\Classes\Ajax_Handler $ajax_handler */
|
10 |
+
if ( empty( $ajax_handler->errors ) && $this->isSpam() ) {
|
11 |
+
$msg = sprintf( __( "This appears to be spam - failed %s AntiBot protection checks.", 'wp-simple-firewall' ),
|
12 |
+
$this->getCon()->getHumanName() );
|
13 |
+
$ajax_handler->add_error( 'shield-antibot', $msg );
|
14 |
+
$ajax_handler->add_error_message( $msg );
|
15 |
+
}
|
16 |
+
}, 1000, 2 );
|
17 |
+
}
|
18 |
+
|
19 |
+
protected function getProviderName() :string {
|
20 |
+
return 'Elementor Pro';
|
21 |
+
}
|
22 |
+
|
23 |
+
public static function IsProviderInstalled() :bool {
|
24 |
+
return defined( 'ELEMENTOR_PRO_VERSION' ) && @function_exists( 'elementor_pro_load_plugin' );
|
25 |
+
}
|
26 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FluentForms.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* This form only provides a filter on the "Akismet" spam result, not a general spam result.
|
7 |
+
*
|
8 |
+
* Luckily the error message within the plugin is non-Akismet specific.
|
9 |
+
*
|
10 |
+
* Class FluentForms
|
11 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers
|
12 |
+
*/
|
13 |
+
class FluentForms extends Base {
|
14 |
+
|
15 |
+
protected function run() {
|
16 |
+
add_filter( 'fluentform_akismet_spam_result', function ( $wasSpam ) {
|
17 |
+
return $wasSpam || $this->isSpam();
|
18 |
+
}, 1000 );
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function getProviderName() :string {
|
22 |
+
return 'Fluent Forms';
|
23 |
+
}
|
24 |
+
|
25 |
+
public static function IsProviderInstalled() :bool {
|
26 |
+
return defined( 'FLUENTFORM' ) && @class_exists( '\FluentForm\Framework\Foundation\Bootstrap' );
|
27 |
+
}
|
28 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FormidableForms.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class FormidableForms extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_filter( 'frm_validate_entry', function ( $errors ) {
|
9 |
+
if ( !is_array( $errors ) || empty( $errors[ 'spam' ] ) ) {
|
10 |
+
if ( $this->isSpam() ) {
|
11 |
+
if ( !is_array( $errors ) ) {
|
12 |
+
$errors = [];
|
13 |
+
}
|
14 |
+
// string taken from Formidable forms FrmEntryValidate.php
|
15 |
+
$errors[ 'spam' ] = __( 'Your entry appears to be spam!', 'formidable' );
|
16 |
+
}
|
17 |
+
}
|
18 |
+
return $errors;
|
19 |
+
}, 1000 );
|
20 |
+
}
|
21 |
+
|
22 |
+
protected function getProviderName() :string {
|
23 |
+
return 'Formidable Forms';
|
24 |
+
}
|
25 |
+
|
26 |
+
public static function IsProviderInstalled() :bool {
|
27 |
+
return function_exists( 'load_formidable_forms' ) && @class_exists( '\FrmHooksController' );
|
28 |
+
}
|
29 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Forminator.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class Forminator extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_filter( 'forminator_spam_protection', function ( $wasSpam ) {
|
9 |
+
return $wasSpam || $this->isSpam();
|
10 |
+
}, 1000 );
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function getProviderName() :string {
|
14 |
+
return 'Forminator';
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function IsProviderInstalled() :bool {
|
18 |
+
return defined( 'FORMINATOR_VERSION' ) && @class_exists( '\Forminator' );
|
19 |
+
}
|
20 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/GravityForms.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class GravityForms extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_filter( 'gform_entry_is_spam', function ( $wasSpam ) {
|
9 |
+
return $wasSpam || $this->isSpam();
|
10 |
+
}, 1000 );
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function getProviderName() :string {
|
14 |
+
return 'Gravity Forms';
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function IsProviderInstalled() :bool {
|
18 |
+
return @class_exists( '\GFForms' )
|
19 |
+
&& isset( \GFForms::$version )
|
20 |
+
&& version_compare( \GFForms::$version, '2.4.17', '>=' );
|
21 |
+
}
|
22 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Groundhogg.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class Groundhogg extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_filter( 'groundhogg/form/submission_handler/is_spam', function ( $wasSpam ) {
|
9 |
+
return $wasSpam || $this->isSpam();
|
10 |
+
}, 1000 );
|
11 |
+
}
|
12 |
+
|
13 |
+
protected function getProviderName() :string {
|
14 |
+
return 'Groundhogg';
|
15 |
+
}
|
16 |
+
|
17 |
+
public static function IsProviderInstalled() :bool {
|
18 |
+
return defined( 'GROUNDHOGG_TEXT_DOMAIN' ) && defined( 'GROUNDHOGG_VERSION' )
|
19 |
+
&& version_compare( GROUNDHOGG_VERSION, '2.4.5.5', '>=' );
|
20 |
+
}
|
21 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Helpers/NinjaForms_ShieldSpamAction.php
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers\Helpers;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers\NinjaForms;
|
6 |
+
|
7 |
+
final class NinjaForms_ShieldSpamAction extends \NF_Abstracts_Action {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* @var string
|
11 |
+
*/
|
12 |
+
protected $_name = 'shieldantibot';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var NinjaForms
|
16 |
+
*/
|
17 |
+
private $shieldNinjaFormsHandler;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var array
|
21 |
+
*/
|
22 |
+
protected $_tags = [ 'spam', 'filtering', 'shield' ];
|
23 |
+
|
24 |
+
public function __construct() {
|
25 |
+
parent::__construct();
|
26 |
+
$this->_nicename = esc_html__( 'Shield Anti-Spam', 'ninja-forms' );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @param NinjaForms $handler
|
31 |
+
* @return $this
|
32 |
+
*/
|
33 |
+
public function setHandler( NinjaForms $handler ) {
|
34 |
+
$this->shieldNinjaFormsHandler = $handler;
|
35 |
+
return $this;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @inheritDoc
|
40 |
+
*/
|
41 |
+
public function process( $action_settings, $form_id, $data ) {
|
42 |
+
if ( $this->shieldNinjaFormsHandler->isSpam() ) {
|
43 |
+
$data[ 'errors' ][ 'form' ][ 'spam' ] = esc_html__( 'There was an error trying to send your message. Please try again later', 'ninja-forms' );
|
44 |
+
}
|
45 |
+
return $data;
|
46 |
+
}
|
47 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/KaliForms.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class KaliForms extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
add_filter( 'kaliforms_before_form_process', function ( $data ) {
|
9 |
+
if ( is_array( $data ) && empty( $data[ 'error_bag' ] ) && $this->isSpam() ) {
|
10 |
+
$data[ 'admin_stop_execution' ] = true;
|
11 |
+
$data[ 'admin_stop_reason' ] = __( 'Your entry appears to be spam!', 'wp-simple-firewall' );
|
12 |
+
$data[ 'error_bag' ] = [
|
13 |
+
__( 'SPAM Bot detected.', 'wp-simple-firewall' )
|
14 |
+
];
|
15 |
+
}
|
16 |
+
return $data;
|
17 |
+
}, 1000 );
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function getProviderName() :string {
|
21 |
+
return 'Kali Forms';
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function IsProviderInstalled() :bool {
|
25 |
+
return defined( 'KALIFORMS_PLUGIN_FILE' ) && @class_exists( '\KaliForms\Inc\KaliForms' );
|
26 |
+
}
|
27 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/NinjaForms.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers\Helpers\NinjaForms_ShieldSpamAction;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* A rather convoluted way to integrate. First you must add your custom "action" to the list
|
9 |
+
* of actions to be executed on a submission.
|
10 |
+
*
|
11 |
+
* Then you must create a Custom Action class which will handle the action and add it to the
|
12 |
+
* registered action.
|
13 |
+
*
|
14 |
+
* Unfortunately the action register is executed early and so hooking to Init breaks it.
|
15 |
+
*
|
16 |
+
* Class NinjaForms
|
17 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers
|
18 |
+
*/
|
19 |
+
class NinjaForms extends Base {
|
20 |
+
|
21 |
+
protected function run() {
|
22 |
+
|
23 |
+
add_filter( 'ninja_forms_register_actions', function ( $actions ) {
|
24 |
+
$actions[ 'shieldantibot' ] = ( new NinjaForms_ShieldSpamAction() )
|
25 |
+
->setHandler( $this );
|
26 |
+
return $actions;
|
27 |
+
}, 1000 );
|
28 |
+
|
29 |
+
add_filter( 'ninja_forms_submission_actions', function ( $actions ) {
|
30 |
+
$actions[] = [
|
31 |
+
'id' => 'shieldantibot',
|
32 |
+
'settings' => [
|
33 |
+
'active' => true,
|
34 |
+
'type' => 'shieldantibot',
|
35 |
+
]
|
36 |
+
];
|
37 |
+
return $actions;
|
38 |
+
}, 1000 );
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function getProviderName() :string {
|
42 |
+
return 'Ninja Forms';
|
43 |
+
}
|
44 |
+
|
45 |
+
public static function IsProviderInstalled() :bool {
|
46 |
+
return @class_exists( '\Ninja_Forms' );
|
47 |
+
}
|
48 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WPForms.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class WPForms extends Base {
|
6 |
+
|
7 |
+
private $workingFormID = null;
|
8 |
+
|
9 |
+
protected function run() {
|
10 |
+
add_filter( 'wpforms_process_before_form_data',
|
11 |
+
function ( $formData, $formEntry ) {
|
12 |
+
$this->workingFormID = absint( $formEntry[ 'id' ] );
|
13 |
+
return $formData;
|
14 |
+
},
|
15 |
+
1000, 2
|
16 |
+
);
|
17 |
+
|
18 |
+
add_filter( 'wpforms_process_initial_errors', function ( $errors, $formData ) {
|
19 |
+
|
20 |
+
if ( empty( $errors[ $this->workingFormID ] ) && $this->isSpam() ) {
|
21 |
+
$errors[ $this->workingFormID ] = [
|
22 |
+
'header' => __( 'Shield detected this as a SPAM Bot submission.' ),
|
23 |
+
];
|
24 |
+
}
|
25 |
+
|
26 |
+
return $errors;
|
27 |
+
}, 1000, 2 );
|
28 |
+
}
|
29 |
+
|
30 |
+
protected function getProviderName() :string {
|
31 |
+
return 'WP Forms';
|
32 |
+
}
|
33 |
+
|
34 |
+
public static function IsProviderInstalled() :bool {
|
35 |
+
return defined( 'WPFORMS_VERSION' ) && function_exists( 'wpforms' );
|
36 |
+
}
|
37 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WpForo.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam\Handlers;
|
4 |
+
|
5 |
+
class WpForo extends Base {
|
6 |
+
|
7 |
+
protected function run() {
|
8 |
+
foreach ( $this->getFiltersToMonitor() as $filter ) {
|
9 |
+
add_filter( $filter, function ( array $args = [] ) {
|
10 |
+
|
11 |
+
$status = $args[ 'status' ] ?? null;
|
12 |
+
if ( $status !== 1 && $this->isSpam() ) {
|
13 |
+
if ( !empty( WPF()->current_userid ) ) {
|
14 |
+
WPF()->moderation->ban_for_spam( WPF()->current_userid );
|
15 |
+
}
|
16 |
+
$args[ 'status' ] = 1; // 1 signifies not approved
|
17 |
+
}
|
18 |
+
|
19 |
+
return $args;
|
20 |
+
}, 1000 );
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
private function getFiltersToMonitor() :array {
|
25 |
+
return [
|
26 |
+
'wpforo_add_topic_data_filter',
|
27 |
+
'wpforo_edit_topic_data_filter',
|
28 |
+
'wpforo_add_post_data_filter',
|
29 |
+
'wpforo_edit_post_data_filter',
|
30 |
+
];
|
31 |
+
}
|
32 |
+
|
33 |
+
protected function getProviderName() :string {
|
34 |
+
return 'wpForo';
|
35 |
+
}
|
36 |
+
|
37 |
+
public static function IsProviderInstalled() :bool {
|
38 |
+
return function_exists( 'WPF' ) && @class_exists( 'wpForo' ) && !empty( WPF()->tools_antispam[ 'spam_filter' ] );
|
39 |
+
}
|
40 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/Spam/SpamController.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Spam;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\Common\BaseBotDetectionController;
|
6 |
+
|
7 |
+
class SpamController extends BaseBotDetectionController {
|
8 |
+
|
9 |
+
protected function isEnabled() :bool {
|
10 |
+
return !empty( $this->getOptions()->getOpt( 'form_spam_providers' ) );
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* @return Handlers\Base[]
|
15 |
+
*/
|
16 |
+
public function enumProviders() :array {
|
17 |
+
return [
|
18 |
+
new Handlers\ContactForm7(),
|
19 |
+
new Handlers\ElementorPro(),
|
20 |
+
new Handlers\FormidableForms(),
|
21 |
+
new Handlers\FluentForms(),
|
22 |
+
new Handlers\Forminator(),
|
23 |
+
new Handlers\GravityForms(),
|
24 |
+
new Handlers\KaliForms(),
|
25 |
+
new Handlers\NinjaForms(),
|
26 |
+
new Handlers\WPForms(),
|
27 |
+
new Handlers\WpForo(),
|
28 |
+
];
|
29 |
+
}
|
30 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Base.php
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
7 |
+
|
8 |
+
abstract class Base extends Integrations\Lib\Bots\Common\BaseHandler {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var string
|
12 |
+
*/
|
13 |
+
private $auditAction;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var string
|
17 |
+
*/
|
18 |
+
private $auditUser;
|
19 |
+
|
20 |
+
private static $isBot = null;
|
21 |
+
|
22 |
+
protected function run() {
|
23 |
+
/** @var LoginGuard\Options $opts */
|
24 |
+
$opts = $this->getCon()->getModule_LoginGuard()->getOptions();
|
25 |
+
if ( $opts->isProtectLogin() ) {
|
26 |
+
$this->login();
|
27 |
+
}
|
28 |
+
if ( $opts->isProtectRegister() ) {
|
29 |
+
$this->register();
|
30 |
+
}
|
31 |
+
if ( $opts->isProtectLostPassword() ) {
|
32 |
+
$this->lostpassword();
|
33 |
+
}
|
34 |
+
$this->checkout();
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function login() {
|
38 |
+
}
|
39 |
+
|
40 |
+
protected function register() {
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function lostpassword() {
|
44 |
+
}
|
45 |
+
|
46 |
+
protected function checkout() {
|
47 |
+
}
|
48 |
+
|
49 |
+
public function getAuditAction() :string {
|
50 |
+
return sprintf( '%s-%s', $this->getHandlerSlug(), empty( $this->auditAction ) ? 'unknown' : $this->auditAction );
|
51 |
+
}
|
52 |
+
|
53 |
+
public function getAuditUser() :string {
|
54 |
+
return empty( $this->auditUser ) ? 'unknown' : $this->auditUser;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param string $action
|
59 |
+
* @return $this
|
60 |
+
*/
|
61 |
+
protected function setAuditAction( string $action ) {
|
62 |
+
$this->auditAction = $action;
|
63 |
+
return $this;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @param string $user
|
68 |
+
* @return $this
|
69 |
+
*/
|
70 |
+
protected function setAuditUser( string $user ) {
|
71 |
+
$this->auditUser = sanitize_user( $user );
|
72 |
+
return $this;
|
73 |
+
}
|
74 |
+
|
75 |
+
public function checkIsBot() :bool {
|
76 |
+
if ( is_null( self::$isBot ) ) {
|
77 |
+
self::$isBot = $this->isBot();
|
78 |
+
$this->getCon()->fireEvent(
|
79 |
+
sprintf( 'user_form_bot_%s', self::$isBot ? 'fail' : 'pass' ),
|
80 |
+
[
|
81 |
+
'audit' => [
|
82 |
+
'form_provider' => $this->getProviderName(),
|
83 |
+
'action' => $this->getAuditAction(),
|
84 |
+
'username' => $this->getAuditUser(),
|
85 |
+
]
|
86 |
+
]
|
87 |
+
);
|
88 |
+
}
|
89 |
+
return self::$isBot;
|
90 |
+
}
|
91 |
+
|
92 |
+
public function isEnabled() :bool {
|
93 |
+
/** @var Integrations\Options $opts */
|
94 |
+
$opts = $this->getOptions();
|
95 |
+
return in_array( $this->getHandlerSlug(), $opts->getUserFormProviders() );
|
96 |
+
}
|
97 |
+
|
98 |
+
protected function getErrorMessage() :string {
|
99 |
+
return sprintf( __( '%s Bot Check Failed.', 'wp-simple-firewall' ), $this->getCon()->getHumanName() );
|
100 |
+
}
|
101 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Buddypress.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Buddypress
|
7 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
8 |
+
*/
|
9 |
+
class Buddypress extends Base {
|
10 |
+
|
11 |
+
protected function register() {
|
12 |
+
add_action( 'bp_signup_validate', [ $this, 'checkRegister_BP' ], 10 );
|
13 |
+
}
|
14 |
+
|
15 |
+
public function checkRegister_BP() {
|
16 |
+
if ( $this->setAuditAction( 'register' )->checkIsBot() ) {
|
17 |
+
wp_die( $this->getErrorMessage() );
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function getProviderName() :string {
|
22 |
+
return 'BuddyPress';
|
23 |
+
}
|
24 |
+
|
25 |
+
public static function IsProviderInstalled() :bool {
|
26 |
+
return @class_exists( 'BuddyPress' );
|
27 |
+
}
|
28 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/EasyDigitalDownloads.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class EasyDigitalDownloads
|
7 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
8 |
+
*/
|
9 |
+
class EasyDigitalDownloads extends Base {
|
10 |
+
|
11 |
+
protected function register() {
|
12 |
+
add_action( 'edd_process_register_form', [ $this, 'checkRegister_EDD' ], 10 );
|
13 |
+
}
|
14 |
+
|
15 |
+
public function checkRegister_EDD() {
|
16 |
+
if ( $this->setAuditAction( 'register' )->checkIsBot() ) {
|
17 |
+
edd_set_error( $this->getCon()->prefix( rand() ), $this->getErrorMessage() );
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function getProviderName() :string {
|
22 |
+
return 'Easy Digital Downloads';
|
23 |
+
}
|
24 |
+
|
25 |
+
public static function IsProviderInstalled() :bool {
|
26 |
+
return function_exists( 'edd_set_error' ) && @class_exists( 'Easy_Digital_Downloads' );
|
27 |
+
}
|
28 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LearnPress.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class LearnPress
|
7 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
8 |
+
*/
|
9 |
+
class LearnPress extends Base {
|
10 |
+
|
11 |
+
protected function login() {
|
12 |
+
add_filter( 'learn-press/login-validate-field', [ $this, 'checkLogin_LP' ], 100 );
|
13 |
+
}
|
14 |
+
|
15 |
+
protected function register() {
|
16 |
+
add_filter( 'learn-press/register-validate-field', [ $this, 'checkRegister_LP' ], 100, 1 );
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @param string|\WP_Error $maybeError
|
21 |
+
* @return string|\WP_Error
|
22 |
+
*/
|
23 |
+
public function checkLogin_LP( $maybeError ) {
|
24 |
+
if ( !is_wp_error( $maybeError ) && $this->setAuditAction( 'login' )->checkIsBot() ) {
|
25 |
+
$maybeError = new \WP_Error( 'shield-fail-login', $this->getErrorMessage() );
|
26 |
+
}
|
27 |
+
return $maybeError;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param string|\WP_Error $maybeError
|
32 |
+
* @return string|\WP_Error
|
33 |
+
*/
|
34 |
+
public function checkRegister_LP( $maybeError ) {
|
35 |
+
if ( !is_wp_error( $maybeError ) && $this->setAuditAction( 'register' )->checkIsBot() ) {
|
36 |
+
$maybeError = new \WP_Error( 'shield-fail-register', $this->getErrorMessage() );
|
37 |
+
}
|
38 |
+
return $maybeError;
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function getProviderName() :string {
|
42 |
+
return 'LearnPress';
|
43 |
+
}
|
44 |
+
|
45 |
+
public static function IsProviderInstalled() :bool {
|
46 |
+
return @class_exists( 'LearnPress' );
|
47 |
+
}
|
48 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LifterLMS.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Lost Password is mimicked after WordPress so no separate integration necessary
|
7 |
+
* Class LifterLMS
|
8 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
9 |
+
*/
|
10 |
+
class LifterLMS extends Base {
|
11 |
+
|
12 |
+
protected function login() {
|
13 |
+
add_filter( 'llms_after_user_login_data_validation', [ $this, 'checkLogin_LLMS' ], 100 );
|
14 |
+
}
|
15 |
+
|
16 |
+
protected function register() {
|
17 |
+
add_filter( 'lifterlms_user_registration_data', [ $this, 'checkRegister_LLMS' ], 100 );
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @param bool|\WP_Error $valid
|
22 |
+
* @return bool|\WP_Error
|
23 |
+
*/
|
24 |
+
public function checkLogin_LLMS( $valid ) {
|
25 |
+
if ( !is_wp_error( $valid ) && $this->setAuditAction( 'login' )->checkIsBot() ) {
|
26 |
+
$valid = new \WP_Error( 'shield-fail-login', $this->getErrorMessage() );
|
27 |
+
}
|
28 |
+
return $valid;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param bool|\WP_Error $valid
|
33 |
+
* @return bool|\WP_Error
|
34 |
+
*/
|
35 |
+
public function checkRegister_LLMS( $valid ) {
|
36 |
+
if ( !is_wp_error( $valid ) && $this->setAuditAction( 'register' )->checkIsBot() ) {
|
37 |
+
$valid = new \WP_Error( 'shield-fail-register', $this->getErrorMessage() );
|
38 |
+
}
|
39 |
+
return $valid;
|
40 |
+
}
|
41 |
+
|
42 |
+
protected function getProviderName() :string {
|
43 |
+
return 'LifterLMS';
|
44 |
+
}
|
45 |
+
|
46 |
+
public static function IsProviderInstalled() :bool {
|
47 |
+
return defined( 'LLMS_PLUGIN_FILE' ) && @class_exists( 'LifterLMS' )
|
48 |
+
&& defined( 'LLMS_VERSION' ) && version_compare( LLMS_VERSION, '4.20', '>' );
|
49 |
+
}
|
50 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/MemberPress.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Errors are passed about using an array of strings.
|
7 |
+
*
|
8 |
+
* Class MemberPress
|
9 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
10 |
+
*/
|
11 |
+
class MemberPress extends Base {
|
12 |
+
|
13 |
+
protected function login() {
|
14 |
+
add_filter( 'mepr-validate-login', [ $this, 'checkLogin_MP' ], 100 );
|
15 |
+
}
|
16 |
+
|
17 |
+
protected function register() {
|
18 |
+
add_filter( 'mepr-validate-signup', [ $this, 'checkRegister_MP' ], 10, 2 );
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function lostpassword() {
|
22 |
+
add_filter( 'mepr-validate-forgot-password', [ $this, 'checkLostPassword_MP' ], 100 );
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @param array $errors
|
27 |
+
* @return array
|
28 |
+
*/
|
29 |
+
public function checkLogin_MP( $errors ) {
|
30 |
+
if ( empty( $errors ) && $this->setAuditAction( 'login' )->checkIsBot() ) {
|
31 |
+
$errors = [
|
32 |
+
$this->getErrorMessage()
|
33 |
+
];
|
34 |
+
}
|
35 |
+
return $errors;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @param array $errors
|
40 |
+
* @return array
|
41 |
+
*/
|
42 |
+
public function checkLostPassword_MP( $errors ) {
|
43 |
+
if ( empty( $errors ) && $this->setAuditAction( 'lostpassword' )->checkIsBot() ) {
|
44 |
+
$errors = [
|
45 |
+
$this->getErrorMessage()
|
46 |
+
];
|
47 |
+
}
|
48 |
+
return $errors;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @param string[] $errors
|
53 |
+
* @return string[]
|
54 |
+
*/
|
55 |
+
public function checkRegister_MP( $errors ) {
|
56 |
+
if ( empty( $errors ) && $this->setAuditAction( 'register' )->checkIsBot() ) {
|
57 |
+
$errors = [
|
58 |
+
$this->getErrorMessage()
|
59 |
+
];
|
60 |
+
}
|
61 |
+
return $errors;
|
62 |
+
}
|
63 |
+
|
64 |
+
protected function getProviderName() :string {
|
65 |
+
return 'MemberPress';
|
66 |
+
}
|
67 |
+
|
68 |
+
public static function IsProviderInstalled() :bool {
|
69 |
+
return function_exists( 'mepr_autoloader' ) || @class_exists( '\MeprAccountCtrl' );
|
70 |
+
}
|
71 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/PaidMemberSubscriptions.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class PaidMemberSubscriptions
|
7 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
8 |
+
*/
|
9 |
+
class PaidMemberSubscriptions extends Base {
|
10 |
+
|
11 |
+
protected function register() {
|
12 |
+
add_filter( 'pms_register_form_validation', [ $this, 'checkRegister_PMS' ], 100 );
|
13 |
+
}
|
14 |
+
|
15 |
+
public function checkRegister_PMS() {
|
16 |
+
if ( $this->setAuditAction( 'register' )->checkIsBot() ) {
|
17 |
+
\pms_errors()->add( 'shield-fail-register', $this->getErrorMessage() );
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function getProviderName() :string {
|
22 |
+
return 'Paid Member Subscriptions';
|
23 |
+
}
|
24 |
+
|
25 |
+
public static function IsProviderInstalled() :bool {
|
26 |
+
return @class_exists( 'Paid_Member_Subscriptions' ) && function_exists( 'pms_errors' );
|
27 |
+
}
|
28 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/ProfileBuilder.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* https://wordpress.org/plugins/profile-builder/
|
7 |
+
*
|
8 |
+
* Class ProfileBuilder
|
9 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
10 |
+
*/
|
11 |
+
class ProfileBuilder extends Base {
|
12 |
+
|
13 |
+
protected function register() {
|
14 |
+
add_filter( 'wppb_output_field_errors_filter', [ $this, 'checkRegister_PB' ], 100 );
|
15 |
+
}
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @param array $errors
|
19 |
+
* @return array
|
20 |
+
*/
|
21 |
+
public function checkRegister_PB( $errors ) {
|
22 |
+
if ( empty( $errors ) && $this->setAuditAction( 'register' )->checkIsBot() ) {
|
23 |
+
$errors[ 'shield-fail-register' ] = sprintf( '<span class="wppb-form-error">%s</span>', $this->getErrorMessage() );
|
24 |
+
}
|
25 |
+
return $errors;
|
26 |
+
}
|
27 |
+
|
28 |
+
protected function getProviderName() :string {
|
29 |
+
return 'Profile Builder';
|
30 |
+
}
|
31 |
+
|
32 |
+
public static function IsProviderInstalled() :bool {
|
33 |
+
return defined( 'PROFILE_BUILDER_VERSION' );
|
34 |
+
}
|
35 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/UltimateMember.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* https://wordpress.org/plugins/ultimate-member/
|
7 |
+
*
|
8 |
+
* Class UltimateMember
|
9 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
10 |
+
*/
|
11 |
+
class UltimateMember extends Base {
|
12 |
+
|
13 |
+
protected function login() {
|
14 |
+
add_action( 'um_submit_form_login', [ $this, 'checkLogin_UM' ], 100 );
|
15 |
+
}
|
16 |
+
|
17 |
+
protected function register() {
|
18 |
+
add_action( 'um_submit_form_register', [ $this, 'checkRegister_UM' ], 5, 0 );
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function lostpassword() {
|
22 |
+
add_action( 'um_submit_form_password_reset', [ $this, 'checkLostPassword_UM' ], 5, 0 );
|
23 |
+
}
|
24 |
+
|
25 |
+
public function checkLogin_UM() {
|
26 |
+
if ( $this->setAuditAction( 'login' )->checkIsBot() ) {
|
27 |
+
\UM()->form()->add_error( 'shield-fail-login', $this->getErrorMessage() );
|
28 |
+
}
|
29 |
+
}
|
30 |
+
|
31 |
+
public function checkLostPassword_UM() {
|
32 |
+
if ( $this->setAuditAction( 'lostpassword' )->checkIsBot() ) {
|
33 |
+
\UM()->form()->add_error( 'shield-fail-lostpassword', $this->getErrorMessage() );
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
public function checkRegister_UM() {
|
38 |
+
if ( $this->setAuditAction( 'register' )->checkIsBot() ) {
|
39 |
+
\UM()->form()->add_error( 'shield-fail-register', $this->getErrorMessage() );
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
protected function getProviderName() :string {
|
44 |
+
return 'Ultimate Member';
|
45 |
+
}
|
46 |
+
|
47 |
+
public static function IsProviderInstalled() :bool {
|
48 |
+
return function_exists( '\UM' ) && @class_exists( '\UM' ) && method_exists( '\UM', 'form' );
|
49 |
+
}
|
50 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WPMembers.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* https://wordpress.org/plugins/wp-members/
|
7 |
+
*
|
8 |
+
* Class WPMembers
|
9 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
10 |
+
*/
|
11 |
+
class WPMembers extends Base {
|
12 |
+
|
13 |
+
protected function register() {
|
14 |
+
add_action( 'wpmem_pre_register_data', [ $this, 'checkRegister_WM' ], 5, 0 );
|
15 |
+
}
|
16 |
+
|
17 |
+
protected function lostpassword() {
|
18 |
+
add_action( 'wpmem_pwdreset_args', [ $this, 'checkLostPassword_WM' ], 5, 1 );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Again, nowhere to add custom validation so we hack it a little and clear
|
23 |
+
* the argument for user and email and this triggers a failure.
|
24 |
+
* @param array $args
|
25 |
+
* @return array
|
26 |
+
*/
|
27 |
+
public function checkLostPassword_WM( array $args ) {
|
28 |
+
if ( $this->setAuditAction( 'lostpassword' )->checkIsBot() ) {
|
29 |
+
$args[ 'user' ] = null;
|
30 |
+
$args[ 'email' ] = null;
|
31 |
+
}
|
32 |
+
return $args;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Offers no direct validation filter, so we jump in right before the DB insert.
|
37 |
+
*/
|
38 |
+
public function checkRegister_WM() {
|
39 |
+
if ( $this->setAuditAction( 'register' )->checkIsBot() ) {
|
40 |
+
global $wpmem_themsg;
|
41 |
+
$wpmem_themsg = $this->getErrorMessage();
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
protected function getProviderName() :string {
|
46 |
+
return 'WP Members';
|
47 |
+
}
|
48 |
+
|
49 |
+
public static function IsProviderInstalled() :bool {
|
50 |
+
return defined( 'WPMEM_VERSION' ) && function_exists( 'wpmem_init' );
|
51 |
+
}
|
52 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WooCommerce.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class WooCommerce
|
7 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
8 |
+
*/
|
9 |
+
class WooCommerce extends Base {
|
10 |
+
|
11 |
+
protected function login() {
|
12 |
+
add_filter( 'woocommerce_process_login_errors', [ $this, 'checkLogin_Woo' ], 10, 2 );
|
13 |
+
}
|
14 |
+
|
15 |
+
protected function register() {
|
16 |
+
add_filter( 'woocommerce_process_registration_errors', [ $this, 'checkRegister_Woo' ], 10, 2 );
|
17 |
+
}
|
18 |
+
|
19 |
+
protected function checkout() {
|
20 |
+
add_action( 'woocommerce_after_checkout_validation', [ $this, 'checkCheckout_Woo' ], 10, 2 );
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @param array $data
|
25 |
+
* @param \WP_Error $wpError
|
26 |
+
*/
|
27 |
+
public function checkCheckout_Woo( $data, $wpError ) {
|
28 |
+
if ( empty( $wpError->get_error_code() ) && $this->setAuditAction( 'checkout' )->checkIsBot() ) {
|
29 |
+
$wpError->add( 'shield-user-checkout', $this->getErrorMessage() );
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @param null|\WP_User|\WP_Error $wpError
|
35 |
+
* @param string $username
|
36 |
+
* @return \WP_User|\WP_Error
|
37 |
+
*/
|
38 |
+
public function checkLogin_Woo( $wpError, $username ) {
|
39 |
+
if ( empty( $wpError->get_error_code() ) && $this->setAuditAction( 'login' )->checkIsBot() ) {
|
40 |
+
$this->setAuditUser( $username );
|
41 |
+
$wpError->add( 'shield-user-login', $this->getErrorMessage() );
|
42 |
+
}
|
43 |
+
return $wpError;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @param \WP_Error $wpError
|
48 |
+
* @param string $username
|
49 |
+
* @return \WP_Error
|
50 |
+
*/
|
51 |
+
public function checkRegister_Woo( $wpError, $username ) {
|
52 |
+
if ( empty( $wpError->get_error_code() ) && $this->setAuditAction( 'register' )->checkIsBot() ) {
|
53 |
+
$this->setAuditUser( $username );
|
54 |
+
$wpError->add( 'shield-user-register', $this->getErrorMessage() );
|
55 |
+
}
|
56 |
+
return $wpError;
|
57 |
+
}
|
58 |
+
|
59 |
+
protected function getProviderName() :string {
|
60 |
+
return 'WooCommerce';
|
61 |
+
}
|
62 |
+
|
63 |
+
public static function IsProviderInstalled() :bool {
|
64 |
+
return @class_exists( 'WooCommerce' );
|
65 |
+
}
|
66 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WordPress.php
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Services\Services;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class WordPress
|
9 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\Handlers
|
10 |
+
*/
|
11 |
+
class WordPress extends Base {
|
12 |
+
|
13 |
+
protected function login() {
|
14 |
+
// We give it a priority of 10 so that we can jump in before WordPress does its own validation.
|
15 |
+
add_filter( 'authenticate', [ $this, 'checkLogin_WP' ], 10, 2 );
|
16 |
+
}
|
17 |
+
|
18 |
+
protected function register() {
|
19 |
+
add_filter( 'registration_errors', [ $this, 'checkRegister_WP' ], 10, 2 );
|
20 |
+
}
|
21 |
+
|
22 |
+
protected function lostpassword() {
|
23 |
+
add_action( 'lostpassword_post', [ $this, 'checkLostPassword_WP' ], 10, 2 );
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Should be a filter added to WordPress's "authenticate" filter, but before WordPress performs
|
28 |
+
* it's own authentication (theirs is priority 30, so we could go in at around 20).
|
29 |
+
* @param null|\WP_User|\WP_Error $userOrError
|
30 |
+
* @param string $username
|
31 |
+
* @return \WP_User|\WP_Error
|
32 |
+
*/
|
33 |
+
public function checkLogin_WP( $userOrError, $username ) {
|
34 |
+
if ( !is_wp_error( $userOrError ) || empty( $userOrError->get_error_codes() ) ) {
|
35 |
+
$this->setAuditAction( 'login' )
|
36 |
+
->setAuditUser( $username );
|
37 |
+
if ( $this->checkIsBot() ) {
|
38 |
+
$userOrError = new \WP_Error( 'shield-fail-login', $this->getErrorMessage() );
|
39 |
+
remove_filter( 'authenticate', 'wp_authenticate_username_password', 20 ); // wp-includes/user.php
|
40 |
+
remove_filter( 'authenticate', 'wp_authenticate_email_password', 20 ); // wp-includes/user.php
|
41 |
+
}
|
42 |
+
}
|
43 |
+
return $userOrError;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @param \WP_Error $wpError
|
48 |
+
* @param \WP_User|false $user
|
49 |
+
*/
|
50 |
+
public function checkLostPassword_WP( $wpError = null, $user = false ) {
|
51 |
+
if ( is_wp_error( $wpError ) && empty( $wpError->get_error_codes() ) ) {
|
52 |
+
$this->setAuditAction( 'lostpassword' );
|
53 |
+
if ( $user instanceof \WP_User ) {
|
54 |
+
$this->setAuditUser( $user->user_login );
|
55 |
+
}
|
56 |
+
else {
|
57 |
+
$this->setAuditUser( sanitize_user( Services::Request()->post( 'user_login', '' ) ) );
|
58 |
+
}
|
59 |
+
if ( $this->checkIsBot() ) {
|
60 |
+
$wpError->add( 'shield-fail-lostpassword', $this->getErrorMessage() );
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @param \WP_Error $wpError
|
67 |
+
* @param string $username
|
68 |
+
* @return \WP_Error
|
69 |
+
*/
|
70 |
+
public function checkRegister_WP( $wpError, $username ) {
|
71 |
+
if ( !is_wp_error( $wpError ) || empty( $wpError->get_error_codes() ) ) {
|
72 |
+
$this->setAuditAction( 'register' )
|
73 |
+
->setAuditUser( $username );
|
74 |
+
if ( $this->checkIsBot() ) {
|
75 |
+
$wpError = new \WP_Error( 'shield-fail-login', $this->getErrorMessage() );
|
76 |
+
}
|
77 |
+
}
|
78 |
+
return $wpError;
|
79 |
+
}
|
80 |
+
|
81 |
+
protected function getProviderName() :string {
|
82 |
+
return 'WordPress';
|
83 |
+
}
|
84 |
+
|
85 |
+
public static function IsProviderInstalled() :bool {
|
86 |
+
return true;
|
87 |
+
}
|
88 |
+
|
89 |
+
protected function isProOnly() :bool {
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
}
|
src/lib/src/Modules/Integrations/Lib/Bots/UserForms/UserFormsController.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Options;
|
7 |
+
use FernleafSystems\Wordpress\Services\Services;
|
8 |
+
|
9 |
+
class UserFormsController extends Integrations\Lib\Bots\Common\BaseBotDetectionController {
|
10 |
+
|
11 |
+
protected function canRun() :bool {
|
12 |
+
/** @var Options $loginOpts */
|
13 |
+
$loginOpts = $this->getCon()->getModule_LoginGuard()->getOptions();
|
14 |
+
return parent::canRun() && Services::Request()->isPost()
|
15 |
+
&& !Services::WpUsers()->isUserLoggedIn()
|
16 |
+
&& $loginOpts->isEnabledAntiBot();
|
17 |
+
}
|
18 |
+
|
19 |
+
protected function isEnabled() :bool {
|
20 |
+
/** @var Integrations\Options $opts */
|
21 |
+
$opts = $this->getOptions();
|
22 |
+
return !empty( $opts->getUserFormProviders() );
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return Handlers\Base[]
|
27 |
+
*/
|
28 |
+
public function enumProviders() :array {
|
29 |
+
return [
|
30 |
+
new Handlers\Buddypress(),
|
31 |
+
new Handlers\EasyDigitalDownloads(),
|
32 |
+
new Handlers\LearnPress(),
|
33 |
+
new Handlers\LifterLMS(),
|
34 |
+
new Handlers\MemberPress(),
|
35 |
+
new Handlers\PaidMemberSubscriptions(),
|
36 |
+
new Handlers\ProfileBuilder(),
|
37 |
+
new Handlers\UltimateMember(),
|
38 |
+
new Handlers\WooCommerce(),
|
39 |
+
new Handlers\WordPress(),
|
40 |
+
new Handlers\WPMembers(),
|
41 |
+
];
|
42 |
+
}
|
43 |
+
}
|
src/lib/src/Modules/Integrations/Lib/MainWP/Controller.php
CHANGED
@@ -2,16 +2,12 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Client;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Common\MainWPVO;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server;
|
9 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
10 |
|
11 |
-
class Controller {
|
12 |
-
|
13 |
-
use ModConsumer;
|
14 |
-
use ExecOnce;
|
15 |
|
16 |
const MIN_VERSION_MAINWP = '4.1';
|
17 |
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Client;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Common\MainWPVO;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server;
|
|
|
9 |
|
10 |
+
class Controller extends ExecOnceModConsumer {
|
|
|
|
|
|
|
11 |
|
12 |
const MIN_VERSION_MAINWP = '4.1';
|
13 |
|
src/lib/src/Modules/Integrations/Lib/MainWP/Server/Data/SyncHandler.php
CHANGED
@@ -2,14 +2,10 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server\Data;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use MainWP\Dashboard\MainWP_DB;
|
8 |
|
9 |
-
class SyncHandler {
|
10 |
-
|
11 |
-
use ModConsumer;
|
12 |
-
use ExecOnce;
|
13 |
|
14 |
protected function run() {
|
15 |
add_action( 'mainwp_sync_others_data', function ( $othersData, $website ) {
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server\Data;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
use MainWP\Dashboard\MainWP_DB;
|
7 |
|
8 |
+
class SyncHandler extends ExecOnceModConsumer {
|
|
|
|
|
|
|
9 |
|
10 |
protected function run() {
|
11 |
add_action( 'mainwp_sync_others_data', function ( $othersData, $website ) {
|
src/lib/src/Modules/Integrations/Lib/MainWP/Server/UI/ExtensionSettingsPage.php
CHANGED
@@ -2,17 +2,13 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server\UI;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
|
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Controller;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server\UI\PageRender;
|
9 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
-
class ExtensionSettingsPage {
|
13 |
-
|
14 |
-
use ModConsumer;
|
15 |
-
use ExecOnce;
|
16 |
|
17 |
protected function run() {
|
18 |
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server\UI;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Controller;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\MainWP\Server\UI\PageRender;
|
|
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
+
class ExtensionSettingsPage extends ExecOnceModConsumer {
|
|
|
|
|
|
|
12 |
|
13 |
protected function run() {
|
14 |
|
src/lib/src/Modules/Integrations/Lib/Spam/Handlers/Base.php
CHANGED
@@ -2,14 +2,10 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Spam\Handlers;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
-
abstract class Base {
|
10 |
-
|
11 |
-
use ModConsumer;
|
12 |
-
use ExecOnce;
|
13 |
|
14 |
const SLUG = '';
|
15 |
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Spam\Handlers;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
+
abstract class Base extends ExecOnceModConsumer {
|
|
|
|
|
|
|
9 |
|
10 |
const SLUG = '';
|
11 |
|
src/lib/src/Modules/Integrations/Lib/Spam/SpamController.php
CHANGED
@@ -5,6 +5,11 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Spam;
|
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
|
|
|
|
|
|
|
|
|
|
|
8 |
class SpamController {
|
9 |
|
10 |
use ModConsumer;
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
|
8 |
+
/**
|
9 |
+
* Class SpamController
|
10 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Spam
|
11 |
+
* @deprecated 11.2
|
12 |
+
*/
|
13 |
class SpamController {
|
14 |
|
15 |
use ModConsumer;
|
src/lib/src/Modules/Integrations/ModCon.php
CHANGED
@@ -12,6 +12,11 @@ class ModCon extends BaseShield\ModCon {
|
|
12 |
*/
|
13 |
private $mwp;
|
14 |
|
|
|
|
|
|
|
|
|
|
|
15 |
public function getControllerMWP() :Lib\MainWP\Controller {
|
16 |
if ( empty( $this->mwp ) ) {
|
17 |
$this->mwp = ( new Lib\MainWP\Controller() )
|
@@ -19,4 +24,12 @@ class ModCon extends BaseShield\ModCon {
|
|
19 |
}
|
20 |
return $this->mwp;
|
21 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
12 |
*/
|
13 |
private $mwp;
|
14 |
|
15 |
+
/**
|
16 |
+
* @var Lib\Bots\UserForms\UserFormsController
|
17 |
+
*/
|
18 |
+
private $userFormsCon;
|
19 |
+
|
20 |
public function getControllerMWP() :Lib\MainWP\Controller {
|
21 |
if ( empty( $this->mwp ) ) {
|
22 |
$this->mwp = ( new Lib\MainWP\Controller() )
|
24 |
}
|
25 |
return $this->mwp;
|
26 |
}
|
27 |
+
|
28 |
+
public function getController_UserForms() :Lib\Bots\UserForms\UserFormsController {
|
29 |
+
if ( !$this->userFormsCon instanceof Lib\Bots\UserForms\UserFormsController ) {
|
30 |
+
$this->userFormsCon = ( new Lib\Bots\UserForms\UserFormsController() )
|
31 |
+
->setMod( $this );
|
32 |
+
}
|
33 |
+
return $this->userFormsCon;
|
34 |
+
}
|
35 |
}
|
src/lib/src/Modules/Integrations/Options.php
CHANGED
@@ -9,4 +9,16 @@ class Options extends BaseShield\Options {
|
|
9 |
public function isEnabledMainWP() :bool {
|
10 |
return $this->isOpt( 'enable_mainwp', 'Y' );
|
11 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
9 |
public function isEnabledMainWP() :bool {
|
10 |
return $this->isOpt( 'enable_mainwp', 'Y' );
|
11 |
}
|
12 |
+
|
13 |
+
public function getUserFormProviders() :array {
|
14 |
+
$userForms = $this->getOpt( 'user_form_providers' );
|
15 |
+
if ( !is_array( $userForms ) ) {
|
16 |
+
$userForms = [];
|
17 |
+
}
|
18 |
+
if ( !in_array( 'wordpress', $userForms ) ) {
|
19 |
+
$userForms[] = 'wordpress';
|
20 |
+
$this->setOpt( 'user_form_providers', $userForms );
|
21 |
+
}
|
22 |
+
return array_unique( $userForms );
|
23 |
+
}
|
24 |
}
|
src/lib/src/Modules/Integrations/Processor.php
CHANGED
@@ -3,6 +3,7 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
|
|
|
6 |
|
7 |
class Processor extends BaseShield\Processor {
|
8 |
|
@@ -10,9 +11,15 @@ class Processor extends BaseShield\Processor {
|
|
10 |
/** @var ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
$mod->getControllerMWP()->execute();
|
13 |
-
|
14 |
-
(
|
15 |
-
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
18 |
}
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
|
6 |
+
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
class Processor extends BaseShield\Processor {
|
9 |
|
11 |
/** @var ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
$mod->getControllerMWP()->execute();
|
14 |
+
|
15 |
+
if ( !empty( Services::IP()->getRequestIp() ) ) {
|
16 |
+
( new Lib\Bots\Spam\SpamController() )
|
17 |
+
->setMod( $this->getMod() )
|
18 |
+
->execute();
|
19 |
+
|
20 |
+
add_action( 'init', function () use ( $mod ) {
|
21 |
+
$mod->getController_UserForms()->execute();
|
22 |
+
}, -100 );
|
23 |
+
}
|
24 |
}
|
25 |
}
|
src/lib/src/Modules/Integrations/Strings.php
CHANGED
@@ -11,12 +11,18 @@ class Strings extends Base\Strings {
|
|
11 |
*/
|
12 |
protected function getAuditMessages() :array {
|
13 |
return [
|
14 |
-
'spam_form_pass'
|
15 |
__( '"%s" submission passed SPAM check.', 'wp-simple-firewall' ),
|
16 |
],
|
17 |
-
'spam_form_fail'
|
18 |
__( '"%s" submission failed SPAM check.', 'wp-simple-firewall' )
|
19 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
];
|
21 |
}
|
22 |
|
@@ -40,6 +46,21 @@ class Strings extends Base\Strings {
|
|
40 |
];
|
41 |
break;
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
default:
|
44 |
return parent::getSectionStrings( $section );
|
45 |
}
|
@@ -57,6 +78,7 @@ class Strings extends Base\Strings {
|
|
57 |
* @throws \Exception
|
58 |
*/
|
59 |
public function getOptionStrings( string $key ) :array {
|
|
|
60 |
|
61 |
switch ( $key ) {
|
62 |
|
@@ -72,6 +94,22 @@ class Strings extends Base\Strings {
|
|
72 |
];
|
73 |
break;
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
default:
|
76 |
return parent::getOptionStrings( $key );
|
77 |
}
|
11 |
*/
|
12 |
protected function getAuditMessages() :array {
|
13 |
return [
|
14 |
+
'spam_form_pass' => [
|
15 |
__( '"%s" submission passed SPAM check.', 'wp-simple-firewall' ),
|
16 |
],
|
17 |
+
'spam_form_fail' => [
|
18 |
__( '"%s" submission failed SPAM check.', 'wp-simple-firewall' )
|
19 |
],
|
20 |
+
'user_form_bot_pass' => [
|
21 |
+
__( '"%s" submission for form "%s" with username "%s" passed Bot check.', 'wp-simple-firewall' ),
|
22 |
+
],
|
23 |
+
'user_form_bot_fail' => [
|
24 |
+
__( '"%s" submission for form "%s" with username "%s" failed Bot check.', 'wp-simple-firewall' ),
|
25 |
+
],
|
26 |
];
|
27 |
}
|
28 |
|
46 |
];
|
47 |
break;
|
48 |
|
49 |
+
case 'section_user_forms':
|
50 |
+
$titleShort = __( 'User Forms Bot Checking', 'wp-simple-firewall' );
|
51 |
+
$title = __( 'User Forms Bot Checking', 'wp-simple-firewall' );
|
52 |
+
$summary = [
|
53 |
+
sprintf( '%s - %s %s', __( 'Summary', 'wp-simple-firewall' ),
|
54 |
+
__( "Shield can automatically protect 3rd party login and registration forms against Bots.", 'wp-simple-firewall' ),
|
55 |
+
__( "It uses our exclusive AntiBot Detection Engine to reliably identify bots.", 'wp-simple-firewall' )
|
56 |
+
),
|
57 |
+
sprintf( '%s - %s (%s)', __( 'Recommendation', 'wp-simple-firewall' ),
|
58 |
+
__( "Only enable the integrations you require.", 'wp-simple-firewall' ),
|
59 |
+
__( "WordPress is always enabled.", 'wp-simple-firewall' )
|
60 |
+
),
|
61 |
+
];
|
62 |
+
break;
|
63 |
+
|
64 |
default:
|
65 |
return parent::getSectionStrings( $section );
|
66 |
}
|
78 |
* @throws \Exception
|
79 |
*/
|
80 |
public function getOptionStrings( string $key ) :array {
|
81 |
+
$con = $this->getCon();
|
82 |
|
83 |
switch ( $key ) {
|
84 |
|
94 |
];
|
95 |
break;
|
96 |
|
97 |
+
case 'user_form_providers' :
|
98 |
+
$name = __( 'User Forms Bot Detection', 'wp-simple-firewall' );
|
99 |
+
$summary = __( "Select The User Forms Provider That You Use", 'wp-simple-firewall' );
|
100 |
+
$desc = [
|
101 |
+
__( 'This is a ShieldPRO-only feature.', 'wp-simple-firewall' ),
|
102 |
+
__( 'Many 3rd party plugins provide custom user login, registration, and lost password forms.', 'wp-simple-firewall' )
|
103 |
+
.' '.__( "They aren't normally checked for Bots since they require a custom integration.", 'wp-simple-firewall' ),
|
104 |
+
__( "Select your 3rd party providers to have Shield automatically detect Bot requests to these forms.", 'wp-simple-firewall' ),
|
105 |
+
sprintf( '%s: %s', __( 'Important', 'wp-simple-firewall' ),
|
106 |
+
__( 'Only the form types (login, registration, lost password), that you have selected in the Login Guard module will be checked.', 'wp-simple-firewall' ) ),
|
107 |
+
sprintf( '<a href="%s">%s</a>', $con->getModule_LoginGuard()
|
108 |
+
->getUrl_DirectLinkToSection( 'section_brute_force_login_protection' ),
|
109 |
+
sprintf( __( 'Choose the types of forms you want %s to check', 'wp-simple-firewall' ), $con->getHumanName() ) ),
|
110 |
+
];
|
111 |
+
break;
|
112 |
+
|
113 |
default:
|
114 |
return parent::getOptionStrings( $key );
|
115 |
}
|
src/lib/src/Modules/Integrations/UI.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
6 |
+
|
7 |
+
class UI extends Modules\BaseShield\UI {
|
8 |
+
|
9 |
+
protected function getSectionNotices( string $section ) :array {
|
10 |
+
$notices = [];
|
11 |
+
|
12 |
+
/** @var Modules\LoginGuard\Options $loginGuardOpts */
|
13 |
+
$loginGuardOpts = $this->getCon()->getModule_LoginGuard()->getOptions();
|
14 |
+
$locations = $loginGuardOpts->getBotProtectionLocations();
|
15 |
+
$locations = array_intersect_key(
|
16 |
+
array_merge(
|
17 |
+
array_flip( $locations ),
|
18 |
+
[
|
19 |
+
'login' => __( 'Login', 'wp-simple-firewall' ),
|
20 |
+
'register' => __( 'Registration', 'wp-simple-firewall' ),
|
21 |
+
'password' => __( 'Lost Password', 'wp-simple-firewall' ),
|
22 |
+
'checkout_woo' => __( 'Checkout', 'wp-simple-firewall' ),
|
23 |
+
]
|
24 |
+
),
|
25 |
+
array_flip( $locations )
|
26 |
+
);
|
27 |
+
$locations = empty( $locations ) ? __( 'None', 'wp-simple-firewall' ) : implode( ', ', $locations );
|
28 |
+
|
29 |
+
switch ( $section ) {
|
30 |
+
|
31 |
+
case 'section_user_forms':
|
32 |
+
if ( $loginGuardOpts->isEnabledAntiBot() ) {
|
33 |
+
$notices[] = sprintf( '%s: %s %s', __( 'Note', 'wp-simple-firewall' ),
|
34 |
+
sprintf(
|
35 |
+
__( "The following forms are protected by AntiBot Detection: %s.", 'wp-simple-firewall' ),
|
36 |
+
$locations
|
37 |
+
),
|
38 |
+
sprintf( '<a href="%s" target="_blank">%s</a>',
|
39 |
+
$this->getCon()->getModule_LoginGuard()->getUrl_AdminPage(),
|
40 |
+
__( 'Click here to review those settings.', 'wp-simple-firewall' ) )
|
41 |
+
);
|
42 |
+
}
|
43 |
+
break;
|
44 |
+
}
|
45 |
+
|
46 |
+
return $notices;
|
47 |
+
}
|
48 |
+
|
49 |
+
protected function getSectionWarnings( string $section ) :array {
|
50 |
+
$warnings = [];
|
51 |
+
|
52 |
+
/** @var Modules\LoginGuard\Options $loginGuardOpts */
|
53 |
+
$loginGuardOpts = $this->getCon()->getModule_LoginGuard()->getOptions();
|
54 |
+
|
55 |
+
switch ( $section ) {
|
56 |
+
|
57 |
+
case 'section_user_forms':
|
58 |
+
if ( !$loginGuardOpts->isEnabledAntiBot() ) {
|
59 |
+
$warnings[] = sprintf( '%s: %s %s', __( 'Important', 'wp-simple-firewall' ),
|
60 |
+
__( "Use of the AntiBot Detection Engine for user forms isn't turned on in the Login Guard module.", 'wp-simple-firewall' ),
|
61 |
+
sprintf( '<a href="%s" target="_blank">%s</a>',
|
62 |
+
$this->getCon()->getModule_LoginGuard()->getUrl_AdminPage(),
|
63 |
+
__( 'Click here to review those settings.', 'wp-simple-firewall' ) )
|
64 |
+
);
|
65 |
+
}
|
66 |
+
break;
|
67 |
+
}
|
68 |
+
|
69 |
+
return $warnings;
|
70 |
+
}
|
71 |
+
}
|
src/lib/src/Modules/Integrations/Upgrade.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Integrations\Lib\Bots\UserForms\UserFormsController;
|
7 |
+
|
8 |
+
class Upgrade extends Base\Upgrade {
|
9 |
+
|
10 |
+
protected function upgrade_1120() {
|
11 |
+
/** @var Options $opts */
|
12 |
+
$opts = $this->getOptions();
|
13 |
+
$providers = ( new UserFormsController() )
|
14 |
+
->setMod( $this->getMod() )
|
15 |
+
->enumProviders();
|
16 |
+
|
17 |
+
$enabledProviders = $opts->getUserFormProviders();
|
18 |
+
foreach ( $providers as $provider ) {
|
19 |
+
if ( $provider::IsProviderInstalled() ) {
|
20 |
+
$enabledProviders[] = $provider->getHandlerSlug();
|
21 |
+
}
|
22 |
+
}
|
23 |
+
$opts->setOpt( 'user_form_providers', array_unique( $enabledProviders ) );
|
24 |
+
}
|
25 |
+
}
|
src/lib/src/Modules/License/Lib/LookupRequest.php
CHANGED
@@ -1,7 +1,8 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\License\Lib;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\ShieldNetApi\HandshakingNonce;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
@@ -11,39 +12,24 @@ class LookupRequest {
|
|
11 |
|
12 |
use ModConsumer;
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
public function lookup() {
|
18 |
-
$oCon = $this->getCon();
|
19 |
-
$oOpts = $this->getOptions();
|
20 |
|
21 |
{
|
22 |
-
$
|
23 |
-
$
|
24 |
-
$
|
25 |
-
$
|
26 |
-
$
|
27 |
-
$
|
28 |
-
$
|
29 |
-
'version_shield' => $
|
30 |
'version_php' => Services::Data()->getPhpVersionCleaned()
|
31 |
];
|
32 |
-
$
|
33 |
}
|
34 |
|
35 |
-
return $
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @param string $sNonce - empty string to clear the nonce
|
40 |
-
*/
|
41 |
-
private function setKeylessHandshakeNonce( $sNonce = '' ) {
|
42 |
-
$oOpts = $this->getOptions();
|
43 |
-
$oOpts->setOpt( 'keyless_handshake_hash', $sNonce )
|
44 |
-
->setOpt( 'keyless_handshake_until',
|
45 |
-
empty( $sNonce ) ? 0 : Services::Request()->ts() + $oOpts->getDef( 'keyless_handshake_expire' )
|
46 |
-
);
|
47 |
-
$this->getMod()->saveModOptions();
|
48 |
}
|
49 |
}
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\License\Lib;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\License\EddLicenseVO;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\ShieldNetApi\HandshakingNonce;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
12 |
|
13 |
use ModConsumer;
|
14 |
|
15 |
+
public function lookup() :EddLicenseVO {
|
16 |
+
$con = $this->getCon();
|
17 |
+
$opts = $this->getOptions();
|
|
|
|
|
|
|
18 |
|
19 |
{
|
20 |
+
$lookup = new Lookup();
|
21 |
+
$lookup->lookup_url_stub = $opts->getDef( 'license_store_url_api' );
|
22 |
+
$lookup->item_id = $opts->getDef( 'license_item_id' );
|
23 |
+
$lookup->install_id = $con->getSiteInstallationId();
|
24 |
+
$lookup->url = Services::WpGeneral()->getHomeUrl( '', true );
|
25 |
+
$lookup->nonce = ( new HandshakingNonce() )->setMod( $this->getMod() )->create();
|
26 |
+
$lookup->meta = [
|
27 |
+
'version_shield' => $con->getVersion(),
|
28 |
'version_php' => Services::Data()->getPhpVersionCleaned()
|
29 |
];
|
30 |
+
$license = $lookup->lookup();
|
31 |
}
|
32 |
|
33 |
+
return ( new EddLicenseVO() )->applyFromArray( $license->getRawDataAsArray() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
}
|
35 |
}
|
src/lib/src/Modules/License/Lib/PluginNameSuffix.php
CHANGED
@@ -4,7 +4,6 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\License\Lib;
|
|
4 |
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin;
|
8 |
|
9 |
class PluginNameSuffix {
|
10 |
|
@@ -13,9 +12,8 @@ class PluginNameSuffix {
|
|
13 |
|
14 |
protected function canRun() :bool {
|
15 |
$con = $this->getCon();
|
16 |
-
|
17 |
-
|
18 |
-
return (bool)apply_filters( 'shield/add_pro_suffix', $con->isPremiumActive() && !$optsSecAdmin->isEnabledWhitelabel() );
|
19 |
}
|
20 |
|
21 |
protected function run() {
|
4 |
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
|
|
7 |
|
8 |
class PluginNameSuffix {
|
9 |
|
12 |
|
13 |
protected function canRun() :bool {
|
14 |
$con = $this->getCon();
|
15 |
+
return (bool)apply_filters( 'shield/add_pro_suffix',
|
16 |
+
$con->isPremiumActive() && !$con->getModule_SecAdmin()->getWhiteLabelController()->isEnabled() );
|
|
|
17 |
}
|
18 |
|
19 |
protected function run() {
|
src/lib/src/Modules/License/Lib/Verify.php
CHANGED
@@ -14,51 +14,50 @@ class Verify {
|
|
14 |
* @throws \Exception
|
15 |
*/
|
16 |
public function run() {
|
17 |
-
$con = $this->getCon();
|
18 |
/** @var License\ModCon $mod */
|
19 |
$mod = $this->getMod();
|
20 |
/** @var License\Options $opts */
|
21 |
$opts = $this->getOptions();
|
22 |
-
$
|
23 |
|
24 |
$this->preVerify();
|
25 |
|
26 |
-
$
|
27 |
|
28 |
-
$
|
29 |
->setMod( $mod )
|
30 |
->lookup();
|
31 |
|
32 |
-
$
|
33 |
|
34 |
-
if ( $
|
35 |
-
$
|
36 |
-
$
|
37 |
-
$
|
38 |
-
if ( !$
|
39 |
$opts->setOptAt( 'license_activated_at' );
|
40 |
}
|
41 |
$mod->clearLastErrors();
|
42 |
-
$opts->setOpt( 'license_data', $
|
43 |
-
$
|
44 |
}
|
45 |
-
elseif ( $
|
46 |
-
$
|
47 |
// License lookup failed but request was successful - so use what we get
|
48 |
-
$
|
49 |
-
$
|
50 |
}
|
51 |
-
elseif ( $
|
52 |
|
53 |
$mod->setLastErrors( [
|
54 |
__( 'The most recent request to verify the site license encountered a problem.', 'wp-simple-firewall' )
|
55 |
] );
|
56 |
|
57 |
-
if ( Services::Request()->ts() > $
|
58 |
-
$
|
59 |
-
$
|
60 |
}
|
61 |
-
elseif ( $
|
62 |
/**
|
63 |
* At this stage we have a license stored, but we couldn't
|
64 |
* verify it, but we're within the grace period for checking.
|
@@ -71,15 +70,15 @@ class Verify {
|
|
71 |
}
|
72 |
}
|
73 |
else { // all else fails, clear any license details entirely
|
74 |
-
$
|
75 |
-
$
|
76 |
}
|
77 |
|
78 |
-
$
|
79 |
-
$opts->setOpt( 'license_data', $
|
80 |
$this->getMod()->saveModOptions();
|
81 |
|
82 |
-
if ( !$
|
83 |
throw new \Exception( 'License API HTTP Request Failed.' );
|
84 |
}
|
85 |
}
|
14 |
* @throws \Exception
|
15 |
*/
|
16 |
public function run() {
|
|
|
17 |
/** @var License\ModCon $mod */
|
18 |
$mod = $this->getMod();
|
19 |
/** @var License\Options $opts */
|
20 |
$opts = $this->getOptions();
|
21 |
+
$licHandler = $mod->getLicenseHandler();
|
22 |
|
23 |
$this->preVerify();
|
24 |
|
25 |
+
$existing = $licHandler->getLicense();
|
26 |
|
27 |
+
$license = ( new LookupRequest() )
|
28 |
->setMod( $mod )
|
29 |
->lookup();
|
30 |
|
31 |
+
$isSuccessfulApiRequest = false;
|
32 |
|
33 |
+
if ( $license->isValid() ) {
|
34 |
+
$isSuccessfulApiRequest = true;
|
35 |
+
$existing = $license;
|
36 |
+
$existing->updateLastVerifiedAt( true );
|
37 |
+
if ( !$licHandler->isActive() ) {
|
38 |
$opts->setOptAt( 'license_activated_at' );
|
39 |
}
|
40 |
$mod->clearLastErrors();
|
41 |
+
$opts->setOpt( 'license_data', $existing->getRawDataAsArray() ); // need to do this before event
|
42 |
+
$this->getCon()->fireEvent( 'lic_check_success' );
|
43 |
}
|
44 |
+
elseif ( $license->isReady() ) {
|
45 |
+
$isSuccessfulApiRequest = true;
|
46 |
// License lookup failed but request was successful - so use what we get
|
47 |
+
$licHandler->deactivate();
|
48 |
+
$existing = $licHandler->getLicense();
|
49 |
}
|
50 |
+
elseif ( $existing->isReady() ) { // Has a stored license but license HTTP request failed
|
51 |
|
52 |
$mod->setLastErrors( [
|
53 |
__( 'The most recent request to verify the site license encountered a problem.', 'wp-simple-firewall' )
|
54 |
] );
|
55 |
|
56 |
+
if ( Services::Request()->ts() > $licHandler->getRegistrationExpiresAt() ) {
|
57 |
+
$licHandler->deactivate();
|
58 |
+
$existing = $licHandler->getLicense();
|
59 |
}
|
60 |
+
elseif ( $licHandler->isLastVerifiedExpired() ) {
|
61 |
/**
|
62 |
* At this stage we have a license stored, but we couldn't
|
63 |
* verify it, but we're within the grace period for checking.
|
70 |
}
|
71 |
}
|
72 |
else { // all else fails, clear any license details entirely
|
73 |
+
$licHandler->clearLicense();
|
74 |
+
$existing = $licHandler->getLicense();
|
75 |
}
|
76 |
|
77 |
+
$existing->last_request_at = Services::Request()->ts();
|
78 |
+
$opts->setOpt( 'license_data', $existing->getRawDataAsArray() );
|
79 |
$this->getMod()->saveModOptions();
|
80 |
|
81 |
+
if ( !$isSuccessfulApiRequest ) {
|
82 |
throw new \Exception( 'License API HTTP Request Failed.' );
|
83 |
}
|
84 |
}
|
src/lib/src/Modules/Lockdown/Insights/OverviewCards.php
CHANGED
@@ -6,24 +6,15 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
|
6 |
|
7 |
class OverviewCards extends Modules\Base\Insights\OverviewCards {
|
8 |
|
9 |
-
|
10 |
/** @var Modules\Lockdown\ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
/** @var Modules\Lockdown\Options $opts */
|
13 |
$opts = $this->getOptions();
|
14 |
|
15 |
-
$cardSection = [
|
16 |
-
'title' => __( 'WordPress Lockdown', 'wp-simple-firewall' ),
|
17 |
-
'subtitle' => __( 'Restrict WP Functionality e.g. XMLRPC & REST API', 'wp-simple-firewall' ),
|
18 |
-
'href_options' => $mod->getUrl_AdminPage()
|
19 |
-
];
|
20 |
-
|
21 |
$cards = [];
|
22 |
|
23 |
-
if (
|
24 |
-
$cards[ 'mod' ] = $this->getModDisabledCard();
|
25 |
-
}
|
26 |
-
else {
|
27 |
$bUserCanEdit = current_user_can( 'edit_plugins' );
|
28 |
|
29 |
if ( !$bUserCanEdit ) {
|
@@ -70,7 +61,14 @@ class OverviewCards extends Modules\Base\Insights\OverviewCards {
|
|
70 |
];
|
71 |
}
|
72 |
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
76 |
}
|
6 |
|
7 |
class OverviewCards extends Modules\Base\Insights\OverviewCards {
|
8 |
|
9 |
+
protected function buildModCards() :array {
|
10 |
/** @var Modules\Lockdown\ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
/** @var Modules\Lockdown\Options $opts */
|
13 |
$opts = $this->getOptions();
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
$cards = [];
|
16 |
|
17 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
18 |
$bUserCanEdit = current_user_can( 'edit_plugins' );
|
19 |
|
20 |
if ( !$bUserCanEdit ) {
|
61 |
];
|
62 |
}
|
63 |
|
64 |
+
return $cards;
|
65 |
+
}
|
66 |
+
|
67 |
+
protected function getSectionTitle() :string {
|
68 |
+
return __( 'WordPress Lockdown', 'wp-simple-firewall' );
|
69 |
+
}
|
70 |
+
|
71 |
+
protected function getSectionSubTitle() :string {
|
72 |
+
return __( 'Restrict WP Functionality e.g. XMLRPC & REST API', 'wp-simple-firewall' );
|
73 |
}
|
74 |
}
|
src/lib/src/Modules/Lockdown/Lib/CleanRubbish.php
CHANGED
@@ -2,14 +2,10 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Lockdown\Lib;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
-
class CleanRubbish {
|
10 |
-
|
11 |
-
use ModConsumer;
|
12 |
-
use ExecOnce;
|
13 |
|
14 |
protected function canRun() :bool {
|
15 |
return $this->getOptions()->isOpt( 'clean_wp_rubbish', 'Y' );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Lockdown\Lib;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
+
class CleanRubbish extends ExecOnceModConsumer {
|
|
|
|
|
|
|
9 |
|
10 |
protected function canRun() :bool {
|
11 |
return $this->getOptions()->isOpt( 'clean_wp_rubbish', 'Y' );
|
src/lib/src/Modules/LoginGuard/AjaxHandler.php
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
4 |
|
@@ -11,6 +11,10 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
11 |
protected function processAjaxAction( string $action ) :array {
|
12 |
|
13 |
switch ( $action ) {
|
|
|
|
|
|
|
|
|
14 |
case 'gen_backup_codes':
|
15 |
$response = $this->ajaxExec_GenBackupCodes();
|
16 |
break;
|
@@ -23,16 +27,28 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
23 |
$response = $this->ajaxExec_Disable2faEmail();
|
24 |
break;
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
case 'resend_verification_email':
|
27 |
$response = $this->ajaxExec_ResendEmailVerification();
|
28 |
break;
|
29 |
|
|
|
|
|
|
|
|
|
30 |
case 'u2f_remove':
|
31 |
$response = $this->ajaxExec_ProfileU2fRemove();
|
32 |
break;
|
33 |
|
34 |
-
case '
|
35 |
-
$response = $this->
|
36 |
break;
|
37 |
|
38 |
default:
|
@@ -42,19 +58,38 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
42 |
return $response;
|
43 |
}
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
protected function ajaxExec_GenBackupCodes() :array {
|
46 |
/** @var ModCon $mod */
|
47 |
$mod = $this->getMod();
|
48 |
-
/** @var TwoFactor\Provider\
|
49 |
-
$
|
50 |
-
->getProviders()[ TwoFactor\Provider\Backup::SLUG ];
|
51 |
-
$pass = $oBU->resetSecret( Services::WpUsers()->getCurrentWpUser() );
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
}
|
56 |
|
57 |
return [
|
|
|
58 |
'code' => $pass,
|
59 |
'success' => true
|
60 |
];
|
@@ -63,16 +98,60 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
63 |
private function ajaxExec_DeleteBackupCodes() :array {
|
64 |
/** @var ModCon $mod */
|
65 |
$mod = $this->getMod();
|
66 |
-
/** @var TwoFactor\Provider\
|
67 |
-
$
|
68 |
-
|
69 |
-
$oBU->deleteSecret( Services::WpUsers()->getCurrentWpUser() );
|
70 |
$mod->setFlashAdminNotice( __( 'Multi-factor login backup code has been removed from your profile', 'wp-simple-firewall' ) );
|
|
|
71 |
return [
|
|
|
72 |
'success' => true
|
73 |
];
|
74 |
}
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
private function ajaxExec_Disable2faEmail() :array {
|
77 |
/** @var ModCon $mod */
|
78 |
$mod = $this->getMod();
|
@@ -84,15 +163,41 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
84 |
];
|
85 |
}
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
private function ajaxExec_ProfileU2fRemove() :array {
|
88 |
/** @var ModCon $mod */
|
89 |
$mod = $this->getMod();
|
|
|
|
|
|
|
90 |
|
91 |
$key = Services::Request()->post( 'u2fid' );
|
92 |
if ( !empty( $key ) ) {
|
93 |
-
(
|
94 |
-
->setMod( $mod )
|
95 |
-
->removeRegisteredU2fId( Services::WpUsers()->getCurrentWpUser(), $key );
|
96 |
}
|
97 |
return [
|
98 |
'success' => !empty( $key ),
|
@@ -101,28 +206,23 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
101 |
];
|
102 |
}
|
103 |
|
104 |
-
|
105 |
-
* @return array
|
106 |
-
*/
|
107 |
-
private function ajaxExec_ProfileYubikeyRemove() {
|
108 |
/** @var ModCon $mod */
|
109 |
$mod = $this->getMod();
|
|
|
|
|
|
|
110 |
|
111 |
-
$
|
112 |
-
|
113 |
-
->setMod( $mod )
|
114 |
-
->addRemoveRegisteredYubiId( Services::WpUsers()->getCurrentWpUser(), $key, false );
|
115 |
return [
|
116 |
-
'success' =>
|
117 |
-
'message' =>
|
118 |
'page_reload' => true
|
119 |
];
|
120 |
}
|
121 |
|
122 |
-
|
123 |
-
* @return array
|
124 |
-
*/
|
125 |
-
private function ajaxExec_ResendEmailVerification() {
|
126 |
/** @var ModCon $mod */
|
127 |
$mod = $this->getMod();
|
128 |
/** @var Options $opts */
|
@@ -130,21 +230,21 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
130 |
$success = true;
|
131 |
|
132 |
if ( !$opts->isEnabledEmailAuth() ) {
|
133 |
-
$
|
134 |
$success = false;
|
135 |
}
|
136 |
elseif ( $opts->getIfCanSendEmailVerified() ) {
|
137 |
-
$
|
138 |
}
|
139 |
else {
|
140 |
-
$
|
141 |
$mod->setIfCanSendEmail( false )
|
142 |
->sendEmailVerifyCanSend();
|
143 |
}
|
144 |
|
145 |
return [
|
146 |
'success' => $success,
|
147 |
-
'message' => $
|
148 |
];
|
149 |
}
|
150 |
}
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
4 |
|
11 |
protected function processAjaxAction( string $action ) :array {
|
12 |
|
13 |
switch ( $action ) {
|
14 |
+
case 'mfa_remove_all':
|
15 |
+
$response = $this->ajaxExec_MfaRemoveAll();
|
16 |
+
break;
|
17 |
+
|
18 |
case 'gen_backup_codes':
|
19 |
$response = $this->ajaxExec_GenBackupCodes();
|
20 |
break;
|
27 |
$response = $this->ajaxExec_Disable2faEmail();
|
28 |
break;
|
29 |
|
30 |
+
case 'user_ga_toggle':
|
31 |
+
$response = $this->ajaxExec_UserGaToggle();
|
32 |
+
break;
|
33 |
+
|
34 |
+
case 'user_email2fa_toggle':
|
35 |
+
$response = $this->ajaxExec_User2faEmailToggle();
|
36 |
+
break;
|
37 |
+
|
38 |
case 'resend_verification_email':
|
39 |
$response = $this->ajaxExec_ResendEmailVerification();
|
40 |
break;
|
41 |
|
42 |
+
case 'u2f_add':
|
43 |
+
$response = $this->ajaxExec_ProfileU2fAdd();
|
44 |
+
break;
|
45 |
+
|
46 |
case 'u2f_remove':
|
47 |
$response = $this->ajaxExec_ProfileU2fRemove();
|
48 |
break;
|
49 |
|
50 |
+
case 'user_yubikey_toggle':
|
51 |
+
$response = $this->ajaxExec_UserYubikeyToggle();
|
52 |
break;
|
53 |
|
54 |
default:
|
58 |
return $response;
|
59 |
}
|
60 |
|
61 |
+
private function ajaxExec_MfaRemoveAll() :array {
|
62 |
+
/** @var ModCon $mod */
|
63 |
+
$mod = $this->getMod();
|
64 |
+
$userID = Services::Request()->post( 'user_id' );
|
65 |
+
if ( !empty( $userID ) ) {
|
66 |
+
$result = $mod->getLoginIntentController()->removeAllFactorsForUser( (int)$userID );
|
67 |
+
$response = [
|
68 |
+
'success' => $result->success,
|
69 |
+
'message' => $result->success ? $result->msg_text : $result->error_text,
|
70 |
+
];
|
71 |
+
}
|
72 |
+
else {
|
73 |
+
$response = [
|
74 |
+
'success' => false,
|
75 |
+
'message' => 'Invalid request with no User ID',
|
76 |
+
];
|
77 |
+
}
|
78 |
+
|
79 |
+
return $response;
|
80 |
+
}
|
81 |
+
|
82 |
protected function ajaxExec_GenBackupCodes() :array {
|
83 |
/** @var ModCon $mod */
|
84 |
$mod = $this->getMod();
|
85 |
+
/** @var TwoFactor\Provider\BackupCodes $provider */
|
86 |
+
$provider = $mod->getLoginIntentController()->getProviders()[ TwoFactor\Provider\BackupCodes::SLUG ];
|
|
|
|
|
87 |
|
88 |
+
$pass = $provider->resetSecret( Services::WpUsers()->getCurrentWpUser() );
|
89 |
+
$pass = implode( '-', str_split( $pass, 5 ) );
|
|
|
90 |
|
91 |
return [
|
92 |
+
'message' => sprintf( 'Your backup login code is:<br/><code>%s</code>', $pass ),
|
93 |
'code' => $pass,
|
94 |
'success' => true
|
95 |
];
|
98 |
private function ajaxExec_DeleteBackupCodes() :array {
|
99 |
/** @var ModCon $mod */
|
100 |
$mod = $this->getMod();
|
101 |
+
/** @var TwoFactor\Provider\BackupCodes $provider */
|
102 |
+
$provider = $mod->getLoginIntentController()->getProviders()[ TwoFactor\Provider\BackupCodes::SLUG ];
|
103 |
+
$provider->deleteSecret( Services::WpUsers()->getCurrentWpUser() );
|
|
|
104 |
$mod->setFlashAdminNotice( __( 'Multi-factor login backup code has been removed from your profile', 'wp-simple-firewall' ) );
|
105 |
+
|
106 |
return [
|
107 |
+
'message' => __( 'Your backup login codes have been deleted.', 'wp-simple-firewall' ),
|
108 |
'success' => true
|
109 |
];
|
110 |
}
|
111 |
|
112 |
+
private function ajaxExec_UserGaToggle() :array {
|
113 |
+
/** @var ModCon $mod */
|
114 |
+
$mod = $this->getMod();
|
115 |
+
/** @var TwoFactor\Provider\GoogleAuth $provider */
|
116 |
+
$provider = $mod->getLoginIntentController()->getProviders()[ TwoFactor\Provider\GoogleAuth::SLUG ];
|
117 |
+
|
118 |
+
$otp = Services::Request()->post( 'ga_otp', '' );
|
119 |
+
$result = empty( $otp ) ?
|
120 |
+
$provider->removeGaOnAccount( Services::WpUsers()->getCurrentWpUser() )
|
121 |
+
: $provider->activateGaOnAccount( Services::WpUsers()->getCurrentWpUser(), $otp );
|
122 |
+
|
123 |
+
return [
|
124 |
+
'success' => $result->success,
|
125 |
+
'message' => $result->success ? $result->msg_text : $result->error_text,
|
126 |
+
'page_reload' => true
|
127 |
+
];
|
128 |
+
}
|
129 |
+
|
130 |
+
private function ajaxExec_User2faEmailToggle() :array {
|
131 |
+
/** @var ModCon $mod */
|
132 |
+
$mod = $this->getMod();
|
133 |
+
/** @var TwoFactor\Provider\Email $provider */
|
134 |
+
$provider = $mod->getLoginIntentController()->getProviders()[ TwoFactor\Provider\Email::SLUG ];
|
135 |
+
|
136 |
+
$turnOn = Services::Request()->post( 'direction' ) == 'on';
|
137 |
+
$provider->setProfileValidated( Services::WpUsers()->getCurrentWpUser(), $turnOn );
|
138 |
+
$success = $turnOn === $provider->isProfileActive( Services::WpUsers()->getCurrentWpUser() );
|
139 |
+
|
140 |
+
if ( $success ) {
|
141 |
+
$msg = $turnOn ? __( 'Email 2FA activated.', 'wp-simple-firewall' )
|
142 |
+
: __( 'Email 2FA deactivated.', 'wp-simple-firewall' );
|
143 |
+
}
|
144 |
+
else {
|
145 |
+
$msg = __( "Email 2FA settings couldn't be changed.", 'wp-simple-firewall' );
|
146 |
+
}
|
147 |
+
|
148 |
+
return [
|
149 |
+
'success' => $success,
|
150 |
+
'message' => $msg,
|
151 |
+
'page_reload' => true
|
152 |
+
];
|
153 |
+
}
|
154 |
+
|
155 |
private function ajaxExec_Disable2faEmail() :array {
|
156 |
/** @var ModCon $mod */
|
157 |
$mod = $this->getMod();
|
163 |
];
|
164 |
}
|
165 |
|
166 |
+
private function ajaxExec_ProfileU2fAdd() :array {
|
167 |
+
/** @var ModCon $mod */
|
168 |
+
$mod = $this->getMod();
|
169 |
+
/** @var TwoFactor\Provider\U2F $provider */
|
170 |
+
$provider = $mod->getLoginIntentController()->getProviders()[ TwoFactor\Provider\U2F::SLUG ];
|
171 |
+
|
172 |
+
$u2fReg = Services::Request()->post( 'icwp_wpsf_new_u2f_response' );
|
173 |
+
if ( empty( $u2fReg ) ) {
|
174 |
+
$response = [
|
175 |
+
'success' => false,
|
176 |
+
'message' => __( 'U2F registration details were missing in the request.', 'wp-simple-firewall' ),
|
177 |
+
'page_reload' => true
|
178 |
+
];
|
179 |
+
}
|
180 |
+
else {
|
181 |
+
$result = $provider->addNewRegistration( Services::WpUsers()->getCurrentWpUser(), $u2fReg );
|
182 |
+
$response = [
|
183 |
+
'success' => $result->success,
|
184 |
+
'message' => $result->success ? $result->msg_text : $result->error_text,
|
185 |
+
'page_reload' => true
|
186 |
+
];
|
187 |
+
}
|
188 |
+
return $response;
|
189 |
+
}
|
190 |
+
|
191 |
private function ajaxExec_ProfileU2fRemove() :array {
|
192 |
/** @var ModCon $mod */
|
193 |
$mod = $this->getMod();
|
194 |
+
/** @var TwoFactor\Provider\U2F $provider */
|
195 |
+
$provider = $mod->getLoginIntentController()
|
196 |
+
->getProviders()[ TwoFactor\Provider\U2F::SLUG ];
|
197 |
|
198 |
$key = Services::Request()->post( 'u2fid' );
|
199 |
if ( !empty( $key ) ) {
|
200 |
+
$provider->removeRegisteredU2fId( Services::WpUsers()->getCurrentWpUser(), $key );
|
|
|
|
|
201 |
}
|
202 |
return [
|
203 |
'success' => !empty( $key ),
|
206 |
];
|
207 |
}
|
208 |
|
209 |
+
private function ajaxExec_UserYubikeyToggle() :array {
|
|
|
|
|
|
|
210 |
/** @var ModCon $mod */
|
211 |
$mod = $this->getMod();
|
212 |
+
/** @var TwoFactor\Provider\Yubikey $provider */
|
213 |
+
$provider = $mod->getLoginIntentController()
|
214 |
+
->getProviders()[ TwoFactor\Provider\Yubikey::SLUG ];
|
215 |
|
216 |
+
$otp = Services::Request()->post( 'otp', '' );
|
217 |
+
$result = $provider->toggleRegisteredYubiID( Services::WpUsers()->getCurrentWpUser(), $otp );
|
|
|
|
|
218 |
return [
|
219 |
+
'success' => $result->success,
|
220 |
+
'message' => $result->success ? $result->msg_text : $result->error_text,
|
221 |
'page_reload' => true
|
222 |
];
|
223 |
}
|
224 |
|
225 |
+
private function ajaxExec_ResendEmailVerification() :array {
|
|
|
|
|
|
|
226 |
/** @var ModCon $mod */
|
227 |
$mod = $this->getMod();
|
228 |
/** @var Options $opts */
|
230 |
$success = true;
|
231 |
|
232 |
if ( !$opts->isEnabledEmailAuth() ) {
|
233 |
+
$msg = __( 'Email 2FA option is not currently enabled.', 'wp-simple-firewall' );
|
234 |
$success = false;
|
235 |
}
|
236 |
elseif ( $opts->getIfCanSendEmailVerified() ) {
|
237 |
+
$msg = __( 'Email sending has already been verified.', 'wp-simple-firewall' );
|
238 |
}
|
239 |
else {
|
240 |
+
$msg = __( 'Verification email resent.', 'wp-simple-firewall' );
|
241 |
$mod->setIfCanSendEmail( false )
|
242 |
->sendEmailVerifyCanSend();
|
243 |
}
|
244 |
|
245 |
return [
|
246 |
'success' => $success,
|
247 |
+
'message' => $msg
|
248 |
];
|
249 |
}
|
250 |
}
|
src/lib/src/Modules/LoginGuard/Insights/OverviewCards.php
CHANGED
@@ -7,24 +7,16 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
-
|
11 |
/** @var LoginGuard\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var LoginGuard\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
16 |
-
$cardSection = [
|
17 |
-
'title' => __( 'Login Guard', 'wp-simple-firewall' ),
|
18 |
-
'subtitle' => __( 'Brute Force Protection & Identity Verification', 'wp-simple-firewall' ),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage()
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
-
if (
|
25 |
-
|
26 |
-
}
|
27 |
-
else {
|
28 |
$hasBotCheck = $opts->isEnabledAntiBot() || $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha();
|
29 |
|
30 |
$boLogin = $hasBotCheck && $opts->isProtectLogin();
|
@@ -67,7 +59,14 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
67 |
];
|
68 |
}
|
69 |
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
}
|
73 |
}
|
7 |
|
8 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
9 |
|
10 |
+
protected function buildModCards() :array {
|
11 |
/** @var LoginGuard\ModCon $mod */
|
12 |
$mod = $this->getMod();
|
13 |
/** @var LoginGuard\Options $opts */
|
14 |
$opts = $this->getOptions();
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
$cards = [];
|
17 |
|
18 |
+
if ( $mod->isModOptEnabled() ) {
|
19 |
+
|
|
|
|
|
20 |
$hasBotCheck = $opts->isEnabledAntiBot() || $opts->isEnabledGaspCheck() || $mod->isEnabledCaptcha();
|
21 |
|
22 |
$boLogin = $hasBotCheck && $opts->isProtectLogin();
|
59 |
];
|
60 |
}
|
61 |
|
62 |
+
return $cards;
|
63 |
+
}
|
64 |
+
|
65 |
+
protected function getSectionTitle() :string {
|
66 |
+
return __( 'Login Guard', 'wp-simple-firewall' );
|
67 |
+
}
|
68 |
+
|
69 |
+
protected function getSectionSubTitle() :string {
|
70 |
+
return __( 'Brute Force Protection & Identity Verification', 'wp-simple-firewall' );
|
71 |
}
|
72 |
}
|
src/lib/src/Modules/LoginGuard/Lib/AntiBot/AntibotSetup.php
CHANGED
@@ -2,17 +2,13 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
|
8 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib\Captcha\CaptchaConfigVO;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
-
class AntibotSetup {
|
13 |
-
|
14 |
-
use ModConsumer;
|
15 |
-
use ExecOnce;
|
16 |
|
17 |
protected function canRun() :bool {
|
18 |
return !Services::WpUsers()->isUserLoggedIn();
|
@@ -30,12 +26,7 @@ class AntibotSetup {
|
|
30 |
->setMod( $mod );
|
31 |
}
|
32 |
|
33 |
-
if (
|
34 |
-
$providers[] = ( new AntiBot\ProtectionProviders\AntiBot() )
|
35 |
-
->setMod( $mod );
|
36 |
-
}
|
37 |
-
else {
|
38 |
-
|
39 |
if ( $opts->isEnabledGaspCheck() ) {
|
40 |
$providers[] = ( new AntiBot\ProtectionProviders\GaspJs() )
|
41 |
->setMod( $mod );
|
@@ -96,7 +87,7 @@ class AntibotSetup {
|
|
96 |
}
|
97 |
|
98 |
foreach ( $formProviders as $form ) {
|
99 |
-
$form->setMod( $mod )->
|
100 |
}
|
101 |
}
|
102 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
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\Services\Services;
|
10 |
|
11 |
+
class AntibotSetup extends ExecOnceModConsumer {
|
|
|
|
|
|
|
12 |
|
13 |
protected function canRun() :bool {
|
14 |
return !Services::WpUsers()->isUserLoggedIn();
|
26 |
->setMod( $mod );
|
27 |
}
|
28 |
|
29 |
+
if ( !$opts->isEnabledAntiBot() ) {
|
|
|
|
|
|
|
|
|
|
|
30 |
if ( $opts->isEnabledGaspCheck() ) {
|
31 |
$providers[] = ( new AntiBot\ProtectionProviders\GaspJs() )
|
32 |
->setMod( $mod );
|
87 |
}
|
88 |
|
89 |
foreach ( $formProviders as $form ) {
|
90 |
+
$form->setMod( $mod )->execute();
|
91 |
}
|
92 |
}
|
93 |
}
|
src/lib/src/Modules/LoginGuard/Lib/AntiBot/FormProviders/BaseFormProvider.php
CHANGED
@@ -2,13 +2,13 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot\FormProviders;
|
4 |
|
|
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
-
abstract class BaseFormProvider {
|
10 |
-
|
11 |
-
use ModConsumer;
|
12 |
|
13 |
/**
|
14 |
* @var string
|
@@ -25,21 +25,21 @@ abstract class BaseFormProvider {
|
|
25 |
*/
|
26 |
private static $aProtectionProviders;
|
27 |
|
28 |
-
public static function SetProviders( array $
|
29 |
-
self::$aProtectionProviders = $
|
30 |
}
|
31 |
|
32 |
/**
|
33 |
-
* @return true
|
34 |
* @throws \Exception
|
35 |
*/
|
36 |
protected function checkProviders() {
|
37 |
-
|
38 |
-
|
39 |
-
$oProvider->performCheck( $this );
|
40 |
-
}
|
41 |
}
|
42 |
-
|
|
|
|
|
|
|
43 |
}
|
44 |
|
45 |
protected function checkThenDie() {
|
@@ -51,7 +51,7 @@ abstract class BaseFormProvider {
|
|
51 |
}
|
52 |
}
|
53 |
|
54 |
-
|
55 |
/** @var LoginGuard\Options $opts */
|
56 |
$opts = $this->getOptions();
|
57 |
if ( $opts->isProtectLogin() ) {
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\AntiBot\FormProviders;
|
4 |
|
5 |
+
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
+
abstract class BaseFormProvider extends ExecOnceModConsumer {
|
|
|
|
|
12 |
|
13 |
/**
|
14 |
* @var string
|
25 |
*/
|
26 |
private static $aProtectionProviders;
|
27 |
|
28 |
+
public static function SetProviders( array $providers ) {
|
29 |
+
self::$aProtectionProviders = $providers;
|
30 |
}
|
31 |
|
32 |
/**
|
|
|
33 |
* @throws \Exception
|
34 |
*/
|
35 |
protected function checkProviders() {
|
36 |
+
foreach ( $this->getProtectionProviders() as $provider ) {
|
37 |
+
$provider->performCheck( $this );
|
|
|
|
|
38 |
}
|
39 |
+
}
|
40 |
+
|
41 |
+
protected function getProtectionProviders() :array {
|
42 |
+
return is_array( self::$aProtectionProviders ) ? self::$aProtectionProviders : [];
|
43 |
}
|
44 |
|
45 |
protected function checkThenDie() {
|
51 |
}
|
52 |
}
|
53 |
|
54 |
+
protected function run() {
|
55 |
/** @var LoginGuard\Options $opts */
|
56 |
$opts = $this->getOptions();
|
57 |
if ( $opts->isProtectLogin() ) {
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php
CHANGED
@@ -19,12 +19,12 @@ class LoginIntentPage {
|
|
19 |
* @return string
|
20 |
*/
|
21 |
public function renderForm() {
|
22 |
-
$
|
23 |
/** @var LoginGuard\ModCon $mod */
|
24 |
-
$mod = $
|
25 |
/** @var LoginGuard\Options $opts */
|
26 |
-
$opts = $
|
27 |
-
$con = $
|
28 |
$req = Services::Request();
|
29 |
$WP = Services::WpGeneral();
|
30 |
|
@@ -83,7 +83,7 @@ class LoginIntentPage {
|
|
83 |
function ( $oProvider ) {
|
84 |
return $oProvider->getFormField();
|
85 |
},
|
86 |
-
$
|
87 |
) ),
|
88 |
'time_remaining' => $nTimeRemaining,
|
89 |
'message_type' => 'info',
|
@@ -96,7 +96,7 @@ class LoginIntentPage {
|
|
96 |
],
|
97 |
'flags' => [
|
98 |
'can_skip_mfa' => $opts->isMfaSkip(),
|
99 |
-
'show_branded_links' => !$
|
100 |
]
|
101 |
];
|
102 |
|
@@ -137,7 +137,7 @@ class LoginIntentPage {
|
|
137 |
'favicon' => $con->urls->forImage( 'pluginlogo_24x24.png' ),
|
138 |
],
|
139 |
'flags' => [
|
140 |
-
'show_branded_links' => !$
|
141 |
'has_u2f' => isset( $oIC->getProvidersForUser(
|
142 |
Services::WpUsers()->getCurrentWpUser(), true )[ LoginGuard\Lib\TwoFactor\Provider\U2F::SLUG ] )
|
143 |
],
|
@@ -154,7 +154,7 @@ class LoginIntentPage {
|
|
154 |
'src' => $con->urls->forJs( 'u2f-bundle.js' ),
|
155 |
],
|
156 |
[
|
157 |
-
'src' => $con->urls->forJs( 'u2f
|
158 |
]
|
159 |
]
|
160 |
];
|
19 |
* @return string
|
20 |
*/
|
21 |
public function renderForm() {
|
22 |
+
$mfaCon = $this->getMfaCon();
|
23 |
/** @var LoginGuard\ModCon $mod */
|
24 |
+
$mod = $mfaCon->getMod();
|
25 |
/** @var LoginGuard\Options $opts */
|
26 |
+
$opts = $mfaCon->getOptions();
|
27 |
+
$con = $mfaCon->getCon();
|
28 |
$req = Services::Request();
|
29 |
$WP = Services::WpGeneral();
|
30 |
|
83 |
function ( $oProvider ) {
|
84 |
return $oProvider->getFormField();
|
85 |
},
|
86 |
+
$mfaCon->getProvidersForUser( Services::WpUsers()->getCurrentWpUser(), true )
|
87 |
) ),
|
88 |
'time_remaining' => $nTimeRemaining,
|
89 |
'message_type' => 'info',
|
96 |
],
|
97 |
'flags' => [
|
98 |
'can_skip_mfa' => $opts->isMfaSkip(),
|
99 |
+
'show_branded_links' => !$con->getModule_SecAdmin()->getWhiteLabelController()->isEnabled(),
|
100 |
]
|
101 |
];
|
102 |
|
137 |
'favicon' => $con->urls->forImage( 'pluginlogo_24x24.png' ),
|
138 |
],
|
139 |
'flags' => [
|
140 |
+
'show_branded_links' => !$con->getModule_SecAdmin()->getWhiteLabelController()->isEnabled(),
|
141 |
'has_u2f' => isset( $oIC->getProvidersForUser(
|
142 |
Services::WpUsers()->getCurrentWpUser(), true )[ LoginGuard\Lib\TwoFactor\Provider\U2F::SLUG ] )
|
143 |
],
|
154 |
'src' => $con->urls->forJs( 'u2f-bundle.js' ),
|
155 |
],
|
156 |
[
|
157 |
+
'src' => $con->urls->forJs( 'login/u2f.js' ),
|
158 |
]
|
159 |
]
|
160 |
];
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor;
|
4 |
|
|
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Update;
|
@@ -18,7 +19,7 @@ class MfaController {
|
|
18 |
/**
|
19 |
* @var Provider\BaseProvider[]
|
20 |
*/
|
21 |
-
private $
|
22 |
|
23 |
/**
|
24 |
* @var LoginIntentPage
|
@@ -26,8 +27,8 @@ class MfaController {
|
|
26 |
private $oLoginIntentPageHandler;
|
27 |
|
28 |
protected function run() {
|
29 |
-
add_action( 'init', [ $this, 'onWpInit' ]
|
30 |
-
add_action( 'wp_loaded', [ $this, 'onWpLoaded' ]
|
31 |
$this->setupLoginCaptureHooks();
|
32 |
$this->handleLoginLink();
|
33 |
}
|
@@ -43,6 +44,7 @@ class MfaController {
|
|
43 |
( new UserProfile() )
|
44 |
->setMfaController( $this )
|
45 |
->run();
|
|
|
46 |
|
47 |
add_shortcode( 'SHIELD_2FA_LOGIN', function () {
|
48 |
return $this->getLoginIntentPageHandler()->renderForm();
|
@@ -59,7 +61,7 @@ class MfaController {
|
|
59 |
if ( $this->isSubjectToLoginIntent( $user )
|
60 |
&& !Services::WpUsers()->isAppPasswordAuth() && !$this->canUserMfaSkip( $user ) ) {
|
61 |
|
62 |
-
$providers = $this->getProvidersForUser( $user );
|
63 |
if ( !empty( $providers ) ) {
|
64 |
foreach ( $providers as $provider ) {
|
65 |
$provider->captureLoginAttempt( $user );
|
@@ -87,16 +89,21 @@ class MfaController {
|
|
87 |
} );
|
88 |
}
|
89 |
|
|
|
|
|
|
|
90 |
private function processEmail2faLink() {
|
91 |
$req = Services::Request();
|
92 |
$user = sanitize_user( $req->query( 'user' ) );
|
93 |
if ( empty( $user ) ) {
|
94 |
throw new \Exception( 'Not valid data.' );
|
95 |
}
|
|
|
96 |
$user = Services::WpUsers()->getUserByUsername( $user );
|
97 |
if ( !$user instanceof \WP_User ) {
|
98 |
throw new \Exception( 'Not valid data.' );
|
99 |
}
|
|
|
100 |
$providers = $this->getProvidersForUser( $user, true );
|
101 |
if ( !isset( $providers[ Provider\Email::SLUG ] ) ) {
|
102 |
throw new \Exception( 'Not a support provider' );
|
@@ -104,6 +111,7 @@ class MfaController {
|
|
104 |
if ( !$providers[ Provider\Email::SLUG ]->validateLoginIntent( $user ) ) {
|
105 |
throw new \Exception( 'Login validation failed.' );
|
106 |
}
|
|
|
107 |
$providers[ Provider\Email::SLUG ]->postSuccessActions( $user );
|
108 |
if ( (int)$user->ID !== (int)Services::WpUsers()->getCurrentWpUserId() ) {
|
109 |
throw new \Exception( 'Action completed successfully. Please refresh your browser where you logged-in.' );
|
@@ -149,38 +157,43 @@ class MfaController {
|
|
149 |
* @return Provider\BaseProvider[]
|
150 |
*/
|
151 |
public function getProviders() :array {
|
152 |
-
if ( !is_array( $this->
|
153 |
-
$this->
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
|
|
|
|
|
|
|
|
|
|
160 |
}
|
161 |
-
return $this->
|
162 |
}
|
163 |
|
164 |
/**
|
165 |
* Ensures that BackupCode provider isn't supplied on its own, and the user profile is setup for each.
|
166 |
* @param \WP_User $user
|
167 |
-
* @param bool $
|
168 |
* @return Provider\BaseProvider[]
|
169 |
*/
|
170 |
-
public function getProvidersForUser( $user, $
|
171 |
$Ps = array_filter( $this->getProviders(),
|
172 |
-
function ( $
|
173 |
-
/** @var Provider\BaseProvider $
|
174 |
-
return $
|
175 |
-
&& ( !$
|
176 |
}
|
177 |
);
|
178 |
|
179 |
// Neither BackupCode NOR U2F should EVER be the only 1 provider available.
|
180 |
if ( count( $Ps ) === 1 ) {
|
181 |
-
/** @var Provider\BaseProvider $
|
182 |
-
$
|
183 |
-
if ( !$
|
184 |
$Ps = [];
|
185 |
}
|
186 |
}
|
@@ -245,9 +258,8 @@ class MfaController {
|
|
245 |
|
246 |
/**
|
247 |
* assume that a user is logged in.
|
248 |
-
* @return bool
|
249 |
*/
|
250 |
-
private function validateLoginIntentRequest() {
|
251 |
try {
|
252 |
$valid = ( new ValidateLoginIntentRequest() )
|
253 |
->setMfaController( $this )
|
@@ -278,6 +290,27 @@ class MfaController {
|
|
278 |
return count( $this->getProvidersForUser( $user, true ) ) > 0;
|
279 |
}
|
280 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
private function getLoginIntentExpiresAt() :int {
|
282 |
return $this->getCon()
|
283 |
->getModule_Sessions()
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor;
|
4 |
|
5 |
+
use FernleafSystems\Utilities\Data\Response\StdResponse;
|
6 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Update;
|
19 |
/**
|
20 |
* @var Provider\BaseProvider[]
|
21 |
*/
|
22 |
+
private $providers;
|
23 |
|
24 |
/**
|
25 |
* @var LoginIntentPage
|
27 |
private $oLoginIntentPageHandler;
|
28 |
|
29 |
protected function run() {
|
30 |
+
add_action( 'init', [ $this, 'onWpInit' ] );
|
31 |
+
add_action( 'wp_loaded', [ $this, 'onWpLoaded' ] );
|
32 |
$this->setupLoginCaptureHooks();
|
33 |
$this->handleLoginLink();
|
34 |
}
|
44 |
( new UserProfile() )
|
45 |
->setMfaController( $this )
|
46 |
->run();
|
47 |
+
( new MfaProfilesController() )->setMfaController( $this )->execute();
|
48 |
|
49 |
add_shortcode( 'SHIELD_2FA_LOGIN', function () {
|
50 |
return $this->getLoginIntentPageHandler()->renderForm();
|
61 |
if ( $this->isSubjectToLoginIntent( $user )
|
62 |
&& !Services::WpUsers()->isAppPasswordAuth() && !$this->canUserMfaSkip( $user ) ) {
|
63 |
|
64 |
+
$providers = $this->getProvidersForUser( $user, true );
|
65 |
if ( !empty( $providers ) ) {
|
66 |
foreach ( $providers as $provider ) {
|
67 |
$provider->captureLoginAttempt( $user );
|
89 |
} );
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* @throws \Exception
|
94 |
+
*/
|
95 |
private function processEmail2faLink() {
|
96 |
$req = Services::Request();
|
97 |
$user = sanitize_user( $req->query( 'user' ) );
|
98 |
if ( empty( $user ) ) {
|
99 |
throw new \Exception( 'Not valid data.' );
|
100 |
}
|
101 |
+
|
102 |
$user = Services::WpUsers()->getUserByUsername( $user );
|
103 |
if ( !$user instanceof \WP_User ) {
|
104 |
throw new \Exception( 'Not valid data.' );
|
105 |
}
|
106 |
+
|
107 |
$providers = $this->getProvidersForUser( $user, true );
|
108 |
if ( !isset( $providers[ Provider\Email::SLUG ] ) ) {
|
109 |
throw new \Exception( 'Not a support provider' );
|
111 |
if ( !$providers[ Provider\Email::SLUG ]->validateLoginIntent( $user ) ) {
|
112 |
throw new \Exception( 'Login validation failed.' );
|
113 |
}
|
114 |
+
|
115 |
$providers[ Provider\Email::SLUG ]->postSuccessActions( $user );
|
116 |
if ( (int)$user->ID !== (int)Services::WpUsers()->getCurrentWpUserId() ) {
|
117 |
throw new \Exception( 'Action completed successfully. Please refresh your browser where you logged-in.' );
|
157 |
* @return Provider\BaseProvider[]
|
158 |
*/
|
159 |
public function getProviders() :array {
|
160 |
+
if ( !is_array( $this->providers ) ) {
|
161 |
+
$this->providers = array_map(
|
162 |
+
function ( $provider ) {
|
163 |
+
return $provider->setMod( $this->getMod() );
|
164 |
+
},
|
165 |
+
[
|
166 |
+
Provider\Email::SLUG => new Provider\Email(),
|
167 |
+
Provider\GoogleAuth::SLUG => new Provider\GoogleAuth(),
|
168 |
+
Provider\Yubikey::SLUG => new Provider\Yubikey(),
|
169 |
+
Provider\BackupCodes::SLUG => new Provider\BackupCodes(),
|
170 |
+
Provider\U2F::SLUG => new Provider\U2F(),
|
171 |
+
]
|
172 |
+
);
|
173 |
}
|
174 |
+
return $this->providers;
|
175 |
}
|
176 |
|
177 |
/**
|
178 |
* Ensures that BackupCode provider isn't supplied on its own, and the user profile is setup for each.
|
179 |
* @param \WP_User $user
|
180 |
+
* @param bool $onlyActiveProfiles
|
181 |
* @return Provider\BaseProvider[]
|
182 |
*/
|
183 |
+
public function getProvidersForUser( \WP_User $user, $onlyActiveProfiles = false ) :array {
|
184 |
$Ps = array_filter( $this->getProviders(),
|
185 |
+
function ( $provider ) use ( $user, $onlyActiveProfiles ) {
|
186 |
+
/** @var Provider\BaseProvider $provider */
|
187 |
+
return $provider->isProviderAvailableToUser( $user )
|
188 |
+
&& ( !$onlyActiveProfiles || $provider->isProfileActive( $user ) );
|
189 |
}
|
190 |
);
|
191 |
|
192 |
// Neither BackupCode NOR U2F should EVER be the only 1 provider available.
|
193 |
if ( count( $Ps ) === 1 ) {
|
194 |
+
/** @var Provider\BaseProvider $first */
|
195 |
+
$first = reset( $Ps );
|
196 |
+
if ( !$first::STANDALONE ) {
|
197 |
$Ps = [];
|
198 |
}
|
199 |
}
|
258 |
|
259 |
/**
|
260 |
* assume that a user is logged in.
|
|
|
261 |
*/
|
262 |
+
private function validateLoginIntentRequest() :bool {
|
263 |
try {
|
264 |
$valid = ( new ValidateLoginIntentRequest() )
|
265 |
->setMfaController( $this )
|
290 |
return count( $this->getProvidersForUser( $user, true ) ) > 0;
|
291 |
}
|
292 |
|
293 |
+
public function removeAllFactorsForUser( int $userID ) :StdResponse {
|
294 |
+
$result = new StdResponse();
|
295 |
+
|
296 |
+
$user = Services::WpUsers()->getUserById( $userID );
|
297 |
+
if ( $user instanceof \WP_User ) {
|
298 |
+
foreach ( $this->getProvidersForUser( $user, true ) as $provider ) {
|
299 |
+
$provider->remove( $user );
|
300 |
+
}
|
301 |
+
$result->success = true;
|
302 |
+
$result->msg_text = sprintf( __( 'All MFA providers removed from user with ID %s.' ),
|
303 |
+
$userID );
|
304 |
+
}
|
305 |
+
else {
|
306 |
+
$result->success = false;
|
307 |
+
$result->error_text = sprintf( __( "User doesn't exist with ID %s." ),
|
308 |
+
$userID );
|
309 |
+
}
|
310 |
+
|
311 |
+
return $result;
|
312 |
+
}
|
313 |
+
|
314 |
private function getLoginIntentExpiresAt() :int {
|
315 |
return $this->getCon()
|
316 |
->getModule_Sessions()
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/MfaProfilesController.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor;
|
4 |
+
|
5 |
+
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
8 |
+
use FernleafSystems\Wordpress\Services\Services;
|
9 |
+
|
10 |
+
class MfaProfilesController {
|
11 |
+
|
12 |
+
use MfaControllerConsumer;
|
13 |
+
use ExecOnce;
|
14 |
+
|
15 |
+
private $rendered = false;
|
16 |
+
|
17 |
+
private $isFrontend = false;
|
18 |
+
|
19 |
+
protected function run() {
|
20 |
+
$this->defineShortcodes();
|
21 |
+
if ( Services::WpUsers()->isUserLoggedIn() ) {
|
22 |
+
add_action( 'wp', function () {
|
23 |
+
$this->enqueueAssets( true );
|
24 |
+
} );
|
25 |
+
add_action( 'admin_init', function () {
|
26 |
+
$this->enqueueAssets( false );
|
27 |
+
} );
|
28 |
+
}
|
29 |
+
}
|
30 |
+
|
31 |
+
private function enqueueAssets( bool $isFrontend ) {
|
32 |
+
$this->isFrontend = $isFrontend;
|
33 |
+
add_filter( 'shield/custom_enqueues', function ( array $enqueues, $hook = '' ) {
|
34 |
+
|
35 |
+
if ( $this->isFrontend || in_array( $hook, [ 'profile.php', 'user-edit.php' ] ) ) {
|
36 |
+
$enqueues[ Enqueue::JS ][] = 'shield/userprofile';
|
37 |
+
$enqueues[ Enqueue::CSS ][] = 'shield/dialog';
|
38 |
+
|
39 |
+
if ( $this->isFrontend ) {
|
40 |
+
add_filter( 'shield/custom_dequeues', function ( $assets ) {
|
41 |
+
if ( !$this->rendered ) {
|
42 |
+
$assets[ Enqueue::JS ][] = 'shield/userprofile';
|
43 |
+
$assets[ Enqueue::CSS ][] = 'shield/dialog';
|
44 |
+
}
|
45 |
+
return $assets;
|
46 |
+
} );
|
47 |
+
}
|
48 |
+
|
49 |
+
add_filter( 'shield/custom_localisations', function ( array $localz ) {
|
50 |
+
$mfaCon = $this->getMfaCon();
|
51 |
+
$user = Services::WpUsers()->getCurrentWpUser();
|
52 |
+
$providers = $user instanceof \WP_User ? $mfaCon->getProvidersForUser( $user ) : [];
|
53 |
+
$localz[] = [
|
54 |
+
'shield/userprofile',
|
55 |
+
'shield_vars_userprofile',
|
56 |
+
[
|
57 |
+
'ajax' => [
|
58 |
+
'mfa_remove_all' => $mfaCon->getMod()->getAjaxActionData( 'mfa_remove_all' )
|
59 |
+
],
|
60 |
+
'vars' => [
|
61 |
+
'providers' => array_map( function ( $provider ) {
|
62 |
+
return $provider->getJavascriptVars();
|
63 |
+
}, $providers )
|
64 |
+
],
|
65 |
+
'strings' => [
|
66 |
+
'are_you_sure' => __( 'Are you sure?', 'wp-simple-firewall' )
|
67 |
+
],
|
68 |
+
]
|
69 |
+
];
|
70 |
+
return $localz;
|
71 |
+
} );
|
72 |
+
}
|
73 |
+
|
74 |
+
return $enqueues;
|
75 |
+
}, 10, $this->isFrontend ? 1 : 2 );
|
76 |
+
}
|
77 |
+
|
78 |
+
private function loadUserProfileMFA( $attributes = [] ) :string {
|
79 |
+
$this->rendered = true;
|
80 |
+
return ( new Profiles\RenderCustomForms() )
|
81 |
+
->setMfaController( $this->getMfaCon() )
|
82 |
+
->setWpUser( Services::WpUsers()->getCurrentWpUser() )
|
83 |
+
->render( is_array( $attributes ) ? $attributes : [] );
|
84 |
+
}
|
85 |
+
|
86 |
+
private function defineShortcodes() {
|
87 |
+
if ( $this->getMfaCon()->getCon()->isPremiumActive() ) {
|
88 |
+
add_shortcode( 'SHIELD_USER_PROFILE_MFA', function ( $attributes ) {
|
89 |
+
return $this->loadUserProfileMFA( $attributes );
|
90 |
+
} );
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/CustomForms.php
DELETED
@@ -1,67 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Profiles;
|
4 |
-
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
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 ExecOnce;
|
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 |
-
$user = $this->getWpUser();
|
40 |
-
|
41 |
-
$aProviders = $oMC->getProvidersForUser( $user, 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/Lib/TwoFactor/Profiles/RenderCustomForms.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Profiles;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\MfaControllerConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpUserConsumer;
|
7 |
+
|
8 |
+
class RenderCustomForms {
|
9 |
+
|
10 |
+
use MfaControllerConsumer;
|
11 |
+
use WpUserConsumer;
|
12 |
+
|
13 |
+
private $attributes;
|
14 |
+
|
15 |
+
public function render( array $attributes ) :string {
|
16 |
+
$this->attributes = $attributes;
|
17 |
+
return $this->getMfaCon()
|
18 |
+
->getMod()
|
19 |
+
->renderTemplate( '/user/profile/mfa/main.twig', $this->buildRenderData() );
|
20 |
+
}
|
21 |
+
|
22 |
+
private function buildRenderData() :array {
|
23 |
+
$mfaCon = $this->getMfaCon();
|
24 |
+
$con = $mfaCon->getCon();
|
25 |
+
$pluginName = $con->getHumanName();
|
26 |
+
|
27 |
+
$user = $this->getWpUser();
|
28 |
+
$providers = $user instanceof \WP_User ? $mfaCon->getProvidersForUser( $user ) : [];
|
29 |
+
$providerRenders = $user instanceof \WP_User ?
|
30 |
+
array_map( function ( $provider ) {
|
31 |
+
return $provider->renderUserProfileCustomForm( $this->getWpUser() );
|
32 |
+
}, $providers )
|
33 |
+
: [];
|
34 |
+
|
35 |
+
$data = [
|
36 |
+
'content' => [
|
37 |
+
'providers' => $providerRenders,
|
38 |
+
],
|
39 |
+
'flags' => [
|
40 |
+
'has_providers' => !empty( $providers ),
|
41 |
+
'logged_in' => $user instanceof \WP_User,
|
42 |
+
],
|
43 |
+
'strings' => [
|
44 |
+
'title' => sprintf( __( '%s MFA Options', 'wp-simple-firewall' ), $pluginName ),
|
45 |
+
'not_logged_in' => __( 'Not currently logged-in.', 'wp-simple-firewall' ),
|
46 |
+
'no_providers' => __( 'There are currently no 2FA providers available on your account.', 'wp-simple-firewall' ),
|
47 |
+
],
|
48 |
+
'vars' => [
|
49 |
+
'provider_data' => ''
|
50 |
+
],
|
51 |
+
];
|
52 |
+
|
53 |
+
return apply_filters( 'shield/render_data_custom_profiles_mfa', $data );
|
54 |
+
}
|
55 |
+
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/{Backup.php → BackupCodes.php}
RENAMED
@@ -5,15 +5,27 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFact
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
6 |
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
-
class
|
9 |
|
10 |
const SLUG = 'backupcode';
|
11 |
const STANDALONE = false;
|
12 |
|
13 |
-
public function
|
14 |
-
|
|
|
15 |
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
'strings' => [
|
18 |
'button_gen_code' => __( 'Generate ONE-Time Backup 2FA Login Code', 'wp-simple-firewall' ),
|
19 |
'button_del_code' => __( 'Delete Login Backup Code', 'wp-simple-firewall' ),
|
@@ -28,30 +40,17 @@ class Backup extends BaseProvider {
|
|
28 |
'title' => __( 'Backup Login Code', 'wp-simple-firewall' ),
|
29 |
'cant_add_other_user' => sprintf( __( "Sorry, %s may not be added to another user's account.", 'wp-simple-firewall' ), 'Backup Codes' ),
|
30 |
'cant_remove_admins' => sprintf( __( "Sorry, %s may only be removed from another user's account by a Security Administrator.", 'wp-simple-firewall' ), __( 'Backup Codes', 'wp-simple-firewall' ) ),
|
31 |
-
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $
|
|
|
32 |
'remove_more_info' => sprintf( __( 'Understand how to remove Google Authenticator', 'wp-simple-firewall' ) )
|
33 |
]
|
34 |
];
|
35 |
-
|
36 |
-
return $this->getMod()
|
37 |
-
->renderTemplate(
|
38 |
-
'/snippets/user/profile/mfa/mfa_backup.twig',
|
39 |
-
Services::DataManipulation()->mergeArraysRecursive( $this->getCommonData( $user ), $aData ),
|
40 |
-
true
|
41 |
-
);
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* @inheritDoc
|
46 |
-
*/
|
47 |
-
public function renderUserEditProfileOptions( \WP_User $user ) {
|
48 |
-
// Allow no actions to be taken on other user profiles
|
49 |
}
|
50 |
|
51 |
/**
|
52 |
* @return array
|
53 |
*/
|
54 |
-
public function getFormField() {
|
55 |
return [
|
56 |
'name' => $this->getLoginFormParameter(),
|
57 |
'type' => 'text',
|
@@ -137,22 +136,23 @@ class Backup extends BaseProvider {
|
|
137 |
* @param \WP_User $user
|
138 |
*/
|
139 |
private function sendBackupCodeUsedEmail( \WP_User $user ) {
|
140 |
-
$aEmailContent = [
|
141 |
-
__( 'This is a quick notice to inform you that your Backup Login code was just used.', 'wp-simple-firewall' ),
|
142 |
-
__( "Your WordPress account had only 1 backup login code.", 'wp-simple-firewall' )
|
143 |
-
.' '.__( "You must go to your profile and regenerate a new code if you want to use this method again.", 'wp-simple-firewall' ),
|
144 |
-
'',
|
145 |
-
sprintf( '<strong>%s</strong>', __( 'Login Details', 'wp-simple-firewall' ) ),
|
146 |
-
sprintf( '%s: %s', __( 'URL', 'wp-simple-firewall' ), Services::WpGeneral()->getHomeUrl() ),
|
147 |
-
sprintf( '%s: %s', __( 'Username', 'wp-simple-firewall' ), $user->user_login ),
|
148 |
-
sprintf( '%s: %s', __( 'IP Address', 'wp-simple-firewall' ), Services::IP()->getRequestIp() ),
|
149 |
-
'',
|
150 |
-
__( 'Thank You.', 'wp-simple-firewall' ),
|
151 |
-
];
|
152 |
-
|
153 |
-
$sTitle = sprintf( __( "Notice: %s", 'wp-simple-firewall' ), __( "Backup Login Code Just Used", 'wp-simple-firewall' ) );
|
154 |
$this->getMod()
|
155 |
->getEmailProcessor()
|
156 |
-
->sendEmailWithWrap(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
}
|
158 |
}
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
6 |
use FernleafSystems\Wordpress\Services\Services;
|
7 |
|
8 |
+
class BackupCodes extends BaseProvider {
|
9 |
|
10 |
const SLUG = 'backupcode';
|
11 |
const STANDALONE = false;
|
12 |
|
13 |
+
public function getProviderName() :string {
|
14 |
+
return 'Backup Codes';
|
15 |
+
}
|
16 |
|
17 |
+
public function getJavascriptVars() :array {
|
18 |
+
return [
|
19 |
+
'ajax' => [
|
20 |
+
'gen_backup_codes' => $this->getMod()->getAjaxActionData( 'gen_backup_codes' ),
|
21 |
+
'del_backup_codes' => $this->getMod()->getAjaxActionData( 'del_backup_codes' ),
|
22 |
+
],
|
23 |
+
];
|
24 |
+
}
|
25 |
+
|
26 |
+
protected function getProviderSpecificRenderData( \WP_User $user ) :array {
|
27 |
+
error_log( var_export( $this->hasValidatedProfile( $user ), true ) );
|
28 |
+
return [
|
29 |
'strings' => [
|
30 |
'button_gen_code' => __( 'Generate ONE-Time Backup 2FA Login Code', 'wp-simple-firewall' ),
|
31 |
'button_del_code' => __( 'Delete Login Backup Code', 'wp-simple-firewall' ),
|
40 |
'title' => __( 'Backup Login Code', 'wp-simple-firewall' ),
|
41 |
'cant_add_other_user' => sprintf( __( "Sorry, %s may not be added to another user's account.", 'wp-simple-firewall' ), 'Backup Codes' ),
|
42 |
'cant_remove_admins' => sprintf( __( "Sorry, %s may only be removed from another user's account by a Security Administrator.", 'wp-simple-firewall' ), __( 'Backup Codes', 'wp-simple-firewall' ) ),
|
43 |
+
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $this->getCon()
|
44 |
+
->getHumanName() ),
|
45 |
'remove_more_info' => sprintf( __( 'Understand how to remove Google Authenticator', 'wp-simple-firewall' ) )
|
46 |
]
|
47 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
* @return array
|
52 |
*/
|
53 |
+
public function getFormField() :array {
|
54 |
return [
|
55 |
'name' => $this->getLoginFormParameter(),
|
56 |
'type' => 'text',
|
136 |
* @param \WP_User $user
|
137 |
*/
|
138 |
private function sendBackupCodeUsedEmail( \WP_User $user ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
$this->getMod()
|
140 |
->getEmailProcessor()
|
141 |
+
->sendEmailWithWrap(
|
142 |
+
$user->user_email,
|
143 |
+
sprintf( __( "Notice: %s", 'wp-simple-firewall' ), __( "Backup Login Code Just Used", 'wp-simple-firewall' ) ),
|
144 |
+
[
|
145 |
+
__( 'This is a quick notice to inform you that your Backup Login code was just used.', 'wp-simple-firewall' ),
|
146 |
+
__( "Your WordPress account had only 1 backup login code.", 'wp-simple-firewall' )
|
147 |
+
.' '.__( "You must go to your profile and regenerate a new code if you want to use this method again.", 'wp-simple-firewall' ),
|
148 |
+
'',
|
149 |
+
sprintf( '<strong>%s</strong>', __( 'Login Details', 'wp-simple-firewall' ) ),
|
150 |
+
sprintf( '%s: %s', __( 'URL', 'wp-simple-firewall' ), Services::WpGeneral()->getHomeUrl() ),
|
151 |
+
sprintf( '%s: %s', __( 'Username', 'wp-simple-firewall' ), $user->user_login ),
|
152 |
+
sprintf( '%s: %s', __( 'IP Address', 'wp-simple-firewall' ), Services::IP()->getRequestIp() ),
|
153 |
+
'',
|
154 |
+
__( 'Thank You.', 'wp-simple-firewall' ),
|
155 |
+
]
|
156 |
+
);
|
157 |
}
|
158 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php
CHANGED
@@ -23,9 +23,12 @@ abstract class BaseProvider {
|
|
23 |
public function __construct() {
|
24 |
}
|
25 |
|
26 |
-
public function
|
|
|
27 |
}
|
28 |
|
|
|
|
|
29 |
/**
|
30 |
* Assumes this is only called on active profiles
|
31 |
* @param \WP_User $user
|
@@ -108,14 +111,20 @@ abstract class BaseProvider {
|
|
108 |
return $sNewSecret;
|
109 |
}
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
/**
|
112 |
* @param \WP_User $user
|
113 |
-
* @param bool $
|
114 |
* @return $this
|
115 |
*/
|
116 |
-
public function setProfileValidated( $user, $
|
117 |
$this->getCon()
|
118 |
-
->getUserMeta( $user )->{static::SLUG.'_validated'} = $
|
119 |
return $this;
|
120 |
}
|
121 |
|
@@ -156,16 +165,48 @@ abstract class BaseProvider {
|
|
156 |
* @return string
|
157 |
*/
|
158 |
public function renderUserProfileOptions( \WP_User $user ) :string {
|
159 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
}
|
161 |
|
162 |
/**
|
163 |
* ONLY TO BE HOOKED TO USER PROFILE EDIT
|
164 |
* @param \WP_User $user
|
165 |
* @return string
|
|
|
166 |
*/
|
167 |
public function renderUserEditProfileOptions( \WP_User $user ) {
|
168 |
-
return
|
169 |
}
|
170 |
|
171 |
/**
|
@@ -191,10 +232,7 @@ abstract class BaseProvider {
|
|
191 |
public function captureLoginAttempt( \WP_User $user ) {
|
192 |
}
|
193 |
|
194 |
-
|
195 |
-
* @return array
|
196 |
-
*/
|
197 |
-
public function getFormField() {
|
198 |
return [];
|
199 |
}
|
200 |
|
@@ -224,25 +262,21 @@ abstract class BaseProvider {
|
|
224 |
return trim( Services::Request()->request( $this->getLoginFormParameter(), false, '' ) );
|
225 |
}
|
226 |
|
227 |
-
|
228 |
-
* @param \WP_User $user
|
229 |
-
* @return array
|
230 |
-
*/
|
231 |
-
protected function getCommonData( \WP_User $user ) {
|
232 |
return [
|
233 |
'flags' => [
|
234 |
'has_validated_profile' => $this->hasValidatedProfile( $user ),
|
235 |
'is_enforced' => $this->isEnforced( $user ),
|
236 |
'is_profile_active' => $this->isProfileActive( $user ),
|
237 |
-
'is_my_user_profile' => $user->ID == Services::WpUsers()->getCurrentWpUserId(),
|
238 |
-
'i_am_valid_admin' => $this->getCon()->isPluginAdmin(),
|
239 |
'user_to_edit_is_admin' => Services::WpUsers()->isUserAdmin( $user ),
|
|
|
240 |
],
|
241 |
'vars' => [
|
242 |
'otp_field_name' => $this->getLoginFormParameter(),
|
243 |
],
|
244 |
'strings' => [
|
245 |
-
'is_enforced'
|
|
|
246 |
],
|
247 |
];
|
248 |
}
|
23 |
public function __construct() {
|
24 |
}
|
25 |
|
26 |
+
public function getJavascriptVars() :array {
|
27 |
+
return [];
|
28 |
}
|
29 |
|
30 |
+
abstract public function getProviderName() :string;
|
31 |
+
|
32 |
/**
|
33 |
* Assumes this is only called on active profiles
|
34 |
* @param \WP_User $user
|
111 |
return $sNewSecret;
|
112 |
}
|
113 |
|
114 |
+
public function remove( \WP_User $user ) {
|
115 |
+
$meta = $this->getCon()->getUserMeta( $user );
|
116 |
+
$meta->{static::SLUG.'_secret'} = null;
|
117 |
+
$this->setProfileValidated( $user, false );
|
118 |
+
}
|
119 |
+
|
120 |
/**
|
121 |
* @param \WP_User $user
|
122 |
+
* @param bool $validated set true for validated, false for invalidated
|
123 |
* @return $this
|
124 |
*/
|
125 |
+
public function setProfileValidated( $user, $validated = true ) {
|
126 |
$this->getCon()
|
127 |
+
->getUserMeta( $user )->{static::SLUG.'_validated'} = $validated;
|
128 |
return $this;
|
129 |
}
|
130 |
|
165 |
* @return string
|
166 |
*/
|
167 |
public function renderUserProfileOptions( \WP_User $user ) :string {
|
168 |
+
return $this->getMod()
|
169 |
+
->renderTemplate(
|
170 |
+
sprintf( '/admin/user/profile/mfa/mfa_%s.twig', static::SLUG ),
|
171 |
+
$this->getProfileRenderData( $user )
|
172 |
+
);
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
177 |
+
* functions. Otherwise we need to be careful of mixing up users.
|
178 |
+
* @param \WP_User $user
|
179 |
+
* @return string
|
180 |
+
*/
|
181 |
+
public function renderUserProfileCustomForm( \WP_User $user ) :string {
|
182 |
+
$data = $this->getProfileRenderData( $user );
|
183 |
+
$data[ 'flags' ][ 'show_explanatory_text' ] = false;
|
184 |
+
return $this->getMod()
|
185 |
+
->renderTemplate(
|
186 |
+
sprintf( '/user/profile/mfa/provider_%s.twig', static::SLUG ),
|
187 |
+
$data
|
188 |
+
);
|
189 |
+
}
|
190 |
+
|
191 |
+
public function getProfileRenderData( \WP_User $user ) :array {
|
192 |
+
return Services::DataManipulation()->mergeArraysRecursive(
|
193 |
+
$this->getCommonData( $user ),
|
194 |
+
$this->getProviderSpecificRenderData( $user )
|
195 |
+
);
|
196 |
+
}
|
197 |
+
|
198 |
+
protected function getProviderSpecificRenderData( \WP_User $user ) :array {
|
199 |
+
return [];
|
200 |
}
|
201 |
|
202 |
/**
|
203 |
* ONLY TO BE HOOKED TO USER PROFILE EDIT
|
204 |
* @param \WP_User $user
|
205 |
* @return string
|
206 |
+
* @deprecated 11.2
|
207 |
*/
|
208 |
public function renderUserEditProfileOptions( \WP_User $user ) {
|
209 |
+
return '';
|
210 |
}
|
211 |
|
212 |
/**
|
232 |
public function captureLoginAttempt( \WP_User $user ) {
|
233 |
}
|
234 |
|
235 |
+
public function getFormField() :array {
|
|
|
|
|
|
|
236 |
return [];
|
237 |
}
|
238 |
|
262 |
return trim( Services::Request()->request( $this->getLoginFormParameter(), false, '' ) );
|
263 |
}
|
264 |
|
265 |
+
protected function getCommonData( \WP_User $user ) :array {
|
|
|
|
|
|
|
|
|
266 |
return [
|
267 |
'flags' => [
|
268 |
'has_validated_profile' => $this->hasValidatedProfile( $user ),
|
269 |
'is_enforced' => $this->isEnforced( $user ),
|
270 |
'is_profile_active' => $this->isProfileActive( $user ),
|
|
|
|
|
271 |
'user_to_edit_is_admin' => Services::WpUsers()->isUserAdmin( $user ),
|
272 |
+
'show_explanatory_text' => true
|
273 |
],
|
274 |
'vars' => [
|
275 |
'otp_field_name' => $this->getLoginFormParameter(),
|
276 |
],
|
277 |
'strings' => [
|
278 |
+
'is_enforced' => __( 'This setting is enforced by your security administrator.', 'wp-simple-firewall' ),
|
279 |
+
'provider_name' => $this->getProviderName()
|
280 |
],
|
281 |
];
|
282 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProviderV2.php
DELETED
@@ -1,279 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
-
|
5 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules;
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpUserConsumer;
|
7 |
-
use FernleafSystems\Wordpress\Services\Services;
|
8 |
-
|
9 |
-
abstract class BaseProviderV2 implements ProviderInterface {
|
10 |
-
|
11 |
-
use Modules\ModConsumer;
|
12 |
-
use WpUserConsumer;
|
13 |
-
|
14 |
-
const SLUG = '';
|
15 |
-
/**
|
16 |
-
* Set to true if this provider can be used in isolation. False if there
|
17 |
-
* must be at least 1 other 2FA provider active.
|
18 |
-
*/
|
19 |
-
const STANDALONE = true;
|
20 |
-
/**
|
21 |
-
* Always a screen, but maybe an json-encoded string, e.g. '[]', like U2F
|
22 |
-
*/
|
23 |
-
const DEFAULT_SECRET = '';
|
24 |
-
|
25 |
-
public function __construct() {
|
26 |
-
}
|
27 |
-
|
28 |
-
public function setupProfile() {
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Assumes this is only called on active profiles
|
33 |
-
* @return bool
|
34 |
-
*/
|
35 |
-
public function validateLoginIntent() {
|
36 |
-
$valid = false;
|
37 |
-
$sReqOtpCode = $this->fetchCodeFromRequest();
|
38 |
-
if ( !empty( $sReqOtpCode ) ) {
|
39 |
-
$valid = $this->processOtp( $this->getWpUser(), $sReqOtpCode );
|
40 |
-
$this->postOtpProcessAction( $this->getWpUser(), $valid );
|
41 |
-
}
|
42 |
-
return $valid;
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @return string
|
47 |
-
*/
|
48 |
-
protected function getSecret() {
|
49 |
-
$secret = $this->getMeta()->{static::SLUG.'_secret'};
|
50 |
-
return empty( $secret ) ? static::DEFAULT_SECRET : $secret;
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* @return bool
|
55 |
-
*/
|
56 |
-
public function hasValidatedProfile() {
|
57 |
-
return $this->getMeta()->{static::SLUG.'_validated'} === true;
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* @return bool
|
62 |
-
*/
|
63 |
-
protected function hasValidSecret() {
|
64 |
-
return $this->isSecretValid( $this->getSecret() );
|
65 |
-
}
|
66 |
-
|
67 |
-
/**
|
68 |
-
* @return bool
|
69 |
-
*/
|
70 |
-
public function isEnforced() {
|
71 |
-
return false;
|
72 |
-
}
|
73 |
-
|
74 |
-
/**
|
75 |
-
* @param \WP_User $user
|
76 |
-
* @return bool
|
77 |
-
*/
|
78 |
-
public function isProfileActive() {
|
79 |
-
return $this->hasValidSecret( $user );
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* @return bool
|
84 |
-
*/
|
85 |
-
public function isProviderAvailableToUser() {
|
86 |
-
return $this->isProviderEnabled();
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* @return bool
|
91 |
-
*/
|
92 |
-
abstract public function isProviderEnabled();
|
93 |
-
|
94 |
-
/**
|
95 |
-
* @param string $secret
|
96 |
-
* @return bool
|
97 |
-
*/
|
98 |
-
protected function isSecretValid( $secret ) {
|
99 |
-
return !empty( $secret ) && is_string( $secret );
|
100 |
-
}
|
101 |
-
|
102 |
-
/**
|
103 |
-
* @param \WP_User $user
|
104 |
-
* @return $this
|
105 |
-
*/
|
106 |
-
public function deleteSecret( $user ) {
|
107 |
-
$this->getCon()
|
108 |
-
->getUserMeta( $user )->{static::SLUG.'_secret'} = null;
|
109 |
-
return $this;
|
110 |
-
}
|
111 |
-
|
112 |
-
/**
|
113 |
-
* @param \WP_User $user
|
114 |
-
* @return string
|
115 |
-
*/
|
116 |
-
public function resetSecret( \WP_User $user ) {
|
117 |
-
$sNewSecret = $this->genNewSecret( $user );
|
118 |
-
$this->setSecret( $user, $sNewSecret );
|
119 |
-
return $sNewSecret;
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* @param \WP_User $user
|
124 |
-
* @param bool $bValidated set true for validated, false for invalidated
|
125 |
-
* @return $this
|
126 |
-
*/
|
127 |
-
public function setProfileValidated( $user, $bValidated = true ) {
|
128 |
-
$this->getCon()
|
129 |
-
->getUserMeta( $user )->{static::SLUG.'_validated'} = $bValidated;
|
130 |
-
return $this;
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* @param \WP_User $user
|
135 |
-
* @param string $sNewSecret
|
136 |
-
* @return $this
|
137 |
-
*/
|
138 |
-
protected function setSecret( $user, $sNewSecret ) {
|
139 |
-
$this->getCon()
|
140 |
-
->getUserMeta( $user )->{static::SLUG.'_secret'} = $sNewSecret;
|
141 |
-
return $this;
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* @param \WP_User $user
|
146 |
-
* @return string|mixed
|
147 |
-
*/
|
148 |
-
protected function genNewSecret( \WP_User $user ) {
|
149 |
-
return '';
|
150 |
-
}
|
151 |
-
|
152 |
-
/**
|
153 |
-
* @param \WP_User $user
|
154 |
-
* @param string $otp
|
155 |
-
* @return bool
|
156 |
-
*/
|
157 |
-
abstract protected function processOtp( \WP_User $user, $otp );
|
158 |
-
|
159 |
-
/**
|
160 |
-
* Only to be fired if and when Login has been completely verified.
|
161 |
-
* @param \WP_User $user
|
162 |
-
* @return $this
|
163 |
-
*/
|
164 |
-
public function postSuccessActions( \WP_User $user ) {
|
165 |
-
return $this;
|
166 |
-
}
|
167 |
-
|
168 |
-
/**
|
169 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
170 |
-
* functions. Otherwise we need to be careful of mixing up users.
|
171 |
-
* @param \WP_User $user
|
172 |
-
* @return string
|
173 |
-
*/
|
174 |
-
public function renderUserProfileOptions( \WP_User $user ) {
|
175 |
-
return '';
|
176 |
-
}
|
177 |
-
|
178 |
-
/**
|
179 |
-
* ONLY TO BE HOOKED TO USER PROFILE EDIT
|
180 |
-
* @param \WP_User $user
|
181 |
-
* @return string
|
182 |
-
*/
|
183 |
-
public function renderUserEditProfileOptions( \WP_User $user ) {
|
184 |
-
return $this->renderUserProfileOptions( $user );
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* @param \WP_User $user
|
189 |
-
*/
|
190 |
-
public function handleEditOtherUserProfileSubmit( \WP_User $user ) {
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* @param \WP_User $user
|
195 |
-
*/
|
196 |
-
protected function processRemovalFromAccount( $user ) {
|
197 |
-
}
|
198 |
-
|
199 |
-
/**
|
200 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile,
|
201 |
-
* so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
|
202 |
-
* @param \WP_User $user
|
203 |
-
*/
|
204 |
-
public function handleUserProfileSubmit( \WP_User $user ) {
|
205 |
-
}
|
206 |
-
|
207 |
-
/**
|
208 |
-
* @param \WP_User $user
|
209 |
-
*/
|
210 |
-
public function captureLoginAttempt( $user ) {
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* @return array
|
215 |
-
*/
|
216 |
-
public function getFormField() {
|
217 |
-
return [];
|
218 |
-
}
|
219 |
-
|
220 |
-
/**
|
221 |
-
* @param \WP_User $user
|
222 |
-
* @param bool $bIsSuccess
|
223 |
-
*/
|
224 |
-
abstract protected function auditLogin( \WP_User $user, $bIsSuccess );
|
225 |
-
|
226 |
-
/**
|
227 |
-
* @param \WP_User $user
|
228 |
-
* @param bool $bIsOtpSuccess
|
229 |
-
* @return $this
|
230 |
-
*/
|
231 |
-
protected function postOtpProcessAction( \WP_User $user, $bIsOtpSuccess ) {
|
232 |
-
$this->auditLogin( $user, $bIsOtpSuccess );
|
233 |
-
return $this;
|
234 |
-
}
|
235 |
-
|
236 |
-
/**
|
237 |
-
* @return string
|
238 |
-
*/
|
239 |
-
protected function getLoginFormParameter() {
|
240 |
-
return $this->getCon()->prefixOption( static::SLUG.'_otp' );
|
241 |
-
}
|
242 |
-
|
243 |
-
/**
|
244 |
-
* @return string
|
245 |
-
*/
|
246 |
-
protected function fetchCodeFromRequest() {
|
247 |
-
return trim( Services::Request()->request( $this->getLoginFormParameter(), false, '' ) );
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
* @param \WP_User $user
|
252 |
-
* @return array
|
253 |
-
*/
|
254 |
-
protected function getCommonData( \WP_User $user ) {
|
255 |
-
return [
|
256 |
-
'flags' => [
|
257 |
-
'has_validated_profile' => $this->hasValidatedProfile( $user ),
|
258 |
-
'is_enforced' => $this->isEnforced( $user ),
|
259 |
-
'is_profile_active' => $this->isProfileActive( $user ),
|
260 |
-
'is_my_user_profile' => $user->ID == Services::WpUsers()->getCurrentWpUserId(),
|
261 |
-
'i_am_valid_admin' => $this->getCon()->isPluginAdmin(),
|
262 |
-
'user_to_edit_is_admin' => Services::WpUsers()->isUserAdmin( $user ),
|
263 |
-
],
|
264 |
-
'vars' => [
|
265 |
-
'otp_field_name' => $this->getLoginFormParameter(),
|
266 |
-
],
|
267 |
-
'strings' => [
|
268 |
-
'is_enforced' => __( 'This setting is enforced by your security administrator.', 'wp-simple-firewall' ),
|
269 |
-
],
|
270 |
-
];
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* @return \FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta
|
275 |
-
*/
|
276 |
-
protected function getMeta() {
|
277 |
-
return $this->getCon()->getUserMeta( $this->getWpUser() );
|
278 |
-
}
|
279 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Email.php
CHANGED
@@ -16,6 +16,14 @@ class Email extends BaseProvider {
|
|
16 |
$this->sendEmailTwoFactorVerify( $user );
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
/**
|
20 |
* @param \WP_User $user
|
21 |
* @param bool $bIsSuccess
|
@@ -60,7 +68,7 @@ class Email extends BaseProvider {
|
|
60 |
/**
|
61 |
* @return array
|
62 |
*/
|
63 |
-
public function getFormField() {
|
64 |
return [
|
65 |
'name' => $this->getLoginFormParameter(),
|
66 |
'type' => 'text',
|
@@ -79,25 +87,25 @@ class Email extends BaseProvider {
|
|
79 |
$bWasEnabled = $this->isProfileActive( $user );
|
80 |
$bToEnable = Services::Request()->post( 'shield_enable_mfaemail' ) === 'Y';
|
81 |
|
82 |
-
$
|
83 |
-
$
|
84 |
if ( $bToEnable ) {
|
85 |
$this->setProfileValidated( $user );
|
86 |
if ( !$bWasEnabled ) {
|
87 |
-
$
|
88 |
}
|
89 |
}
|
90 |
elseif ( $this->isEnforced( $user ) ) {
|
91 |
-
$
|
92 |
-
$
|
93 |
}
|
94 |
else {
|
95 |
$this->setProfileValidated( $user, false );
|
96 |
-
$
|
97 |
}
|
98 |
|
99 |
-
if ( !empty( $
|
100 |
-
$this->getMod()->setFlashAdminNotice( $
|
101 |
}
|
102 |
}
|
103 |
|
@@ -192,23 +200,16 @@ class Email extends BaseProvider {
|
|
192 |
);
|
193 |
}
|
194 |
|
195 |
-
|
196 |
-
|
197 |
'strings' => [
|
198 |
'label_email_authentication' => __( 'Email Authentication', 'wp-simple-firewall' ),
|
199 |
'title' => __( 'Email Authentication', 'wp-simple-firewall' ),
|
200 |
-
'description_email_authentication_checkbox' => __( '
|
201 |
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $this->getCon()
|
202 |
->getHumanName() )
|
203 |
]
|
204 |
];
|
205 |
-
|
206 |
-
return $this->getMod()
|
207 |
-
->renderTemplate(
|
208 |
-
'/snippets/user/profile/mfa/mfa_email.twig',
|
209 |
-
Services::DataManipulation()->mergeArraysRecursive( $this->getCommonData( $user ), $aData ),
|
210 |
-
true
|
211 |
-
);
|
212 |
}
|
213 |
|
214 |
public function isProviderEnabled() :bool {
|
@@ -234,7 +235,7 @@ class Email extends BaseProvider {
|
|
234 |
$this->getLoginFormParameter() => $otp,
|
235 |
'shield_nonce_action' => $action,
|
236 |
'shield_nonce' => $this->getCon()
|
237 |
-
|
238 |
],
|
239 |
Services::WpGeneral()->getHomeUrl()
|
240 |
);
|
@@ -280,4 +281,8 @@ class Email extends BaseProvider {
|
|
280 |
private function storeCodes( \WP_User $user, array $codes ) {
|
281 |
return $this->setSecret( $user, $codes );
|
282 |
}
|
|
|
|
|
|
|
|
|
283 |
}
|
16 |
$this->sendEmailTwoFactorVerify( $user );
|
17 |
}
|
18 |
|
19 |
+
public function getJavascriptVars() :array {
|
20 |
+
return [
|
21 |
+
'ajax' => [
|
22 |
+
'user_email2fa_toggle' => $this->getMod()->getAjaxActionData( 'user_email2fa_toggle' ),
|
23 |
+
],
|
24 |
+
];
|
25 |
+
}
|
26 |
+
|
27 |
/**
|
28 |
* @param \WP_User $user
|
29 |
* @param bool $bIsSuccess
|
68 |
/**
|
69 |
* @return array
|
70 |
*/
|
71 |
+
public function getFormField() :array {
|
72 |
return [
|
73 |
'name' => $this->getLoginFormParameter(),
|
74 |
'type' => 'text',
|
87 |
$bWasEnabled = $this->isProfileActive( $user );
|
88 |
$bToEnable = Services::Request()->post( 'shield_enable_mfaemail' ) === 'Y';
|
89 |
|
90 |
+
$msg = null;
|
91 |
+
$error = false;
|
92 |
if ( $bToEnable ) {
|
93 |
$this->setProfileValidated( $user );
|
94 |
if ( !$bWasEnabled ) {
|
95 |
+
$msg = __( 'Email Two-Factor Authentication has been enabled.', 'wp-simple-firewall' );
|
96 |
}
|
97 |
}
|
98 |
elseif ( $this->isEnforced( $user ) ) {
|
99 |
+
$msg = __( "Email Two-Factor Authentication couldn't be disabled because it is enforced based on your user roles.", 'wp-simple-firewall' );
|
100 |
+
$error = true;
|
101 |
}
|
102 |
else {
|
103 |
$this->setProfileValidated( $user, false );
|
104 |
+
$msg = __( 'Email Two-Factor Authentication has been disabled.', 'wp-simple-firewall' );
|
105 |
}
|
106 |
|
107 |
+
if ( !empty( $msg ) ) {
|
108 |
+
$this->getMod()->setFlashAdminNotice( $msg, $error );
|
109 |
}
|
110 |
}
|
111 |
|
200 |
);
|
201 |
}
|
202 |
|
203 |
+
protected function getProviderSpecificRenderData( \WP_User $user ) :array {
|
204 |
+
return [
|
205 |
'strings' => [
|
206 |
'label_email_authentication' => __( 'Email Authentication', 'wp-simple-firewall' ),
|
207 |
'title' => __( 'Email Authentication', 'wp-simple-firewall' ),
|
208 |
+
'description_email_authentication_checkbox' => __( 'Toggle the option to enable/disable email-based login authentication.', 'wp-simple-firewall' ),
|
209 |
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $this->getCon()
|
210 |
->getHumanName() )
|
211 |
]
|
212 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
}
|
214 |
|
215 |
public function isProviderEnabled() :bool {
|
235 |
$this->getLoginFormParameter() => $otp,
|
236 |
'shield_nonce_action' => $action,
|
237 |
'shield_nonce' => $this->getCon()
|
238 |
+
->nonce_handler->create( $action, $opts->getLoginIntentMinutes()*60 ),
|
239 |
],
|
240 |
Services::WpGeneral()->getHomeUrl()
|
241 |
);
|
281 |
private function storeCodes( \WP_User $user, array $codes ) {
|
282 |
return $this->setSecret( $user, $codes );
|
283 |
}
|
284 |
+
|
285 |
+
public function getProviderName() :string {
|
286 |
+
return 'Email';
|
287 |
+
}
|
288 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/GoogleAuth.php
CHANGED
@@ -3,6 +3,7 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
|
5 |
use Dolondro\GoogleAuthenticator;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
@@ -19,24 +20,31 @@ class GoogleAuth extends BaseProvider {
|
|
19 |
return parent::isProfileActive( $user ) && $this->hasValidatedProfile( $user );
|
20 |
}
|
21 |
|
22 |
-
public function
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
-
|
|
|
26 |
|
27 |
-
$
|
|
|
28 |
'hrefs' => [
|
29 |
-
'src_chart_url' => $
|
30 |
],
|
31 |
'vars' => [
|
32 |
-
'ga_secret' => $
|
33 |
],
|
34 |
'strings' => [
|
35 |
-
'enter_auth_app_code' => __( 'Enter
|
36 |
'description_otp_code' => __( 'Provide the current code generated by your Google Authenticator app.', 'wp-simple-firewall' ),
|
37 |
'description_chart_url' => __( 'Use your Google Authenticator app to scan this QR code and enter the 6-digit one time password.', 'wp-simple-firewall' ),
|
38 |
'description_ga_secret' => __( 'If you have a problem with scanning the QR code enter the long code manually into the app.', 'wp-simple-firewall' ),
|
39 |
-
'desc_remove' => __( '
|
40 |
'label_check_to_remove' => sprintf( __( 'Remove %s', 'wp-simple-firewall' ), __( 'Google Authenticator', 'wp-simple-firewall' ) ),
|
41 |
'label_enter_code' => __( 'Google Authenticator Code', 'wp-simple-firewall' ),
|
42 |
'label_ga_secret' => __( 'Manual Code', 'wp-simple-firewall' ),
|
@@ -44,17 +52,11 @@ class GoogleAuth extends BaseProvider {
|
|
44 |
'title' => __( 'Google Authenticator', 'wp-simple-firewall' ),
|
45 |
'cant_add_other_user' => sprintf( __( "Sorry, %s may not be added to another user's account.", 'wp-simple-firewall' ), 'Google Authenticator' ),
|
46 |
'cant_remove_admins' => sprintf( __( "Sorry, %s may only be removed from another user's account by a Security Administrator.", 'wp-simple-firewall' ), __( 'Google Authenticator', 'wp-simple-firewall' ) ),
|
47 |
-
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $
|
48 |
-
'remove_more_info' =>
|
|
|
49 |
],
|
50 |
];
|
51 |
-
|
52 |
-
return $this->getMod()
|
53 |
-
->renderTemplate(
|
54 |
-
'/snippets/user/profile/mfa/mfa_ga.twig',
|
55 |
-
Services::DataManipulation()->mergeArraysRecursive( $this->getCommonData( $user ), $aData ),
|
56 |
-
true
|
57 |
-
);
|
58 |
}
|
59 |
|
60 |
/**
|
@@ -62,10 +64,10 @@ class GoogleAuth extends BaseProvider {
|
|
62 |
* @return string
|
63 |
*/
|
64 |
public function getGaRegisterChartUrl( $user ) {
|
65 |
-
$
|
66 |
if ( !empty( $user ) ) {
|
67 |
try {
|
68 |
-
$
|
69 |
->generateUri(
|
70 |
$this->getGaSecret( $user )
|
71 |
);
|
@@ -73,7 +75,7 @@ class GoogleAuth extends BaseProvider {
|
|
73 |
catch ( \InvalidArgumentException $e ) {
|
74 |
}
|
75 |
}
|
76 |
-
return $
|
77 |
}
|
78 |
|
79 |
/**
|
@@ -86,11 +88,37 @@ class GoogleAuth extends BaseProvider {
|
|
86 |
// Can only edit other users if you're admin/security-admin
|
87 |
if ( $this->getCon()->isPluginAdmin() && Services::Request()->post( 'shield_turn_off_ga' ) === 'Y' ) {
|
88 |
$this->processRemovalFromAccount( $user );
|
89 |
-
$
|
90 |
-
$this->getMod()->setFlashAdminNotice( $
|
91 |
}
|
92 |
}
|
93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
/**
|
95 |
* @param \WP_User $user
|
96 |
* @return $this
|
@@ -105,39 +133,39 @@ class GoogleAuth extends BaseProvider {
|
|
105 |
* @inheritDoc
|
106 |
*/
|
107 |
public function handleUserProfileSubmit( \WP_User $user ) {
|
108 |
-
$
|
109 |
|
110 |
if ( Services::Request()->post( 'shield_turn_off_ga' ) === 'Y' ) {
|
111 |
-
$
|
112 |
$this->processRemovalFromAccount( $user );
|
113 |
-
$this->getMod()->setFlashAdminNotice( $
|
114 |
/**
|
115 |
-
* $
|
116 |
-
* $
|
117 |
*/
|
118 |
}
|
119 |
-
elseif ( !empty( $
|
120 |
-
$
|
121 |
-
if ( $
|
122 |
$this->setProfileValidated( $user );
|
123 |
-
$
|
124 |
__( '%s was successfully added to your account.', 'wp-simple-firewall' ),
|
125 |
__( 'Google Authenticator', 'wp-simple-firewall' )
|
126 |
);
|
127 |
}
|
128 |
else {
|
129 |
$this->resetSecret( $user );
|
130 |
-
$
|
131 |
-
|
132 |
}
|
133 |
-
$this->getMod()->setFlashAdminNotice( $
|
134 |
}
|
135 |
}
|
136 |
|
137 |
/**
|
138 |
* @return array
|
139 |
*/
|
140 |
-
public function getFormField() {
|
141 |
return [
|
142 |
'name' => $this->getLoginFormParameter(),
|
143 |
'type' => 'text',
|
@@ -241,4 +269,8 @@ class GoogleAuth extends BaseProvider {
|
|
241 |
$opts = $this->getOptions();
|
242 |
return $opts->isEnabledGoogleAuthenticator();
|
243 |
}
|
|
|
|
|
|
|
|
|
244 |
}
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
|
5 |
use Dolondro\GoogleAuthenticator;
|
6 |
+
use FernleafSystems\Utilities\Data\Response\StdResponse;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
20 |
return parent::isProfileActive( $user ) && $this->hasValidatedProfile( $user );
|
21 |
}
|
22 |
|
23 |
+
public function getJavascriptVars() :array {
|
24 |
+
return [
|
25 |
+
'ajax' => [
|
26 |
+
'user_ga_toggle' => $this->getMod()->getAjaxActionData( 'user_ga_toggle' ),
|
27 |
+
],
|
28 |
+
];
|
29 |
+
}
|
30 |
|
31 |
+
protected function getProviderSpecificRenderData( \WP_User $user ) :array {
|
32 |
+
$con = $this->getCon();
|
33 |
|
34 |
+
$validatedProfile = $this->hasValidatedProfile( $user );
|
35 |
+
return [
|
36 |
'hrefs' => [
|
37 |
+
'src_chart_url' => $validatedProfile ? '' : $this->getGaRegisterChartUrl( $user ),
|
38 |
],
|
39 |
'vars' => [
|
40 |
+
'ga_secret' => $validatedProfile ? $this->getSecret( $user ) : $this->resetSecret( $user ),
|
41 |
],
|
42 |
'strings' => [
|
43 |
+
'enter_auth_app_code' => __( 'Enter 6-digit Code from App', 'wp-simple-firewall' ),
|
44 |
'description_otp_code' => __( 'Provide the current code generated by your Google Authenticator app.', 'wp-simple-firewall' ),
|
45 |
'description_chart_url' => __( 'Use your Google Authenticator app to scan this QR code and enter the 6-digit one time password.', 'wp-simple-firewall' ),
|
46 |
'description_ga_secret' => __( 'If you have a problem with scanning the QR code enter the long code manually into the app.', 'wp-simple-firewall' ),
|
47 |
+
'desc_remove' => __( 'Click to immediately remove Google Authenticator login authentication.', 'wp-simple-firewall' ),
|
48 |
'label_check_to_remove' => sprintf( __( 'Remove %s', 'wp-simple-firewall' ), __( 'Google Authenticator', 'wp-simple-firewall' ) ),
|
49 |
'label_enter_code' => __( 'Google Authenticator Code', 'wp-simple-firewall' ),
|
50 |
'label_ga_secret' => __( 'Manual Code', 'wp-simple-firewall' ),
|
52 |
'title' => __( 'Google Authenticator', 'wp-simple-firewall' ),
|
53 |
'cant_add_other_user' => sprintf( __( "Sorry, %s may not be added to another user's account.", 'wp-simple-firewall' ), 'Google Authenticator' ),
|
54 |
'cant_remove_admins' => sprintf( __( "Sorry, %s may only be removed from another user's account by a Security Administrator.", 'wp-simple-firewall' ), __( 'Google Authenticator', 'wp-simple-firewall' ) ),
|
55 |
+
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $con->getHumanName() ),
|
56 |
+
'remove_more_info' => __( 'Understand how to remove Google Authenticator', 'wp-simple-firewall' ),
|
57 |
+
'remove_google_auth' => __( 'Remove Google Authenticator', 'wp-simple-firewall' )
|
58 |
],
|
59 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
}
|
61 |
|
62 |
/**
|
64 |
* @return string
|
65 |
*/
|
66 |
public function getGaRegisterChartUrl( $user ) {
|
67 |
+
$url = '';
|
68 |
if ( !empty( $user ) ) {
|
69 |
try {
|
70 |
+
$url = ( new GoogleAuthenticator\QrImageGenerator\EndroidQrImageGenerator() )
|
71 |
->generateUri(
|
72 |
$this->getGaSecret( $user )
|
73 |
);
|
75 |
catch ( \InvalidArgumentException $e ) {
|
76 |
}
|
77 |
}
|
78 |
+
return $url;
|
79 |
}
|
80 |
|
81 |
/**
|
88 |
// Can only edit other users if you're admin/security-admin
|
89 |
if ( $this->getCon()->isPluginAdmin() && Services::Request()->post( 'shield_turn_off_ga' ) === 'Y' ) {
|
90 |
$this->processRemovalFromAccount( $user );
|
91 |
+
$msg = __( 'Google Authenticator was successfully removed from the account.', 'wp-simple-firewall' );
|
92 |
+
$this->getMod()->setFlashAdminNotice( $msg );
|
93 |
}
|
94 |
}
|
95 |
|
96 |
+
public function removeGaOnAccount( \WP_User $user ) :StdResponse {
|
97 |
+
$this->processRemovalFromAccount( $user );
|
98 |
+
$response = new StdResponse();
|
99 |
+
$response->success = true;
|
100 |
+
$response->msg_text = __( 'Google Authenticator was successfully removed from the account.', 'wp-simple-firewall' );
|
101 |
+
return $response;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function activateGaOnAccount( \WP_User $user, string $otp ) :StdResponse {
|
105 |
+
$response = new StdResponse();
|
106 |
+
$response->success = $this->processOtp( $user, $otp );
|
107 |
+
if ( $response->success ) {
|
108 |
+
$this->setProfileValidated( $user );
|
109 |
+
$response->msg_text = sprintf(
|
110 |
+
__( '%s was successfully added to your account.', 'wp-simple-firewall' ),
|
111 |
+
__( 'Google Authenticator', 'wp-simple-firewall' )
|
112 |
+
);
|
113 |
+
}
|
114 |
+
else {
|
115 |
+
$this->resetSecret( $user );
|
116 |
+
$response->error_text = __( 'One Time Password (OTP) was not valid.', 'wp-simple-firewall' )
|
117 |
+
.' '.__( 'Please try again.', 'wp-simple-firewall' );
|
118 |
+
}
|
119 |
+
return $response;
|
120 |
+
}
|
121 |
+
|
122 |
/**
|
123 |
* @param \WP_User $user
|
124 |
* @return $this
|
133 |
* @inheritDoc
|
134 |
*/
|
135 |
public function handleUserProfileSubmit( \WP_User $user ) {
|
136 |
+
$otp = $this->fetchCodeFromRequest();
|
137 |
|
138 |
if ( Services::Request()->post( 'shield_turn_off_ga' ) === 'Y' ) {
|
139 |
+
$flash = __( 'Google Authenticator was successfully removed from the account.', 'wp-simple-firewall' );
|
140 |
$this->processRemovalFromAccount( $user );
|
141 |
+
$this->getMod()->setFlashAdminNotice( $flash );
|
142 |
/**
|
143 |
+
* $flash = __( 'An email has been sent to you in order to confirm Google Authenticator removal', 'wp-simple-firewall' );
|
144 |
+
* $flash = __( 'We tried to send an email for you to confirm Google Authenticator removal but it failed.', 'wp-simple-firewall' );
|
145 |
*/
|
146 |
}
|
147 |
+
elseif ( !empty( $otp ) && !$this->hasValidatedProfile( $user ) ) { // Add GA to profile
|
148 |
+
$validOTP = $this->processOtp( $user, $otp );
|
149 |
+
if ( $validOTP ) {
|
150 |
$this->setProfileValidated( $user );
|
151 |
+
$flash = sprintf(
|
152 |
__( '%s was successfully added to your account.', 'wp-simple-firewall' ),
|
153 |
__( 'Google Authenticator', 'wp-simple-firewall' )
|
154 |
);
|
155 |
}
|
156 |
else {
|
157 |
$this->resetSecret( $user );
|
158 |
+
$flash = __( 'One Time Password (OTP) was not valid.', 'wp-simple-firewall' )
|
159 |
+
.' '.__( 'Please try again.', 'wp-simple-firewall' );
|
160 |
}
|
161 |
+
$this->getMod()->setFlashAdminNotice( $flash, !$validOTP );
|
162 |
}
|
163 |
}
|
164 |
|
165 |
/**
|
166 |
* @return array
|
167 |
*/
|
168 |
+
public function getFormField() :array {
|
169 |
return [
|
170 |
'name' => $this->getLoginFormParameter(),
|
171 |
'type' => 'text',
|
269 |
$opts = $this->getOptions();
|
270 |
return $opts->isEnabledGoogleAuthenticator();
|
271 |
}
|
272 |
+
|
273 |
+
public function getProviderName() :string {
|
274 |
+
return 'Google Authenticator';
|
275 |
+
}
|
276 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/ProviderInterface.php
CHANGED
@@ -46,23 +46,10 @@ interface ProviderInterface {
|
|
46 |
*/
|
47 |
public function handleUserProfileSubmit();
|
48 |
|
49 |
-
/**
|
50 |
-
* Process the edit of user profile that is not the current user
|
51 |
-
* @return string
|
52 |
-
*/
|
53 |
-
public function handleEditOtherUserProfileSubmit();
|
54 |
-
|
55 |
-
|
56 |
/**
|
57 |
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
58 |
* functions. Otherwise we need to be careful of mixing up users.
|
59 |
* @return string
|
60 |
*/
|
61 |
public function renderUserProfileOptions();
|
62 |
-
|
63 |
-
/**
|
64 |
-
* ONLY TO BE HOOKED TO USER PROFILE EDIT
|
65 |
-
* @return string
|
66 |
-
*/
|
67 |
-
public function renderUserEditProfileOptions();
|
68 |
}
|
46 |
*/
|
47 |
public function handleUserProfileSubmit();
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
/**
|
50 |
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
51 |
* functions. Otherwise we need to be careful of mixing up users.
|
52 |
* @return string
|
53 |
*/
|
54 |
public function renderUserProfileOptions();
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/U2F.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
@@ -17,52 +18,37 @@ class U2F extends BaseProvider {
|
|
17 |
return parent::isProfileActive( $user ) && $this->hasValidatedProfile( $user );
|
18 |
}
|
19 |
|
20 |
-
public function
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
.' '.__( 'Please retry or refresh the page.', 'wp-simple-firewall' ),
|
46 |
-
'do_save' => __( 'Key registration was successful.', 'wp-simple-firewall' )
|
47 |
-
.' '.__( 'Please now save your profile settings.', 'wp-simple-firewall' ),
|
48 |
-
'prompt_dialog' => __( 'Please provide a label to identify the new U2F device.', 'wp-simple-firewall' ),
|
49 |
-
'err_no_label' => __( 'Device registration may not proceed without a unique label.', 'wp-simple-firewall' ),
|
50 |
-
'err_invalid_label' => __( 'Device label must contain letters, numbers, underscore, or hypen, and be no more than 16 characters.', 'wp-simple-firewall' ),
|
51 |
-
]
|
52 |
-
]
|
53 |
-
];
|
54 |
-
return $localz;
|
55 |
-
} );
|
56 |
-
}
|
57 |
-
|
58 |
-
return $enqueues;
|
59 |
-
}, 10, 2 );
|
60 |
}
|
61 |
|
62 |
/**
|
63 |
* @return array
|
64 |
*/
|
65 |
-
public function getFormField() {
|
66 |
$user = Services::WpUsers()->getCurrentWpUser();
|
67 |
|
68 |
$aFieldData = [];
|
@@ -101,11 +87,22 @@ class U2F extends BaseProvider {
|
|
101 |
* @throws \u2flib_server\Error
|
102 |
*/
|
103 |
private function createNewU2fRegistrationRequest( \WP_User $user ) {
|
104 |
-
$
|
105 |
-
list( $
|
106 |
->getRegisterData( $this->getRegistrations( $user ) );
|
107 |
-
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
}
|
110 |
|
111 |
/**
|
@@ -113,12 +110,12 @@ class U2F extends BaseProvider {
|
|
113 |
* @return \stdClass[]
|
114 |
*/
|
115 |
private function getRegistrations( \WP_User $user ) {
|
116 |
-
$
|
117 |
return array_map(
|
118 |
-
function ( $
|
119 |
-
return (object)$
|
120 |
},
|
121 |
-
is_array( $
|
122 |
);
|
123 |
}
|
124 |
|
@@ -132,18 +129,15 @@ class U2F extends BaseProvider {
|
|
132 |
return sprintf( 'https://%s%s', $aPs[ 'host' ], $sPort );
|
133 |
}
|
134 |
|
135 |
-
|
136 |
-
|
137 |
-
$bValidated = $this->hasValidatedProfile( $user );
|
138 |
-
|
139 |
-
$aData = [
|
140 |
'strings' => [
|
141 |
'title' => __( 'U2F', 'wp-simple-firewall' ),
|
142 |
'button_reg_key' => __( 'Register A New U2F Security Key', 'wp-simple-firewall' ),
|
143 |
'prompt' => __( 'Click To Register A U2F Device.', 'wp-simple-firewall' ),
|
144 |
],
|
145 |
'flags' => [
|
146 |
-
'is_validated' => $
|
147 |
],
|
148 |
'vars' => [
|
149 |
'registrations' => array_map(
|
@@ -163,67 +157,72 @@ class U2F extends BaseProvider {
|
|
163 |
)
|
164 |
],
|
165 |
];
|
166 |
-
|
167 |
-
return $this->getMod()
|
168 |
-
->renderTemplate(
|
169 |
-
'/snippets/user/profile/mfa/mfa_u2f.twig',
|
170 |
-
Services::DataManipulation()->mergeArraysRecursive( $this->getCommonData( $user ), $aData ),
|
171 |
-
true
|
172 |
-
);
|
173 |
}
|
174 |
|
175 |
/**
|
176 |
* @inheritDoc
|
177 |
*/
|
178 |
-
public function
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
180 |
}
|
181 |
|
182 |
-
|
183 |
-
|
184 |
-
*/
|
185 |
-
public function handleUserProfileSubmit( \WP_User $user ) {
|
186 |
-
$isError = false;
|
187 |
-
$msg = null;
|
188 |
-
|
189 |
-
$sU2fResponse = Services::Request()->post( 'icwp_wpsf_new_u2f_response' );
|
190 |
-
if ( !empty( $sU2fResponse ) ) {
|
191 |
-
$oMeta = $this->getCon()->getUserMeta( $user );
|
192 |
-
|
193 |
-
try {
|
194 |
-
$oDecodedResponse = json_decode( $sU2fResponse );
|
195 |
-
$sLabel = preg_replace( '#[^a-z0-9_-]#i', '', $oDecodedResponse->label );
|
196 |
-
if ( strlen( $sLabel ) > 16 ) {
|
197 |
-
throw new \Exception( 'U2F Device label is larger than 16 characters.' );
|
198 |
-
}
|
199 |
-
if ( array_key_exists( $sLabel, $this->getRegistrations( $user ) ) ) {
|
200 |
-
throw new \Exception( 'U2F Device with this label already exists.' );
|
201 |
-
}
|
202 |
|
203 |
-
|
204 |
-
$oRegistration = ( new \u2flib_server\U2F( $this->getU2fAppID() ) )->doRegister(
|
205 |
-
new RegisterRequest( $oRegRequest->challenge, $oRegRequest->appId ),
|
206 |
-
$oDecodedResponse
|
207 |
-
);
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
214 |
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
}
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
$e->getMessage() );
|
221 |
}
|
222 |
-
}
|
223 |
|
224 |
-
|
225 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
}
|
228 |
|
229 |
protected function processOtp( \WP_User $user, string $otp ) :bool {
|
@@ -269,12 +268,12 @@ class U2F extends BaseProvider {
|
|
269 |
|
270 |
/**
|
271 |
* @param \WP_User $user
|
272 |
-
* @param array $
|
273 |
* @return $this
|
274 |
*/
|
275 |
-
private function storeRegistrations( \WP_User $user, array $
|
276 |
-
return $this->setProfileValidated( $user, !empty( $
|
277 |
-
->setSecret( $user, json_encode( $
|
278 |
}
|
279 |
|
280 |
/**
|
@@ -331,4 +330,8 @@ class U2F extends BaseProvider {
|
|
331 |
$opts = $this->getOptions();
|
332 |
return $opts->isEnabledU2F();
|
333 |
}
|
|
|
|
|
|
|
|
|
334 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
|
5 |
+
use FernleafSystems\Utilities\Data\Response\StdResponse;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
18 |
return parent::isProfileActive( $user ) && $this->hasValidatedProfile( $user );
|
19 |
}
|
20 |
|
21 |
+
public function getJavascriptVars() :array {
|
22 |
+
$user = Services::WpUsers()->getCurrentWpUser();
|
23 |
+
list( $reg, $signs ) = $this->createNewU2fRegistrationRequest( $user );
|
24 |
+
return [
|
25 |
+
'reg_request' => $reg,
|
26 |
+
'signs' => $signs,
|
27 |
+
'ajax' => [
|
28 |
+
'u2f_add' => $this->getMod()->getAjaxActionData( 'u2f_add' ),
|
29 |
+
'u2f_remove' => $this->getMod()->getAjaxActionData( 'u2f_remove' ),
|
30 |
+
],
|
31 |
+
'flags' => [
|
32 |
+
'has_validated' => $this->hasValidatedProfile( $user )
|
33 |
+
],
|
34 |
+
'strings' => [
|
35 |
+
'not_supported' => __( 'U2F Security Key registration is not supported in this browser', 'wp-simple-firewall' ),
|
36 |
+
'failed' => __( 'Key registration failed.', 'wp-simple-firewall' )
|
37 |
+
.' '.__( "Perhaps the device isn't supported, or you've already registered it.", 'wp-simple-firewall' )
|
38 |
+
.' '.__( 'Please retry or refresh the page.', 'wp-simple-firewall' ),
|
39 |
+
'do_save' => __( 'Key registration was successful.', 'wp-simple-firewall' )
|
40 |
+
.' '.__( 'Please now save your profile settings.', 'wp-simple-firewall' ),
|
41 |
+
'prompt_dialog' => __( 'Please provide a label to identify the new U2F device.', 'wp-simple-firewall' ),
|
42 |
+
'err_no_label' => __( 'Device registration may not proceed without a unique label.', 'wp-simple-firewall' ),
|
43 |
+
'err_invalid_label' => __( 'Device label must contain letters, numbers, underscore, or hypen, and be no more than 16 characters.', 'wp-simple-firewall' ),
|
44 |
+
]
|
45 |
+
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
|
48 |
/**
|
49 |
* @return array
|
50 |
*/
|
51 |
+
public function getFormField() :array {
|
52 |
$user = Services::WpUsers()->getCurrentWpUser();
|
53 |
|
54 |
$aFieldData = [];
|
87 |
* @throws \u2flib_server\Error
|
88 |
*/
|
89 |
private function createNewU2fRegistrationRequest( \WP_User $user ) {
|
90 |
+
$meta = $this->getCon()->getUserMeta( $user );
|
91 |
+
list( $newRegRequest, $signRequests ) = ( new \u2flib_server\U2F( $this->getU2fAppID() ) )
|
92 |
->getRegisterData( $this->getRegistrations( $user ) );
|
93 |
+
|
94 |
+
// Store requests as an array to allow for multiple requests to be kept
|
95 |
+
unset( $meta->u2f_regrequest ); // Old property
|
96 |
+
$userRegRequests = array_filter(
|
97 |
+
is_array( $meta->u2f_regrequests ) ? $meta->u2f_regrequests : [],
|
98 |
+
function ( $ts ) {
|
99 |
+
return Services::Request()->ts() - $ts < MINUTE_IN_SECONDS*10;
|
100 |
+
}
|
101 |
+
);
|
102 |
+
$userRegRequests[ json_encode( $newRegRequest ) ] = Services::Request()->ts();
|
103 |
+
$meta->u2f_regrequests = $userRegRequests;
|
104 |
+
|
105 |
+
return [ $newRegRequest, $signRequests ];
|
106 |
}
|
107 |
|
108 |
/**
|
110 |
* @return \stdClass[]
|
111 |
*/
|
112 |
private function getRegistrations( \WP_User $user ) {
|
113 |
+
$regs = json_decode( $this->getSecret( $user ), true );
|
114 |
return array_map(
|
115 |
+
function ( $reg ) {
|
116 |
+
return (object)$reg;
|
117 |
},
|
118 |
+
is_array( $regs ) ? $regs : []
|
119 |
);
|
120 |
}
|
121 |
|
129 |
return sprintf( 'https://%s%s', $aPs[ 'host' ], $sPort );
|
130 |
}
|
131 |
|
132 |
+
protected function getProviderSpecificRenderData( \WP_User $user ) :array {
|
133 |
+
return [
|
|
|
|
|
|
|
134 |
'strings' => [
|
135 |
'title' => __( 'U2F', 'wp-simple-firewall' ),
|
136 |
'button_reg_key' => __( 'Register A New U2F Security Key', 'wp-simple-firewall' ),
|
137 |
'prompt' => __( 'Click To Register A U2F Device.', 'wp-simple-firewall' ),
|
138 |
],
|
139 |
'flags' => [
|
140 |
+
'is_validated' => $this->hasValidatedProfile( $user )
|
141 |
],
|
142 |
'vars' => [
|
143 |
'registrations' => array_map(
|
157 |
)
|
158 |
],
|
159 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
}
|
161 |
|
162 |
/**
|
163 |
* @inheritDoc
|
164 |
*/
|
165 |
+
public function handleUserProfileSubmit( \WP_User $user ) {
|
166 |
+
$rawU2fResponse = Services::Request()->post( 'icwp_wpsf_new_u2f_response' );
|
167 |
+
if ( !empty( $rawU2fResponse ) ) {
|
168 |
+
$result = $this->addNewRegistration( $user, json_decode( $rawU2fResponse, true ) );
|
169 |
+
$this->getMod()
|
170 |
+
->setFlashAdminNotice( $result->success ? $result->msg_text : $result->error_text, $result->failed );
|
171 |
+
}
|
172 |
}
|
173 |
|
174 |
+
public function addNewRegistration( \WP_User $user, array $u2fResponse ) :StdResponse {
|
175 |
+
$response = new StdResponse();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
|
177 |
+
$meta = $this->getCon()->getUserMeta( $user );
|
|
|
|
|
|
|
|
|
178 |
|
179 |
+
try {
|
180 |
+
$u2fResponse = (object)$u2fResponse;
|
181 |
+
$label = preg_replace( '#[^a-z0-9_-]#i', '', $u2fResponse->label );
|
182 |
+
if ( strlen( $label ) > 16 ) {
|
183 |
+
throw new \Exception( 'U2F Device label is larger than 16 characters.' );
|
184 |
+
}
|
185 |
+
if ( array_key_exists( $label, $this->getRegistrations( $user ) ) ) {
|
186 |
+
throw new \Exception( 'U2F Device with this label already exists.' );
|
187 |
+
}
|
188 |
|
189 |
+
$U2FRegistration = null;
|
190 |
+
foreach ( $meta->u2f_regrequests as $u2fRequest => $ts ) {
|
191 |
+
try {
|
192 |
+
$regRequest = json_decode( $u2fRequest );
|
193 |
+
$U2FRegistration = ( new \u2flib_server\U2F( $this->getU2fAppID() ) )->doRegister(
|
194 |
+
new RegisterRequest( $regRequest->challenge, $regRequest->appId ),
|
195 |
+
$u2fResponse
|
196 |
+
);
|
197 |
+
$regReqs = $meta->u2f_regrequests;
|
198 |
+
unset( $regReqs[ $u2fRequest ] );
|
199 |
+
$meta->u2f_regrequests = $regReqs;
|
200 |
+
break;
|
201 |
+
}
|
202 |
+
catch ( \Exception $e ) {
|
203 |
+
}
|
204 |
}
|
205 |
+
|
206 |
+
if ( empty( $U2FRegistration ) ) {
|
207 |
+
throw new \Exception( "Couldn't find a suitable U2F challenge to verify." );
|
|
|
208 |
}
|
|
|
209 |
|
210 |
+
// attach the device label
|
211 |
+
$confirmedReg = get_object_vars( $U2FRegistration );
|
212 |
+
$confirmedReg[ 'label' ] = $label;
|
213 |
+
$this->addRegistration( $user, $confirmedReg )
|
214 |
+
->setProfileValidated( $user );
|
215 |
+
|
216 |
+
$response->msg_text = __( 'U2F Device was successfully registered on your profile.', 'wp-simple-firewall' );
|
217 |
+
$response->success = true;
|
218 |
}
|
219 |
+
catch ( \Exception $e ) {
|
220 |
+
$response->success = false;
|
221 |
+
$response->error_text = sprintf( __( 'U2F Device registration failed with the following error: %s', 'wp-simple-firewall' ),
|
222 |
+
$e->getMessage() );
|
223 |
+
}
|
224 |
+
|
225 |
+
return $response;
|
226 |
}
|
227 |
|
228 |
protected function processOtp( \WP_User $user, string $otp ) :bool {
|
268 |
|
269 |
/**
|
270 |
* @param \WP_User $user
|
271 |
+
* @param array $regs
|
272 |
* @return $this
|
273 |
*/
|
274 |
+
private function storeRegistrations( \WP_User $user, array $regs ) {
|
275 |
+
return $this->setProfileValidated( $user, !empty( $regs ) )
|
276 |
+
->setSecret( $user, json_encode( $regs ) );
|
277 |
}
|
278 |
|
279 |
/**
|
330 |
$opts = $this->getOptions();
|
331 |
return $opts->isEnabledU2F();
|
332 |
}
|
333 |
+
|
334 |
+
public function getProviderName() :string {
|
335 |
+
return 'U2F';
|
336 |
+
}
|
337 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Yubikey.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
@@ -12,56 +12,40 @@ class Yubikey extends BaseProvider {
|
|
12 |
const OTP_LENGTH = 12;
|
13 |
const URL_YUBIKEY_VERIFY = 'https://api.yubico.com/wsapi/2.0/verify';
|
14 |
|
15 |
-
public function
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
'shield/userprofile',
|
23 |
-
'icwp_wpsf_vars_profileyubikey',
|
24 |
-
[ 'yubikey_remove' => $this->getMod()->getAjaxActionData( 'yubikey_remove' ) ]
|
25 |
-
];
|
26 |
-
return $localz;
|
27 |
-
} );
|
28 |
-
}
|
29 |
-
return $enqueues;
|
30 |
-
}, 10, 2 );
|
31 |
}
|
32 |
|
33 |
-
|
34 |
$con = $this->getCon();
|
35 |
-
|
36 |
-
$aData = [
|
37 |
'vars' => [
|
38 |
'yubi_ids' => $this->getYubiIds( $user ),
|
39 |
],
|
40 |
'strings' => [
|
41 |
-
'registered_yubi_ids'
|
42 |
-
'no_active_yubi_ids'
|
43 |
-
'
|
44 |
-
'
|
45 |
-
'
|
|
|
46 |
__( 'You may add as many Yubikey devices to your profile as you need to.', 'wp-simple-firewall' ) ),
|
47 |
-
'description_otp_code'
|
48 |
-
'description_otp'
|
49 |
-
'label_enter_code'
|
50 |
-
'label_enter_otp'
|
51 |
-
'title'
|
52 |
-
'cant_add_other_user'
|
53 |
-
'cant_remove_admins'
|
54 |
-
'provided_by'
|
55 |
-
'remove_more_info'
|
56 |
],
|
57 |
];
|
58 |
-
|
59 |
-
return $this->getMod()
|
60 |
-
->renderTemplate(
|
61 |
-
'/snippets/user/profile/mfa/mfa_yubikey.twig',
|
62 |
-
Services::DataManipulation()->mergeArraysRecursive( $this->getCommonData( $user ), $aData ),
|
63 |
-
true
|
64 |
-
);
|
65 |
}
|
66 |
|
67 |
/**
|
@@ -148,56 +132,88 @@ class Yubikey extends BaseProvider {
|
|
148 |
}
|
149 |
|
150 |
/**
|
151 |
-
* @param string $
|
152 |
* @return bool
|
153 |
*/
|
154 |
-
private function sendYubiOtpRequest( $
|
155 |
-
/** @var LoginGuard\Options $
|
156 |
-
$
|
157 |
-
$
|
158 |
-
$
|
159 |
-
|
160 |
-
if ( preg_match( '#^[a-z]{44}$#', $
|
161 |
-
$
|
162 |
-
'otp' => $
|
163 |
'nonce' => md5( uniqid( $this->getCon()->getUniqueRequestId() ) ),
|
164 |
-
'id' => $
|
165 |
];
|
166 |
|
167 |
-
$
|
168 |
-
add_query_arg( $aParts, self::URL_YUBIKEY_VERIFY )
|
169 |
-
);
|
170 |
|
171 |
-
unset( $
|
172 |
-
$
|
173 |
|
174 |
-
$
|
175 |
-
foreach ( $
|
176 |
-
if ( !preg_match( sprintf( '#%s=%s#', $
|
177 |
-
$
|
178 |
break;
|
179 |
}
|
180 |
}
|
181 |
}
|
182 |
|
183 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
}
|
185 |
|
186 |
/**
|
187 |
* @param \WP_User $user
|
188 |
-
* @param string $
|
189 |
-
* @param bool $
|
190 |
* @return $this
|
191 |
*/
|
192 |
-
public function addRemoveRegisteredYubiId( \WP_User $user, $
|
193 |
-
$
|
194 |
-
|
195 |
-
|
|
|
|
|
|
|
|
|
|
|
196 |
}
|
197 |
else {
|
198 |
-
$
|
199 |
}
|
200 |
-
return $this->setSecret( $user, implode( ',', array_unique( array_filter( $
|
201 |
}
|
202 |
|
203 |
/**
|
@@ -219,7 +235,7 @@ class Yubikey extends BaseProvider {
|
|
219 |
/**
|
220 |
* @return array
|
221 |
*/
|
222 |
-
public function getFormField() {
|
223 |
return [
|
224 |
'name' => $this->getLoginFormParameter(),
|
225 |
'type' => 'text',
|
@@ -250,4 +266,8 @@ class Yubikey extends BaseProvider {
|
|
250 |
}
|
251 |
return $bValid;
|
252 |
}
|
|
|
|
|
|
|
|
|
253 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard\Lib\TwoFactor\Provider;
|
4 |
|
5 |
+
use FernleafSystems\Utilities\Data\Response\StdResponse;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\LoginGuard;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
12 |
const OTP_LENGTH = 12;
|
13 |
const URL_YUBIKEY_VERIFY = 'https://api.yubico.com/wsapi/2.0/verify';
|
14 |
|
15 |
+
public function getJavascriptVars() :array {
|
16 |
+
return [
|
17 |
+
'ajax' => [
|
18 |
+
'user_yubikey_toggle' => $this->getMod()->getAjaxActionData( 'user_yubikey_toggle' ),
|
19 |
+
'user_yubikey_remove' => $this->getMod()->getAjaxActionData( 'user_yubikey_remove' )
|
20 |
+
],
|
21 |
+
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
23 |
|
24 |
+
protected function getProviderSpecificRenderData( \WP_User $user ) :array {
|
25 |
$con = $this->getCon();
|
26 |
+
return [
|
|
|
27 |
'vars' => [
|
28 |
'yubi_ids' => $this->getYubiIds( $user ),
|
29 |
],
|
30 |
'strings' => [
|
31 |
+
'registered_yubi_ids' => __( 'Registered Yubikey devices', 'wp-simple-firewall' ),
|
32 |
+
'no_active_yubi_ids' => __( 'There are no registered Yubikey devices on this profile.', 'wp-simple-firewall' ),
|
33 |
+
'placeholder_enter_otp' => __( 'Enter One Time Password From Yubikey', 'wp-simple-firewall' ),
|
34 |
+
'enter_otp' => __( 'To register a new Yubikey device, enter a One Time Password from the Yubikey.', 'wp-simple-firewall' ),
|
35 |
+
'to_remove_device' => __( 'To remove a Yubikey device, enter the registered device ID and save.', 'wp-simple-firewall' ),
|
36 |
+
'multiple_for_pro' => sprintf( '[%s] %s', __( 'Pro Only', 'wp-simple-firewall' ),
|
37 |
__( 'You may add as many Yubikey devices to your profile as you need to.', 'wp-simple-firewall' ) ),
|
38 |
+
'description_otp_code' => __( 'This is your unique Yubikey Device ID.', 'wp-simple-firewall' ),
|
39 |
+
'description_otp' => __( 'Provide a One Time Password from your Yubikey.', 'wp-simple-firewall' ),
|
40 |
+
'label_enter_code' => __( 'Yubikey ID', 'wp-simple-firewall' ),
|
41 |
+
'label_enter_otp' => __( 'Yubikey OTP', 'wp-simple-firewall' ),
|
42 |
+
'title' => __( 'Yubikey Authentication', 'wp-simple-firewall' ),
|
43 |
+
'cant_add_other_user' => sprintf( __( "Sorry, %s may not be added to another user's account.", 'wp-simple-firewall' ), 'Yubikey' ),
|
44 |
+
'cant_remove_admins' => sprintf( __( "Sorry, %s may only be removed from another user's account by a Security Administrator.", 'wp-simple-firewall' ), __( 'Yubikey', 'wp-simple-firewall' ) ),
|
45 |
+
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $con->getHumanName() ),
|
46 |
+
'remove_more_info' => sprintf( __( 'Understand how to remove Google Authenticator', 'wp-simple-firewall' ) )
|
47 |
],
|
48 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
|
51 |
/**
|
132 |
}
|
133 |
|
134 |
/**
|
135 |
+
* @param string $otp
|
136 |
* @return bool
|
137 |
*/
|
138 |
+
private function sendYubiOtpRequest( $otp ) {
|
139 |
+
/** @var LoginGuard\Options $opts */
|
140 |
+
$opts = $this->getOptions();
|
141 |
+
$otp = trim( $otp );
|
142 |
+
$success = false;
|
143 |
+
|
144 |
+
if ( preg_match( '#^[a-z]{44}$#', $otp ) ) {
|
145 |
+
$parts = [
|
146 |
+
'otp' => $otp,
|
147 |
'nonce' => md5( uniqid( $this->getCon()->getUniqueRequestId() ) ),
|
148 |
+
'id' => $opts->getYubikeyAppId()
|
149 |
];
|
150 |
|
151 |
+
$response = Services::HttpRequest()->getContent( add_query_arg( $parts, self::URL_YUBIKEY_VERIFY ) );
|
|
|
|
|
152 |
|
153 |
+
unset( $parts[ 'id' ] );
|
154 |
+
$parts[ 'status' ] = 'OK';
|
155 |
|
156 |
+
$success = true;
|
157 |
+
foreach ( $parts as $key => $value ) {
|
158 |
+
if ( !preg_match( sprintf( '#%s=%s#', $key, $value ), $response ) ) {
|
159 |
+
$success = false;
|
160 |
break;
|
161 |
}
|
162 |
}
|
163 |
}
|
164 |
|
165 |
+
return $success;
|
166 |
+
}
|
167 |
+
|
168 |
+
public function toggleRegisteredYubiID( \WP_User $user, string $key ) :StdResponse {
|
169 |
+
$response = new StdResponse();
|
170 |
+
$response->success = true;
|
171 |
+
|
172 |
+
if ( strlen( $key ) > self::OTP_LENGTH ) {
|
173 |
+
$key = substr( $key, 0, self::OTP_LENGTH );
|
174 |
+
}
|
175 |
+
$IDs = $this->getYubiIds( $user );
|
176 |
+
|
177 |
+
if ( in_array( $key, $IDs ) ) {
|
178 |
+
$IDs = Services::DataManipulation()->removeFromArrayByValue( $IDs, $key );
|
179 |
+
$response->msg_text = sprintf(
|
180 |
+
__( '%s was removed from your profile.', 'wp-simple-firewall' ),
|
181 |
+
__( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $key )
|
182 |
+
);
|
183 |
+
}
|
184 |
+
else {
|
185 |
+
$IDs[] = $key;
|
186 |
+
$response->msg_text = sprintf(
|
187 |
+
__( '%s was added to your profile.', 'wp-simple-firewall' ),
|
188 |
+
__( 'Yubikey Device', 'wp-simple-firewall' ).sprintf( ' (%s)', $key )
|
189 |
+
);
|
190 |
+
}
|
191 |
+
|
192 |
+
$this->setSecret( $user, implode( ',', array_unique( array_filter( $IDs ) ) ) );
|
193 |
+
|
194 |
+
return $response;
|
195 |
}
|
196 |
|
197 |
/**
|
198 |
* @param \WP_User $user
|
199 |
+
* @param string $key
|
200 |
+
* @param bool $add - true to add; false to remove
|
201 |
* @return $this
|
202 |
*/
|
203 |
+
public function addRemoveRegisteredYubiId( \WP_User $user, string $key, $add = true ) {
|
204 |
+
$IDs = $this->getYubiIds( $user );
|
205 |
+
|
206 |
+
if ( strlen( $key ) > self::OTP_LENGTH ) {
|
207 |
+
$key = substr( $key, 0, self::OTP_LENGTH );
|
208 |
+
}
|
209 |
+
|
210 |
+
if ( $add ) {
|
211 |
+
$IDs[] = $key;
|
212 |
}
|
213 |
else {
|
214 |
+
$IDs = Services::DataManipulation()->removeFromArrayByValue( $IDs, $key );
|
215 |
}
|
216 |
+
return $this->setSecret( $user, implode( ',', array_unique( array_filter( $IDs ) ) ) );
|
217 |
}
|
218 |
|
219 |
/**
|
235 |
/**
|
236 |
* @return array
|
237 |
*/
|
238 |
+
public function getFormField() :array {
|
239 |
return [
|
240 |
'name' => $this->getLoginFormParameter(),
|
241 |
'type' => 'text',
|
266 |
}
|
267 |
return $bValid;
|
268 |
}
|
269 |
+
|
270 |
+
public function getProviderName() :string {
|
271 |
+
return 'Yubikey';
|
272 |
+
}
|
273 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/UserProfile.php
CHANGED
@@ -10,89 +10,89 @@ class UserProfile {
|
|
10 |
use MfaControllerConsumer;
|
11 |
|
12 |
public function run() {
|
13 |
-
if ( is_admin() ) {
|
14 |
add_action( 'show_user_profile', [ $this, 'addOptionsToUserProfile' ] );
|
15 |
-
add_action( '
|
16 |
-
if ( $this->getMfaCon()->getCon()->isPluginAdmin() ) {
|
17 |
-
add_action( 'edit_user_profile', [ $this, 'addOptionsToUserEditProfile' ] );
|
18 |
-
add_action( 'edit_user_profile_update', [ $this, 'handleEditOtherUserProfileSubmit' ] );
|
19 |
-
}
|
20 |
-
|
21 |
-
$oWpUsers = Services::WpUsers();
|
22 |
-
if ( $oWpUsers->isUserLoggedIn() ) {
|
23 |
-
$oMC = $this->getMfaCon();
|
24 |
-
foreach ( $oMC->getProvidersForUser( $oWpUsers->getCurrentWpUser(), false ) as $oP ) {
|
25 |
-
$oP->setupProfile();
|
26 |
-
}
|
27 |
-
}
|
28 |
}
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
33 |
* functions. Otherwise we need to be careful of mixing up users.
|
34 |
-
* @param \WP_User $
|
35 |
*/
|
36 |
-
public function addOptionsToUserProfile( $
|
37 |
$oMC = $this->getMfaCon();
|
38 |
-
$
|
39 |
-
$
|
40 |
-
if ( count( $
|
41 |
-
$
|
42 |
-
foreach ( $
|
43 |
-
$
|
44 |
}
|
45 |
|
46 |
-
$aData = [
|
47 |
-
'is_my_user_profile' => ( $oUser->ID == $oWpUsers->getCurrentWpUserId() ),
|
48 |
-
'i_am_valid_admin' => $oMC->getCon()->isPluginAdmin(),
|
49 |
-
'user_to_edit_is_admin' => $oWpUsers->isUserAdmin( $oUser ),
|
50 |
-
'strings' => [
|
51 |
-
'title' => __( 'Multi-Factor Authentication', 'wp-simple-firewall' ),
|
52 |
-
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $oMC->getCon()
|
53 |
-
->getHumanName() )
|
54 |
-
],
|
55 |
-
'mfa_rows' => $aRows,
|
56 |
-
];
|
57 |
-
|
58 |
echo $oMC->getMod()
|
59 |
->renderTemplate(
|
60 |
-
'/
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
true
|
63 |
);
|
64 |
}
|
65 |
}
|
66 |
|
67 |
-
/**
|
68 |
-
* This MUST only ever be hooked into when the User is looking at their OWN profile,
|
69 |
-
* so we can use "current user" functions. Otherwise we need to be careful of mixing up users.
|
70 |
-
* @param int $nSavingUserId
|
71 |
-
*/
|
72 |
-
public function handleUserProfileSubmit( $nSavingUserId ) {
|
73 |
-
$oUser = Services::WpUsers()->getUserById( $nSavingUserId );
|
74 |
-
foreach ( $this->getMfaCon()->getProvidersForUser( $oUser ) as $oProvider ) {
|
75 |
-
$oProvider->handleUserProfileSubmit( $oUser );
|
76 |
-
}
|
77 |
-
}
|
78 |
-
|
79 |
/**
|
80 |
* ONLY TO BE HOOKED TO USER PROFILE EDIT
|
81 |
-
* @param \WP_User $
|
82 |
*/
|
83 |
-
public function addOptionsToUserEditProfile( $
|
84 |
-
$this->
|
85 |
-
|
|
|
|
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
}
|
98 |
}
|
10 |
use MfaControllerConsumer;
|
11 |
|
12 |
public function run() {
|
13 |
+
if ( is_admin() ) {
|
14 |
add_action( 'show_user_profile', [ $this, 'addOptionsToUserProfile' ] );
|
15 |
+
add_action( 'edit_user_profile', [ $this, 'addOptionsToUserEditProfile' ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
17 |
}
|
18 |
|
19 |
/**
|
20 |
* This MUST only ever be hooked into when the User is looking at their OWN profile, so we can use "current user"
|
21 |
* functions. Otherwise we need to be careful of mixing up users.
|
22 |
+
* @param \WP_User $user
|
23 |
*/
|
24 |
+
public function addOptionsToUserProfile( $user ) {
|
25 |
$oMC = $this->getMfaCon();
|
26 |
+
$WPU = Services::WpUsers();
|
27 |
+
$providers = $oMC->getProvidersForUser( $user );
|
28 |
+
if ( count( $providers ) > 0 ) {
|
29 |
+
$rows = [];
|
30 |
+
foreach ( $providers as $provider ) {
|
31 |
+
$rows[ $provider::SLUG ] = $provider->renderUserProfileOptions( $user );
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
echo $oMC->getMod()
|
35 |
->renderTemplate(
|
36 |
+
'/admin/user/profile/mfa/mfa_container.twig',
|
37 |
+
[
|
38 |
+
'user_to_edit_is_admin' => $WPU->isUserAdmin( $user ),
|
39 |
+
'strings' => [
|
40 |
+
'title' => __( 'Multi-Factor Authentication', 'wp-simple-firewall' ),
|
41 |
+
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $oMC->getCon()
|
42 |
+
->getHumanName() )
|
43 |
+
],
|
44 |
+
'mfa_rows' => $rows,
|
45 |
+
],
|
46 |
true
|
47 |
);
|
48 |
}
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
/**
|
52 |
* ONLY TO BE HOOKED TO USER PROFILE EDIT
|
53 |
+
* @param \WP_User $user
|
54 |
*/
|
55 |
+
public function addOptionsToUserEditProfile( $user ) {
|
56 |
+
$mfaCon = $this->getMfaCon();
|
57 |
+
$con = $mfaCon->getCon();
|
58 |
+
$WPU = Services::WpUsers();
|
59 |
+
$pluginName = $con->getHumanName();
|
60 |
|
61 |
+
$providers = array_map(
|
62 |
+
function ( $provider ) {
|
63 |
+
return $provider->getProviderName();
|
64 |
+
},
|
65 |
+
$mfaCon->getProvidersForUser( $user, true )
|
66 |
+
);
|
67 |
+
|
68 |
+
echo $mfaCon->getMod()
|
69 |
+
->renderTemplate(
|
70 |
+
'/admin/user/profile/mfa/remove_for_other_user.twig',
|
71 |
+
[
|
72 |
+
'flags' => [
|
73 |
+
'has_factors' => count( $providers ) > 0,
|
74 |
+
'is_admin_profile' => $WPU->isUserAdmin( $user ),
|
75 |
+
'can_remove' => $con->isPluginAdmin() || !$WPU->isUserAdmin( $user ),
|
76 |
+
],
|
77 |
+
'vars' => [
|
78 |
+
'user_id' => $user->ID,
|
79 |
+
'mfa_factor_names' => $providers,
|
80 |
+
],
|
81 |
+
'strings' => [
|
82 |
+
'title' => __( 'Multi-Factor Authentication', 'wp-simple-firewall' ),
|
83 |
+
'provided_by' => sprintf( __( 'Provided by %s', 'wp-simple-firewall' ), $pluginName ),
|
84 |
+
'currently_active' => __( 'Currently active MFA Providers on this profile are' ),
|
85 |
+
'remove_all' => __( 'Remove All MFA Providers' ),
|
86 |
+
'remove_all_from' => __( 'Remove All MFA Providers From This User Profile' ),
|
87 |
+
'remove_warning' => __( "Certain providers may not be removed if they're enforced." ),
|
88 |
+
'no_providers' => __( 'There are no MFA providers active on this user account.' ),
|
89 |
+
'only_secadmin' => sprintf( __( 'Only %s Security Admins may modify the MFA settings of another admin account.' ),
|
90 |
+
$pluginName ),
|
91 |
+
'authenticate' => sprintf( __( 'You may authenticate with the %s Security Admin system and return here.' ),
|
92 |
+
$pluginName ),
|
93 |
+
],
|
94 |
+
],
|
95 |
+
true
|
96 |
+
);
|
97 |
}
|
98 |
}
|
src/lib/src/Modules/LoginGuard/Lib/TwoFactor/ValidateLoginIntentRequest.php
CHANGED
@@ -33,12 +33,12 @@ class ValidateLoginIntentRequest {
|
|
33 |
|
34 |
$validated = false;
|
35 |
{ // Backup code is special case
|
36 |
-
if ( isset( $providers[ Provider\
|
37 |
-
if ( $providers[ Provider\
|
38 |
$validated = true;
|
39 |
-
$aSuccessfulProviders[] = $providers[ Provider\
|
40 |
}
|
41 |
-
unset( $providers[ Provider\
|
42 |
}
|
43 |
}
|
44 |
|
33 |
|
34 |
$validated = false;
|
35 |
{ // Backup code is special case
|
36 |
+
if ( isset( $providers[ Provider\BackupCodes::SLUG ] ) ) {
|
37 |
+
if ( $providers[ Provider\BackupCodes::SLUG ]->validateLoginIntent( $user ) ) {
|
38 |
$validated = true;
|
39 |
+
$aSuccessfulProviders[] = $providers[ Provider\BackupCodes::SLUG ];
|
40 |
}
|
41 |
+
unset( $providers[ Provider\BackupCodes::SLUG ] );
|
42 |
}
|
43 |
}
|
44 |
|
src/lib/src/Modules/LoginGuard/ModCon.php
CHANGED
@@ -266,8 +266,8 @@ class ModCon extends BaseShield\ModCon {
|
|
266 |
return $text;
|
267 |
}
|
268 |
|
269 |
-
public function
|
270 |
-
$this->getOptions()->setOpt( '
|
271 |
}
|
272 |
|
273 |
public function getScriptLocalisations() :array {
|
@@ -276,8 +276,10 @@ class ModCon extends BaseShield\ModCon {
|
|
276 |
'global-plugin',
|
277 |
'icwp_wpsf_vars_lg',
|
278 |
[
|
279 |
-
'
|
280 |
-
|
|
|
|
|
281 |
]
|
282 |
];
|
283 |
return $locals;
|
266 |
return $text;
|
267 |
}
|
268 |
|
269 |
+
public function setEnabledAntiBotDetection( bool $enable ) {
|
270 |
+
$this->getOptions()->setOpt( 'enable_antibot_check', $enable ? 'Y' : 'N' );
|
271 |
}
|
272 |
|
273 |
public function getScriptLocalisations() :array {
|
276 |
'global-plugin',
|
277 |
'icwp_wpsf_vars_lg',
|
278 |
[
|
279 |
+
'ajax' => [
|
280 |
+
'gen_backup_codes' => $this->getAjaxActionData( 'gen_backup_codes' ),
|
281 |
+
'del_backup_codes' => $this->getAjaxActionData( 'del_backup_codes' ),
|
282 |
+
],
|
283 |
]
|
284 |
];
|
285 |
return $locals;
|
src/lib/src/Modules/LoginGuard/Options.php
CHANGED
@@ -6,6 +6,10 @@ use FernleafSystems\Wordpress\Plugin\Shield\Modules\BaseShield;
|
|
6 |
|
7 |
class Options extends BaseShield\Options {
|
8 |
|
|
|
|
|
|
|
|
|
9 |
public function getLoginIntentMinutes() :int {
|
10 |
return (int)max( 1, apply_filters(
|
11 |
$this->getCon()->prefix( 'login_intent_timeout' ),
|
6 |
|
7 |
class Options extends BaseShield\Options {
|
8 |
|
9 |
+
public function getBotProtectionLocations() :array {
|
10 |
+
return is_array( $this->getOpt( 'bot_protection_locations' ) ) ? $this->getOpt( 'bot_protection_locations' ) : [];
|
11 |
+
}
|
12 |
+
|
13 |
public function getLoginIntentMinutes() :int {
|
14 |
return (int)max( 1, apply_filters(
|
15 |
$this->getCon()->prefix( 'login_intent_timeout' ),
|
src/lib/src/Modules/LoginGuard/Strings.php
CHANGED
@@ -144,6 +144,7 @@ class Strings extends Base\Strings {
|
|
144 |
* @throws \Exception
|
145 |
*/
|
146 |
public function getOptionStrings( string $key ) :array {
|
|
|
147 |
/** @var ModCon $mod */
|
148 |
$mod = $this->getMod();
|
149 |
$modName = $mod->getMainFeatureName();
|
@@ -211,7 +212,10 @@ class Strings extends Base\Strings {
|
|
211 |
|
212 |
case 'enable_google_recaptcha_login' :
|
213 |
$name = __( 'CAPTCHA', 'wp-simple-firewall' );
|
214 |
-
$summary =
|
|
|
|
|
|
|
215 |
$desc = __( 'Use CAPTCHA on the user account forms such as login, register, etc.', 'wp-simple-firewall' ).'<br />'
|
216 |
.sprintf( __( 'Use of any theme other than "%s", requires a Pro license.', 'wp-simple-firewall' ), __( 'Light Theme', 'wp-simple-firewall' ) )
|
217 |
.'<br/>'.sprintf( '%s - %s', __( 'Note', 'wp-simple-firewall' ), __( "You'll need to setup your CAPTCHA API Keys in 'General' settings.", 'wp-simple-firewall' ) )
|
@@ -219,11 +223,11 @@ class Strings extends Base\Strings {
|
|
219 |
break;
|
220 |
|
221 |
case 'enable_antibot_check' :
|
222 |
-
$name = __( 'AntiBot Detection Engine', 'wp-simple-firewall' );
|
223 |
-
$summary = __(
|
224 |
$desc = [
|
225 |
sprintf( __( "AntiBot Detection Engine is %s's exclusive bot-detection technology that removes the needs for CAPTCHA and other challenges.", 'wp-simple-firewall' ),
|
226 |
-
$
|
227 |
__( 'This feature is designed to replace the CAPTCHA and Bot Protection options.', 'wp-simple-firewall' ),
|
228 |
sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ),
|
229 |
__( "Switching on this feature will disable the CAPTCHA and Bot Protection settings.", 'wp-simple-firewall' ) )
|
@@ -233,22 +237,35 @@ class Strings extends Base\Strings {
|
|
233 |
case 'bot_protection_locations' :
|
234 |
$name = __( 'Protection Locations', 'wp-simple-firewall' );
|
235 |
$summary = __( 'Which Forms Should Be Protected', 'wp-simple-firewall' );
|
236 |
-
$desc =
|
237 |
-
|
|
|
|
|
|
|
|
|
|
|
238 |
break;
|
239 |
|
240 |
case 'enable_login_gasp_check' :
|
241 |
$name = __( 'Bot Protection', 'wp-simple-firewall' );
|
242 |
-
$summary =
|
243 |
-
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
245 |
break;
|
246 |
|
247 |
case 'antibot_form_ids' :
|
248 |
$name = __( 'AntiBot Forms', 'wp-simple-firewall' );
|
249 |
-
$summary =
|
|
|
|
|
|
|
250 |
$desc = [
|
251 |
-
__( 'Provide DOM selectors to
|
252 |
__( 'IDs are prefixed with "#".', 'wp-simple-firewall' ),
|
253 |
__( 'Classes are prefixed with ".".', 'wp-simple-firewall' ),
|
254 |
__( 'IDs are preferred over classes.', 'wp-simple-firewall' )
|
@@ -276,7 +293,6 @@ class Strings extends Base\Strings {
|
|
276 |
$desc = [
|
277 |
__( 'Allow users to register U2F devices to complete their login.', 'wp-simple-firewall' ),
|
278 |
__( "Currently only U2F keys are supported. Built-in fingerprint scanners aren't supported (yet).", 'wp-simple-firewall' ),
|
279 |
-
__( "Beta! This may only be used when at least 1 other 2FA option is enabled on a user account.", 'wp-simple-firewall' ),
|
280 |
];
|
281 |
break;
|
282 |
|
144 |
* @throws \Exception
|
145 |
*/
|
146 |
public function getOptionStrings( string $key ) :array {
|
147 |
+
$con = $this->getCon();
|
148 |
/** @var ModCon $mod */
|
149 |
$mod = $this->getMod();
|
150 |
$modName = $mod->getMainFeatureName();
|
212 |
|
213 |
case 'enable_google_recaptcha_login' :
|
214 |
$name = __( 'CAPTCHA', 'wp-simple-firewall' );
|
215 |
+
$summary = sprintf( '[DEPRECATED - %s] : %s',
|
216 |
+
'Please use the newer AntiBot setting above',
|
217 |
+
__( 'Protect WordPress Account Access Requests With CAPTCHA', 'wp-simple-firewall' )
|
218 |
+
);
|
219 |
$desc = __( 'Use CAPTCHA on the user account forms such as login, register, etc.', 'wp-simple-firewall' ).'<br />'
|
220 |
.sprintf( __( 'Use of any theme other than "%s", requires a Pro license.', 'wp-simple-firewall' ), __( 'Light Theme', 'wp-simple-firewall' ) )
|
221 |
.'<br/>'.sprintf( '%s - %s', __( 'Note', 'wp-simple-firewall' ), __( "You'll need to setup your CAPTCHA API Keys in 'General' settings.", 'wp-simple-firewall' ) )
|
223 |
break;
|
224 |
|
225 |
case 'enable_antibot_check' :
|
226 |
+
$name = __( 'AntiBot Detection Engine (ADE)', 'wp-simple-firewall' );
|
227 |
+
$summary = __( 'Use ADE To Detect Bots And Block Brute Force Logins', 'wp-simple-firewall' );
|
228 |
$desc = [
|
229 |
sprintf( __( "AntiBot Detection Engine is %s's exclusive bot-detection technology that removes the needs for CAPTCHA and other challenges.", 'wp-simple-firewall' ),
|
230 |
+
$con->getHumanName() ),
|
231 |
__( 'This feature is designed to replace the CAPTCHA and Bot Protection options.', 'wp-simple-firewall' ),
|
232 |
sprintf( '%s - %s', __( 'Important', 'wp-simple-firewall' ),
|
233 |
__( "Switching on this feature will disable the CAPTCHA and Bot Protection settings.", 'wp-simple-firewall' ) )
|
237 |
case 'bot_protection_locations' :
|
238 |
$name = __( 'Protection Locations', 'wp-simple-firewall' );
|
239 |
$summary = __( 'Which Forms Should Be Protected', 'wp-simple-firewall' );
|
240 |
+
$desc = [
|
241 |
+
__( 'Choose the forms for which bot protection measures will be deployed.', 'wp-simple-firewall' ),
|
242 |
+
sprintf( '%s - %s', __( 'Note', 'wp-simple-firewall' ), sprintf( __( "Use with 3rd party systems such as %s, requires a Pro license.", 'wp-simple-firewall' ), 'WooCommerce' ) ),
|
243 |
+
sprintf( '<a href="%s">%s</a>', $con->getModule_Integrations()
|
244 |
+
->getUrl_DirectLinkToSection( 'section_user_forms' ),
|
245 |
+
sprintf( __( "Choose the 3rd party plugins you want %s to also integrate with.", 'wp-simple-firewall' ), $con->getHumanName() ) )
|
246 |
+
];
|
247 |
break;
|
248 |
|
249 |
case 'enable_login_gasp_check' :
|
250 |
$name = __( 'Bot Protection', 'wp-simple-firewall' );
|
251 |
+
$summary = sprintf( '[DEPRECATED - %s] %s',
|
252 |
+
'Please use the newer AntiBot setting above',
|
253 |
+
__( 'Protect WP Login From Automated Login Attempts By Bots', 'wp-simple-firewall' )
|
254 |
+
);
|
255 |
+
$desc = [
|
256 |
+
__( 'Adds a dynamically (Javascript) generated checkbox to the login form that prevents bots using automated login techniques.', 'wp-simple-firewall' ),
|
257 |
+
sprintf( '%s: %s', __( 'Recommendation', 'wp-simple-firewall' ), __( 'ON', 'wp-simple-firewall' ) )
|
258 |
+
];
|
259 |
break;
|
260 |
|
261 |
case 'antibot_form_ids' :
|
262 |
$name = __( 'AntiBot Forms', 'wp-simple-firewall' );
|
263 |
+
$summary = sprintf( '%s %s',
|
264 |
+
'[DEPRECATED - Please use the newer AntiBot setting above]',
|
265 |
+
__( 'Enter The Selectors Of The 3rd Party Login Forms For Use With AntiBot JS', 'wp-simple-firewall' )
|
266 |
+
);
|
267 |
$desc = [
|
268 |
+
__( 'Provide DOM selectors to attach AntiBot protection to any form.', 'wp-simple-firewall' ),
|
269 |
__( 'IDs are prefixed with "#".', 'wp-simple-firewall' ),
|
270 |
__( 'Classes are prefixed with ".".', 'wp-simple-firewall' ),
|
271 |
__( 'IDs are preferred over classes.', 'wp-simple-firewall' )
|
293 |
$desc = [
|
294 |
__( 'Allow users to register U2F devices to complete their login.', 'wp-simple-firewall' ),
|
295 |
__( "Currently only U2F keys are supported. Built-in fingerprint scanners aren't supported (yet).", 'wp-simple-firewall' ),
|
|
|
296 |
];
|
297 |
break;
|
298 |
|
src/lib/src/Modules/LoginGuard/UI.php
CHANGED
@@ -8,12 +8,34 @@ use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Time\WorldTimeApi;
|
|
8 |
class UI extends BaseShield\UI {
|
9 |
|
10 |
protected function getSectionWarnings( string $section ) :array {
|
|
|
|
|
|
|
|
|
11 |
$warnings = [];
|
12 |
|
13 |
-
if ( $section == 'section_brute_force_login_protection'
|
14 |
-
|
15 |
-
if (
|
16 |
-
$warnings[] =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
18 |
}
|
19 |
|
@@ -37,24 +59,4 @@ class UI extends BaseShield\UI {
|
|
37 |
|
38 |
return $warnings;
|
39 |
}
|
40 |
-
|
41 |
-
/**
|
42 |
-
* @return string
|
43 |
-
*/
|
44 |
-
private function getPremiumOnlyIntegration() {
|
45 |
-
$aIntegrations = [
|
46 |
-
'WooCommerce' => 'WooCommerce',
|
47 |
-
'Easy_Digital_Downloads' => 'Easy Digital Downloads',
|
48 |
-
'BuddyPress' => 'BuddyPress',
|
49 |
-
];
|
50 |
-
|
51 |
-
$sIntegration = '';
|
52 |
-
foreach ( $aIntegrations as $classToIntegrate => $sName ) {
|
53 |
-
if ( class_exists( $classToIntegrate ) ) {
|
54 |
-
$sIntegration = $sName;
|
55 |
-
break;
|
56 |
-
}
|
57 |
-
}
|
58 |
-
return $sIntegration;
|
59 |
-
}
|
60 |
}
|
8 |
class UI extends BaseShield\UI {
|
9 |
|
10 |
protected function getSectionWarnings( string $section ) :array {
|
11 |
+
$con = $this->getCon();
|
12 |
+
/** @var Options $opts */
|
13 |
+
$opts = $this->getOptions();
|
14 |
+
|
15 |
$warnings = [];
|
16 |
|
17 |
+
if ( $section == 'section_brute_force_login_protection' ) {
|
18 |
+
|
19 |
+
if ( empty( $opts->getBotProtectionLocations() ) ) {
|
20 |
+
$warnings[] = __( "AntiBot detection isn't being applied to your site because you haven't selected any forms to protect, such as Login or Register.", 'wp-simple-firewall' );
|
21 |
+
}
|
22 |
+
|
23 |
+
$installedButNotEnabledProviders = array_filter(
|
24 |
+
$con->getModule_Integrations()
|
25 |
+
->getController_UserForms()
|
26 |
+
->getInstalledProviders(),
|
27 |
+
function ( $provider ) {
|
28 |
+
return !$provider->isEnabled();
|
29 |
+
}
|
30 |
+
);
|
31 |
+
if ( !empty( $installedButNotEnabledProviders ) ) {
|
32 |
+
$warnings[] = sprintf( __( "%s has an integration available to protect the login forms of a 3rd party plugin you're using: %s", 'wp-simple-firewall' ),
|
33 |
+
$con->getHumanName(),
|
34 |
+
sprintf( '<a href="%s">%s</a>',
|
35 |
+
$con->getModule_Integrations()->getUrl_DirectLinkToSection( 'section_user_forms' ),
|
36 |
+
sprintf( __( "View the available integrations.", 'wp-simple-firewall' ), $con->getHumanName() )
|
37 |
+
)
|
38 |
+
);
|
39 |
}
|
40 |
}
|
41 |
|
59 |
|
60 |
return $warnings;
|
61 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
src/lib/src/Modules/Plugin/AdminNotices.php
CHANGED
@@ -249,13 +249,16 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
|
|
249 |
|
250 |
private function buildNotice_WelcomeWizard( NoticeVO $notice ) {
|
251 |
$name = $this->getCon()->getHumanName();
|
|
|
252 |
$notice->render_data = [
|
253 |
-
'notice_attributes' => [
|
|
|
|
|
254 |
'strings' => [
|
255 |
'dismiss' => __( "I don't need the setup wizard just now", 'wp-simple-firewall' ),
|
256 |
'title' => sprintf( __( 'Get started quickly with the %s Setup Wizard', 'wp-simple-firewall' ), $name ),
|
257 |
'setup' => sprintf( __( 'The welcome wizard will help you get setup quickly and become familiar with some of the core %s features', 'wp-simple-firewall' ), $name ),
|
258 |
-
'launch' =>
|
259 |
],
|
260 |
'hrefs' => [
|
261 |
'wizard' => $this->getMod()->getUrl_Wizard( 'welcome' ),
|
@@ -311,11 +314,15 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
|
|
311 |
|
312 |
protected function isDisplayNeeded( NoticeVO $notice ) :bool {
|
313 |
$con = $this->getCon();
|
314 |
-
/** @var Options $
|
315 |
-
$
|
316 |
|
317 |
switch ( $notice->id ) {
|
318 |
|
|
|
|
|
|
|
|
|
319 |
case 'plugin-too-old':
|
320 |
$needed = $this->isNeeded_PluginTooOld();
|
321 |
break;
|
@@ -329,7 +336,7 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
|
|
329 |
break;
|
330 |
|
331 |
case 'plugin-disabled':
|
332 |
-
$needed = $
|
333 |
break;
|
334 |
|
335 |
case 'update-available':
|
@@ -341,7 +348,7 @@ class AdminNotices extends Shield\Modules\Base\AdminNotices {
|
|
341 |
break;
|
342 |
|
343 |
case 'allow-tracking':
|
344 |
-
$needed = !$
|
345 |
break;
|
346 |
|
347 |
default:
|
249 |
|
250 |
private function buildNotice_WelcomeWizard( NoticeVO $notice ) {
|
251 |
$name = $this->getCon()->getHumanName();
|
252 |
+
$insideWizard = Services::Request()->query( 'wizard', false ) === 'welcome';
|
253 |
$notice->render_data = [
|
254 |
+
'notice_attributes' => [
|
255 |
+
'insideWizard' => $insideWizard ? 1 : 0,
|
256 |
+
],
|
257 |
'strings' => [
|
258 |
'dismiss' => __( "I don't need the setup wizard just now", 'wp-simple-firewall' ),
|
259 |
'title' => sprintf( __( 'Get started quickly with the %s Setup Wizard', 'wp-simple-firewall' ), $name ),
|
260 |
'setup' => sprintf( __( 'The welcome wizard will help you get setup quickly and become familiar with some of the core %s features', 'wp-simple-firewall' ), $name ),
|
261 |
+
'launch' => sprintf( __( "Launch the welcome wizard", 'wp-simple-firewall' ), $name ),
|
262 |
],
|
263 |
'hrefs' => [
|
264 |
'wizard' => $this->getMod()->getUrl_Wizard( 'welcome' ),
|
314 |
|
315 |
protected function isDisplayNeeded( NoticeVO $notice ) :bool {
|
316 |
$con = $this->getCon();
|
317 |
+
/** @var Options $opts */
|
318 |
+
$opts = $this->getOptions();
|
319 |
|
320 |
switch ( $notice->id ) {
|
321 |
|
322 |
+
case 'wizard_welcome':
|
323 |
+
$needed = false;
|
324 |
+
break;
|
325 |
+
|
326 |
case 'plugin-too-old':
|
327 |
$needed = $this->isNeeded_PluginTooOld();
|
328 |
break;
|
336 |
break;
|
337 |
|
338 |
case 'plugin-disabled':
|
339 |
+
$needed = $opts->isPluginGloballyDisabled();
|
340 |
break;
|
341 |
|
342 |
case 'update-available':
|
348 |
break;
|
349 |
|
350 |
case 'allow-tracking':
|
351 |
+
$needed = !$opts->isTrackingPermissionSet();
|
352 |
break;
|
353 |
|
354 |
default:
|
src/lib/src/Modules/Plugin/AjaxHandler.php
CHANGED
@@ -56,6 +56,9 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
56 |
$response = $this->ajaxExec_MarkTourFinished();
|
57 |
break;
|
58 |
|
|
|
|
|
|
|
59 |
default:
|
60 |
$response = parent::processAjaxAction( $action );
|
61 |
}
|
@@ -63,6 +66,18 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
63 |
return $response;
|
64 |
}
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
private function ajaxExec_PluginBadgeClose() :array {
|
67 |
/** @var ModCon $mod */
|
68 |
$mod = $this->getMod();
|
56 |
$response = $this->ajaxExec_MarkTourFinished();
|
57 |
break;
|
58 |
|
59 |
+
case 'wizard_step':
|
60 |
+
$response = $this->ajaxExec_Wizard();
|
61 |
+
break;
|
62 |
default:
|
63 |
$response = parent::processAjaxAction( $action );
|
64 |
}
|
66 |
return $response;
|
67 |
}
|
68 |
|
69 |
+
private function ajaxExec_Wizard() {
|
70 |
+
$params = FormParams::Retrieve();
|
71 |
+
// step will be step1, step2 etc.
|
72 |
+
$currentStep = intval( str_replace( 'step', '', $params[ 'step' ] ) );
|
73 |
+
$data = $params[ $params[ 'step' ] ];
|
74 |
+
return [
|
75 |
+
'success' => true,
|
76 |
+
'message' => $currentStep < 3 ? $data : 'done done done',
|
77 |
+
'next' => $currentStep < 3 ? 'step'.++$currentStep : 'done',
|
78 |
+
];
|
79 |
+
}
|
80 |
+
|
81 |
private function ajaxExec_PluginBadgeClose() :array {
|
82 |
/** @var ModCon $mod */
|
83 |
$mod = $this->getMod();
|
src/lib/src/Modules/Plugin/Components/PluginBadge.php
CHANGED
@@ -17,8 +17,12 @@ class PluginBadge {
|
|
17 |
public function run() {
|
18 |
/** @var Plugin\Options $opts */
|
19 |
$opts = $this->getOptions();
|
20 |
-
$
|
21 |
-
|
|
|
|
|
|
|
|
|
22 |
if ( $display ) {
|
23 |
add_action( 'wp_enqueue_scripts', [ $this, 'includeJquery' ] );
|
24 |
add_action( 'login_enqueue_scripts', [ $this, 'includeJquery' ] );
|
@@ -63,10 +67,11 @@ class PluginBadge {
|
|
63 |
*/
|
64 |
public function render( $isFloating = false ) {
|
65 |
$con = $this->getCon();
|
66 |
-
|
67 |
-
$secAdminOpts = $con->getModule_SecAdmin()->getOptions();
|
68 |
|
69 |
-
if ( $
|
|
|
|
|
70 |
$badgeUrl = $secAdminOpts->getOpt( 'wl_homeurl' );
|
71 |
$name = $secAdminOpts->getOpt( 'wl_pluginnamemain' );
|
72 |
$logo = $secAdminOpts->getOpt( 'wl_dashboardlogourl' );
|
17 |
public function run() {
|
18 |
/** @var Plugin\Options $opts */
|
19 |
$opts = $this->getOptions();
|
20 |
+
$req = Services::Request();
|
21 |
+
|
22 |
+
$display = apply_filters( 'shield/show_security_badge',
|
23 |
+
$opts->isOpt( 'display_plugin_badge', 'Y' ) && ( $req->cookie( $this->getCookieIdBadgeState() ) != 'closed' )
|
24 |
+
);
|
25 |
+
|
26 |
if ( $display ) {
|
27 |
add_action( 'wp_enqueue_scripts', [ $this, 'includeJquery' ] );
|
28 |
add_action( 'login_enqueue_scripts', [ $this, 'includeJquery' ] );
|
67 |
*/
|
68 |
public function render( $isFloating = false ) {
|
69 |
$con = $this->getCon();
|
70 |
+
$wlCon = $con->getModule_SecAdmin()->getWhiteLabelController();
|
|
|
71 |
|
72 |
+
if ( $wlCon->isEnabled() && $wlCon->isReplacePluginBadge() ) {
|
73 |
+
/** @var Modules\SecurityAdmin\Options $secAdminOpts */
|
74 |
+
$secAdminOpts = $con->getModule_SecAdmin()->getOptions();
|
75 |
$badgeUrl = $secAdminOpts->getOpt( 'wl_homeurl' );
|
76 |
$name = $secAdminOpts->getOpt( 'wl_pluginnamemain' );
|
77 |
$logo = $secAdminOpts->getOpt( 'wl_dashboardlogourl' );
|
src/lib/src/Modules/Plugin/Insights/OverviewCards.php
CHANGED
@@ -9,29 +9,19 @@ use FernleafSystems\Wordpress\Services\Utilities\Ssl;
|
|
9 |
|
10 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
11 |
|
12 |
-
|
13 |
/** @var Plugin\ModCon $mod */
|
14 |
$mod = $this->getMod();
|
15 |
/** @var Plugin\Options $opts */
|
16 |
$opts = $this->getOptions();
|
17 |
|
18 |
-
$cardSection = [
|
19 |
-
'title' => __( 'General Settings', 'wp-simple-firewall' ),
|
20 |
-
'subtitle' => sprintf( __( 'General %s Settings', 'wp-simple-firewall' ),
|
21 |
-
$this->getCon()->getHumanName() ),
|
22 |
-
'href_options' => $mod->getUrl_AdminPage()
|
23 |
-
];
|
24 |
-
|
25 |
$cards = [];
|
26 |
|
27 |
-
if (
|
28 |
-
$cards[] = $this->getModDisabledCard();
|
29 |
-
}
|
30 |
-
else {
|
31 |
$bHasSupportEmail = Services::Data()->validEmail( $opts->getOpt( 'block_send_email_address' ) );
|
32 |
$cards[ 'reports' ] = [
|
33 |
'name' => __( 'Reporting Email', 'wp-simple-firewall' ),
|
34 |
-
'state' => $bHasSupportEmail ? 1 :
|
35 |
'summary' => $bHasSupportEmail ?
|
36 |
sprintf( __( 'Email address for reports set to: %s', 'wp-simple-firewall' ), $mod->getPluginReportEmail() )
|
37 |
: sprintf( __( 'No reporting address provided - defaulting to: %s', 'wp-simple-firewall' ), $mod->getPluginReportEmail() ),
|
@@ -57,14 +47,20 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
57 |
];
|
58 |
}
|
59 |
|
60 |
-
|
61 |
$cards,
|
62 |
$this->getNoticesSsl(),
|
63 |
$this->getNoticesDb()
|
64 |
);
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
-
|
67 |
-
return
|
|
|
68 |
}
|
69 |
|
70 |
private function getNoticesDb() :array {
|
9 |
|
10 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
11 |
|
12 |
+
protected function buildModCards() :array {
|
13 |
/** @var Plugin\ModCon $mod */
|
14 |
$mod = $this->getMod();
|
15 |
/** @var Plugin\Options $opts */
|
16 |
$opts = $this->getOptions();
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
$cards = [];
|
19 |
|
20 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
21 |
$bHasSupportEmail = Services::Data()->validEmail( $opts->getOpt( 'block_send_email_address' ) );
|
22 |
$cards[ 'reports' ] = [
|
23 |
'name' => __( 'Reporting Email', 'wp-simple-firewall' ),
|
24 |
+
'state' => $bHasSupportEmail ? 1 : 0,
|
25 |
'summary' => $bHasSupportEmail ?
|
26 |
sprintf( __( 'Email address for reports set to: %s', 'wp-simple-firewall' ), $mod->getPluginReportEmail() )
|
27 |
: sprintf( __( 'No reporting address provided - defaulting to: %s', 'wp-simple-firewall' ), $mod->getPluginReportEmail() ),
|
47 |
];
|
48 |
}
|
49 |
|
50 |
+
return array_merge(
|
51 |
$cards,
|
52 |
$this->getNoticesSsl(),
|
53 |
$this->getNoticesDb()
|
54 |
);
|
55 |
+
}
|
56 |
+
|
57 |
+
protected function getSectionTitle() :string {
|
58 |
+
return __( 'General Settings', 'wp-simple-firewall' );
|
59 |
+
}
|
60 |
|
61 |
+
protected function getSectionSubTitle() :string {
|
62 |
+
return sprintf( __( 'General %s Settings', 'wp-simple-firewall' ),
|
63 |
+
$this->getCon()->getHumanName() );
|
64 |
}
|
65 |
|
66 |
private function getNoticesDb() :array {
|
src/lib/src/Modules/Plugin/Lib/PluginTelemetry.php
CHANGED
@@ -2,21 +2,18 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Events\Select;
|
|
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\ModCon;
|
9 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
10 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
|
11 |
use FernleafSystems\Wordpress\Services\Services;
|
12 |
|
13 |
-
class PluginTelemetry {
|
14 |
|
15 |
-
use ModConsumer;
|
16 |
-
use ExecOnce;
|
17 |
use PluginCronsConsumer;
|
18 |
|
19 |
-
protected function canRun() :bool
|
20 |
/** @var Plugin\Options $opts */
|
21 |
$opts = $this->getOptions();
|
22 |
return $opts->isTrackingEnabled() || !$opts->isTrackingPermissionSet();
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin\Lib;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Crons\PluginCronsConsumer;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Events\Select;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\ModCon;
|
|
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Plugin;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
+
class PluginTelemetry extends ExecOnceModConsumer {
|
13 |
|
|
|
|
|
14 |
use PluginCronsConsumer;
|
15 |
|
16 |
+
protected function canRun() :bool {
|
17 |
/** @var Plugin\Options $opts */
|
18 |
$opts = $this->getOptions();
|
19 |
return $opts->isTrackingEnabled() || !$opts->isTrackingPermissionSet();
|
src/lib/src/Modules/Plugin/Strings.php
CHANGED
@@ -235,7 +235,7 @@ class Strings extends Base\Strings {
|
|
235 |
|
236 |
case 'display_plugin_badge' :
|
237 |
$name = __( 'Show Plugin Badge', 'wp-simple-firewall' );
|
238 |
-
$summary = __( 'Display Plugin Badge
|
239 |
$desc = [
|
240 |
__( 'Enabling this option helps support the plugin by spreading the word about it on your website.', 'wp-simple-firewall' )
|
241 |
.' '.__( 'The plugin badge also lets visitors know your are taking your website security seriously.', 'wp-simple-firewall' ),
|
235 |
|
236 |
case 'display_plugin_badge' :
|
237 |
$name = __( 'Show Plugin Badge', 'wp-simple-firewall' );
|
238 |
+
$summary = __( 'Display Plugin Security Badge To Your Visitors', 'wp-simple-firewall' );
|
239 |
$desc = [
|
240 |
__( 'Enabling this option helps support the plugin by spreading the word about it on your website.', 'wp-simple-firewall' )
|
241 |
.' '.__( 'The plugin badge also lets visitors know your are taking your website security seriously.', 'wp-simple-firewall' ),
|
src/lib/src/Modules/Plugin/UI.php
CHANGED
@@ -38,6 +38,33 @@ class UI extends BaseShield\UI {
|
|
38 |
];
|
39 |
}
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
/**
|
42 |
* @param array $aOptParams
|
43 |
* @return array
|
38 |
];
|
39 |
}
|
40 |
|
41 |
+
public function buildInsightsVars_Wizard( $wizard, $step ) :array {
|
42 |
+
$data = [];
|
43 |
+
switch ( $wizard ) {
|
44 |
+
case 'welcome':
|
45 |
+
$data = [
|
46 |
+
'steps' => [
|
47 |
+
'step1' => 'content for step1',
|
48 |
+
'step2' => 'content for step2',
|
49 |
+
'step3' => 'content for step3',
|
50 |
+
],
|
51 |
+
'currentStep' => 'step'.$step,
|
52 |
+
'ajax' => [
|
53 |
+
'wizard_step' => $this->getMod()->getAjaxActionData( 'wizard_step', true ),
|
54 |
+
],
|
55 |
+
'strings' => [
|
56 |
+
'hohoho' => sprintf( __( '%s %s Page' ), $wizard, $this->getCon()->getHumanName() ),
|
57 |
+
],
|
58 |
+
'showSideNav' => 0,
|
59 |
+
];
|
60 |
+
break;
|
61 |
+
default:
|
62 |
+
break;
|
63 |
+
}
|
64 |
+
|
65 |
+
return $data;
|
66 |
+
}
|
67 |
+
|
68 |
/**
|
69 |
* @param array $aOptParams
|
70 |
* @return array
|
src/lib/src/Modules/Reporting/Lib/ReportingController.php
CHANGED
@@ -44,6 +44,7 @@ class ReportingController {
|
|
44 |
}
|
45 |
}
|
46 |
catch ( \Exception $e ) {
|
|
|
47 |
}
|
48 |
}
|
49 |
|
@@ -56,6 +57,7 @@ class ReportingController {
|
|
56 |
}
|
57 |
}
|
58 |
catch ( \Exception $e ) {
|
|
|
59 |
}
|
60 |
}
|
61 |
|
44 |
}
|
45 |
}
|
46 |
catch ( \Exception $e ) {
|
47 |
+
var_dump( $e->getMessage() );
|
48 |
}
|
49 |
}
|
50 |
|
57 |
}
|
58 |
}
|
59 |
catch ( \Exception $e ) {
|
60 |
+
var_dump( $e->getMessage() );
|
61 |
}
|
62 |
}
|
63 |
|
src/lib/src/Modules/Reporting/Lib/Reports/CreateReportVO.php
CHANGED
@@ -77,52 +77,65 @@ class CreateReportVO {
|
|
77 |
* @throws \Exception
|
78 |
*/
|
79 |
private function setIntervalBoundaries() {
|
|
|
80 |
|
81 |
-
$
|
82 |
-
$
|
83 |
|
84 |
switch ( $this->rep->interval ) {
|
85 |
// case 'realtime':
|
86 |
// break;
|
87 |
case 'lifetime': // TODO
|
88 |
$start = 0;
|
89 |
-
$end = $
|
90 |
break;
|
91 |
case 'hourly':
|
92 |
-
$
|
93 |
-
$
|
94 |
-
$
|
|
|
95 |
break;
|
|
|
96 |
case 'daily':
|
97 |
-
$
|
98 |
-
$
|
99 |
-
$
|
|
|
100 |
break;
|
|
|
101 |
case 'weekly':
|
102 |
-
$
|
103 |
-
$
|
104 |
-
$
|
|
|
105 |
break;
|
|
|
106 |
case 'monthly':
|
107 |
-
$
|
108 |
-
$
|
109 |
-
$start = $
|
110 |
-
$end = $
|
111 |
break;
|
|
|
112 |
case 'yearly':
|
113 |
-
$
|
114 |
-
$
|
115 |
-
$
|
|
|
116 |
break;
|
|
|
117 |
default:
|
118 |
throw new \Exception( 'Not a supported frequency' );
|
119 |
}
|
120 |
|
121 |
-
if ( $this->rep->previous instanceof Reports\EntryVO
|
122 |
-
&& $end <= $this->rep->previous->interval_end_at ) {
|
123 |
throw new \Exception( 'Attempting to create a duplicate report based on interval.' );
|
124 |
}
|
125 |
|
|
|
|
|
|
|
|
|
126 |
$this->rep->interval_start_at = $start;
|
127 |
$this->rep->interval_end_at = $end;
|
128 |
|
@@ -142,12 +155,4 @@ class CreateReportVO {
|
|
142 |
$this->rep->rid = is_numeric( $prevID ) ? $prevID + 1 : 1;
|
143 |
return $this;
|
144 |
}
|
145 |
-
|
146 |
-
/**
|
147 |
-
* TODO
|
148 |
-
* @return bool
|
149 |
-
*/
|
150 |
-
private function isOnDemandReport() {
|
151 |
-
return !Services::WpGeneral()->isCron();
|
152 |
-
}
|
153 |
}
|
77 |
* @throws \Exception
|
78 |
*/
|
79 |
private function setIntervalBoundaries() {
|
80 |
+
$req = Services::Request();
|
81 |
|
82 |
+
$intervalToReport = $req->carbon( true );
|
83 |
+
$currentIntervalStart = $req->carbon( true );
|
84 |
|
85 |
switch ( $this->rep->interval ) {
|
86 |
// case 'realtime':
|
87 |
// break;
|
88 |
case 'lifetime': // TODO
|
89 |
$start = 0;
|
90 |
+
$end = $intervalToReport->timestamp;
|
91 |
break;
|
92 |
case 'hourly':
|
93 |
+
$currentIntervalStart->startOfHour();
|
94 |
+
$intervalToReport->subHour();
|
95 |
+
$start = $intervalToReport->startOfHour()->timestamp;
|
96 |
+
$end = $intervalToReport->endOfHour()->timestamp;
|
97 |
break;
|
98 |
+
|
99 |
case 'daily':
|
100 |
+
$currentIntervalStart->startOfDay();
|
101 |
+
$intervalToReport->subDay();
|
102 |
+
$start = $intervalToReport->startOfDay()->timestamp;
|
103 |
+
$end = $intervalToReport->endOfDay()->timestamp;
|
104 |
break;
|
105 |
+
|
106 |
case 'weekly':
|
107 |
+
$currentIntervalStart->startOfWeek();
|
108 |
+
$intervalToReport->subWeek();
|
109 |
+
$start = $intervalToReport->startOfWeek()->timestamp;
|
110 |
+
$end = $intervalToReport->endOfWeek()->timestamp;
|
111 |
break;
|
112 |
+
|
113 |
case 'monthly':
|
114 |
+
$currentIntervalStart->startOfMonth();
|
115 |
+
$intervalToReport->day( 15 )->subMonth();
|
116 |
+
$start = $intervalToReport->startOfMonth()->timestamp;
|
117 |
+
$end = $intervalToReport->endOfMonth()->timestamp;
|
118 |
break;
|
119 |
+
|
120 |
case 'yearly':
|
121 |
+
$currentIntervalStart->startOfYear();
|
122 |
+
$intervalToReport->subYear();
|
123 |
+
$start = $intervalToReport->startOfYear()->timestamp;
|
124 |
+
$end = $intervalToReport->endOfYear()->timestamp;
|
125 |
break;
|
126 |
+
|
127 |
default:
|
128 |
throw new \Exception( 'Not a supported frequency' );
|
129 |
}
|
130 |
|
131 |
+
if ( $this->rep->previous instanceof Reports\EntryVO && $end <= $this->rep->previous->interval_end_at ) {
|
|
|
132 |
throw new \Exception( 'Attempting to create a duplicate report based on interval.' );
|
133 |
}
|
134 |
|
135 |
+
if ( $end > $currentIntervalStart->timestamp ) { // sanity check
|
136 |
+
throw new \Exception( 'Attempting to create for an interval greater than the current interval.' );
|
137 |
+
}
|
138 |
+
|
139 |
$this->rep->interval_start_at = $start;
|
140 |
$this->rep->interval_end_at = $end;
|
141 |
|
155 |
$this->rep->rid = is_numeric( $prevID ) ? $prevID + 1 : 1;
|
156 |
return $this;
|
157 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
}
|
src/lib/src/Modules/SecurityAdmin/Insights/OverviewCards.php
CHANGED
@@ -6,19 +6,12 @@ use FernleafSystems\Wordpress\Plugin\Shield;
|
|
6 |
|
7 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
8 |
|
9 |
-
|
10 |
/** @var Shield\Modules\SecurityAdmin\ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
/** @var Shield\Modules\SecurityAdmin\Options $opts */
|
13 |
$opts = $this->getOptions();
|
14 |
|
15 |
-
$cardSection = [
|
16 |
-
'title' => __( 'Security Admin', 'wp-simple-firewall' ),
|
17 |
-
'subtitle' => sprintf( __( 'Prevent Tampering With %s Settings', 'wp-simple-firewall' ),
|
18 |
-
$this->getCon()->getHumanName() ),
|
19 |
-
'href_options' => $mod->getUrl_AdminPage()
|
20 |
-
];
|
21 |
-
|
22 |
$cards = [];
|
23 |
|
24 |
$enabled = $mod->getSecurityAdminController()->isEnabledSecAdmin();
|
@@ -59,7 +52,15 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
59 |
];
|
60 |
}
|
61 |
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
}
|
65 |
}
|
6 |
|
7 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
8 |
|
9 |
+
protected function buildModCards() :array {
|
10 |
/** @var Shield\Modules\SecurityAdmin\ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
/** @var Shield\Modules\SecurityAdmin\Options $opts */
|
13 |
$opts = $this->getOptions();
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
$cards = [];
|
16 |
|
17 |
$enabled = $mod->getSecurityAdminController()->isEnabledSecAdmin();
|
52 |
];
|
53 |
}
|
54 |
|
55 |
+
return $cards;
|
56 |
+
}
|
57 |
+
|
58 |
+
protected function getSectionTitle() :string {
|
59 |
+
return __( 'Security Admin', 'wp-simple-firewall' );
|
60 |
+
}
|
61 |
+
|
62 |
+
protected function getSectionSubTitle() :string {
|
63 |
+
return sprintf( __( 'Prevent Tampering With %s Settings', 'wp-simple-firewall' ),
|
64 |
+
$this->getCon()->getHumanName() );
|
65 |
}
|
66 |
}
|
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/Base.php
CHANGED
@@ -2,11 +2,8 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\SecurityAdmin\Restrictions;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
|
8 |
-
class Base {
|
9 |
|
10 |
-
use ExecOnce;
|
11 |
-
use ModConsumer;
|
12 |
}
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\SecurityAdmin\Restrictions;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
|
7 |
+
class Base extends ExecOnceModConsumer {
|
8 |
|
|
|
|
|
9 |
}
|
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/WpOptions.php
CHANGED
@@ -28,7 +28,6 @@ class WpOptions extends Base {
|
|
28 |
* @param string $key
|
29 |
* @param mixed $oldValue
|
30 |
* @return mixed
|
31 |
-
* @deprecated 11.1
|
32 |
*/
|
33 |
public function blockOptionsSaves( $newValue, $key, $oldValue ) {
|
34 |
/** @var Options $opts */
|
28 |
* @param string $key
|
29 |
* @param mixed $oldValue
|
30 |
* @return mixed
|
|
|
31 |
*/
|
32 |
public function blockOptionsSaves( $newValue, $key, $oldValue ) {
|
33 |
/** @var Options $opts */
|
src/lib/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php
CHANGED
@@ -2,17 +2,13 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\SecurityAdmin;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\ModCon;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Options;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
-
class SecurityAdminController {
|
13 |
-
|
14 |
-
use ExecOnce;
|
15 |
-
use ModConsumer;
|
16 |
|
17 |
private $validPinRequest;
|
18 |
|
@@ -28,21 +24,10 @@ class SecurityAdminController {
|
|
28 |
} );
|
29 |
add_action( 'init', function () {
|
30 |
if ( !$this->getCon()->isPluginAdmin() ) {
|
31 |
-
|
32 |
-
|
33 |
-
->execute();
|
34 |
-
|
35 |
-
->setMod( $this->getMod() )
|
36 |
-
->execute();
|
37 |
-
( new Restrictions\Themes() )
|
38 |
-
->setMod( $this->getMod() )
|
39 |
-
->execute();
|
40 |
-
( new Restrictions\Posts() )
|
41 |
-
->setMod( $this->getMod() )
|
42 |
-
->execute();
|
43 |
-
( new Restrictions\Users() )
|
44 |
-
->setMod( $this->getMod() )
|
45 |
-
->execute();
|
46 |
|
47 |
if ( !$this->getCon()->isThisPluginModuleRequest() ) {
|
48 |
add_action( 'admin_footer', [ $this, 'printPinLoginForm' ] );
|
@@ -51,6 +36,19 @@ class SecurityAdminController {
|
|
51 |
} );
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
public function isEnabledSecAdmin() :bool {
|
55 |
/** @var Options $opts */
|
56 |
$opts = $this->getOptions();
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\SecurityAdmin;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Controller\Assets\Enqueue;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\ModCon;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Options;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
+
class SecurityAdminController extends ExecOnceModConsumer {
|
|
|
|
|
|
|
12 |
|
13 |
private $validPinRequest;
|
14 |
|
24 |
} );
|
25 |
add_action( 'init', function () {
|
26 |
if ( !$this->getCon()->isPluginAdmin() ) {
|
27 |
+
|
28 |
+
foreach ( $this->getAllRestrictionZones() as $zone ) {
|
29 |
+
$zone->setMod( $this->getMod() )->execute();
|
30 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
if ( !$this->getCon()->isThisPluginModuleRequest() ) {
|
33 |
add_action( 'admin_footer', [ $this, 'printPinLoginForm' ] );
|
36 |
} );
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* @return Restrictions\Base[]
|
41 |
+
*/
|
42 |
+
private function getAllRestrictionZones() :array {
|
43 |
+
return [
|
44 |
+
new Restrictions\WpOptions(),
|
45 |
+
new Restrictions\Plugins(),
|
46 |
+
new Restrictions\Themes(),
|
47 |
+
new Restrictions\Posts(),
|
48 |
+
new Restrictions\Users(),
|
49 |
+
];
|
50 |
+
}
|
51 |
+
|
52 |
public function isEnabledSecAdmin() :bool {
|
53 |
/** @var Options $opts */
|
54 |
$opts = $this->getOptions();
|
src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php
CHANGED
@@ -37,7 +37,7 @@ class BuildOptions {
|
|
37 |
* @param string $key
|
38 |
* @return string
|
39 |
*/
|
40 |
-
|
41 |
$opts = $this->getOptions();
|
42 |
|
43 |
$url = $opts->getOpt( $key );
|
37 |
* @param string $key
|
38 |
* @return string
|
39 |
*/
|
40 |
+
public function buildWlImageUrl( string $key ) {
|
41 |
$opts = $this->getOptions();
|
42 |
|
43 |
$url = $opts->getOpt( $key );
|
src/lib/src/Modules/SecurityAdmin/Lib/WhiteLabel/{ApplyLabels.php → WhitelabelController.php}
RENAMED
@@ -1,21 +1,23 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\WhiteLabel;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
-
class
|
11 |
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
protected function canRun() :bool {
|
16 |
-
|
17 |
-
$opts = $this->getOptions();
|
18 |
-
return $opts->isEnabledWhitelabel();
|
19 |
}
|
20 |
|
21 |
protected function run() {
|
@@ -30,7 +32,8 @@ class ApplyLabels {
|
|
30 |
public function onWpInit() {
|
31 |
/** @var SecurityAdmin\Options $opts */
|
32 |
$opts = $this->getOptions();
|
33 |
-
if ( $opts->
|
|
|
34 |
$this->hideUpdates();
|
35 |
}
|
36 |
}
|
@@ -72,7 +75,7 @@ class ApplyLabels {
|
|
72 |
* @param array $pluginLabels
|
73 |
* @return array
|
74 |
*/
|
75 |
-
public function applyPluginLabels( $pluginLabels ) {
|
76 |
$labels = ( new BuildOptions() )
|
77 |
->setMod( $this->getMod() )
|
78 |
->build();
|
@@ -114,18 +117,33 @@ class ApplyLabels {
|
|
114 |
return array_merge( $labels, $pluginLabels );
|
115 |
}
|
116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
/**
|
118 |
* @filter
|
119 |
-
* @param array $
|
120 |
* @param string $pluginBaseFile
|
121 |
* @return array
|
122 |
*/
|
123 |
-
public function removePluginMetaLinks( $
|
124 |
if ( $pluginBaseFile == $this->getCon()->base_file ) {
|
125 |
-
unset( $
|
126 |
-
unset( $
|
127 |
}
|
128 |
-
return $
|
129 |
}
|
130 |
|
131 |
/**
|
@@ -134,10 +152,7 @@ class ApplyLabels {
|
|
134 |
* @return \stdClass
|
135 |
*/
|
136 |
public function hidePluginUpdatesFromUI( $plugins ) {
|
137 |
-
$
|
138 |
-
if ( isset( $plugins->response[ $file ] ) ) {
|
139 |
-
unset( $plugins->response[ $file ] );
|
140 |
-
}
|
141 |
return $plugins;
|
142 |
}
|
143 |
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin\Lib\WhiteLabel;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin;
|
7 |
use FernleafSystems\Wordpress\Services\Services;
|
8 |
|
9 |
+
class WhitelabelController extends ExecOnceModConsumer {
|
10 |
|
11 |
+
public function isEnabled() :bool {
|
12 |
+
/** @var SecurityAdmin\ModCon $mod */
|
13 |
+
$mod = $this->getMod();
|
14 |
+
return $this->getCon()->isPremiumActive()
|
15 |
+
&& $this->getOptions()->isOpt( 'whitelabel_enable', 'Y' )
|
16 |
+
&& $mod->getSecurityAdminController()->isEnabledSecAdmin();
|
17 |
+
}
|
18 |
|
19 |
protected function canRun() :bool {
|
20 |
+
return $this->isEnabled();
|
|
|
|
|
21 |
}
|
22 |
|
23 |
protected function run() {
|
32 |
public function onWpInit() {
|
33 |
/** @var SecurityAdmin\Options $opts */
|
34 |
$opts = $this->getOptions();
|
35 |
+
if ( $opts->isOpt( 'wl_hide_updates', 'Y' ) && $this->isNeedToHideUpdates() && !$this->getCon()
|
36 |
+
->isPluginAdmin() ) {
|
37 |
$this->hideUpdates();
|
38 |
}
|
39 |
}
|
75 |
* @param array $pluginLabels
|
76 |
* @return array
|
77 |
*/
|
78 |
+
public function applyPluginLabels( array $pluginLabels ) :array {
|
79 |
$labels = ( new BuildOptions() )
|
80 |
->setMod( $this->getMod() )
|
81 |
->build();
|
117 |
return array_merge( $labels, $pluginLabels );
|
118 |
}
|
119 |
|
120 |
+
public function isReplacePluginBadge() :bool {
|
121 |
+
return $this->getOptions()->isOpt( 'wl_replace_badge_url', 'Y' );
|
122 |
+
}
|
123 |
+
|
124 |
+
public function verifyUrls() {
|
125 |
+
$DP = Services::Data();
|
126 |
+
$opts = $this->getOptions();
|
127 |
+
$optsBuilder = ( new BuildOptions() )->setMod( $this->getMod() );
|
128 |
+
foreach ( [ 'wl_menuiconurl', 'wl_dashboardlogourl', 'wl_login2fa_logourl' ] as $key ) {
|
129 |
+
if ( $opts->isOptChanged( $key ) && !$DP->isValidWebUrl( $optsBuilder->buildWlImageUrl( $key ) ) ) {
|
130 |
+
$opts->resetOptToDefault( $key );
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
/**
|
136 |
* @filter
|
137 |
+
* @param array $pluginMeta
|
138 |
* @param string $pluginBaseFile
|
139 |
* @return array
|
140 |
*/
|
141 |
+
public function removePluginMetaLinks( $pluginMeta, $pluginBaseFile ) {
|
142 |
if ( $pluginBaseFile == $this->getCon()->base_file ) {
|
143 |
+
unset( $pluginMeta[ 2 ] ); // View details
|
144 |
+
unset( $pluginMeta[ 3 ] ); // Rate 5*
|
145 |
}
|
146 |
+
return $pluginMeta;
|
147 |
}
|
148 |
|
149 |
/**
|
152 |
* @return \stdClass
|
153 |
*/
|
154 |
public function hidePluginUpdatesFromUI( $plugins ) {
|
155 |
+
unset( $plugins->response[ $this->getCon()->base_file ] );
|
|
|
|
|
|
|
156 |
return $plugins;
|
157 |
}
|
158 |
|
src/lib/src/Modules/SecurityAdmin/ModCon.php
CHANGED
@@ -11,12 +11,7 @@ class ModCon extends BaseShield\ModCon {
|
|
11 |
const HASH_DELETE = '32f68a60cef40faedbc6af20298c1a1e';
|
12 |
|
13 |
/**
|
14 |
-
* @var
|
15 |
-
*/
|
16 |
-
private $bValidSecAdminRequest;
|
17 |
-
|
18 |
-
/**
|
19 |
-
* @var Lib\WhiteLabel\ApplyLabels
|
20 |
*/
|
21 |
private $whitelabelCon;
|
22 |
|
@@ -29,9 +24,9 @@ class ModCon extends BaseShield\ModCon {
|
|
29 |
add_action( $this->prefix( 'pre_deactivate_plugin' ), [ $this, 'preDeactivatePlugin' ] );
|
30 |
}
|
31 |
|
32 |
-
public function getWhiteLabelController() :Lib\WhiteLabel\
|
33 |
-
if ( !$this->whitelabelCon instanceof Lib\WhiteLabel\
|
34 |
-
$this->whitelabelCon = ( new Lib\WhiteLabel\
|
35 |
->setMod( $this );
|
36 |
}
|
37 |
return $this->whitelabelCon;
|
@@ -54,13 +49,7 @@ class ModCon extends BaseShield\ModCon {
|
|
54 |
$opts = $this->getOptions();
|
55 |
|
56 |
// Verify whitelabel images
|
57 |
-
|
58 |
-
foreach ( [ 'wl_menuiconurl', 'wl_dashboardlogourl', 'wl_login2fa_logourl' ] as $key ) {
|
59 |
-
if ( !Services::Data()->isValidWebUrl( $this->buildWlImageUrl( $key ) ) ) {
|
60 |
-
$opts->resetOptToDefault( $key );
|
61 |
-
}
|
62 |
-
}
|
63 |
-
}
|
64 |
|
65 |
$opts->setOpt( 'sec_admin_users',
|
66 |
( new Lib\SecurityAdmin\VerifySecurityAdminList() )
|
@@ -91,30 +80,6 @@ class ModCon extends BaseShield\ModCon {
|
|
91 |
}
|
92 |
}
|
93 |
|
94 |
-
/**
|
95 |
-
* @return array
|
96 |
-
* @deprecated 11.1
|
97 |
-
*/
|
98 |
-
public function getWhitelabelOptions() :array {
|
99 |
-
$opts = $this->getOptions();
|
100 |
-
$main = $opts->getOpt( 'wl_pluginnamemain' );
|
101 |
-
$menu = $opts->getOpt( 'wl_namemenu' );
|
102 |
-
if ( empty( $menu ) ) {
|
103 |
-
$menu = $main;
|
104 |
-
}
|
105 |
-
|
106 |
-
return [
|
107 |
-
'name_main' => $main,
|
108 |
-
'name_menu' => $menu,
|
109 |
-
'name_company' => $opts->getOpt( 'wl_companyname' ),
|
110 |
-
'description' => $opts->getOpt( 'wl_description' ),
|
111 |
-
'url_home' => $opts->getOpt( 'wl_homeurl' ),
|
112 |
-
'url_icon' => $this->buildWlImageUrl( 'wl_menuiconurl' ),
|
113 |
-
'url_dashboardlogourl' => $this->buildWlImageUrl( 'wl_dashboardlogourl' ),
|
114 |
-
'url_login2fa_logourl' => $this->buildWlImageUrl( 'wl_login2fa_logourl' ),
|
115 |
-
];
|
116 |
-
}
|
117 |
-
|
118 |
/**
|
119 |
* We cater for 3 options:
|
120 |
* Full URL
|
@@ -122,6 +87,7 @@ class ModCon extends BaseShield\ModCon {
|
|
122 |
* Or Plugin image URL i.e. doesn't start with HTTP or /
|
123 |
* @param string $key
|
124 |
* @return string
|
|
|
125 |
*/
|
126 |
private function buildWlImageUrl( $key ) {
|
127 |
$opts = $this->getOptions();
|
@@ -142,19 +108,6 @@ class ModCon extends BaseShield\ModCon {
|
|
142 |
return $url;
|
143 |
}
|
144 |
|
145 |
-
/**
|
146 |
-
* @deprecated 11.0
|
147 |
-
*/
|
148 |
-
public function isWlEnabled() :bool {
|
149 |
-
/** @var Options $opts */
|
150 |
-
$opts = $this->getOptions();
|
151 |
-
return $opts->isEnabledWhitelabel() && $this->isPremium();
|
152 |
-
}
|
153 |
-
|
154 |
-
public function isWlHideUpdates() :bool {
|
155 |
-
return $this->isEnabledWhitelabel() && $this->getOptions()->isOpt( 'wl_hide_updates', 'Y' );
|
156 |
-
}
|
157 |
-
|
158 |
/**
|
159 |
* Used by Wizard. TODO: sort out the wizard requests!
|
160 |
* @param string $pin
|
@@ -231,116 +184,4 @@ class ModCon extends BaseShield\ModCon {
|
|
231 |
);
|
232 |
}
|
233 |
}
|
234 |
-
|
235 |
-
/**
|
236 |
-
* No checking of admin capabilities in-case of infinite loop with
|
237 |
-
* admin access caps check
|
238 |
-
* @return bool
|
239 |
-
* @deprecated 11.1
|
240 |
-
*/
|
241 |
-
public function isRegisteredSecAdminUser() {
|
242 |
-
/** @var Options $opts */
|
243 |
-
$opts = $this->getOptions();
|
244 |
-
$sUser = Services::WpUsers()->getCurrentWpUsername();
|
245 |
-
return !empty( $sUser ) && in_array( $sUser, $opts->getSecurityAdminUsers() );
|
246 |
-
}
|
247 |
-
|
248 |
-
/**
|
249 |
-
* @return bool
|
250 |
-
* @deprecated 11.1
|
251 |
-
*/
|
252 |
-
public function isEnabledSecurityAdmin() :bool {
|
253 |
-
/** @var Options $opts */
|
254 |
-
$opts = $this->getOptions();
|
255 |
-
return $this->isModOptEnabled() &&
|
256 |
-
( count( $opts->getSecurityAdminUsers() ) > 0 ||
|
257 |
-
( $opts->hasSecurityPIN() && $this->getSecAdminTimeout() > 0 )
|
258 |
-
);
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* @return bool
|
263 |
-
* @deprecated 11.1
|
264 |
-
*/
|
265 |
-
public function isSecAdminSessionValid() :bool {
|
266 |
-
return $this->getSecAdminTimeLeft() > 0;
|
267 |
-
}
|
268 |
-
|
269 |
-
/**
|
270 |
-
* Only returns greater than 0 if you have a valid Sec admin session
|
271 |
-
* @deprecated 11.1
|
272 |
-
*/
|
273 |
-
public function getSecAdminTimeLeft() :int {
|
274 |
-
$nLeft = 0;
|
275 |
-
if ( $this->getCon()->getModule_Sessions()->getSessionCon()->hasSession() ) {
|
276 |
-
|
277 |
-
$nSecAdminAt = $this->getSession()->getSecAdminAt();
|
278 |
-
if ( $this->isRegisteredSecAdminUser() ) {
|
279 |
-
$nLeft = 0;
|
280 |
-
}
|
281 |
-
elseif ( $nSecAdminAt > 0 ) {
|
282 |
-
$nLeft = $this->getSecAdminTimeout() - ( Services::Request()->ts() - $nSecAdminAt );
|
283 |
-
}
|
284 |
-
}
|
285 |
-
return (int)max( 0, $nLeft );
|
286 |
-
}
|
287 |
-
|
288 |
-
/**
|
289 |
-
* @return int
|
290 |
-
* @deprecated 11.1
|
291 |
-
*/
|
292 |
-
public function getSecAdminTimeout() :int {
|
293 |
-
return (int)$this->getOptions()->getOpt( 'admin_access_timeout' )*MINUTE_IN_SECONDS;
|
294 |
-
}
|
295 |
-
|
296 |
-
/**
|
297 |
-
* Ensures that all entries are valid users.
|
298 |
-
* @param string[] $aSecUsers
|
299 |
-
* @return string[]
|
300 |
-
* @deprecated 11.1
|
301 |
-
*/
|
302 |
-
private function verifySecAdminUsers( $aSecUsers ) {
|
303 |
-
return $aSecUsers;
|
304 |
-
}
|
305 |
-
|
306 |
-
/**
|
307 |
-
* @return bool
|
308 |
-
* @deprecated 11.1
|
309 |
-
*/
|
310 |
-
private function isAccessKeyRequest() :bool {
|
311 |
-
return strlen( Services::Request()->post( 'sec_admin_key', '' ) ) > 0;
|
312 |
-
}
|
313 |
-
|
314 |
-
public function verifyAccessKey( string $key ) :bool {
|
315 |
-
/** @var Options $opts */
|
316 |
-
$opts = $this->getOptions();
|
317 |
-
return !empty( $key ) && hash_equals( $opts->getSecurityPIN(), md5( $key ) );
|
318 |
-
}
|
319 |
-
|
320 |
-
/**
|
321 |
-
* @return bool
|
322 |
-
* @deprecated 11.1
|
323 |
-
*/
|
324 |
-
public function testSecAccessKeyRequest() :bool {
|
325 |
-
return ( new Lib\SecurityAdmin\Ops\VerifyPinRequest() )
|
326 |
-
->setMod( $this )
|
327 |
-
->run();
|
328 |
-
}
|
329 |
-
|
330 |
-
/**
|
331 |
-
* @return bool
|
332 |
-
* @deprecated 11.1
|
333 |
-
*/
|
334 |
-
public function isValidSecAdminRequest() :bool {
|
335 |
-
return false;
|
336 |
-
}
|
337 |
-
|
338 |
-
/**
|
339 |
-
* @param bool $bSetOn
|
340 |
-
* @return bool
|
341 |
-
* @deprecated 11.1
|
342 |
-
*/
|
343 |
-
public function setSecurityAdminStatusOnOff( $bSetOn = false ) {
|
344 |
-
return false;
|
345 |
-
}
|
346 |
}
|
11 |
const HASH_DELETE = '32f68a60cef40faedbc6af20298c1a1e';
|
12 |
|
13 |
/**
|
14 |
+
* @var Lib\WhiteLabel\WhitelabelController
|
|
|
|
|
|
|
|
|
|
|
15 |
*/
|
16 |
private $whitelabelCon;
|
17 |
|
24 |
add_action( $this->prefix( 'pre_deactivate_plugin' ), [ $this, 'preDeactivatePlugin' ] );
|
25 |
}
|
26 |
|
27 |
+
public function getWhiteLabelController() :Lib\WhiteLabel\WhitelabelController {
|
28 |
+
if ( !$this->whitelabelCon instanceof Lib\WhiteLabel\WhitelabelController ) {
|
29 |
+
$this->whitelabelCon = ( new Lib\WhiteLabel\WhitelabelController() )
|
30 |
->setMod( $this );
|
31 |
}
|
32 |
return $this->whitelabelCon;
|
49 |
$opts = $this->getOptions();
|
50 |
|
51 |
// Verify whitelabel images
|
52 |
+
$this->getWhiteLabelController()->verifyUrls();
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
$opts->setOpt( 'sec_admin_users',
|
55 |
( new Lib\SecurityAdmin\VerifySecurityAdminList() )
|
80 |
}
|
81 |
}
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
/**
|
84 |
* We cater for 3 options:
|
85 |
* Full URL
|
87 |
* Or Plugin image URL i.e. doesn't start with HTTP or /
|
88 |
* @param string $key
|
89 |
* @return string
|
90 |
+
* @deprecated 11.2
|
91 |
*/
|
92 |
private function buildWlImageUrl( $key ) {
|
93 |
$opts = $this->getOptions();
|
108 |
return $url;
|
109 |
}
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
/**
|
112 |
* Used by Wizard. TODO: sort out the wizard requests!
|
113 |
* @param string $pin
|
184 |
);
|
185 |
}
|
186 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
}
|
src/lib/src/Modules/SecurityAdmin/Options.php
CHANGED
@@ -86,6 +86,10 @@ class Options extends BaseShield\Options {
|
|
86 |
return strlen( $this->getSecurityPIN() ) == 32;
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
89 |
public function isEnabledWhitelabel() :bool {
|
90 |
return $this->isOpt( 'whitelabel_enable', 'Y' ) && $this->isPremium();
|
91 |
}
|
@@ -98,11 +102,19 @@ class Options extends BaseShield\Options {
|
|
98 |
return $this->isOpt( 'admin_access_restrict_admin_users', 'Y' );
|
99 |
}
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
public function isReplacePluginBadge() :bool {
|
106 |
return $this->isOpt( 'wl_replace_badge_url', 'Y' );
|
107 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
86 |
return strlen( $this->getSecurityPIN() ) == 32;
|
87 |
}
|
88 |
|
89 |
+
/**
|
90 |
+
* @return bool
|
91 |
+
* @deprecated 11.2
|
92 |
+
*/
|
93 |
public function isEnabledWhitelabel() :bool {
|
94 |
return $this->isOpt( 'whitelabel_enable', 'Y' ) && $this->isPremium();
|
95 |
}
|
102 |
return $this->isOpt( 'admin_access_restrict_admin_users', 'Y' );
|
103 |
}
|
104 |
|
105 |
+
/**
|
106 |
+
* @return bool
|
107 |
+
* @deprecated 11.2
|
108 |
+
*/
|
109 |
public function isReplacePluginBadge() :bool {
|
110 |
return $this->isOpt( 'wl_replace_badge_url', 'Y' );
|
111 |
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* @return bool
|
115 |
+
* @deprecated 11.2
|
116 |
+
*/
|
117 |
+
public function isWlHideUpdates() :bool {
|
118 |
+
return false;
|
119 |
+
}
|
120 |
}
|
src/lib/src/Modules/SecurityAdmin/Processor.php
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
<?php
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin;
|
4 |
|
@@ -9,164 +9,7 @@ class Processor extends BaseShield\Processor {
|
|
9 |
protected function run() {
|
10 |
/** @var ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
-
|
13 |
-
/** @var Options $opts */
|
14 |
-
$opts = $this->getOptions();
|
15 |
-
if ( $opts->isEnabledWhitelabel() ) {
|
16 |
-
$mod->getWhiteLabelController()->execute();
|
17 |
-
}
|
18 |
-
|
19 |
$mod->getSecurityAdminController()->execute();
|
20 |
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @param bool $bHasPermission
|
24 |
-
* @return bool
|
25 |
-
* @deprecated 11.1
|
26 |
-
*/
|
27 |
-
public function adjustUserAdminPermissions( $bHasPermission = true ) :bool {
|
28 |
-
return $bHasPermission;
|
29 |
-
}
|
30 |
-
|
31 |
-
public function onWpInit() {
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @param int $nUserId
|
36 |
-
* @param string $sRole
|
37 |
-
* @deprecated 11.1
|
38 |
-
*/
|
39 |
-
public function restrictAddUserRole( $nUserId, $sRole ) {
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* @param int $nUserId
|
44 |
-
* @param string $sRole
|
45 |
-
* @param array $aOldRoles
|
46 |
-
* @deprecated 11.1
|
47 |
-
*/
|
48 |
-
public function restrictSetUserRole( $nUserId, $sRole, $aOldRoles = [] ) {
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* @param int $nUserId
|
53 |
-
* @param string $sRole
|
54 |
-
* @deprecated 11.1
|
55 |
-
*/
|
56 |
-
public function restrictRemoveUserRole( $nUserId, $sRole ) {
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* @param int $nId
|
61 |
-
* @deprecated 11.1
|
62 |
-
*/
|
63 |
-
public function restrictAdminUserDelete( $nId ) {
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* @param array[] $roles
|
68 |
-
* @return array[]
|
69 |
-
* @deprecated 11.1
|
70 |
-
*/
|
71 |
-
public function restrictEditableRoles( $roles ) {
|
72 |
-
return $roles;
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* This hooked function captures the attempts to modify the user role using the standard
|
77 |
-
* WordPress profile edit pages. It doesn't sufficiently capture the AJAX request to
|
78 |
-
* modify user roles. (see user role hooks)
|
79 |
-
* @param array $allCaps
|
80 |
-
* @param $cap
|
81 |
-
* @param array $args
|
82 |
-
* @return array
|
83 |
-
* @deprecated 11.1
|
84 |
-
*/
|
85 |
-
public function restrictAdminUserChanges( $allCaps, $cap, $args ) {
|
86 |
-
return $allCaps;
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* @deprecated 11.1
|
91 |
-
*/
|
92 |
-
public function blockOptionsSaves( $mNewOptionValue, $key, $mOldValue ) {
|
93 |
-
return $mNewOptionValue;
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* @deprecated 11.1
|
98 |
-
*/
|
99 |
-
private function isOptionForThisPlugin( string $key ) :bool {
|
100 |
-
return preg_match( $this->getOptionRegexPattern(), $key ) > 0;
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* @deprecated 11.1
|
105 |
-
*/
|
106 |
-
private function isOptionRestricted( string $key ) :bool {
|
107 |
-
/** @var Options $opts */
|
108 |
-
$opts = $this->getOptions();
|
109 |
-
return $opts->getAdminAccessArea_Options()
|
110 |
-
&& in_array( $key, $opts->getOptionsToRestrict() );
|
111 |
-
}
|
112 |
-
|
113 |
-
/**
|
114 |
-
* @param array $aAllCaps
|
115 |
-
* @param $cap
|
116 |
-
* @param array $aArgs
|
117 |
-
* @return array
|
118 |
-
* @deprecated 11.1
|
119 |
-
*/
|
120 |
-
public function disablePluginManipulation( $aAllCaps, $cap, $aArgs ) {
|
121 |
-
return $aAllCaps;
|
122 |
-
}
|
123 |
-
|
124 |
-
/**
|
125 |
-
* @param array $aAllCaps
|
126 |
-
* @param $cap
|
127 |
-
* @param array $aArgs
|
128 |
-
* @return array
|
129 |
-
* @deprecated 11.1
|
130 |
-
*/
|
131 |
-
public function disableThemeManipulation( $aAllCaps, $cap, $aArgs ) {
|
132 |
-
// If we're registered with Admin Access we don't modify anything
|
133 |
-
if ( $this->getCon()->isPluginAdmin() ) {
|
134 |
-
return $aAllCaps;
|
135 |
-
}
|
136 |
-
|
137 |
-
return $aAllCaps;
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* @param array $aAllCaps
|
142 |
-
* @param $cap
|
143 |
-
* @param array $args
|
144 |
-
* @return array
|
145 |
-
* @deprecated 11.1
|
146 |
-
*/
|
147 |
-
public function disablePostsManipulation( $aAllCaps, $cap, $args ) {
|
148 |
-
return $aAllCaps;
|
149 |
-
}
|
150 |
-
|
151 |
-
/**
|
152 |
-
* @deprecated 11.1
|
153 |
-
*/
|
154 |
-
private function getOptionRegexPattern() :string {
|
155 |
-
return sprintf( '/^%s.*_options$/', $this->getCon()->getOptionStoragePrefix() );
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* @deprecated 11.1
|
160 |
-
*/
|
161 |
-
public function printAdminAccessAjaxForm() {
|
162 |
-
}
|
163 |
-
|
164 |
-
/**
|
165 |
-
* @param string $sLinkText
|
166 |
-
* @return string
|
167 |
-
* @deprecated 11.1
|
168 |
-
*/
|
169 |
-
protected function getUnlockLinkHtml( $sLinkText = '' ) {
|
170 |
-
return '';
|
171 |
-
}
|
172 |
}
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\SecurityAdmin;
|
4 |
|
9 |
protected function run() {
|
10 |
/** @var ModCon $mod */
|
11 |
$mod = $this->getMod();
|
12 |
+
$mod->getWhiteLabelController()->execute();
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
$mod->getSecurityAdminController()->execute();
|
14 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
src/lib/src/Modules/Sessions/Lib/Ops/Retrieve.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\{
|
6 |
+
EntryVO,
|
7 |
+
Select
|
8 |
+
};
|
9 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
10 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\ModCon;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class Retrieve
|
14 |
+
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops
|
15 |
+
* @deprecated 11.2
|
16 |
+
*/
|
17 |
+
class Retrieve {
|
18 |
+
|
19 |
+
use ModConsumer;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param string $ip
|
23 |
+
* @return EntryVO|null
|
24 |
+
*/
|
25 |
+
public function byIP( string $ip ) {
|
26 |
+
return $this->getSelector()->filterByIp( $ip )->first();
|
27 |
+
}
|
28 |
+
|
29 |
+
public function byUsername( string $username ) :bool {
|
30 |
+
return $this->getSelector()->filterByUsername( $username )->first();
|
31 |
+
}
|
32 |
+
|
33 |
+
private function getSelector() :Select {
|
34 |
+
/** @var ModCon $mod */
|
35 |
+
$mod = $this->getMod();
|
36 |
+
return $mod->getDbHandler_Sessions()->getQuerySelector();
|
37 |
+
}
|
38 |
+
}
|
src/lib/src/Modules/Sessions/Lib/Ops/Terminate.php
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Delete;
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\ModCon;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
|
|
8 |
|
9 |
class Terminate {
|
10 |
|
@@ -20,16 +20,20 @@ class Terminate {
|
|
20 |
}
|
21 |
|
22 |
/**
|
23 |
-
* @param int $
|
24 |
* @return bool
|
25 |
*/
|
26 |
-
public function byRecordId( $
|
27 |
$this->getCon()->fireEvent( 'session_terminate' );
|
28 |
-
return $this->getDeleter()
|
|
|
|
|
29 |
}
|
30 |
|
31 |
public function byUsername( string $username ) :bool {
|
32 |
-
return $this->getDeleter()
|
|
|
|
|
33 |
}
|
34 |
|
35 |
private function getDeleter() :Delete {
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops;
|
4 |
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\Delete;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\ModCon;
|
8 |
|
9 |
class Terminate {
|
10 |
|
20 |
}
|
21 |
|
22 |
/**
|
23 |
+
* @param int $id
|
24 |
* @return bool
|
25 |
*/
|
26 |
+
public function byRecordId( int $id ) {
|
27 |
$this->getCon()->fireEvent( 'session_terminate' );
|
28 |
+
return $this->getDeleter()
|
29 |
+
->setIsSoftDelete()
|
30 |
+
->deleteById( $id );
|
31 |
}
|
32 |
|
33 |
public function byUsername( string $username ) :bool {
|
34 |
+
return $this->getDeleter()
|
35 |
+
->setIsSoftDelete()
|
36 |
+
->forUsername( $username ) !== false;
|
37 |
}
|
38 |
|
39 |
private function getDeleter() :Delete {
|
src/lib/src/Modules/Sessions/Lib/SessionController.php
CHANGED
@@ -5,6 +5,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib;
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\ModCon;
|
|
|
8 |
|
9 |
class SessionController {
|
10 |
|
@@ -15,13 +16,28 @@ class SessionController {
|
|
15 |
*/
|
16 |
private $current;
|
17 |
|
|
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* @return Session\EntryVO|null
|
20 |
*/
|
21 |
public function getCurrent() {
|
22 |
$con = $this->getCon();
|
23 |
-
if ( empty( $this->current ) && did_action( 'init' )
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
return $this->current;
|
27 |
}
|
@@ -45,6 +61,46 @@ class SessionController {
|
|
45 |
return $success;
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
public function queryCreateSession( string $sessionID, \WP_User $user ) :bool {
|
49 |
/** @var ModCon $mod */
|
50 |
$mod = $this->getMod();
|
@@ -69,6 +125,6 @@ class SessionController {
|
|
69 |
$mod = $this->getMod();
|
70 |
/** @var Session\Select $sel */
|
71 |
$sel = $mod->getDbHandler_Sessions()->getQuerySelector();
|
72 |
-
return $sel->retrieveUserSession( $sessionID, $username );
|
73 |
}
|
74 |
}
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\ModCon;
|
8 |
+
use FernleafSystems\Wordpress\Services\Services;
|
9 |
|
10 |
class SessionController {
|
11 |
|
16 |
*/
|
17 |
private $current;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var ?string
|
21 |
+
*/
|
22 |
+
private $sessionID;
|
23 |
+
|
24 |
/**
|
25 |
* @return Session\EntryVO|null
|
26 |
*/
|
27 |
public function getCurrent() {
|
28 |
$con = $this->getCon();
|
29 |
+
if ( empty( $this->current ) && did_action( 'init' ) ) {
|
30 |
+
if ( $this->hasSessionID() ) {
|
31 |
+
$this->current = $this->queryGetSession( $this->getSessionID() );
|
32 |
+
}
|
33 |
+
if ( $con->hasSessionId() ) {
|
34 |
+
if ( empty( $this->current ) ) {
|
35 |
+
$this->current = $this->queryGetSession( $con->getSessionId() );
|
36 |
+
}
|
37 |
+
else {
|
38 |
+
$con->clearSession();
|
39 |
+
}
|
40 |
+
}
|
41 |
}
|
42 |
return $this->current;
|
43 |
}
|
61 |
return $success;
|
62 |
}
|
63 |
|
64 |
+
public function createSession( \WP_User $user, string $sessionID = '' ) :bool {
|
65 |
+
/** @var ModCon $mod */
|
66 |
+
$mod = $this->getMod();
|
67 |
+
|
68 |
+
$success = false;
|
69 |
+
if ( empty( $sessionID ) ) {
|
70 |
+
$sessionID = $this->getSessionID();
|
71 |
+
}
|
72 |
+
|
73 |
+
if ( !empty( $sessionID ) && !empty( $user->user_login ) ) {
|
74 |
+
|
75 |
+
if ( !preg_match( '#^[a-z0-9]{32}$#i', $sessionID ) ) {
|
76 |
+
$sessionID = md5( $sessionID );
|
77 |
+
}
|
78 |
+
|
79 |
+
$this->sessionID = $sessionID;
|
80 |
+
|
81 |
+
/** @var Session\Insert $insert */
|
82 |
+
$insert = $mod->getDbHandler_Sessions()->getQueryInserter();
|
83 |
+
$success = $insert->create( $sessionID, $user->user_login );
|
84 |
+
|
85 |
+
$this->getCon()->fireEvent( 'session_start' );
|
86 |
+
}
|
87 |
+
return $success;
|
88 |
+
}
|
89 |
+
|
90 |
+
public function hasSessionID() :bool {
|
91 |
+
return !empty( $this->getSessionID() );
|
92 |
+
}
|
93 |
+
|
94 |
+
public function getSessionID() :string {
|
95 |
+
if ( empty( $this->sessionID ) ) {
|
96 |
+
$cookie = Services::Request()->cookie( LOGGED_IN_COOKIE );
|
97 |
+
if ( !empty( $cookie ) ) {
|
98 |
+
$this->sessionID = md5( $cookie );
|
99 |
+
}
|
100 |
+
}
|
101 |
+
return (string)$this->sessionID;
|
102 |
+
}
|
103 |
+
|
104 |
public function queryCreateSession( string $sessionID, \WP_User $user ) :bool {
|
105 |
/** @var ModCon $mod */
|
106 |
$mod = $this->getMod();
|
125 |
$mod = $this->getMod();
|
126 |
/** @var Session\Select $sel */
|
127 |
$sel = $mod->getDbHandler_Sessions()->getQuerySelector();
|
128 |
+
return $sel->retrieveUserSession( $sessionID, (string)$username );
|
129 |
}
|
130 |
}
|
src/lib/src/Modules/Sessions/Processor.php
CHANGED
@@ -32,8 +32,12 @@ class Processor extends BaseShield\Processor {
|
|
32 |
}
|
33 |
|
34 |
protected function captureLogin( \WP_User $user ) {
|
35 |
-
$this->
|
36 |
-
|
|
|
|
|
|
|
|
|
37 |
}
|
38 |
|
39 |
public function onWpLoaded() {
|
@@ -49,9 +53,9 @@ class Processor extends BaseShield\Processor {
|
|
49 |
if ( !Services::Rest()->isRest() && !$this->getCon()->plugin_deleting ) {
|
50 |
$session = $mod->getSessionCon()->getCurrent();
|
51 |
if ( $session instanceof Session\EntryVO ) {
|
52 |
-
/** @var Session\Update $
|
53 |
-
$
|
54 |
-
$
|
55 |
}
|
56 |
}
|
57 |
|
@@ -65,7 +69,7 @@ class Processor extends BaseShield\Processor {
|
|
65 |
if ( !$sessCon->hasSession() && $mod->isAutoAddSessions() ) {
|
66 |
$user = Services::WpUsers()->getCurrentWpUser();
|
67 |
if ( $user instanceof \WP_User ) {
|
68 |
-
$sessCon->
|
69 |
}
|
70 |
}
|
71 |
}
|
@@ -93,11 +97,19 @@ class Processor extends BaseShield\Processor {
|
|
93 |
return $msg;
|
94 |
}
|
95 |
|
|
|
|
|
|
|
|
|
96 |
private function activateUserSession( \WP_User $user ) {
|
97 |
/** @var ModCon $mod */
|
98 |
$mod = $this->getMod();
|
99 |
// If they have a currently active session, terminate it (i.e. we replace it)
|
100 |
$mod->getSessionCon()->terminateCurrentSession();
|
101 |
-
$mod->getSessionCon()->
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
}
|
32 |
}
|
33 |
|
34 |
protected function captureLogin( \WP_User $user ) {
|
35 |
+
if ( !empty( $this->getLoggedInCookie() ) ) {
|
36 |
+
$sessonCon = $this->getCon()->getModule_Sessions()->getSessionCon();
|
37 |
+
$sessonCon->terminateCurrentSession();
|
38 |
+
$sessonCon->createSession( $user, $this->getLoggedInCookie() );
|
39 |
+
$this->getCon()->fireEvent( 'login_success' );
|
40 |
+
}
|
41 |
}
|
42 |
|
43 |
public function onWpLoaded() {
|
53 |
if ( !Services::Rest()->isRest() && !$this->getCon()->plugin_deleting ) {
|
54 |
$session = $mod->getSessionCon()->getCurrent();
|
55 |
if ( $session instanceof Session\EntryVO ) {
|
56 |
+
/** @var Session\Update $update */
|
57 |
+
$update = $mod->getDbHandler_Sessions()->getQueryUpdater();
|
58 |
+
$update->updateLastActivity( $session );
|
59 |
}
|
60 |
}
|
61 |
|
69 |
if ( !$sessCon->hasSession() && $mod->isAutoAddSessions() ) {
|
70 |
$user = Services::WpUsers()->getCurrentWpUser();
|
71 |
if ( $user instanceof \WP_User ) {
|
72 |
+
$sessCon->createSession( $user );
|
73 |
}
|
74 |
}
|
75 |
}
|
97 |
return $msg;
|
98 |
}
|
99 |
|
100 |
+
/**
|
101 |
+
* @param \WP_User $user
|
102 |
+
* @deprecated 11.2
|
103 |
+
*/
|
104 |
private function activateUserSession( \WP_User $user ) {
|
105 |
/** @var ModCon $mod */
|
106 |
$mod = $this->getMod();
|
107 |
// If they have a currently active session, terminate it (i.e. we replace it)
|
108 |
$mod->getSessionCon()->terminateCurrentSession();
|
109 |
+
$mod->getSessionCon()->createSession( $user );
|
110 |
+
}
|
111 |
+
|
112 |
+
protected function getHookPriority() :int {
|
113 |
+
return 100;
|
114 |
}
|
115 |
}
|
src/lib/src/Modules/Traffic/Strings.php
CHANGED
@@ -94,8 +94,11 @@ class Strings extends Base\Strings {
|
|
94 |
case 'type_exclusions' :
|
95 |
$name = __( 'Traffic Log Exclusions', 'wp-simple-firewall' );
|
96 |
$summary = __( 'Select Which Types Of Requests To Exclude', 'wp-simple-firewall' );
|
97 |
-
$desc =
|
98 |
-
|
|
|
|
|
|
|
99 |
break;
|
100 |
|
101 |
case 'custom_exclusions' :
|
94 |
case 'type_exclusions' :
|
95 |
$name = __( 'Traffic Log Exclusions', 'wp-simple-firewall' );
|
96 |
$summary = __( 'Select Which Types Of Requests To Exclude', 'wp-simple-firewall' );
|
97 |
+
$desc = [
|
98 |
+
__( "There's no need to have unnecessary traffic noise in your logs, so we automatically exclude certain types of requests.", 'wp-simple-firewall' ),
|
99 |
+
__( "Select request types that you don't want to appear in the traffic viewer.", 'wp-simple-firewall' ),
|
100 |
+
__( 'If a request matches any exclusion rule, it wont show in the traffic logs.', 'wp-simple-firewall' )
|
101 |
+
];
|
102 |
break;
|
103 |
|
104 |
case 'custom_exclusions' :
|
src/lib/src/Modules/UserManagement/AjaxHandler.php
CHANGED
@@ -59,43 +59,43 @@ class AjaxHandler extends Shield\Modules\BaseShield\AjaxHandler {
|
|
59 |
$mod = $this->getMod();
|
60 |
$req = Services::Request();
|
61 |
|
62 |
-
$
|
63 |
|
64 |
-
$
|
65 |
-
if ( empty( $
|
66 |
-
$
|
67 |
-
$
|
68 |
}
|
69 |
elseif ( !in_array( $req->post( 'bulk_action' ), [ 'delete' ] ) ) {
|
70 |
-
$
|
71 |
}
|
72 |
else {
|
73 |
-
$
|
74 |
-
$bIncludesYourSession = in_array( $
|
75 |
|
76 |
-
if ( $bIncludesYourSession && ( count( $
|
77 |
-
$
|
78 |
}
|
79 |
else {
|
80 |
-
$
|
81 |
|
82 |
-
$
|
83 |
->setMod( $this->getCon()->getModule_Sessions() );
|
84 |
-
foreach ( $
|
85 |
-
if ( is_numeric( $
|
86 |
-
$
|
87 |
}
|
88 |
}
|
89 |
-
$
|
90 |
if ( $bIncludesYourSession ) {
|
91 |
-
$
|
92 |
}
|
93 |
}
|
94 |
}
|
95 |
|
96 |
return [
|
97 |
-
'success' => $
|
98 |
-
'message' => $
|
99 |
];
|
100 |
}
|
101 |
|
59 |
$mod = $this->getMod();
|
60 |
$req = Services::Request();
|
61 |
|
62 |
+
$success = false;
|
63 |
|
64 |
+
$IDs = $req->post( 'ids' );
|
65 |
+
if ( empty( $IDs ) || !is_array( $IDs ) ) {
|
66 |
+
$success = false;
|
67 |
+
$msg = __( 'No items selected.', 'wp-simple-firewall' );
|
68 |
}
|
69 |
elseif ( !in_array( $req->post( 'bulk_action' ), [ 'delete' ] ) ) {
|
70 |
+
$msg = __( 'Not a supported action.', 'wp-simple-firewall' );
|
71 |
}
|
72 |
else {
|
73 |
+
$yourId = $mod->getSession()->id;
|
74 |
+
$bIncludesYourSession = in_array( $yourId, $IDs );
|
75 |
|
76 |
+
if ( $bIncludesYourSession && ( count( $IDs ) == 1 ) ) {
|
77 |
+
$msg = __( 'Please logout if you want to delete your own session.', 'wp-simple-firewall' );
|
78 |
}
|
79 |
else {
|
80 |
+
$success = true;
|
81 |
|
82 |
+
$terminator = ( new Sessions\Lib\Ops\Terminate() )
|
83 |
->setMod( $this->getCon()->getModule_Sessions() );
|
84 |
+
foreach ( $IDs as $id ) {
|
85 |
+
if ( is_numeric( $id ) && ( $id != $yourId ) ) {
|
86 |
+
$terminator->byRecordId( (int)$id );
|
87 |
}
|
88 |
}
|
89 |
+
$msg = __( 'Selected items were deleted.', 'wp-simple-firewall' );
|
90 |
if ( $bIncludesYourSession ) {
|
91 |
+
$msg .= ' *'.__( 'Your session was retained', 'wp-simple-firewall' );
|
92 |
}
|
93 |
}
|
94 |
}
|
95 |
|
96 |
return [
|
97 |
+
'success' => $success,
|
98 |
+
'message' => $msg,
|
99 |
];
|
100 |
}
|
101 |
|
src/lib/src/Modules/UserManagement/Insights/OverviewCards.php
CHANGED
@@ -8,24 +8,15 @@ use FernleafSystems\Wordpress\Services\Services;
|
|
8 |
|
9 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
10 |
|
11 |
-
|
12 |
/** @var UserManagement\ModCon $mod */
|
13 |
$mod = $this->getMod();
|
14 |
/** @var UserManagement\Options $opts */
|
15 |
$opts = $this->getOptions();
|
16 |
|
17 |
-
$cardSection = [
|
18 |
-
'title' => __( 'User Management', 'wp-simple-firewall' ),
|
19 |
-
'subtitle' => __( 'Sessions Control & Password Policies', 'wp-simple-firewall' ),
|
20 |
-
'href_options' => $mod->getUrl_AdminPage()
|
21 |
-
];
|
22 |
-
|
23 |
$cards = [];
|
24 |
|
25 |
-
if (
|
26 |
-
$cards[] = $this->getModDisabledCard();
|
27 |
-
}
|
28 |
-
else {
|
29 |
$bHasIdle = $opts->hasSessionIdleTimeout();
|
30 |
$cards[ 'idle' ] = [
|
31 |
'name' => __( 'Idle Users', 'wp-simple-firewall' ),
|
@@ -81,7 +72,14 @@ class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
|
81 |
'help' => __( "The default 'admin' user should be deleted or demoted.", 'wp-simple-firewall' )
|
82 |
];
|
83 |
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
}
|
87 |
}
|
8 |
|
9 |
class OverviewCards extends Shield\Modules\Base\Insights\OverviewCards {
|
10 |
|
11 |
+
protected function buildModCards() :array {
|
12 |
/** @var UserManagement\ModCon $mod */
|
13 |
$mod = $this->getMod();
|
14 |
/** @var UserManagement\Options $opts */
|
15 |
$opts = $this->getOptions();
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
$cards = [];
|
18 |
|
19 |
+
if ( $mod->isModOptEnabled() ) {
|
|
|
|
|
|
|
20 |
$bHasIdle = $opts->hasSessionIdleTimeout();
|
21 |
$cards[ 'idle' ] = [
|
22 |
'name' => __( 'Idle Users', 'wp-simple-firewall' ),
|
72 |
'help' => __( "The default 'admin' user should be deleted or demoted.", 'wp-simple-firewall' )
|
73 |
];
|
74 |
|
75 |
+
return $cards;
|
76 |
+
}
|
77 |
+
|
78 |
+
protected function getSectionTitle() :string {
|
79 |
+
return __( 'User Management', 'wp-simple-firewall' );
|
80 |
+
}
|
81 |
+
|
82 |
+
protected function getSectionSubTitle() :string {
|
83 |
+
return __( 'Sessions Control & Password Policies', 'wp-simple-firewall' );
|
84 |
}
|
85 |
}
|
src/lib/src/Modules/UserManagement/Lib/Password/UserPasswordHandler.php
CHANGED
@@ -2,8 +2,7 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Password;
|
4 |
|
5 |
-
use FernleafSystems\
|
6 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpLoginCapture;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
@@ -13,10 +12,8 @@ use FernleafSystems\Wordpress\Services\Services;
|
|
13 |
* Class UserPasswordController
|
14 |
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Password
|
15 |
*/
|
16 |
-
class UserPasswordHandler {
|
17 |
|
18 |
-
use ModConsumer;
|
19 |
-
use ExecOnce;
|
20 |
use WpLoginCapture;
|
21 |
|
22 |
protected function canRun() :bool {
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Password;
|
4 |
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpLoginCapture;
|
8 |
use FernleafSystems\Wordpress\Services\Services;
|
12 |
* Class UserPasswordController
|
13 |
* @package FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Password
|
14 |
*/
|
15 |
+
class UserPasswordHandler extends ExecOnceModConsumer {
|
16 |
|
|
|
|
|
17 |
use WpLoginCapture;
|
18 |
|
19 |
protected function canRun() :bool {
|
src/lib/src/Modules/UserManagement/Lib/Session/UserSessionHandler.php
CHANGED
@@ -2,17 +2,14 @@
|
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Session;
|
4 |
|
5 |
-
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO;
|
7 |
-
use FernleafSystems\Wordpress\Plugin\Shield\Modules\
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpLoginCapture;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
-
class UserSessionHandler {
|
13 |
|
14 |
-
use ModConsumer;
|
15 |
-
use ExecOnce;
|
16 |
use WpLoginCapture;
|
17 |
|
18 |
protected function canRun() :bool {
|
@@ -106,9 +103,6 @@ class UserSessionHandler {
|
|
106 |
return $opts->hasMaxSessionTimeout() ? min( $timeout, $opts->getMaxSessionTime() ) : $timeout;
|
107 |
}
|
108 |
|
109 |
-
/**
|
110 |
-
* @param \WP_User $user
|
111 |
-
*/
|
112 |
private function enforceSessionLimits( \WP_User $user ) {
|
113 |
/** @var UserManagement\Options $opts */
|
114 |
$opts = $this->getOptions();
|
2 |
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Session;
|
4 |
|
|
|
5 |
use FernleafSystems\Wordpress\Plugin\Shield\Databases\Session\EntryVO;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Utilities\Consumer\WpLoginCapture;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
+
class UserSessionHandler extends ExecOnceModConsumer {
|
12 |
|
|
|
|
|
13 |
use WpLoginCapture;
|
14 |
|
15 |
protected function canRun() :bool {
|
103 |
return $opts->hasMaxSessionTimeout() ? min( $timeout, $opts->getMaxSessionTime() ) : $timeout;
|
104 |
}
|
105 |
|
|
|
|
|
|
|
106 |
private function enforceSessionLimits( \WP_User $user ) {
|
107 |
/** @var UserManagement\Options $opts */
|
108 |
$opts = $this->getOptions();
|
src/lib/src/Modules/UserManagement/Lib/Suspend/UserSuspendController.php
CHANGED
@@ -3,15 +3,13 @@
|
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Suspend;
|
4 |
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
|
|
6 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops\Terminate;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
|
9 |
use FernleafSystems\Wordpress\Services\Services;
|
10 |
|
11 |
-
class UserSuspendController {
|
12 |
-
|
13 |
-
use ModConsumer;
|
14 |
-
use ExecOnce;
|
15 |
|
16 |
protected function canRun() :bool {
|
17 |
/** @var UserManagement\Options $opts */
|
@@ -147,7 +145,7 @@ class UserSuspendController {
|
|
147 |
'form_field' => 'shield_suspend_user',
|
148 |
]
|
149 |
];
|
150 |
-
echo $this->getMod()->renderTemplate( '/
|
151 |
}
|
152 |
|
153 |
public function handleUserSuspendOptionSubmit( int $uid ) {
|
3 |
namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Lib\Suspend;
|
4 |
|
5 |
use FernleafSystems\Utilities\Logic\ExecOnce;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Base\Common\ExecOnceModConsumer;
|
7 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
8 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\Sessions\Lib\Ops\Terminate;
|
9 |
use FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
|
10 |
use FernleafSystems\Wordpress\Services\Services;
|
11 |
|
12 |
+
class UserSuspendController extends ExecOnceModConsumer {
|
|
|
|
|
|
|
13 |
|
14 |
protected function canRun() :bool {
|
15 |
/** @var UserManagement\Options $opts */
|
145 |
'form_field' => 'shield_suspend_user',
|
146 |
]
|
147 |
];
|
148 |
+
echo $this->getMod()->renderTemplate( '/admin/user/profile/suspend.twig', $aData, true );
|
149 |
}
|
150 |
|
151 |
public function handleUserSuspendOptionSubmit( int $uid ) {
|
src/lib/src/Modules/UserManagement/ModCon.php
CHANGED
@@ -11,28 +11,28 @@ class ModCon extends BaseShield\ModCon {
|
|
11 |
* Should have no default email. If no email is set, no notification is sent.
|
12 |
* @return string[]
|
13 |
*/
|
14 |
-
public function getAdminLoginNotificationEmails() {
|
15 |
-
$
|
16 |
|
17 |
-
$
|
18 |
-
if ( !empty( $
|
19 |
-
$
|
20 |
array_map(
|
21 |
function ( $sEmail ) {
|
22 |
return trim( strtolower( $sEmail ) );
|
23 |
},
|
24 |
-
explode( ',', $
|
25 |
),
|
26 |
-
function ( $
|
27 |
-
return Services::Data()->validEmail( $
|
28 |
}
|
29 |
) ) );
|
30 |
-
if (
|
31 |
-
$
|
32 |
}
|
33 |
}
|
34 |
|
35 |
-
return $
|
36 |
}
|
37 |
|
38 |
protected function preProcessOptions() {
|
@@ -54,11 +54,11 @@ class ModCon extends BaseShield\ModCon {
|
|
54 |
) ) )
|
55 |
);
|
56 |
|
57 |
-
$
|
58 |
-
if ( !empty( $
|
59 |
-
$
|
60 |
}
|
61 |
-
$opts->setOpt( 'email_checks', array_unique( $
|
62 |
}
|
63 |
|
64 |
public function isSendUserEmailLoginNotification() :bool {
|
11 |
* Should have no default email. If no email is set, no notification is sent.
|
12 |
* @return string[]
|
13 |
*/
|
14 |
+
public function getAdminLoginNotificationEmails() :array {
|
15 |
+
$emails = [];
|
16 |
|
17 |
+
$rawEmails = $this->getOptions()->getOpt( 'enable_admin_login_email_notification', '' );
|
18 |
+
if ( !empty( $rawEmails ) ) {
|
19 |
+
$emails = array_values( array_unique( array_filter(
|
20 |
array_map(
|
21 |
function ( $sEmail ) {
|
22 |
return trim( strtolower( $sEmail ) );
|
23 |
},
|
24 |
+
explode( ',', $rawEmails )
|
25 |
),
|
26 |
+
function ( $email ) {
|
27 |
+
return Services::Data()->validEmail( $email );
|
28 |
}
|
29 |
) ) );
|
30 |
+
if ( count( $emails ) > 1 && !$this->isPremium() ) {
|
31 |
+
$emails = array_slice( $emails, 0, 1 );
|
32 |
}
|
33 |
}
|
34 |
|
35 |
+
return $emails;
|
36 |
}
|
37 |
|
38 |
protected function preProcessOptions() {
|
54 |
) ) )
|
55 |
);
|
56 |
|
57 |
+
$checks = $opts->getEmailValidationChecks();
|
58 |
+
if ( !empty( $checks ) ) {
|
59 |
+
$checks[] = 'syntax';
|
60 |
}
|
61 |
+
$opts->setOpt( 'email_checks', array_unique( $checks ) );
|
62 |
}
|
63 |
|
64 |
public function isSendUserEmailLoginNotification() :bool {
|
src/lib/src/Modules/UserManagement/Processor.php
CHANGED
@@ -83,20 +83,20 @@ class Processor extends BaseShield\Processor {
|
|
83 |
private function sendLoginNotifications( \WP_User $user ) {
|
84 |
/** @var ModCon $mod */
|
85 |
$mod = $this->getMod();
|
86 |
-
$
|
87 |
-
$
|
88 |
-
$
|
89 |
|
90 |
// do some magic logic so we don't send both to the same person (the assumption being that the admin
|
91 |
// email recipient is actually an admin (or they'll maybe not get any).
|
92 |
-
if ( $
|
93 |
-
$
|
94 |
}
|
95 |
|
96 |
-
if ( $
|
97 |
$this->sendAdminLoginEmailNotification( $user );
|
98 |
}
|
99 |
-
if ( $
|
100 |
$hasLoginIntent = $this->getCon()
|
101 |
->getModule_LoginGuard()
|
102 |
->getLoginIntentController()
|
@@ -134,25 +134,25 @@ class Processor extends BaseShield\Processor {
|
|
134 |
}
|
135 |
|
136 |
add_filter( 'manage_users_custom_column',
|
137 |
-
function ( $
|
138 |
|
139 |
if ( $sColumnName == $sCustomColumnName ) {
|
140 |
-
$
|
141 |
-
$
|
142 |
-
if ( $
|
143 |
-
$nLastLoginTime = $this->getCon()->getUserMeta( $
|
144 |
if ( $nLastLoginTime > 0 ) {
|
145 |
-
$
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
}
|
150 |
}
|
151 |
-
$sNewContent = sprintf( '%s: %s', __( 'Last Login', 'wp-simple-firewall' ), $
|
152 |
-
$
|
153 |
}
|
154 |
|
155 |
-
return $
|
156 |
},
|
157 |
10, 3
|
158 |
);
|
83 |
private function sendLoginNotifications( \WP_User $user ) {
|
84 |
/** @var ModCon $mod */
|
85 |
$mod = $this->getMod();
|
86 |
+
$adminEmails = $mod->getAdminLoginNotificationEmails();
|
87 |
+
$sendAdmin = count( $adminEmails ) > 0;
|
88 |
+
$sendUser = $mod->isSendUserEmailLoginNotification();
|
89 |
|
90 |
// do some magic logic so we don't send both to the same person (the assumption being that the admin
|
91 |
// email recipient is actually an admin (or they'll maybe not get any).
|
92 |
+
if ( $sendAdmin && $sendUser && in_array( strtolower( $user->user_email ), $adminEmails ) ) {
|
93 |
+
$sendUser = false;
|
94 |
}
|
95 |
|
96 |
+
if ( $sendAdmin ) {
|
97 |
$this->sendAdminLoginEmailNotification( $user );
|
98 |
}
|
99 |
+
if ( $sendUser ) {
|
100 |
$hasLoginIntent = $this->getCon()
|
101 |
->getModule_LoginGuard()
|
102 |
->getLoginIntentController()
|
134 |
}
|
135 |
|
136 |
add_filter( 'manage_users_custom_column',
|
137 |
+
function ( $content, $sColumnName, $userID ) use ( $sCustomColumnName ) {
|
138 |
|
139 |
if ( $sColumnName == $sCustomColumnName ) {
|
140 |
+
$value = __( 'Not Recorded', 'wp-simple-firewall' );
|
141 |
+
$user = Services::WpUsers()->getUserById( $userID );
|
142 |
+
if ( $user instanceof \WP_User ) {
|
143 |
+
$nLastLoginTime = $this->getCon()->getUserMeta( $user )->last_login_at;
|
144 |
if ( $nLastLoginTime > 0 ) {
|
145 |
+
$value = Services::Request()
|
146 |
+
->carbon()
|
147 |
+
->setTimestamp( $nLastLoginTime )
|
148 |
+
->diffForHumans();
|
149 |
}
|
150 |
}
|
151 |
+
$sNewContent = sprintf( '%s: %s', __( 'Last Login', 'wp-simple-firewall' ), $value );
|
152 |
+
$content = empty( $content ) ? $sNewContent : $content.'<br/>'.$sNewContent;
|
153 |
}
|
154 |
|
155 |
+
return $content;
|
156 |
},
|
157 |
10, 3
|
158 |
);
|
src/lib/src/Tables/Build/Traffic.php
CHANGED
@@ -145,8 +145,8 @@ class Traffic extends BaseBuild {
|
|
145 |
}
|
146 |
else {
|
147 |
$country = sprintf(
|
148 |
-
'<img class="icon-flag" src="%s" alt="%s"/> %s',
|
149 |
-
sprintf( 'https://
|
150 |
$countryISO,
|
151 |
$geoIP->getCountryName()
|
152 |
);
|
145 |
}
|
146 |
else {
|
147 |
$country = sprintf(
|
148 |
+
'<img class="icon-flag" src="%s" alt="%s" width="24px"/> %s',
|
149 |
+
sprintf( 'https://api.aptoweb.com/api/v1/country/flag/%s.svg', strtolower( $countryISO ) ),
|
150 |
$countryISO,
|
151 |
$geoIP->getCountryName()
|
152 |
);
|
src/lib/src/Tables/Render/Common/BaseTable.php
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\Common;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Modules\ModConsumer;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Scans;
|
7 |
+
|
8 |
+
class BaseTable {
|
9 |
+
|
10 |
+
use ModConsumer;
|
11 |
+
|
12 |
+
const DEFAULT_PER_PAGE = 25;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var int
|
16 |
+
*/
|
17 |
+
protected $pageSize;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var int
|
21 |
+
*/
|
22 |
+
protected $totalRecords = -1;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
protected $records = [];
|
28 |
+
|
29 |
+
protected function extra_tablenav( $which ) {
|
30 |
+
echo sprintf( '<a href="#" data-tableaction="refresh" class="btn btn-sm btn-outline-dark ml-3 tableActionRefresh">%s</a>', __( 'Refresh', 'wp-simple-firewall' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @param object $item
|
35 |
+
* @param string $colName
|
36 |
+
* @return string
|
37 |
+
*/
|
38 |
+
public function column_default( $item, $colName ) {
|
39 |
+
return $item[ $colName ];
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* @param array $aItem
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function column_cb( $aItem ) {
|
47 |
+
return sprintf( '<input type="checkbox" name="ids" value="%s" />', $aItem[ 'id' ] );
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @return array
|
52 |
+
*/
|
53 |
+
public function get_sortable_columns() {
|
54 |
+
return [];
|
55 |
+
// $aCols = $this->get_columns();
|
56 |
+
// foreach ( $aCols as $sCol => $sName ) {
|
57 |
+
// $aCols[ $sCol ] = array( $sCol, false );
|
58 |
+
// }
|
59 |
+
// return $aCols;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @return string[]
|
64 |
+
*/
|
65 |
+
protected function get_table_classes() {
|
66 |
+
return array_merge( parent::get_table_classes(), [ 'odp-table' ] );
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @return \FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\WpListTable\Base
|
71 |
+
*/
|
72 |
+
public function prepare_items() {
|
73 |
+
$aCols = $this->get_columns();
|
74 |
+
$aHidden = [];
|
75 |
+
$this->_column_headers = [ $aCols, $aHidden, $this->get_sortable_columns() ];
|
76 |
+
$this->items = $this->getRecords();
|
77 |
+
|
78 |
+
$this->set_pagination_args(
|
79 |
+
[
|
80 |
+
'total_items' => $this->getTotalRecords(),
|
81 |
+
'per_page' => $this->getPageSize()
|
82 |
+
]
|
83 |
+
);
|
84 |
+
return $this;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* @param string $option
|
89 |
+
* @param int $default
|
90 |
+
* @return int
|
91 |
+
*/
|
92 |
+
protected function get_items_per_page( $option, $default = 20 ) {
|
93 |
+
return $this->getPageSize();
|
94 |
+
}
|
95 |
+
|
96 |
+
public function single_row( $item ) {
|
97 |
+
if ( empty( $item[ 'custom_row' ] ) ) { // it's a normal row so render as always
|
98 |
+
parent::single_row( $item );
|
99 |
+
}
|
100 |
+
else {
|
101 |
+
$this->single_row_custom( $item );
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* override this in order to display a custom row
|
107 |
+
* @param $aItem
|
108 |
+
*/
|
109 |
+
public function single_row_custom( $aItem ) {
|
110 |
+
parent::single_row( $aItem );
|
111 |
+
}
|
112 |
+
|
113 |
+
public function getPageSize() :int {
|
114 |
+
return empty( $this->pageSize ) ? self::DEFAULT_PER_PAGE : $this->pageSize;
|
115 |
+
}
|
116 |
+
|
117 |
+
public function getRecords() :array {
|
118 |
+
return $this->records;
|
119 |
+
}
|
120 |
+
|
121 |
+
public function getTotalRecords() {
|
122 |
+
return $this->totalRecords;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @param array $records
|
127 |
+
* @return $this
|
128 |
+
*/
|
129 |
+
public function setRecords( array $records ) {
|
130 |
+
$this->records = $records;
|
131 |
+
return $this;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* @param int $size
|
136 |
+
* @return $this
|
137 |
+
*/
|
138 |
+
public function setPageSize( $size ) {
|
139 |
+
$this->pageSize = $size;
|
140 |
+
return $this;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* @param int $total
|
145 |
+
* @return $this
|
146 |
+
*/
|
147 |
+
public function setTotalRecords( int $total ) {
|
148 |
+
$this->totalRecords = $total;
|
149 |
+
return $this;
|
150 |
+
}
|
151 |
+
}
|
src/lib/src/Tables/Render/DataTable/Base.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\DataTable;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Scans;
|
6 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\Common\BaseTable;
|
7 |
+
|
8 |
+
class Base extends BaseTable {
|
9 |
+
|
10 |
+
}
|
src/lib/src/Tables/Render/DataTable/ScanBase.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\DataTable;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Scans;
|
6 |
+
|
7 |
+
class ScanBase extends Base {
|
8 |
+
|
9 |
+
}
|
src/lib/src/Tables/Render/DataTable/ScanWcf.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php declare( strict_types=1 );
|
2 |
+
|
3 |
+
namespace FernleafSystems\Wordpress\Plugin\Shield\Tables\Render\DataTable;
|
4 |
+
|
5 |
+
use FernleafSystems\Wordpress\Plugin\Shield\Scans;
|
6 |
+
|
7 |
+
class ScanWcf extends ScanBase {
|
8 |
+
|
9 |
+
}
|
src/lib/src/Tables/Render/WpListTable/ScanBase.php
CHANGED
@@ -11,14 +11,14 @@ class ScanBase extends Base {
|
|
11 |
* @return string
|
12 |
*/
|
13 |
public function column_path( $item ) {
|
14 |
-
$
|
15 |
$item[ 'path' ],
|
16 |
sprintf( '%s: %s', __( 'Path', 'wp-simple-firewall' ), trailingslashit( dirname( $item[ 'path_relabs' ] ) ) )
|
17 |
);
|
18 |
if ( !empty( $item[ 'path_details' ] ) ) {
|
19 |
-
$
|
20 |
}
|
21 |
-
return $
|
22 |
}
|
23 |
|
24 |
//.implode( '; ', $aItem[ 'asset_description' ] )
|
11 |
* @return string
|
12 |
*/
|
13 |
public function column_path( $item ) {
|
14 |
+
$output = sprintf( '<code><span class="font-weight-bolder text-dark" style="font-size: larger">%s</span></code><code>[%s]</code>',
|
15 |
$item[ 'path' ],
|
16 |
sprintf( '%s: %s', __( 'Path', 'wp-simple-firewall' ), trailingslashit( dirname( $item[ 'path_relabs' ] ) ) )
|
17 |
);
|
18 |
if ( !empty( $item[ 'path_details' ] ) ) {
|
19 |
+
$output .= '<p class="mb-0">'.implode( '; ', $item[ 'path_details' ] ).'</p>';
|
20 |
}
|
21 |
+
return $output;
|
22 |
}
|
23 |
|
24 |
//.implode( '; ', $aItem[ 'asset_description' ] )
|
src/lib/src/Users/ShieldUserMeta.php
CHANGED
@@ -7,28 +7,28 @@ use FernleafSystems\Wordpress\Services\Services;
|
|
7 |
/**
|
8 |
* Class UserMeta
|
9 |
* @package FernleafSystems\Wordpress\Plugin\Shield\Users
|
10 |
-
* @property array
|
11 |
-
* @property bool
|
12 |
-
* @property string
|
13 |
-
* @property string
|
14 |
-
* @property string
|
15 |
-
* @property bool
|
16 |
-
* @property string
|
17 |
-
* @property bool
|
18 |
-
* @property string $
|
19 |
-
* @property array
|
20 |
-
* @property string
|
21 |
-
* @property int
|
22 |
-
* @property int
|
23 |
-
* @property int
|
24 |
-
* @property int
|
25 |
-
* @property int
|
26 |
-
* @property string
|
27 |
-
* @property bool
|
28 |
-
* @property int
|
29 |
-
* @property bool
|
30 |
-
* @property bool
|
31 |
-
* @property array
|
32 |
*/
|
33 |
class ShieldUserMeta extends \FernleafSystems\Wordpress\Services\Utilities\PluginUserMeta {
|
34 |
|
7 |
/**
|
8 |
* Class UserMeta
|
9 |
* @package FernleafSystems\Wordpress\Plugin\Shield\Users
|
10 |
+
* @property array $email_secret
|
11 |
+
* @property bool $email_validated
|
12 |
+
* @property string $backupcode_secret
|
13 |
+
* @property string $backupcode_validated
|
14 |
+
* @property string $ga_secret
|
15 |
+
* @property bool $ga_validated
|
16 |
+
* @property string $u2f_secret
|
17 |
+
* @property bool $u2f_validated
|
18 |
+
* @property string[] $u2f_regrequests
|
19 |
+
* @property array $hash_loginmfa
|
20 |
+
* @property string $pass_hash
|
21 |
+
* @property int $first_seen_at
|
22 |
+
* @property int $last_verified_at
|
23 |
+
* @property int $pass_started_at
|
24 |
+
* @property int $pass_reset_last_redirect_at
|
25 |
+
* @property int $pass_check_failed_at
|
26 |
+
* @property string $yubi_secret
|
27 |
+
* @property bool $yubi_validated
|
28 |
+
* @property int $last_login_at
|
29 |
+
* @property bool $wc_social_login_valid
|
30 |
+
* @property bool $hard_suspended_at
|
31 |
+
* @property array $tours
|
32 |
*/
|
33 |
class ShieldUserMeta extends \FernleafSystems\Wordpress\Services\Utilities\PluginUserMeta {
|
34 |
|
src/lib/src/Utilities/Consumer/WpLoginCapture.php
CHANGED
@@ -16,6 +16,11 @@ trait WpLoginCapture {
|
|
16 |
*/
|
17 |
private $isCaptureApplicationLogin = false;
|
18 |
|
|
|
|
|
|
|
|
|
|
|
19 |
abstract protected function captureLogin( \WP_User $user );
|
20 |
|
21 |
protected function getLoginPassword() :string {
|
@@ -30,6 +35,12 @@ trait WpLoginCapture {
|
|
30 |
return $pass;
|
31 |
}
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
protected function isCaptureApplicationLogin() :bool {
|
34 |
return $this->isCaptureApplicationLogin;
|
35 |
}
|
@@ -51,13 +62,18 @@ trait WpLoginCapture {
|
|
51 |
return $this;
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
|
|
54 |
protected function setToCaptureApplicationLogin( bool $capture = true ) :self {
|
55 |
$this->isCaptureApplicationLogin = $capture;
|
56 |
return $this;
|
57 |
}
|
58 |
|
59 |
protected function setupLoginCaptureHooks() {
|
60 |
-
add_action( 'wp_login', [ $this, 'onWpLogin' ],
|
61 |
if ( !Services::WpUsers()->isProfilePage() ) { // Ignore firing during profile update.
|
62 |
add_action( 'set_logged_in_cookie', [ $this, 'onWpSetLoggedInCookie' ], 5, 4 );
|
63 |
}
|
@@ -71,6 +87,9 @@ trait WpLoginCapture {
|
|
71 |
*/
|
72 |
public function onWpSetLoggedInCookie( $cookie, $expire, $expiration, $userID ) {
|
73 |
$user = Services::WpUsers()->getUserById( $userID );
|
|
|
|
|
|
|
74 |
if ( $this->isLoginToBeCaptured() && !$this->isLoginCaptured() && $user instanceof \WP_User ) {
|
75 |
$this->setLoginCaptured();
|
76 |
$this->captureLogin( $user );
|
@@ -87,4 +106,8 @@ trait WpLoginCapture {
|
|
87 |
$this->captureLogin( $user );
|
88 |
}
|
89 |
}
|
|
|
|
|
|
|
|
|
90 |
}
|
16 |
*/
|
17 |
private $isCaptureApplicationLogin = false;
|
18 |
|
19 |
+
/**
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
private $loggedInCookie = '';
|
23 |
+
|
24 |
abstract protected function captureLogin( \WP_User $user );
|
25 |
|
26 |
protected function getLoginPassword() :string {
|
35 |
return $pass;
|
36 |
}
|
37 |
|
38 |
+
protected function getLoggedInCookie() :string {
|
39 |
+
$cookie = empty( $this->loggedInCookie ) ?
|
40 |
+
Services::Request()->cookie( LOGGED_IN_COOKIE ) : $this->loggedInCookie;
|
41 |
+
return is_string( $cookie ) ? $cookie : '';
|
42 |
+
}
|
43 |
+
|
44 |
protected function isCaptureApplicationLogin() :bool {
|
45 |
return $this->isCaptureApplicationLogin;
|
46 |
}
|
62 |
return $this;
|
63 |
}
|
64 |
|
65 |
+
protected function setLoggedInCookie( string $cookieValue ) :self {
|
66 |
+
$this->loggedInCookie = $cookieValue;
|
67 |
+
return $this;
|
68 |
+
}
|
69 |
+
|
70 |
protected function setToCaptureApplicationLogin( bool $capture = true ) :self {
|
71 |
$this->isCaptureApplicationLogin = $capture;
|
72 |
return $this;
|
73 |
}
|
74 |
|
75 |
protected function setupLoginCaptureHooks() {
|
76 |
+
add_action( 'wp_login', [ $this, 'onWpLogin' ], $this->getHookPriority(), 2 );
|
77 |
if ( !Services::WpUsers()->isProfilePage() ) { // Ignore firing during profile update.
|
78 |
add_action( 'set_logged_in_cookie', [ $this, 'onWpSetLoggedInCookie' ], 5, 4 );
|
79 |
}
|
87 |
*/
|
88 |
public function onWpSetLoggedInCookie( $cookie, $expire, $expiration, $userID ) {
|
89 |
$user = Services::WpUsers()->getUserById( $userID );
|
90 |
+
if ( is_string( $cookie ) ) {
|
91 |
+
$this->setLoggedInCookie( $cookie );
|
92 |
+
}
|
93 |
if ( $this->isLoginToBeCaptured() && !$this->isLoginCaptured() && $user instanceof \WP_User ) {
|
94 |
$this->setLoginCaptured();
|
95 |
$this->captureLogin( $user );
|
106 |
$this->captureLogin( $user );
|
107 |
}
|
108 |
}
|
109 |
+
|
110 |
+
protected function getHookPriority() :int {
|
111 |
+
return 10;
|
112 |
+
}
|
113 |
}
|
src/lib/src/Utilities/Consumer/WpUserConsumer.php
CHANGED
@@ -7,21 +7,21 @@ trait WpUserConsumer {
|
|
7 |
/**
|
8 |
* @var \WP_User
|
9 |
*/
|
10 |
-
private $
|
11 |
|
12 |
/**
|
13 |
-
* @return \WP_User
|
14 |
*/
|
15 |
public function getWpUser() {
|
16 |
-
return $this->
|
17 |
}
|
18 |
|
19 |
/**
|
20 |
-
* @param \WP_User $user
|
21 |
* @return $this
|
22 |
*/
|
23 |
-
public function setWpUser(
|
24 |
-
$this->
|
25 |
return $this;
|
26 |
}
|
27 |
}
|
7 |
/**
|
8 |
* @var \WP_User
|
9 |
*/
|
10 |
+
private $wpUser;
|
11 |
|
12 |
/**
|
13 |
+
* @return \WP_User|null
|
14 |
*/
|
15 |
public function getWpUser() {
|
16 |
+
return $this->wpUser;
|
17 |
}
|
18 |
|
19 |
/**
|
20 |
+
* @param \WP_User|null $user
|
21 |
* @return $this
|
22 |
*/
|
23 |
+
public function setWpUser( $user ) {
|
24 |
+
$this->wpUser = $user;
|
25 |
return $this;
|
26 |
}
|
27 |
}
|
src/lib/vendor/bacon/bacon-qr-code/Module.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode;
|
11 |
+
|
12 |
+
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Module for generating QR codes.
|
16 |
+
*/
|
17 |
+
class Module implements AutoloaderProviderInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Get autoloader config.
|
21 |
+
*
|
22 |
+
* @return array
|
23 |
+
*/
|
24 |
+
public function getAutoloaderConfig()
|
25 |
+
{
|
26 |
+
return array(
|
27 |
+
'Zend\Loader\ClassMapAutoloader' => array(
|
28 |
+
__DIR__ . '/autoload_classmap.php',
|
29 |
+
),
|
30 |
+
'Zend\Loader\StandardAutoloader' => array(
|
31 |
+
'namespaces' => array(
|
32 |
+
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
|
33 |
+
),
|
34 |
+
),
|
35 |
+
);
|
36 |
+
}
|
37 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
use ReflectionClass;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* A general enum implementation until we got SplEnum.
|
17 |
+
*/
|
18 |
+
abstract class AbstractEnum
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Default value.
|
22 |
+
*/
|
23 |
+
const __default = null;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Current value.
|
27 |
+
*
|
28 |
+
* @var mixed
|
29 |
+
*/
|
30 |
+
protected $value;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Cache of constants.
|
34 |
+
*
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
protected $constants;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Whether to handle values strict or not.
|
41 |
+
*
|
42 |
+
* @var boolean
|
43 |
+
*/
|
44 |
+
protected $strict;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Creates a new enum.
|
48 |
+
*
|
49 |
+
* @param mixed $initialValue
|
50 |
+
* @param boolean $strict
|
51 |
+
*/
|
52 |
+
public function __construct($initialValue = null, $strict = false)
|
53 |
+
{
|
54 |
+
$this->strict = $strict;
|
55 |
+
$this->change($initialValue);
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Changes the value of the enum.
|
60 |
+
*
|
61 |
+
* @param mixed $value
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
+
public function change($value)
|
65 |
+
{
|
66 |
+
if (!in_array($value, $this->getConstList(), $this->strict)) {
|
67 |
+
throw new Exception\UnexpectedValueException('Value not a const in enum ' . get_class($this));
|
68 |
+
}
|
69 |
+
|
70 |
+
$this->value = $value;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Gets current value.
|
75 |
+
*
|
76 |
+
* @return mixed
|
77 |
+
*/
|
78 |
+
public function get()
|
79 |
+
{
|
80 |
+
return $this->value;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Gets all constants (possible values) as an array.
|
85 |
+
*
|
86 |
+
* @param boolean $includeDefault
|
87 |
+
* @return array
|
88 |
+
*/
|
89 |
+
public function getConstList($includeDefault = true)
|
90 |
+
{
|
91 |
+
if ($this->constants === null) {
|
92 |
+
$reflection = new ReflectionClass($this);
|
93 |
+
$this->constants = $reflection->getConstants();
|
94 |
+
}
|
95 |
+
|
96 |
+
if ($includeDefault) {
|
97 |
+
return $this->constants;
|
98 |
+
}
|
99 |
+
|
100 |
+
$constants = $this->constants;
|
101 |
+
unset($constants['__default']);
|
102 |
+
|
103 |
+
return $constants;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Gets the name of the enum.
|
108 |
+
*
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
public function __toString()
|
112 |
+
{
|
113 |
+
return array_search($this->value, $this->getConstList());
|
114 |
+
}
|
115 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php
ADDED
@@ -0,0 +1,435 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
use SplFixedArray;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* A simple, fast array of bits.
|
16 |
+
*/
|
17 |
+
class BitArray
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Bits represented as an array of integers.
|
21 |
+
*
|
22 |
+
* @var SplFixedArray
|
23 |
+
*/
|
24 |
+
protected $bits;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Size of the bit array in bits.
|
28 |
+
*
|
29 |
+
* @var integer
|
30 |
+
*/
|
31 |
+
protected $size;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Creates a new bit array with a given size.
|
35 |
+
*
|
36 |
+
* @param integer $size
|
37 |
+
*/
|
38 |
+
public function __construct($size = 0)
|
39 |
+
{
|
40 |
+
$this->size = $size;
|
41 |
+
$this->bits = new SplFixedArray(($this->size + 31) >> 3);
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Gets the size in bits.
|
46 |
+
*
|
47 |
+
* @return integer
|
48 |
+
*/
|
49 |
+
public function getSize()
|
50 |
+
{
|
51 |
+
return $this->size;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Gets the size in bytes.
|
56 |
+
*
|
57 |
+
* @return integer
|
58 |
+
*/
|
59 |
+
public function getSizeInBytes()
|
60 |
+
{
|
61 |
+
return ($this->size + 7) >> 3;
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Ensures that the array has a minimum capacity.
|
66 |
+
*
|
67 |
+
* @param integer $size
|
68 |
+
* @return void
|
69 |
+
*/
|
70 |
+
public function ensureCapacity($size)
|
71 |
+
{
|
72 |
+
if ($size > count($this->bits) << 5) {
|
73 |
+
$this->bits->setSize(($size + 31) >> 5);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Gets a specific bit.
|
79 |
+
*
|
80 |
+
* @param integer $i
|
81 |
+
* @return boolean
|
82 |
+
*/
|
83 |
+
public function get($i)
|
84 |
+
{
|
85 |
+
return ($this->bits[$i >> 5] & (1 << ($i & 0x1f))) !== 0;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Sets a specific bit.
|
90 |
+
*
|
91 |
+
* @param integer $i
|
92 |
+
* @return void
|
93 |
+
*/
|
94 |
+
public function set($i)
|
95 |
+
{
|
96 |
+
$this->bits[$i >> 5] = $this->bits[$i >> 5] | 1 << ($i & 0x1f);
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Flips a specific bit.
|
101 |
+
*
|
102 |
+
* @param integer $i
|
103 |
+
* @return void
|
104 |
+
*/
|
105 |
+
public function flip($i)
|
106 |
+
{
|
107 |
+
$this->bits[$i >> 5] ^= 1 << ($i & 0x1f);
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Gets the next set bit position from a given position.
|
112 |
+
*
|
113 |
+
* @param integer $from
|
114 |
+
* @return integer
|
115 |
+
*/
|
116 |
+
public function getNextSet($from)
|
117 |
+
{
|
118 |
+
if ($from >= $this->size) {
|
119 |
+
return $this->size;
|
120 |
+
}
|
121 |
+
|
122 |
+
$bitsOffset = $from >> 5;
|
123 |
+
$currentBits = $this->bits[$bitsOffset];
|
124 |
+
$bitsLength = count($this->bits);
|
125 |
+
|
126 |
+
$currentBits &= ~((1 << ($from & 0x1f)) - 1);
|
127 |
+
|
128 |
+
while ($currentBits === 0) {
|
129 |
+
if (++$bitsOffset === $bitsLength) {
|
130 |
+
return $this->size;
|
131 |
+
}
|
132 |
+
|
133 |
+
$currentBits = $this->bits[$bitsOffset];
|
134 |
+
}
|
135 |
+
|
136 |
+
$result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
|
137 |
+
|
138 |
+
return $result > $this->size ? $this->size : $result;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Gets the next unset bit position from a given position.
|
143 |
+
*
|
144 |
+
* @param integer $from
|
145 |
+
* @return integer
|
146 |
+
*/
|
147 |
+
public function getNextUnset($from)
|
148 |
+
{
|
149 |
+
if ($from >= $this->size) {
|
150 |
+
return $this->size;
|
151 |
+
}
|
152 |
+
|
153 |
+
$bitsOffset = $from >> 5;
|
154 |
+
$currentBits = ~$this->bits[$bitsOffset];
|
155 |
+
$bitsLength = count($this->bits);
|
156 |
+
|
157 |
+
$currentBits &= ~((1 << ($from & 0x1f)) - 1);
|
158 |
+
|
159 |
+
while ($currentBits === 0) {
|
160 |
+
if (++$bitsOffset === $bitsLength) {
|
161 |
+
return $this->size;
|
162 |
+
}
|
163 |
+
|
164 |
+
$currentBits = ~$this->bits[$bitsOffset];
|
165 |
+
}
|
166 |
+
|
167 |
+
$result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
|
168 |
+
|
169 |
+
return $result > $this->size ? $this->size : $result;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Sets a bulk of bits.
|
174 |
+
*
|
175 |
+
* @param integer $i
|
176 |
+
* @param integer $newBits
|
177 |
+
* @return void
|
178 |
+
*/
|
179 |
+
public function setBulk($i, $newBits)
|
180 |
+
{
|
181 |
+
$this->bits[$i >> 5] = $newBits;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Sets a range of bits.
|
186 |
+
*
|
187 |
+
* @param integer $start
|
188 |
+
* @param integer $end
|
189 |
+
* @return void
|
190 |
+
* @throws Exception\InvalidArgumentException
|
191 |
+
*/
|
192 |
+
public function setRange($start, $end)
|
193 |
+
{
|
194 |
+
if ($end < $start) {
|
195 |
+
throw new Exception\InvalidArgumentException('End must be greater or equal to start');
|
196 |
+
}
|
197 |
+
|
198 |
+
if ($end === $start) {
|
199 |
+
return;
|
200 |
+
}
|
201 |
+
|
202 |
+
$end--;
|
203 |
+
|
204 |
+
$firstInt = $start >> 5;
|
205 |
+
$lastInt = $end >> 5;
|
206 |
+
|
207 |
+
for ($i = $firstInt; $i <= $lastInt; $i++) {
|
208 |
+
$firstBit = $i > $firstInt ? 0 : $start & 0x1f;
|
209 |
+
$lastBit = $i < $lastInt ? 31 : $end & 0x1f;
|
210 |
+
|
211 |
+
if ($firstBit === 0 && $lastBit === 31) {
|
212 |
+
$mask = 0x7fffffff;
|
213 |
+
} else {
|
214 |
+
$mask = 0;
|
215 |
+
|
216 |
+
for ($j = $firstBit; $j < $lastBit; $j++) {
|
217 |
+
$mask |= 1 << $j;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
$this->bits[$i] = $this->bits[$i] | $mask;
|
222 |
+
}
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Clears the bit array, unsetting every bit.
|
227 |
+
*
|
228 |
+
* @return void
|
229 |
+
*/
|
230 |
+
public function clear()
|
231 |
+
{
|
232 |
+
$bitsLength = count($this->bits);
|
233 |
+
|
234 |
+
for ($i = 0; $i < $bitsLength; $i++) {
|
235 |
+
$this->bits[$i] = 0;
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Checks if a range of bits is set or not set.
|
241 |
+
*
|
242 |
+
* @param integer $start
|
243 |
+
* @param integer $end
|
244 |
+
* @param integer $value
|
245 |
+
* @return boolean
|
246 |
+
* @throws Exception\InvalidArgumentException
|
247 |
+
*/
|
248 |
+
public function isRange($start, $end, $value)
|
249 |
+
{
|
250 |
+
if ($end < $start) {
|
251 |
+
throw new Exception\InvalidArgumentException('End must be greater or equal to start');
|
252 |
+
}
|
253 |
+
|
254 |
+
if ($end === $start) {
|
255 |
+
return;
|
256 |
+
}
|
257 |
+
|
258 |
+
$end--;
|
259 |
+
|
260 |
+
$firstInt = $start >> 5;
|
261 |
+
$lastInt = $end >> 5;
|
262 |
+
|
263 |
+
for ($i = $firstInt; $i <= $lastInt; $i++) {
|
264 |
+
$firstBit = $i > $firstInt ? 0 : $start & 0x1f;
|
265 |
+
$lastBit = $i < $lastInt ? 31 : $end & 0x1f;
|
266 |
+
|
267 |
+
if ($firstBit === 0 && $lastBit === 31) {
|
268 |
+
$mask = 0x7fffffff;
|
269 |
+
} else {
|
270 |
+
$mask = 0;
|
271 |
+
|
272 |
+
for ($j = $firstBit; $j <= $lastBit; $j++) {
|
273 |
+
$mask |= 1 << $j;
|
274 |
+
}
|
275 |
+
}
|
276 |
+
|
277 |
+
if (($this->bits[$i] & $mask) !== ($value ? $mask : 0)) {
|
278 |
+
return false;
|
279 |
+
}
|
280 |
+
}
|
281 |
+
|
282 |
+
return true;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Appends a bit to the array.
|
287 |
+
*
|
288 |
+
* @param boolean $bit
|
289 |
+
* @return void
|
290 |
+
*/
|
291 |
+
public function appendBit($bit)
|
292 |
+
{
|
293 |
+
$this->ensureCapacity($this->size + 1);
|
294 |
+
|
295 |
+
if ($bit) {
|
296 |
+
$this->bits[$this->size >> 5] = $this->bits[$this->size >> 5] | (1 << ($this->size & 0x1f));
|
297 |
+
}
|
298 |
+
|
299 |
+
$this->size++;
|
300 |
+
}
|
301 |
+
|
302 |
+
/**
|
303 |
+
* Appends a number of bits (up to 32) to the array.
|
304 |
+
*
|
305 |
+
* @param integer $value
|
306 |
+
* @param integer $numBits
|
307 |
+
* @return void
|
308 |
+
* @throws Exception\InvalidArgumentException
|
309 |
+
*/
|
310 |
+
public function appendBits($value, $numBits)
|
311 |
+
{
|
312 |
+
if ($numBits < 0 || $numBits > 32) {
|
313 |
+
throw new Exception\InvalidArgumentException('Num bits must be between 0 and 32');
|
314 |
+
}
|
315 |
+
|
316 |
+
$this->ensureCapacity($this->size + $numBits);
|
317 |
+
|
318 |
+
for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) {
|
319 |
+
$this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) === 1);
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Appends another bit array to this array.
|
325 |
+
*
|
326 |
+
* @param BitArray $other
|
327 |
+
* @return void
|
328 |
+
*/
|
329 |
+
public function appendBitArray(self $other)
|
330 |
+
{
|
331 |
+
$otherSize = $other->getSize();
|
332 |
+
$this->ensureCapacity($this->size + $other->getSize());
|
333 |
+
|
334 |
+
for ($i = 0; $i < $otherSize; $i++) {
|
335 |
+
$this->appendBit($other->get($i));
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Makes an exclusive-or comparision on the current bit array.
|
341 |
+
*
|
342 |
+
* @param BitArray $other
|
343 |
+
* @return void
|
344 |
+
* @throws Exception\InvalidArgumentException
|
345 |
+
*/
|
346 |
+
public function xorBits(self $other)
|
347 |
+
{
|
348 |
+
$bitsLength = count($this->bits);
|
349 |
+
$otherBits = $other->getBitArray();
|
350 |
+
|
351 |
+
if ($bitsLength !== count($otherBits)) {
|
352 |
+
throw new Exception\InvalidArgumentException('Sizes don\'t match');
|
353 |
+
}
|
354 |
+
|
355 |
+
for ($i = 0; $i < $bitsLength; $i++) {
|
356 |
+
$this->bits[$i] = $this->bits[$i] ^ $otherBits[$i];
|
357 |
+
}
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Converts the bit array to a byte array.
|
362 |
+
*
|
363 |
+
* @param integer $bitOffset
|
364 |
+
* @param integer $numBytes
|
365 |
+
* @return SplFixedArray
|
366 |
+
*/
|
367 |
+
public function toBytes($bitOffset, $numBytes)
|
368 |
+
{
|
369 |
+
$bytes = new SplFixedArray($numBytes);
|
370 |
+
|
371 |
+
for ($i = 0; $i < $numBytes; $i++) {
|
372 |
+
$byte = 0;
|
373 |
+
|
374 |
+
for ($j = 0; $j < 8; $j++) {
|
375 |
+
if ($this->get($bitOffset)) {
|
376 |
+
$byte |= 1 << (7 - $j);
|
377 |
+
}
|
378 |
+
|
379 |
+
$bitOffset++;
|
380 |
+
}
|
381 |
+
|
382 |
+
$bytes[$i] = $byte;
|
383 |
+
}
|
384 |
+
|
385 |
+
return $bytes;
|
386 |
+
}
|
387 |
+
|
388 |
+
/**
|
389 |
+
* Gets the internal bit array.
|
390 |
+
*
|
391 |
+
* @return SplFixedArray
|
392 |
+
*/
|
393 |
+
public function getBitArray()
|
394 |
+
{
|
395 |
+
return $this->bits;
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Reverses the array.
|
400 |
+
*
|
401 |
+
* @return void
|
402 |
+
*/
|
403 |
+
public function reverse()
|
404 |
+
{
|
405 |
+
$newBits = new SplFixedArray(count($this->bits));
|
406 |
+
|
407 |
+
for ($i = 0; $i < $this->size; $i++) {
|
408 |
+
if ($this->get($this->size - $i - 1)) {
|
409 |
+
$newBits[$i >> 5] = $newBits[$i >> 5] | (1 << ($i & 0x1f));
|
410 |
+
}
|
411 |
+
}
|
412 |
+
|
413 |
+
$this->bits = newBits;
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Returns a string representation of the bit array.
|
418 |
+
*
|
419 |
+
* @return string
|
420 |
+
*/
|
421 |
+
public function __toString()
|
422 |
+
{
|
423 |
+
$result = '';
|
424 |
+
|
425 |
+
for ($i = 0; $i < $this->size; $i++) {
|
426 |
+
if (($i & 0x07) === 0) {
|
427 |
+
$result .= ' ';
|
428 |
+
}
|
429 |
+
|
430 |
+
$result .= $this->get($i) ? 'X' : '.';
|
431 |
+
}
|
432 |
+
|
433 |
+
return $result;
|
434 |
+
}
|
435 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php
ADDED
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
use SplFixedArray;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Bit matrix.
|
16 |
+
*
|
17 |
+
* Represents a 2D matrix of bits. In function arguments below, and throughout
|
18 |
+
* the common module, x is the column position, and y is the row position. The
|
19 |
+
* ordering is always x, y. The origin is at the top-left.
|
20 |
+
*/
|
21 |
+
class BitMatrix
|
22 |
+
{
|
23 |
+
/**
|
24 |
+
* Width of the bit matrix.
|
25 |
+
*
|
26 |
+
* @var integer
|
27 |
+
*/
|
28 |
+
protected $width;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Height of the bit matrix.
|
32 |
+
*
|
33 |
+
* @var integer
|
34 |
+
*/
|
35 |
+
protected $height;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Size in bits of each individual row.
|
39 |
+
*
|
40 |
+
* @var integer
|
41 |
+
*/
|
42 |
+
protected $rowSize;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Bits representation.
|
46 |
+
*
|
47 |
+
* @var SplFixedArray
|
48 |
+
*/
|
49 |
+
protected $bits;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Creates a new bit matrix with given dimensions.
|
53 |
+
*
|
54 |
+
* @param integer $width
|
55 |
+
* @param integer|null $height
|
56 |
+
* @throws Exception\InvalidArgumentException
|
57 |
+
*/
|
58 |
+
public function __construct($width, $height = null)
|
59 |
+
{
|
60 |
+
if ($height === null) {
|
61 |
+
$height = $width;
|
62 |
+
}
|
63 |
+
|
64 |
+
if ($width < 1 || $height < 1) {
|
65 |
+
throw new Exception\InvalidArgumentException('Both dimensions must be greater than zero');
|
66 |
+
}
|
67 |
+
|
68 |
+
$this->width = $width;
|
69 |
+
$this->height = $height;
|
70 |
+
$this->rowSize = ($width + 31) >> 5;
|
71 |
+
$this->bits = new SplFixedArray($this->rowSize * $height);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Gets the requested bit, where true means black.
|
76 |
+
*
|
77 |
+
* @param integer $x
|
78 |
+
* @param integer $y
|
79 |
+
* @return boolean
|
80 |
+
*/
|
81 |
+
public function get($x, $y)
|
82 |
+
{
|
83 |
+
$offset = $y * $this->rowSize + ($x >> 5);
|
84 |
+
return (BitUtils::unsignedRightShift($this->bits[$offset], ($x & 0x1f)) & 1) !== 0;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Sets the given bit to true.
|
89 |
+
*
|
90 |
+
* @param integer $x
|
91 |
+
* @param integer $y
|
92 |
+
* @return void
|
93 |
+
*/
|
94 |
+
public function set($x, $y)
|
95 |
+
{
|
96 |
+
$offset = $y * $this->rowSize + ($x >> 5);
|
97 |
+
$this->bits[$offset] = $this->bits[$offset] | (1 << ($x & 0x1f));
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Flips the given bit.
|
102 |
+
*
|
103 |
+
* @param integer $x
|
104 |
+
* @param integer $y
|
105 |
+
* @return void
|
106 |
+
*/
|
107 |
+
public function flip($x, $y)
|
108 |
+
{
|
109 |
+
$offset = $y * $this->rowSize + ($x >> 5);
|
110 |
+
$this->bits[$offset] = $this->bits[$offset] ^ (1 << ($x & 0x1f));
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Clears all bits (set to false).
|
115 |
+
*
|
116 |
+
* @return void
|
117 |
+
*/
|
118 |
+
public function clear()
|
119 |
+
{
|
120 |
+
$max = count($this->bits);
|
121 |
+
|
122 |
+
for ($i = 0; $i < $max; $i++) {
|
123 |
+
$this->bits[$i] = 0;
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Sets a square region of the bit matrix to true.
|
129 |
+
*
|
130 |
+
* @param integer $left
|
131 |
+
* @param integer $top
|
132 |
+
* @param integer $width
|
133 |
+
* @param integer $height
|
134 |
+
* @return void
|
135 |
+
*/
|
136 |
+
public function setRegion($left, $top, $width, $height)
|
137 |
+
{
|
138 |
+
if ($top < 0 || $left < 0) {
|
139 |
+
throw new Exception\InvalidArgumentException('Left and top must be non-negative');
|
140 |
+
}
|
141 |
+
|
142 |
+
if ($height < 1 || $width < 1) {
|
143 |
+
throw new Exception\InvalidArgumentException('Width and height must be at least 1');
|
144 |
+
}
|
145 |
+
|
146 |
+
$right = $left + $width;
|
147 |
+
$bottom = $top + $height;
|
148 |
+
|
149 |
+
if ($bottom > $this->height || $right > $this->width) {
|
150 |
+
throw new Exception\InvalidArgumentException('The region must fit inside the matrix');
|
151 |
+
}
|
152 |
+
|
153 |
+
for ($y = $top; $y < $bottom; $y++) {
|
154 |
+
$offset = $y * $this->rowSize;
|
155 |
+
|
156 |
+
for ($x = $left; $x < $right; $x++) {
|
157 |
+
$index = $offset + ($x >> 5);
|
158 |
+
$this->bits[$index] = $this->bits[$index] | (1 << ($x & 0x1f));
|
159 |
+
}
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* A fast method to retrieve one row of data from the matrix as a BitArray.
|
165 |
+
*
|
166 |
+
* @param integer $y
|
167 |
+
* @param BitArray $row
|
168 |
+
* @return BitArray
|
169 |
+
*/
|
170 |
+
public function getRow($y, BitArray $row = null)
|
171 |
+
{
|
172 |
+
if ($row === null || $row->getSize() < $this->width) {
|
173 |
+
$row = new BitArray($this->width);
|
174 |
+
}
|
175 |
+
|
176 |
+
$offset = $y * $this->rowSize;
|
177 |
+
|
178 |
+
for ($x = 0; $x < $this->rowSize; $x++) {
|
179 |
+
$row->setBulk($x << 5, $this->bits[$offset + $x]);
|
180 |
+
}
|
181 |
+
|
182 |
+
return $row;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Sets a row of data from a BitArray.
|
187 |
+
*
|
188 |
+
* @param integer $y
|
189 |
+
* @param BitArray $row
|
190 |
+
* @return void
|
191 |
+
*/
|
192 |
+
public function setRow($y, BitArray $row)
|
193 |
+
{
|
194 |
+
$bits = $row->getBitArray();
|
195 |
+
|
196 |
+
for ($i = 0; $i < $this->rowSize; $i++) {
|
197 |
+
$this->bits[$y * $this->rowSize + $i] = $bits[$i];
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* This is useful in detecting the enclosing rectangle of a 'pure' barcode.
|
203 |
+
*
|
204 |
+
* @return SplFixedArray
|
205 |
+
*/
|
206 |
+
public function getEnclosingRectangle()
|
207 |
+
{
|
208 |
+
$left = $this->width;
|
209 |
+
$top = $this->height;
|
210 |
+
$right = -1;
|
211 |
+
$bottom = -1;
|
212 |
+
|
213 |
+
for ($y = 0; $y < $this->height; $y++) {
|
214 |
+
for ($x32 = 0; $x32 < $this->rowSize; $x32++) {
|
215 |
+
$bits = $this->bits[$y * $this->rowSize + $x32];
|
216 |
+
|
217 |
+
if ($bits !== 0) {
|
218 |
+
if ($y < $top) {
|
219 |
+
$top = $y;
|
220 |
+
}
|
221 |
+
|
222 |
+
if ($y > $bottom) {
|
223 |
+
$bottom = $y;
|
224 |
+
}
|
225 |
+
|
226 |
+
if ($x32 * 32 < $left) {
|
227 |
+
$bit = 0;
|
228 |
+
|
229 |
+
while (($bits << (31 - $bit)) === 0) {
|
230 |
+
$bit++;
|
231 |
+
}
|
232 |
+
|
233 |
+
if (($x32 * 32 + $bit) < $left) {
|
234 |
+
$left = $x32 * 32 + $bit;
|
235 |
+
}
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
if ($x32 * 32 + 31 > $right) {
|
240 |
+
$bit = 31;
|
241 |
+
|
242 |
+
while (BitUtils::unsignedRightShift($bits, $bit) === 0) {
|
243 |
+
$bit--;
|
244 |
+
}
|
245 |
+
|
246 |
+
if (($x32 * 32 + $bit) > $right) {
|
247 |
+
$right = $x32 * 32 + $bit;
|
248 |
+
}
|
249 |
+
}
|
250 |
+
}
|
251 |
+
}
|
252 |
+
|
253 |
+
$width = $right - $left;
|
254 |
+
$height = $bottom - $top;
|
255 |
+
|
256 |
+
if ($width < 0 || $height < 0) {
|
257 |
+
return null;
|
258 |
+
}
|
259 |
+
|
260 |
+
return SplFixedArray::fromArray(array($left, $top, $width, $height), false);
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Gets the most top left set bit.
|
265 |
+
*
|
266 |
+
* This is useful in detecting a corner of a 'pure' barcode.
|
267 |
+
*
|
268 |
+
* @return SplFixedArray
|
269 |
+
*/
|
270 |
+
public function getTopLeftOnBit()
|
271 |
+
{
|
272 |
+
$bitsOffset = 0;
|
273 |
+
|
274 |
+
while ($bitsOffset < count($this->bits) && $this->bits[$bitsOffset] === 0) {
|
275 |
+
$bitsOffset++;
|
276 |
+
}
|
277 |
+
|
278 |
+
if ($bitsOffset === count($this->bits)) {
|
279 |
+
return null;
|
280 |
+
}
|
281 |
+
|
282 |
+
$x = intval($bitsOffset / $this->rowSize);
|
283 |
+
$y = ($bitsOffset % $this->rowSize) << 5;
|
284 |
+
|
285 |
+
$bits = $this->bits[$bitsOffset];
|
286 |
+
$bit = 0;
|
287 |
+
|
288 |
+
while (($bits << (31 - $bit)) === 0) {
|
289 |
+
$bit++;
|
290 |
+
}
|
291 |
+
|
292 |
+
$x += $bit;
|
293 |
+
|
294 |
+
return SplFixedArray::fromArray(array($x, $y), false);
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Gets the most bottom right set bit.
|
299 |
+
*
|
300 |
+
* This is useful in detecting a corner of a 'pure' barcode.
|
301 |
+
*
|
302 |
+
* @return SplFixedArray
|
303 |
+
*/
|
304 |
+
public function getBottomRightOnBit()
|
305 |
+
{
|
306 |
+
$bitsOffset = count($this->bits) - 1;
|
307 |
+
|
308 |
+
while ($bitsOffset >= 0 && $this->bits[$bitsOffset] === 0) {
|
309 |
+
$bitsOffset--;
|
310 |
+
}
|
311 |
+
|
312 |
+
if ($bitsOffset < 0) {
|
313 |
+
return null;
|
314 |
+
}
|
315 |
+
|
316 |
+
$x = intval($bitsOffset / $this->rowSize);
|
317 |
+
$y = ($bitsOffset % $this->rowSize) << 5;
|
318 |
+
|
319 |
+
$bits = $this->bits[$bitsOffset];
|
320 |
+
$bit = 0;
|
321 |
+
|
322 |
+
while (BitUtils::unsignedRightShift($bits, $bit) === 0) {
|
323 |
+
$bit--;
|
324 |
+
}
|
325 |
+
|
326 |
+
$x += $bit;
|
327 |
+
|
328 |
+
return SplFixedArray::fromArray(array($x, $y), false);
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Gets the width of the matrix,
|
333 |
+
*
|
334 |
+
* @return integer
|
335 |
+
*/
|
336 |
+
public function getWidth()
|
337 |
+
{
|
338 |
+
return $this->width;
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Gets the height of the matrix.
|
343 |
+
*
|
344 |
+
* @return integer
|
345 |
+
*/
|
346 |
+
public function getHeight()
|
347 |
+
{
|
348 |
+
return $this->height;
|
349 |
+
}
|
350 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* General bit utilities.
|
14 |
+
*
|
15 |
+
* All utility methods are based on 32-bit integers and also work on 64-bit
|
16 |
+
* systems.
|
17 |
+
*/
|
18 |
+
class BitUtils
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Performs an unsigned right shift.
|
22 |
+
*
|
23 |
+
* This is the same as the unsigned right shift operator ">>>" in other
|
24 |
+
* languages.
|
25 |
+
*
|
26 |
+
* @param integer $a
|
27 |
+
* @param integer $b
|
28 |
+
* @return integer
|
29 |
+
*/
|
30 |
+
public static function unsignedRightShift($a, $b)
|
31 |
+
{
|
32 |
+
return (
|
33 |
+
$a >= 0
|
34 |
+
? $a >> $b
|
35 |
+
: (($a & 0x7fffffff) >> $b) | (0x40000000 >> ($b - 1))
|
36 |
+
);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Gets the number of trailing zeros.
|
41 |
+
*
|
42 |
+
* @param integer $i
|
43 |
+
* @return integer
|
44 |
+
*/
|
45 |
+
public static function numberOfTrailingZeros($i)
|
46 |
+
{
|
47 |
+
$lastPos = strrpos(str_pad(decbin($i), 32, '0', STR_PAD_LEFT), '1');
|
48 |
+
|
49 |
+
return $lastPos === false ? 32 : 31 - $lastPos;
|
50 |
+
}
|
51 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Encapsulates a Character Set ECI, according to "Extended Channel
|
14 |
+
* Interpretations" 5.3.1.1 of ISO 18004.
|
15 |
+
*/
|
16 |
+
class CharacterSetEci extends AbstractEnum
|
17 |
+
{
|
18 |
+
/**#@+
|
19 |
+
* Character set constants.
|
20 |
+
*/
|
21 |
+
const CP437 = 0;
|
22 |
+
const ISO8859_1 = 1;
|
23 |
+
const ISO8859_2 = 4;
|
24 |
+
const ISO8859_3 = 5;
|
25 |
+
const ISO8859_4 = 6;
|
26 |
+
const ISO8859_5 = 7;
|
27 |
+
const ISO8859_6 = 8;
|
28 |
+
const ISO8859_7 = 9;
|
29 |
+
const ISO8859_8 = 10;
|
30 |
+
const ISO8859_9 = 11;
|
31 |
+
const ISO8859_10 = 12;
|
32 |
+
const ISO8859_11 = 13;
|
33 |
+
const ISO8859_12 = 14;
|
34 |
+
const ISO8859_13 = 15;
|
35 |
+
const ISO8859_14 = 16;
|
36 |
+
const ISO8859_15 = 17;
|
37 |
+
const ISO8859_16 = 18;
|
38 |
+
const SJIS = 20;
|
39 |
+
const CP1250 = 21;
|
40 |
+
const CP1251 = 22;
|
41 |
+
const CP1252 = 23;
|
42 |
+
const CP1256 = 24;
|
43 |
+
const UNICODE_BIG_UNMARKED = 25;
|
44 |
+
const UTF8 = 26;
|
45 |
+
const ASCII = 27;
|
46 |
+
const BIG5 = 28;
|
47 |
+
const GB18030 = 29;
|
48 |
+
const EUC_KR = 30;
|
49 |
+
/**#@-*/
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Map between character names and their ECI values.
|
53 |
+
*
|
54 |
+
* @var array
|
55 |
+
*/
|
56 |
+
protected static $nameToEci = array(
|
57 |
+
'ISO-8859-1' => self::ISO8859_1,
|
58 |
+
'ISO-8859-2' => self::ISO8859_2,
|
59 |
+
'ISO-8859-3' => self::ISO8859_3,
|
60 |
+
'ISO-8859-4' => self::ISO8859_4,
|
61 |
+
'ISO-8859-5' => self::ISO8859_5,
|
62 |
+
'ISO-8859-6' => self::ISO8859_6,
|
63 |
+
'ISO-8859-7' => self::ISO8859_7,
|
64 |
+
'ISO-8859-8' => self::ISO8859_8,
|
65 |
+
'ISO-8859-9' => self::ISO8859_9,
|
66 |
+
'ISO-8859-10' => self::ISO8859_10,
|
67 |
+
'ISO-8859-11' => self::ISO8859_11,
|
68 |
+
'ISO-8859-12' => self::ISO8859_12,
|
69 |
+
'ISO-8859-13' => self::ISO8859_13,
|
70 |
+
'ISO-8859-14' => self::ISO8859_14,
|
71 |
+
'ISO-8859-15' => self::ISO8859_15,
|
72 |
+
'ISO-8859-16' => self::ISO8859_16,
|
73 |
+
'SHIFT-JIS' => self::SJIS,
|
74 |
+
'WINDOWS-1250' => self::CP1250,
|
75 |
+
'WINDOWS-1251' => self::CP1251,
|
76 |
+
'WINDOWS-1252' => self::CP1252,
|
77 |
+
'WINDOWS-1256' => self::CP1256,
|
78 |
+
'UTF-16BE' => self::UNICODE_BIG_UNMARKED,
|
79 |
+
'UTF-8' => self::UTF8,
|
80 |
+
'ASCII' => self::ASCII,
|
81 |
+
'GBK' => self::GB18030,
|
82 |
+
'EUC-KR' => self::EUC_KR,
|
83 |
+
);
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Additional possible values for character sets.
|
87 |
+
*
|
88 |
+
* @var array
|
89 |
+
*/
|
90 |
+
protected $additionalValues = array(
|
91 |
+
self::CP437 => 2,
|
92 |
+
self::ASCII => 170,
|
93 |
+
);
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Gets character set ECI by value.
|
97 |
+
*
|
98 |
+
* @param string $name
|
99 |
+
* @return CharacterSetEci|null
|
100 |
+
*/
|
101 |
+
public static function getCharacterSetECIByValue($value)
|
102 |
+
{
|
103 |
+
if ($value < 0 || $value >= 900) {
|
104 |
+
throw new Exception\InvalidArgumentException('Value must be between 0 and 900');
|
105 |
+
}
|
106 |
+
|
107 |
+
if (false !== ($key = array_search($value, self::$additionalValues))) {
|
108 |
+
$value = $key;
|
109 |
+
}
|
110 |
+
|
111 |
+
try {
|
112 |
+
return new self($value);
|
113 |
+
} catch (Exception\UnexpectedValueException $e) {
|
114 |
+
return null;
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Gets character set ECI by name.
|
120 |
+
*
|
121 |
+
* @param string $name
|
122 |
+
* @return CharacterSetEci|null
|
123 |
+
*/
|
124 |
+
public static function getCharacterSetECIByName($name)
|
125 |
+
{
|
126 |
+
$name = strtoupper($name);
|
127 |
+
|
128 |
+
if (isset(self::$nameToEci[$name])) {
|
129 |
+
return new self(self::$nameToEci[$name]);
|
130 |
+
}
|
131 |
+
|
132 |
+
return null;
|
133 |
+
}
|
134 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Encapsualtes the parameters for one error-correction block in one symbol
|
14 |
+
* version. This includes the number of data codewords, and the number of times
|
15 |
+
* a block with these parameters is used consecutively in the QR code version's
|
16 |
+
* format.
|
17 |
+
*/
|
18 |
+
class EcBlock
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* How many times the block is used.
|
22 |
+
*
|
23 |
+
* @var integer
|
24 |
+
*/
|
25 |
+
protected $count;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Number of data codewords.
|
29 |
+
*
|
30 |
+
* @var integer
|
31 |
+
*/
|
32 |
+
protected $dataCodewords;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Creates a new EC block.
|
36 |
+
*
|
37 |
+
* @param integer $count
|
38 |
+
* @param integer $dataCodewords
|
39 |
+
*/
|
40 |
+
public function __construct($count, $dataCodewords)
|
41 |
+
{
|
42 |
+
$this->count = $count;
|
43 |
+
$this->dataCodewords = $dataCodewords;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Returns how many times the block is used.
|
48 |
+
*
|
49 |
+
* @return integer
|
50 |
+
*/
|
51 |
+
public function getCount()
|
52 |
+
{
|
53 |
+
return $this->count;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Returns the number of data codewords.
|
58 |
+
*
|
59 |
+
* @return integer
|
60 |
+
*/
|
61 |
+
public function getDataCodewords()
|
62 |
+
{
|
63 |
+
return $this->dataCodewords;
|
64 |
+
}
|
65 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
use SplFixedArray;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Encapsulates a set of error-correction blocks in one symbol version. Most
|
16 |
+
* versions will use blocks of differing sizes within one version, so, this
|
17 |
+
* encapsulates the parameters for each set of blocks. It also holds the number
|
18 |
+
* of error-correction codewords per block since it will be the same across all
|
19 |
+
* blocks within one version.
|
20 |
+
*/
|
21 |
+
class EcBlocks
|
22 |
+
{
|
23 |
+
/**
|
24 |
+
* Number of EC codewords per block.
|
25 |
+
*
|
26 |
+
* @var integer
|
27 |
+
*/
|
28 |
+
protected $ecCodewordsPerBlock;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* List of EC blocks.
|
32 |
+
*
|
33 |
+
* @var SplFixedArray
|
34 |
+
*/
|
35 |
+
protected $ecBlocks;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Creates a new EC blocks instance.
|
39 |
+
*
|
40 |
+
* @param integer $ecCodewordsPerBlock
|
41 |
+
* @param EcBlock $ecb1
|
42 |
+
* @param EcBlock|null $ecb2
|
43 |
+
*/
|
44 |
+
public function __construct($ecCodewordsPerBlock, EcBlock $ecb1, EcBlock $ecb2 = null)
|
45 |
+
{
|
46 |
+
$this->ecCodewordsPerBlock = $ecCodewordsPerBlock;
|
47 |
+
|
48 |
+
$this->ecBlocks = new SplFixedArray($ecb2 === null ? 1 : 2);
|
49 |
+
$this->ecBlocks[0] = $ecb1;
|
50 |
+
|
51 |
+
if ($ecb2 !== null) {
|
52 |
+
$this->ecBlocks[1] = $ecb2;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Gets the number of EC codewords per block.
|
58 |
+
*
|
59 |
+
* @return integer
|
60 |
+
*/
|
61 |
+
public function getEcCodewordsPerBlock()
|
62 |
+
{
|
63 |
+
return $this->ecCodewordsPerBlock;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Gets the total number of EC block appearances.
|
68 |
+
*
|
69 |
+
* @return integer
|
70 |
+
*/
|
71 |
+
public function getNumBlocks()
|
72 |
+
{
|
73 |
+
$total = 0;
|
74 |
+
|
75 |
+
foreach ($this->ecBlocks as $ecBlock) {
|
76 |
+
$total += $ecBlock->getCount();
|
77 |
+
}
|
78 |
+
|
79 |
+
return $total;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Gets the total count of EC codewords.
|
84 |
+
*
|
85 |
+
* @return integer
|
86 |
+
*/
|
87 |
+
public function getTotalEcCodewords()
|
88 |
+
{
|
89 |
+
return $this->ecCodewordsPerBlock * $this->getNumBlocks();
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Gets the EC blocks included in this collection.
|
94 |
+
*
|
95 |
+
* @return SplFixedArray
|
96 |
+
*/
|
97 |
+
public function getEcBlocks()
|
98 |
+
{
|
99 |
+
return $this->ecBlocks;
|
100 |
+
}
|
101 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Enum representing the four error correction levels.
|
14 |
+
*/
|
15 |
+
class ErrorCorrectionLevel extends AbstractEnum
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Level L, ~7% correction.
|
19 |
+
*/
|
20 |
+
const L = 0x1;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Level M, ~15% correction.
|
24 |
+
*/
|
25 |
+
const M = 0x0;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Level Q, ~25% correction.
|
29 |
+
*/
|
30 |
+
const Q = 0x3;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Level H, ~30% correction.
|
34 |
+
*/
|
35 |
+
const H = 0x2;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Gets the ordinal of this enumeration constant.
|
39 |
+
*
|
40 |
+
* @return integer
|
41 |
+
*/
|
42 |
+
public function getOrdinal()
|
43 |
+
{
|
44 |
+
switch ($this->value) {
|
45 |
+
case self::L:
|
46 |
+
return 0;
|
47 |
+
break;
|
48 |
+
|
49 |
+
case self::M:
|
50 |
+
return 1;
|
51 |
+
break;
|
52 |
+
|
53 |
+
case self::Q:
|
54 |
+
return 2;
|
55 |
+
break;
|
56 |
+
|
57 |
+
case self::H:
|
58 |
+
return 3;
|
59 |
+
break;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php
ADDED
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Encapsulates a QR Code's format information, including the data mask used and
|
14 |
+
* error correction level.
|
15 |
+
*/
|
16 |
+
class FormatInformation
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* Mask for format information.
|
20 |
+
*/
|
21 |
+
const FORMAT_INFO_MASK_QR = 0x5412;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Lookup table for decoding format information.
|
25 |
+
*
|
26 |
+
* See ISO 18004:2006, Annex C, Table C.1
|
27 |
+
*
|
28 |
+
* @var array
|
29 |
+
*/
|
30 |
+
protected static $formatInfoDecodeLookup = array(
|
31 |
+
array(0x5412, 0x00),
|
32 |
+
array(0x5125, 0x01),
|
33 |
+
array(0x5e7c, 0x02),
|
34 |
+
array(0x5b4b, 0x03),
|
35 |
+
array(0x45f9, 0x04),
|
36 |
+
array(0x40ce, 0x05),
|
37 |
+
array(0x4f97, 0x06),
|
38 |
+
array(0x4aa0, 0x07),
|
39 |
+
array(0x77c4, 0x08),
|
40 |
+
array(0x72f3, 0x09),
|
41 |
+
array(0x7daa, 0x0a),
|
42 |
+
array(0x789d, 0x0b),
|
43 |
+
array(0x662f, 0x0c),
|
44 |
+
array(0x6318, 0x0d),
|
45 |
+
array(0x6c41, 0x0e),
|
46 |
+
array(0x6976, 0x0f),
|
47 |
+
array(0x1689, 0x10),
|
48 |
+
array(0x13be, 0x11),
|
49 |
+
array(0x1ce7, 0x12),
|
50 |
+
array(0x19d0, 0x13),
|
51 |
+
array(0x0762, 0x14),
|
52 |
+
array(0x0255, 0x15),
|
53 |
+
array(0x0d0c, 0x16),
|
54 |
+
array(0x083b, 0x17),
|
55 |
+
array(0x355f, 0x18),
|
56 |
+
array(0x3068, 0x19),
|
57 |
+
array(0x3f31, 0x1a),
|
58 |
+
array(0x3a06, 0x1b),
|
59 |
+
array(0x24b4, 0x1c),
|
60 |
+
array(0x2183, 0x1d),
|
61 |
+
array(0x2eda, 0x1e),
|
62 |
+
array(0x2bed, 0x1f),
|
63 |
+
);
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Offset i holds the number of 1 bits in the binary representation of i.
|
67 |
+
*
|
68 |
+
* @var array
|
69 |
+
*/
|
70 |
+
protected static $bitsSetInHalfByte = array(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Error correction level.
|
74 |
+
*
|
75 |
+
* @var ErrorCorrectionLevel
|
76 |
+
*/
|
77 |
+
protected $ecLevel;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Data mask.
|
81 |
+
*
|
82 |
+
* @var integer
|
83 |
+
*/
|
84 |
+
protected $dataMask;
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Creates a new format information instance.
|
88 |
+
*
|
89 |
+
* @param integer $formatInfo
|
90 |
+
*/
|
91 |
+
protected function __construct($formatInfo)
|
92 |
+
{
|
93 |
+
$this->ecLevel = new ErrorCorrectionLevel(($formatInfo >> 3) & 0x3);
|
94 |
+
$this->dataMask = $formatInfo & 0x7;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Checks how many bits are different between two integers.
|
99 |
+
*
|
100 |
+
* @param integer $a
|
101 |
+
* @param integer $b
|
102 |
+
* @return integer
|
103 |
+
*/
|
104 |
+
public static function numBitsDiffering($a, $b)
|
105 |
+
{
|
106 |
+
$a ^= $b;
|
107 |
+
|
108 |
+
return (
|
109 |
+
self::$bitsSetInHalfByte[$a & 0xf]
|
110 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 4) & 0xf)]
|
111 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 8) & 0xf)]
|
112 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 12) & 0xf)]
|
113 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 16) & 0xf)]
|
114 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 20) & 0xf)]
|
115 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 24) & 0xf)]
|
116 |
+
+ self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 28) & 0xf)]
|
117 |
+
);
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Decodes format information.
|
122 |
+
*
|
123 |
+
* @param integer $maskedFormatInfo1
|
124 |
+
* @param integer $maskedFormatInfo2
|
125 |
+
* @return FormatInformation|null
|
126 |
+
*/
|
127 |
+
public static function decodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2)
|
128 |
+
{
|
129 |
+
$formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2);
|
130 |
+
|
131 |
+
if ($formatInfo !== null) {
|
132 |
+
return $formatInfo;
|
133 |
+
}
|
134 |
+
|
135 |
+
// Should return null, but, some QR codes apparently do not mask this
|
136 |
+
// info. Try again by actually masking the pattern first.
|
137 |
+
return self::doDecodeFormatInformation(
|
138 |
+
$maskedFormatInfo1 ^ self::FORMAT_INFO_MASK_QR,
|
139 |
+
$maskedFormatInfo2 ^ self::FORMAT_INFO_MASK_QR
|
140 |
+
);
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Internal method for decoding format information.
|
145 |
+
*
|
146 |
+
* @param integer $maskedFormatInfo1
|
147 |
+
* @param integer $maskedFormatInfo2
|
148 |
+
* @return FormatInformation|null
|
149 |
+
*/
|
150 |
+
protected static function doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2)
|
151 |
+
{
|
152 |
+
$bestDifference = PHP_INT_MAX;
|
153 |
+
$bestFormatInfo = 0;
|
154 |
+
|
155 |
+
foreach (self::$formatInfoDecodeLookup as $decodeInfo) {
|
156 |
+
$targetInfo = $decodeInfo[0];
|
157 |
+
|
158 |
+
if ($targetInfo === $maskedFormatInfo1 || $targetInfo === $maskedFormatInfo2) {
|
159 |
+
// Found an exact match
|
160 |
+
return new self($decodeInfo[1]);
|
161 |
+
}
|
162 |
+
|
163 |
+
$bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo);
|
164 |
+
|
165 |
+
if ($bitsDifference < $bestDifference) {
|
166 |
+
$bestFormatInfo = $decodeInfo[1];
|
167 |
+
$bestDifference = $bitsDifference;
|
168 |
+
}
|
169 |
+
|
170 |
+
if ($maskedFormatInfo1 !== $maskedFormatInfo2) {
|
171 |
+
// Also try the other option
|
172 |
+
$bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo);
|
173 |
+
|
174 |
+
if ($bitsDifference < $bestDifference) {
|
175 |
+
$bestFormatInfo = $decodeInfo[1];
|
176 |
+
$bestDifference = $bitsDifference;
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
// Hamming distance of the 32 masked codes is 7, by construction, so
|
182 |
+
// <= 3 bits differing means we found a match.
|
183 |
+
if ($bestDifference <= 3) {
|
184 |
+
return new self($bestFormatInfo);
|
185 |
+
}
|
186 |
+
|
187 |
+
return null;
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* Gets the error correction level.
|
192 |
+
*
|
193 |
+
* @return ErrorCorrectionLevel
|
194 |
+
*/
|
195 |
+
public function getErrorCorrectionLevel()
|
196 |
+
{
|
197 |
+
return $this->ecLevel;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Gets the data mask.
|
202 |
+
*
|
203 |
+
* @return integer
|
204 |
+
*/
|
205 |
+
public function getDataMask()
|
206 |
+
{
|
207 |
+
return $this->dataMask;
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Hashes the code of the EC level.
|
212 |
+
*
|
213 |
+
* @return integer
|
214 |
+
*/
|
215 |
+
public function hashCode()
|
216 |
+
{
|
217 |
+
return ($this->ecLevel->get() << 3) | $this->dataMask;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Verifies if this instance equals another one.
|
222 |
+
*
|
223 |
+
* @param mixed $other
|
224 |
+
* @return boolean
|
225 |
+
*/
|
226 |
+
public function equals($other) {
|
227 |
+
if (!$other instanceof self) {
|
228 |
+
return false;
|
229 |
+
}
|
230 |
+
|
231 |
+
return (
|
232 |
+
$this->ecLevel->get() === $other->getErrorCorrectionLevel()->get()
|
233 |
+
&& $this->dataMask === $other->getDataMask()
|
234 |
+
);
|
235 |
+
}
|
236 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Enum representing various modes in which data can be encoded to bits.
|
14 |
+
*/
|
15 |
+
class Mode extends AbstractEnum
|
16 |
+
{
|
17 |
+
/**#@+
|
18 |
+
* Mode constants.
|
19 |
+
*/
|
20 |
+
const TERMINATOR = 0x0;
|
21 |
+
const NUMERIC = 0x1;
|
22 |
+
const ALPHANUMERIC = 0x2;
|
23 |
+
const STRUCTURED_APPEND = 0x3;
|
24 |
+
const BYTE = 0x4;
|
25 |
+
const ECI = 0x7;
|
26 |
+
const KANJI = 0x8;
|
27 |
+
const FNC1_FIRST_POSITION = 0x5;
|
28 |
+
const FNC1_SECOND_POSITION = 0x9;
|
29 |
+
const HANZI = 0xd;
|
30 |
+
/**#@-*/
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Character count bits for each version.
|
34 |
+
*
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
protected static $characterCountBitsForVersions = array(
|
38 |
+
self::TERMINATOR => array(0, 0, 0),
|
39 |
+
self::NUMERIC => array(10, 12, 14),
|
40 |
+
self::ALPHANUMERIC => array(9, 11, 13),
|
41 |
+
self::STRUCTURED_APPEND => array(0, 0, 0),
|
42 |
+
self::BYTE => array(8, 16, 16),
|
43 |
+
self::ECI => array(0, 0, 0),
|
44 |
+
self::KANJI => array(8, 10, 12),
|
45 |
+
self::FNC1_FIRST_POSITION => array(0, 0, 0),
|
46 |
+
self::FNC1_SECOND_POSITION => array(0, 0, 0),
|
47 |
+
self::HANZI => array(8, 10, 12),
|
48 |
+
);
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Gets the number of bits used in a specific QR code version.
|
52 |
+
*
|
53 |
+
* @param Version $version
|
54 |
+
* @return integer
|
55 |
+
*/
|
56 |
+
public function getCharacterCountBits(Version $version)
|
57 |
+
{
|
58 |
+
$number = $version->getVersionNumber();
|
59 |
+
|
60 |
+
if ($number <= 9) {
|
61 |
+
$offset = 0;
|
62 |
+
} elseif ($number <= 26) {
|
63 |
+
$offset = 1;
|
64 |
+
} else {
|
65 |
+
$offset = 2;
|
66 |
+
}
|
67 |
+
|
68 |
+
return self::$characterCountBitsForVersions[$this->value][$offset];
|
69 |
+
}
|
70 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php
ADDED
@@ -0,0 +1,476 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
use SplFixedArray;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Reed-Solomon codec for 8-bit characters.
|
17 |
+
*
|
18 |
+
* Based on libfec by Phil Karn, KA9Q.
|
19 |
+
*/
|
20 |
+
class ReedSolomonCodec
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Symbol size in bits.
|
24 |
+
*
|
25 |
+
* @var integer
|
26 |
+
*/
|
27 |
+
protected $symbolSize;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Block size in symbols.
|
31 |
+
*
|
32 |
+
* @var integer
|
33 |
+
*/
|
34 |
+
protected $blockSize;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* First root of RS code generator polynomial, index form.
|
38 |
+
*
|
39 |
+
* @var integer
|
40 |
+
*/
|
41 |
+
protected $firstRoot;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Primitive element to generate polynomial roots, index form.
|
45 |
+
*
|
46 |
+
* @var integer
|
47 |
+
*/
|
48 |
+
protected $primitive;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Prim-th root of 1, index form.
|
52 |
+
*
|
53 |
+
* @var integer
|
54 |
+
*/
|
55 |
+
protected $iPrimitive;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* RS code generator polynomial degree (number of roots).
|
59 |
+
*
|
60 |
+
* @var integer
|
61 |
+
*/
|
62 |
+
protected $numRoots;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Padding bytes at front of shortened block.
|
66 |
+
*
|
67 |
+
* @var integer
|
68 |
+
*/
|
69 |
+
protected $padding;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Log lookup table.
|
73 |
+
*
|
74 |
+
* @var SplFixedArray
|
75 |
+
*/
|
76 |
+
protected $alphaTo;
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Anti-Log lookup table.
|
80 |
+
*
|
81 |
+
* @var SplFixedArray
|
82 |
+
*/
|
83 |
+
protected $indexOf;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Generator polynomial.
|
87 |
+
*
|
88 |
+
* @var SplFixedArray
|
89 |
+
*/
|
90 |
+
protected $generatorPoly;
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Creates a new reed solomon instance.
|
94 |
+
*
|
95 |
+
* @param integer $symbolSize
|
96 |
+
* @param integer $gfPoly
|
97 |
+
* @param integer $firstRoot
|
98 |
+
* @param integer $primitive
|
99 |
+
* @param integer $numRoots
|
100 |
+
* @param integer $padding
|
101 |
+
* @throws Exception\InvalidArgumentException
|
102 |
+
* @throws Exception\RuntimeException
|
103 |
+
*/
|
104 |
+
public function __construct($symbolSize, $gfPoly, $firstRoot, $primitive, $numRoots, $padding)
|
105 |
+
{
|
106 |
+
if ($symbolSize < 0 || $symbolSize > 8) {
|
107 |
+
throw new Exception\InvalidArgumentException('Symbol size must be between 0 and 8');
|
108 |
+
}
|
109 |
+
|
110 |
+
if ($firstRoot < 0 || $firstRoot >= (1 << $symbolSize)) {
|
111 |
+
throw new Exception\InvalidArgumentException('First root must be between 0 and ' . (1 << $symbolSize));
|
112 |
+
}
|
113 |
+
|
114 |
+
if ($numRoots < 0 || $numRoots >= (1 << $symbolSize)) {
|
115 |
+
throw new Exception\InvalidArgumentException('Num roots must be between 0 and ' . (1 << $symbolSize));
|
116 |
+
}
|
117 |
+
|
118 |
+
if ($padding < 0 || $padding >= ((1 << $symbolSize) - 1 - $numRoots)) {
|
119 |
+
throw new Exception\InvalidArgumentException('Padding must be between 0 and ' . ((1 << $symbolSize) - 1 - $numRoots));
|
120 |
+
}
|
121 |
+
|
122 |
+
$this->symbolSize = $symbolSize;
|
123 |
+
$this->blockSize = (1 << $symbolSize) - 1;
|
124 |
+
$this->padding = $padding;
|
125 |
+
$this->alphaTo = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
|
126 |
+
$this->indexOf = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
|
127 |
+
|
128 |
+
// Generate galous field lookup table
|
129 |
+
$this->indexOf[0] = $this->blockSize;
|
130 |
+
$this->alphaTo[$this->blockSize] = 0;
|
131 |
+
|
132 |
+
$sr = 1;
|
133 |
+
|
134 |
+
for ($i = 0; $i < $this->blockSize; $i++) {
|
135 |
+
$this->indexOf[$sr] = $i;
|
136 |
+
$this->alphaTo[$i] = $sr;
|
137 |
+
|
138 |
+
$sr <<= 1;
|
139 |
+
|
140 |
+
if ($sr & (1 << $symbolSize)) {
|
141 |
+
$sr ^= $gfPoly;
|
142 |
+
}
|
143 |
+
|
144 |
+
$sr &= $this->blockSize;
|
145 |
+
}
|
146 |
+
|
147 |
+
if ($sr !== 1) {
|
148 |
+
throw new Exception\RuntimeException('Field generator polynomial is not primitive');
|
149 |
+
}
|
150 |
+
|
151 |
+
// Form RS code generator polynomial from its roots
|
152 |
+
$this->generatorPoly = SplFixedArray::fromArray(array_fill(0, $numRoots + 1, 0), false);
|
153 |
+
$this->firstRoot = $firstRoot;
|
154 |
+
$this->primitive = $primitive;
|
155 |
+
$this->numRoots = $numRoots;
|
156 |
+
|
157 |
+
// Find prim-th root of 1, used in decoding
|
158 |
+
for ($iPrimitive = 1; ($iPrimitive % $primitive) !== 0; $iPrimitive += $this->blockSize);
|
159 |
+
$this->iPrimitive = intval($iPrimitive / $primitive);
|
160 |
+
|
161 |
+
$this->generatorPoly[0] = 1;
|
162 |
+
|
163 |
+
for ($i = 0, $root = $firstRoot * $primitive; $i < $numRoots; $i++, $root += $primitive) {
|
164 |
+
$this->generatorPoly[$i + 1] = 1;
|
165 |
+
|
166 |
+
for ($j = $i; $j > 0; $j--) {
|
167 |
+
if ($this->generatorPoly[$j] !== 0) {
|
168 |
+
$this->generatorPoly[$j] = $this->generatorPoly[$j - 1] ^ $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[$j]] + $root)];
|
169 |
+
} else {
|
170 |
+
$this->generatorPoly[$j] = $this->generatorPoly[$j - 1];
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
$this->generatorPoly[$j] = $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[0]] + $root)];
|
175 |
+
}
|
176 |
+
|
177 |
+
// Convert generator poly to index form for quicker encoding
|
178 |
+
for ($i = 0; $i <= $numRoots; $i++) {
|
179 |
+
$this->generatorPoly[$i] = $this->indexOf[$this->generatorPoly[$i]];
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Encodes data and writes result back into parity array.
|
185 |
+
*
|
186 |
+
* @param SplFixedArray $data
|
187 |
+
* @param SplFixedArray $parity
|
188 |
+
* @return void
|
189 |
+
*/
|
190 |
+
public function encode(SplFixedArray $data, SplFixedArray $parity)
|
191 |
+
{
|
192 |
+
for ($i = 0; $i < $this->numRoots; $i++) {
|
193 |
+
$parity[$i] = 0;
|
194 |
+
}
|
195 |
+
|
196 |
+
$iterations = $this->blockSize - $this->numRoots - $this->padding;
|
197 |
+
|
198 |
+
for ($i = 0; $i < $iterations; $i++) {
|
199 |
+
$feedback = $this->indexOf[$data[$i] ^ $parity[0]];
|
200 |
+
|
201 |
+
if ($feedback !== $this->blockSize) {
|
202 |
+
// Feedback term is non-zero
|
203 |
+
$feedback = $this->modNn($this->blockSize - $this->generatorPoly[$this->numRoots] + $feedback);
|
204 |
+
|
205 |
+
for ($j = 1; $j < $this->numRoots; $j++) {
|
206 |
+
$parity[$j] = $parity[$j] ^ $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[$this->numRoots - $j])];
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
for ($j = 0; $j < $this->numRoots - 1; $j++) {
|
211 |
+
$parity[$j] = $parity[$j + 1];
|
212 |
+
}
|
213 |
+
|
214 |
+
if ($feedback !== $this->blockSize) {
|
215 |
+
$parity[$this->numRoots - 1] = $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[0])];
|
216 |
+
} else {
|
217 |
+
$parity[$this->numRoots - 1] = 0;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Decodes received data.
|
224 |
+
*
|
225 |
+
* @param SplFixedArray $data
|
226 |
+
* @param SplFixedArray|null $erasures
|
227 |
+
* @return null|integer
|
228 |
+
*/
|
229 |
+
public function decode(SplFixedArray $data, SplFixedArray $erasures = null)
|
230 |
+
{
|
231 |
+
// This speeds up the initialization a bit.
|
232 |
+
$numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0), false);
|
233 |
+
$numRoots = SplFixedArray::fromArray(array_fill(0, $this->numRoots, 0), false);
|
234 |
+
|
235 |
+
$lambda = clone $numRootsPlusOne;
|
236 |
+
$b = clone $numRootsPlusOne;
|
237 |
+
$t = clone $numRootsPlusOne;
|
238 |
+
$omega = clone $numRootsPlusOne;
|
239 |
+
$root = clone $numRoots;
|
240 |
+
$loc = clone $numRoots;
|
241 |
+
|
242 |
+
$numErasures = ($erasures !== null ? count($erasures) : 0);
|
243 |
+
|
244 |
+
// Form the Syndromes; i.e., evaluate data(x) at roots of g(x)
|
245 |
+
$syndromes = SplFixedArray::fromArray(array_fill(0, $this->numRoots, $data[0]), false);
|
246 |
+
|
247 |
+
for ($i = 1; $i < $this->blockSize - $this->padding; $i++) {
|
248 |
+
for ($j = 0; $j < $this->numRoots; $j++) {
|
249 |
+
if ($syndromes[$j] === 0) {
|
250 |
+
$syndromes[$j] = $data[$i];
|
251 |
+
} else {
|
252 |
+
$syndromes[$j] = $data[$i] ^ $this->alphaTo[
|
253 |
+
$this->modNn($this->indexOf[$syndromes[$j]] + ($this->firstRoot + $j) * $this->primitive)
|
254 |
+
];
|
255 |
+
}
|
256 |
+
}
|
257 |
+
}
|
258 |
+
|
259 |
+
// Convert syndromes to index form, checking for nonzero conditions
|
260 |
+
$syndromeError = 0;
|
261 |
+
|
262 |
+
for ($i = 0; $i < $this->numRoots; $i++) {
|
263 |
+
$syndromeError |= $syndromes[$i];
|
264 |
+
$syndromes[$i] = $this->indexOf[$syndromes[$i]];
|
265 |
+
}
|
266 |
+
|
267 |
+
if (!$syndromeError) {
|
268 |
+
// If syndrome is zero, data[] is a codeword and there are no errors
|
269 |
+
// to correct, so return data[] unmodified.
|
270 |
+
return 0;
|
271 |
+
}
|
272 |
+
|
273 |
+
$lambda[0] = 1;
|
274 |
+
|
275 |
+
if ($numErasures > 0) {
|
276 |
+
// Init lambda to be the erasure locator polynomial
|
277 |
+
$lambda[1] = $this->alphaTo[$this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[0]))];
|
278 |
+
|
279 |
+
for ($i = 1; $i < $numErasures; $i++) {
|
280 |
+
$u = $this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[$i]));
|
281 |
+
|
282 |
+
for ($j = $i + 1; $j > 0; $j--) {
|
283 |
+
$tmp = $this->indexOf[$lambda[$j - 1]];
|
284 |
+
|
285 |
+
if ($tmp !== $this->blockSize) {
|
286 |
+
$lambda[$j] = $lambda[$j] ^ $this->alphaTo[$this->modNn($u + $tmp)];
|
287 |
+
}
|
288 |
+
}
|
289 |
+
}
|
290 |
+
}
|
291 |
+
|
292 |
+
for ($i = 0; $i <= $this->numRoots; $i++) {
|
293 |
+
$b[$i] = $this->indexOf[$lambda[$i]];
|
294 |
+
}
|
295 |
+
|
296 |
+
// Begin Berlekamp-Massey algorithm to determine error+erasure locator
|
297 |
+
// polynomial
|
298 |
+
$r = $numErasures;
|
299 |
+
$el = $numErasures;
|
300 |
+
|
301 |
+
while (++$r <= $this->numRoots) {
|
302 |
+
// Compute discrepancy at the r-th step in poly form
|
303 |
+
$discrepancyR = 0;
|
304 |
+
|
305 |
+
for ($i = 0; $i < $r; $i++) {
|
306 |
+
if ($lambda[$i] !== 0 && $syndromes[$r - $i - 1] !== $this->blockSize) {
|
307 |
+
$discrepancyR ^= $this->alphaTo[$this->modNn($this->indexOf[$lambda[$i]] + $syndromes[$r - $i - 1])];
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
$discrepancyR = $this->indexOf[$discrepancyR];
|
312 |
+
|
313 |
+
if ($discrepancyR === $this->blockSize) {
|
314 |
+
$tmp = $b->toArray();
|
315 |
+
array_unshift($tmp, $this->blockSize);
|
316 |
+
array_pop($tmp);
|
317 |
+
$b = SplFixedArray::fromArray($tmp, false);
|
318 |
+
} else {
|
319 |
+
$t[0] = $lambda[0];
|
320 |
+
|
321 |
+
for ($i = 0; $i < $this->numRoots; $i++) {
|
322 |
+
if ($b[$i] !== $this->blockSize) {
|
323 |
+
$t[$i + 1] = $lambda[$i + 1] ^ $this->alphaTo[$this->modNn($discrepancyR + $b[$i])];
|
324 |
+
} else {
|
325 |
+
$t[$i + 1] = $lambda[$i + 1];
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
if (2 * $el <= $r + $numErasures - 1) {
|
330 |
+
$el = $r + $numErasures - $el;
|
331 |
+
|
332 |
+
for ($i = 0; $i <= $this->numRoots; $i++) {
|
333 |
+
$b[$i] = (
|
334 |
+
$lambda[$i] === 0
|
335 |
+
? $this->blockSize
|
336 |
+
: $this->modNn($this->indexOf[$lambda[$i]] - $discrepancyR + $this->blockSize)
|
337 |
+
);
|
338 |
+
}
|
339 |
+
} else {
|
340 |
+
$tmp = $b->toArray();
|
341 |
+
array_unshift($tmp, $this->blockSize);
|
342 |
+
array_pop($tmp);
|
343 |
+
$b = SplFixedArray::fromArray($tmp, false);
|
344 |
+
}
|
345 |
+
|
346 |
+
$lambda = clone $t;
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
// Convert lambda to index form and compute deg(lambda(x))
|
351 |
+
$degLambda = 0;
|
352 |
+
|
353 |
+
for ($i = 0; $i <= $this->numRoots; $i++) {
|
354 |
+
$lambda[$i] = $this->indexOf[$lambda[$i]];
|
355 |
+
|
356 |
+
if ($lambda[$i] !== $this->blockSize) {
|
357 |
+
$degLambda = $i;
|
358 |
+
}
|
359 |
+
}
|
360 |
+
|
361 |
+
// Find roots of the error+erasure locator polynomial by Chien search.
|
362 |
+
$reg = clone $lambda;
|
363 |
+
$reg[0] = 0;
|
364 |
+
$count = 0;
|
365 |
+
|
366 |
+
for ($i = 1, $k = $this->iPrimitive - 1; $i <= $this->blockSize; $i++, $k = $this->modNn($k + $this->iPrimitive)) {
|
367 |
+
$q = 1;
|
368 |
+
|
369 |
+
for ($j = $degLambda; $j > 0; $j--) {
|
370 |
+
if ($reg[$j] !== $this->blockSize) {
|
371 |
+
$reg[$j] = $this->modNn($reg[$j] + $j);
|
372 |
+
$q ^= $this->alphaTo[$reg[$j]];
|
373 |
+
}
|
374 |
+
}
|
375 |
+
|
376 |
+
if ($q !== 0) {
|
377 |
+
// Not a root
|
378 |
+
continue;
|
379 |
+
}
|
380 |
+
|
381 |
+
// Store root (index-form) and error location number
|
382 |
+
$root[$count] = $i;
|
383 |
+
$loc[$count] = $k;
|
384 |
+
|
385 |
+
if (++$count === $degLambda) {
|
386 |
+
break;
|
387 |
+
}
|
388 |
+
}
|
389 |
+
|
390 |
+
if ($degLambda !== $count) {
|
391 |
+
// deg(lambda) unequal to number of roots: uncorreactable error
|
392 |
+
// detected
|
393 |
+
return null;
|
394 |
+
}
|
395 |
+
|
396 |
+
// Compute err+eras evaluate poly omega(x) = s(x)*lambda(x) (modulo
|
397 |
+
// x**numRoots). In index form. Also find deg(omega).
|
398 |
+
$degOmega = $degLambda - 1;
|
399 |
+
|
400 |
+
for ($i = 0; $i <= $degOmega; $i++) {
|
401 |
+
$tmp = 0;
|
402 |
+
|
403 |
+
for ($j = $i; $j >= 0; $j--) {
|
404 |
+
if ($syndromes[$i - $j] !== $this->blockSize && $lambda[$j] !== $this->blockSize) {
|
405 |
+
$tmp ^= $this->alphaTo[$this->modNn($syndromes[$i - $j] + $lambda[$j])];
|
406 |
+
}
|
407 |
+
}
|
408 |
+
|
409 |
+
$omega[$i] = $this->indexOf[$tmp];
|
410 |
+
}
|
411 |
+
|
412 |
+
// Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
|
413 |
+
// inv(X(l))**(firstRoot-1) and den = lambda_pr(inv(X(l))) all in poly
|
414 |
+
// form.
|
415 |
+
for ($j = $count - 1; $j >= 0; $j--) {
|
416 |
+
$num1 = 0;
|
417 |
+
|
418 |
+
for ($i = $degOmega; $i >= 0; $i--) {
|
419 |
+
if ($omega[$i] !== $this->blockSize) {
|
420 |
+
$num1 ^= $this->alphaTo[$this->modNn($omega[$i] + $i * $root[$j])];
|
421 |
+
}
|
422 |
+
}
|
423 |
+
|
424 |
+
$num2 = $this->alphaTo[$this->modNn($root[$j] * ($this->firstRoot - 1) + $this->blockSize)];
|
425 |
+
$den = 0;
|
426 |
+
|
427 |
+
// lambda[i+1] for i even is the formal derivativelambda_pr of
|
428 |
+
// lambda[i]
|
429 |
+
for ($i = min($degLambda, $this->numRoots - 1) & ~1; $i >= 0; $i -= 2) {
|
430 |
+
if ($lambda[$i + 1] !== $this->blockSize) {
|
431 |
+
$den ^= $this->alphaTo[$this->modNn($lambda[$i + 1] + $i * $root[$j])];
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
+
// Apply error to data
|
436 |
+
if ($num1 !== 0 && $loc[$j] >= $this->padding) {
|
437 |
+
$data[$loc[$j] - $this->padding] = $data[$loc[$j] - $this->padding] ^ (
|
438 |
+
$this->alphaTo[
|
439 |
+
$this->modNn(
|
440 |
+
$this->indexOf[$num1] + $this->indexOf[$num2] + $this->blockSize - $this->indexOf[$den]
|
441 |
+
)
|
442 |
+
]
|
443 |
+
);
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
if ($erasures !== null) {
|
448 |
+
if (count($erasures) < $count) {
|
449 |
+
$erasures->setSize($count);
|
450 |
+
}
|
451 |
+
|
452 |
+
for ($i = 0; $i < $count; $i++) {
|
453 |
+
$erasures[$i] = $loc[$i];
|
454 |
+
}
|
455 |
+
}
|
456 |
+
|
457 |
+
return $count;
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* Computes $x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, without a slow
|
462 |
+
* divide.
|
463 |
+
*
|
464 |
+
* @param itneger $x
|
465 |
+
* @return integer
|
466 |
+
*/
|
467 |
+
protected function modNn($x)
|
468 |
+
{
|
469 |
+
while ($x >= $this->blockSize) {
|
470 |
+
$x -= $this->blockSize;
|
471 |
+
$x = ($x >> $this->symbolSize) + ($x & $this->blockSize);
|
472 |
+
}
|
473 |
+
|
474 |
+
return $x;
|
475 |
+
}
|
476 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php
ADDED
@@ -0,0 +1,687 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Common;
|
11 |
+
|
12 |
+
use SplFixedArray;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Version representation.
|
16 |
+
*/
|
17 |
+
class Version
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Version decode information.
|
21 |
+
*
|
22 |
+
* @var array
|
23 |
+
*/
|
24 |
+
protected static $versionDecodeInfo = array(
|
25 |
+
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
|
26 |
+
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
|
27 |
+
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
|
28 |
+
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
|
29 |
+
0x27541, 0x28c69
|
30 |
+
);
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Cached version instances.
|
34 |
+
*
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
protected static $versions = array();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Version number of this version.
|
41 |
+
*
|
42 |
+
* @var integer
|
43 |
+
*/
|
44 |
+
protected $versionNumber;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Alignment pattern centers.
|
48 |
+
*
|
49 |
+
* @var SplFixedArray
|
50 |
+
*/
|
51 |
+
protected $alignmentPatternCenters;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Error correction blocks.
|
55 |
+
*
|
56 |
+
* @var SplFixedArray
|
57 |
+
*/
|
58 |
+
protected $errorCorrectionBlocks;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Total number of codewords.
|
62 |
+
*
|
63 |
+
* @var integer
|
64 |
+
*/
|
65 |
+
protected $totalCodewords;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Creates a new version.
|
69 |
+
*
|
70 |
+
* @param integer $versionNumber
|
71 |
+
* @param SplFixedArray $alignmentPatternCenters
|
72 |
+
* @param SplFixedArray $ecBlocks
|
73 |
+
*/
|
74 |
+
protected function __construct(
|
75 |
+
$versionNumber,
|
76 |
+
SplFixedArray $alignmentPatternCenters,
|
77 |
+
SplFixedArray $ecBlocks
|
78 |
+
) {
|
79 |
+
$this->versionNumber = $versionNumber;
|
80 |
+
$this->alignmentPatternCenters = $alignmentPatternCenters;
|
81 |
+
$this->errorCorrectionBlocks = $ecBlocks;
|
82 |
+
|
83 |
+
$totalCodewords = 0;
|
84 |
+
$ecCodewords = $ecBlocks[0]->getEcCodewordsPerBlock();
|
85 |
+
|
86 |
+
foreach ($ecBlocks[0]->getEcBlocks() as $ecBlock) {
|
87 |
+
$totalCodewords += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords);
|
88 |
+
}
|
89 |
+
|
90 |
+
$this->totalCodewords = $totalCodewords;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Gets the version number.
|
95 |
+
*
|
96 |
+
* @return integer
|
97 |
+
*/
|
98 |
+
public function getVersionNumber()
|
99 |
+
{
|
100 |
+
return $this->versionNumber;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Gets the alignment pattern centers.
|
105 |
+
*
|
106 |
+
* @return SplFixedArray
|
107 |
+
*/
|
108 |
+
public function getAlignmentPatternCenters()
|
109 |
+
{
|
110 |
+
return $this->alignmentPatternCenters;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Gets the total number of codewords.
|
115 |
+
*
|
116 |
+
* @return integer
|
117 |
+
*/
|
118 |
+
public function getTotalCodewords()
|
119 |
+
{
|
120 |
+
return $this->totalCodewords;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Gets the dimension for the current version.
|
125 |
+
*
|
126 |
+
* @return integer
|
127 |
+
*/
|
128 |
+
public function getDimensionForVersion()
|
129 |
+
{
|
130 |
+
return 17 + 4 * $this->versionNumber;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Gets the number of EC blocks for a specific EC level.
|
135 |
+
*
|
136 |
+
* @param ErrorCorrectionLevel $ecLevel
|
137 |
+
* @return integer
|
138 |
+
*/
|
139 |
+
public function getEcBlocksForLevel(ErrorCorrectionLevel $ecLevel)
|
140 |
+
{
|
141 |
+
return $this->errorCorrectionBlocks[$ecLevel->getOrdinal()];
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Gets a provisional version number for a specific dimension.
|
146 |
+
*
|
147 |
+
* @param integer $dimension
|
148 |
+
* @return Version
|
149 |
+
* @throws Exception\InvalidArgumentException
|
150 |
+
*/
|
151 |
+
public static function getProvisionalVersionForDimension($dimension)
|
152 |
+
{
|
153 |
+
if ($dimension % 4 !== 1) {
|
154 |
+
throw new Exception\InvalidArgumentException('Dimension is not 1 mod 4');
|
155 |
+
}
|
156 |
+
|
157 |
+
return self::getVersionForNumber(($dimension - 17) >> 2);
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Gets a version instance for a specific version number.
|
162 |
+
*
|
163 |
+
* @param integer $versionNumber
|
164 |
+
* @return Version
|
165 |
+
* @throws Exception\InvalidArgumentException
|
166 |
+
*/
|
167 |
+
public static function getVersionForNumber($versionNumber)
|
168 |
+
{
|
169 |
+
if ($versionNumber < 1 || $versionNumber > 40) {
|
170 |
+
throw new Exception\InvalidArgumentException('Version number must be between 1 and 40');
|
171 |
+
}
|
172 |
+
|
173 |
+
if (!isset(self::$versions[$versionNumber])) {
|
174 |
+
self::buildVersion($versionNumber);
|
175 |
+
}
|
176 |
+
|
177 |
+
return self::$versions[$versionNumber - 1];
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Decodes version information from an integer and returns the version.
|
182 |
+
*
|
183 |
+
* @param integer $versionBits
|
184 |
+
* @return Version|null
|
185 |
+
*/
|
186 |
+
public static function decodeVersionInformation($versionBits)
|
187 |
+
{
|
188 |
+
$bestDifference = PHP_INT_MAX;
|
189 |
+
$bestVersion = 0;
|
190 |
+
|
191 |
+
foreach (self::$versionDecodeInfo as $i => $targetVersion) {
|
192 |
+
if ($targetVersion === $versionBits) {
|
193 |
+
return self::getVersionForNumber($i + 7);
|
194 |
+
}
|
195 |
+
|
196 |
+
$bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion);
|
197 |
+
|
198 |
+
if ($bitsDifference < $bestDifference) {
|
199 |
+
$bestVersion = $i + 7;
|
200 |
+
$bestDifference = $bitsDifference;
|
201 |
+
}
|
202 |
+
}
|
203 |
+
|
204 |
+
if ($bestDifference <= 3) {
|
205 |
+
return self::getVersionForNumber($bestVersion);
|
206 |
+
}
|
207 |
+
|
208 |
+
return null;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Builds the function pattern for the current version.
|
213 |
+
*
|
214 |
+
* @return BitMatrix
|
215 |
+
*/
|
216 |
+
public function buildFunctionPattern()
|
217 |
+
{
|
218 |
+
$dimension = $this->getDimensionForVersion();
|
219 |
+
$bitMatrix = new BitMatrix($dimension);
|
220 |
+
|
221 |
+
// Top left finder pattern + separator + format
|
222 |
+
$bitMatrix->setRegion(0, 0, 9, 9);
|
223 |
+
// Top right finder pattern + separator + format
|
224 |
+
$bitMatrix->setRegion($dimension - 8, 0, 8, 9);
|
225 |
+
// Bottom left finder pattern + separator + format
|
226 |
+
$bitMatrix->setRegion(0, $dimension - 8, 9, 8);
|
227 |
+
|
228 |
+
// Alignment patterns
|
229 |
+
$max = count($this->alignmentPatternCenters);
|
230 |
+
|
231 |
+
for ($x = 0; $x < $max; $x++) {
|
232 |
+
$i = $this->alignmentPatternCenters[$x] - 2;
|
233 |
+
|
234 |
+
for ($y = 0; $y < $max; $y++) {
|
235 |
+
if (($x === 0 && ($y === 0 || $y === $max - 1)) || ($x === $max - 1 && $y === 0)) {
|
236 |
+
// No alignment patterns near the three finder paterns
|
237 |
+
continue;
|
238 |
+
}
|
239 |
+
|
240 |
+
$bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5);
|
241 |
+
}
|
242 |
+
}
|
243 |
+
|
244 |
+
// Vertical timing pattern
|
245 |
+
$bitMatrix->setRegion(6, 9, 1, $dimension - 17);
|
246 |
+
// Horizontal timing pattern
|
247 |
+
$bitMatrix->setRegion(9, 6, $dimension - 17, 1);
|
248 |
+
|
249 |
+
if ($this->versionNumber > 6) {
|
250 |
+
// Version info, top right
|
251 |
+
$bitMatrix->setRegion($dimension - 11, 0, 3, 6);
|
252 |
+
// Version info, bottom left
|
253 |
+
$bitMatrix->setRegion(0, $dimension - 11, 6, 3);
|
254 |
+
}
|
255 |
+
|
256 |
+
return $bitMatrix;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Returns a string representation for the version.
|
261 |
+
*
|
262 |
+
* @return string
|
263 |
+
*/
|
264 |
+
public function __toString()
|
265 |
+
{
|
266 |
+
return (string) $this->versionNumber;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Build and cache a specific version.
|
271 |
+
*
|
272 |
+
* See ISO 18004:2006 6.5.1 Table 9.
|
273 |
+
*
|
274 |
+
* @param integer $versionNumber
|
275 |
+
* @return void
|
276 |
+
*/
|
277 |
+
protected static function buildVersion($versionNumber)
|
278 |
+
{
|
279 |
+
switch ($versionNumber) {
|
280 |
+
case 1:
|
281 |
+
$patterns = array();
|
282 |
+
$ecBlocks = array(
|
283 |
+
new EcBlocks(7, new EcBlock(1, 19)),
|
284 |
+
new EcBlocks(10, new EcBlock(1, 16)),
|
285 |
+
new EcBlocks(13, new EcBlock(1, 13)),
|
286 |
+
new EcBlocks(17, new EcBlock(1, 9)),
|
287 |
+
);
|
288 |
+
break;
|
289 |
+
|
290 |
+
case 2:
|
291 |
+
$patterns = array(6, 18);
|
292 |
+
$ecBlocks = array(
|
293 |
+
new EcBlocks(10, new EcBlock(1, 34)),
|
294 |
+
new EcBlocks(16, new EcBlock(1, 28)),
|
295 |
+
new EcBlocks(22, new EcBlock(1, 22)),
|
296 |
+
new EcBlocks(28, new EcBlock(1, 16)),
|
297 |
+
);
|
298 |
+
break;
|
299 |
+
|
300 |
+
case 3:
|
301 |
+
$patterns = array(6, 22);
|
302 |
+
$ecBlocks = array(
|
303 |
+
new EcBlocks(15, new EcBlock(1, 55)),
|
304 |
+
new EcBlocks(26, new EcBlock(1, 44)),
|
305 |
+
new EcBlocks(18, new EcBlock(2, 17)),
|
306 |
+
new EcBlocks(22, new EcBlock(2, 13)),
|
307 |
+
);
|
308 |
+
break;
|
309 |
+
|
310 |
+
case 4:
|
311 |
+
$patterns = array(6, 26);
|
312 |
+
$ecBlocks = array(
|
313 |
+
new EcBlocks(20, new EcBlock(1, 80)),
|
314 |
+
new EcBlocks(18, new EcBlock(2, 32)),
|
315 |
+
new EcBlocks(26, new EcBlock(3, 24)),
|
316 |
+
new EcBlocks(16, new EcBlock(4, 9)),
|
317 |
+
);
|
318 |
+
break;
|
319 |
+
|
320 |
+
case 5:
|
321 |
+
$patterns = array(6, 30);
|
322 |
+
$ecBlocks = array(
|
323 |
+
new EcBlocks(26, new EcBlock(1, 108)),
|
324 |
+
new EcBlocks(24, new EcBlock(2, 43)),
|
325 |
+
new EcBlocks(18, new EcBlock(2, 15), new EcBlock(2, 16)),
|
326 |
+
new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12)),
|
327 |
+
);
|
328 |
+
break;
|
329 |
+
|
330 |
+
case 6:
|
331 |
+
$patterns = array(6, 34);
|
332 |
+
$ecBlocks = array(
|
333 |
+
new EcBlocks(18, new EcBlock(2, 68)),
|
334 |
+
new EcBlocks(16, new EcBlock(4, 27)),
|
335 |
+
new EcBlocks(24, new EcBlock(4, 19)),
|
336 |
+
new EcBlocks(28, new EcBlock(4, 15)),
|
337 |
+
);
|
338 |
+
break;
|
339 |
+
|
340 |
+
case 7:
|
341 |
+
$patterns = array(6, 22, 38);
|
342 |
+
$ecBlocks = array(
|
343 |
+
new EcBlocks(20, new EcBlock(2, 78)),
|
344 |
+
new EcBlocks(18, new EcBlock(4, 31)),
|
345 |
+
new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)),
|
346 |
+
new EcBlocks(26, new EcBlock(4, 13), new EcBlock(1, 14)),
|
347 |
+
);
|
348 |
+
break;
|
349 |
+
|
350 |
+
case 8:
|
351 |
+
$patterns = array(6, 24, 42);
|
352 |
+
$ecBlocks = array(
|
353 |
+
new EcBlocks(24, new EcBlock(2, 97)),
|
354 |
+
new EcBlocks(22, new EcBlock(2, 38), new EcBlock(2, 39)),
|
355 |
+
new EcBlocks(22, new EcBlock(4, 18), new EcBlock(2, 19)),
|
356 |
+
new EcBlocks(26, new EcBlock(4, 14), new EcBlock(2, 15)),
|
357 |
+
);
|
358 |
+
break;
|
359 |
+
|
360 |
+
case 9:
|
361 |
+
$patterns = array(6, 26, 46);
|
362 |
+
$ecBlocks = array(
|
363 |
+
new EcBlocks(30, new EcBlock(2, 116)),
|
364 |
+
new EcBlocks(22, new EcBlock(3, 36), new EcBlock(2, 37)),
|
365 |
+
new EcBlocks(20, new EcBlock(4, 16), new EcBlock(4, 17)),
|
366 |
+
new EcBlocks(24, new EcBlock(4, 12), new EcBlock(4, 13)),
|
367 |
+
);
|
368 |
+
break;
|
369 |
+
|
370 |
+
case 10:
|
371 |
+
$patterns = array(6, 28, 50);
|
372 |
+
$ecBlocks = array(
|
373 |
+
new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)),
|
374 |
+
new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)),
|
375 |
+
new EcBlocks(24, new EcBlock(6, 19), new EcBlock(2, 20)),
|
376 |
+
new EcBlocks(28, new EcBlock(6, 15), new EcBlock(2, 16)),
|
377 |
+
);
|
378 |
+
break;
|
379 |
+
|
380 |
+
case 11:
|
381 |
+
$patterns = array(6, 30, 54);
|
382 |
+
$ecBlocks = array(
|
383 |
+
new EcBlocks(20, new EcBlock(4, 81)),
|
384 |
+
new EcBlocks(30, new EcBlock(1, 50), new EcBlock(4, 51)),
|
385 |
+
new EcBlocks(28, new EcBlock(4, 22), new EcBlock(4, 23)),
|
386 |
+
new EcBlocks(24, new EcBlock(3, 12), new EcBlock(8, 13)),
|
387 |
+
);
|
388 |
+
break;
|
389 |
+
|
390 |
+
case 12:
|
391 |
+
$patterns = array(6, 32, 58);
|
392 |
+
$ecBlocks = array(
|
393 |
+
new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)),
|
394 |
+
new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)),
|
395 |
+
new EcBlocks(26, new EcBlock(4, 20), new EcBlock(6, 21)),
|
396 |
+
new EcBlocks(28, new EcBlock(7, 14), new EcBlock(4, 15)),
|
397 |
+
);
|
398 |
+
break;
|
399 |
+
|
400 |
+
case 13:
|
401 |
+
$patterns = array(6, 34, 62);
|
402 |
+
$ecBlocks = array(
|
403 |
+
new EcBlocks(26, new EcBlock(4, 107)),
|
404 |
+
new EcBlocks(22, new EcBlock(8, 37), new EcBlock(1, 38)),
|
405 |
+
new EcBlocks(24, new EcBlock(8, 20), new EcBlock(4, 21)),
|
406 |
+
new EcBlocks(22, new EcBlock(12, 11), new EcBlock(4, 12)),
|
407 |
+
);
|
408 |
+
break;
|
409 |
+
|
410 |
+
case 14:
|
411 |
+
$patterns = array(6, 26, 46, 66);
|
412 |
+
$ecBlocks = array(
|
413 |
+
new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1, 116)),
|
414 |
+
new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5, 41)),
|
415 |
+
new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5, 17)),
|
416 |
+
new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13)),
|
417 |
+
);
|
418 |
+
break;
|
419 |
+
|
420 |
+
case 15:
|
421 |
+
$patterns = array(6, 26, 48, 70);
|
422 |
+
$ecBlocks = array(
|
423 |
+
new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)),
|
424 |
+
new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)),
|
425 |
+
new EcBlocks(30, new EcBlock(5, 24), new EcBlock(7, 25)),
|
426 |
+
new EcBlocks(24, new EcBlock(11, 12), new EcBlock(7, 13)),
|
427 |
+
);
|
428 |
+
break;
|
429 |
+
|
430 |
+
case 16:
|
431 |
+
$patterns = array(6, 26, 50, 74);
|
432 |
+
$ecBlocks = array(
|
433 |
+
new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)),
|
434 |
+
new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)),
|
435 |
+
new EcBlocks(24, new EcBlock(15, 19), new EcBlock(2, 20)),
|
436 |
+
new EcBlocks(30, new EcBlock(3, 15), new EcBlock(13, 16)),
|
437 |
+
);
|
438 |
+
break;
|
439 |
+
|
440 |
+
case 17:
|
441 |
+
$patterns = array(6, 30, 54, 78);
|
442 |
+
$ecBlocks = array(
|
443 |
+
new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5, 108)),
|
444 |
+
new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1, 47)),
|
445 |
+
new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15, 23)),
|
446 |
+
new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15)),
|
447 |
+
);
|
448 |
+
break;
|
449 |
+
|
450 |
+
case 18:
|
451 |
+
$patterns = array(6, 30, 56, 82);
|
452 |
+
$ecBlocks = array(
|
453 |
+
new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1, 121)),
|
454 |
+
new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4, 44)),
|
455 |
+
new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1, 23)),
|
456 |
+
new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15)),
|
457 |
+
);
|
458 |
+
break;
|
459 |
+
|
460 |
+
case 19:
|
461 |
+
$patterns = array(6, 30, 58, 86);
|
462 |
+
$ecBlocks = array(
|
463 |
+
new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4, 114)),
|
464 |
+
new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11, 45)),
|
465 |
+
new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4, 22)),
|
466 |
+
new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14)),
|
467 |
+
);
|
468 |
+
break;
|
469 |
+
|
470 |
+
case 20:
|
471 |
+
$patterns = array(6, 34, 62, 90);
|
472 |
+
$ecBlocks = array(
|
473 |
+
new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5, 108)),
|
474 |
+
new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13, 42)),
|
475 |
+
new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5, 25)),
|
476 |
+
new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16)),
|
477 |
+
);
|
478 |
+
break;
|
479 |
+
|
480 |
+
case 21:
|
481 |
+
$patterns = array(6, 28, 50, 72, 94);
|
482 |
+
$ecBlocks = array(
|
483 |
+
new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4, 117)),
|
484 |
+
new EcBlocks(26, new EcBlock(17, 42)),
|
485 |
+
new EcBlocks(28, new EcBlock(17, 22), new EcBlock(6, 23)),
|
486 |
+
new EcBlocks(30, new EcBlock(19, 16), new EcBlock(6, 17)),
|
487 |
+
);
|
488 |
+
break;
|
489 |
+
|
490 |
+
case 22:
|
491 |
+
$patterns = array(6, 26, 50, 74, 98);
|
492 |
+
$ecBlocks = array(
|
493 |
+
new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7, 112)),
|
494 |
+
new EcBlocks(28, new EcBlock(17, 46)),
|
495 |
+
new EcBlocks(30, new EcBlock(7, 24), new EcBlock(16, 25)),
|
496 |
+
new EcBlocks(24, new EcBlock(34, 13)),
|
497 |
+
);
|
498 |
+
break;
|
499 |
+
|
500 |
+
case 23:
|
501 |
+
$patterns = array(6, 30, 54, 78, 102);
|
502 |
+
$ecBlocks = array(
|
503 |
+
new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5, 122)),
|
504 |
+
new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14, 48)),
|
505 |
+
new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14, 25)),
|
506 |
+
new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16)),
|
507 |
+
);
|
508 |
+
break;
|
509 |
+
|
510 |
+
case 24:
|
511 |
+
$patterns = array(6, 28, 54, 80, 106);
|
512 |
+
$ecBlocks = array(
|
513 |
+
new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4, 118)),
|
514 |
+
new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14, 46)),
|
515 |
+
new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16, 25)),
|
516 |
+
new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17)),
|
517 |
+
);
|
518 |
+
break;
|
519 |
+
|
520 |
+
case 25:
|
521 |
+
$patterns = array(6, 32, 58, 84, 110);
|
522 |
+
$ecBlocks = array(
|
523 |
+
new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4, 107)),
|
524 |
+
new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13, 48)),
|
525 |
+
new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22, 25)),
|
526 |
+
new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16)),
|
527 |
+
);
|
528 |
+
break;
|
529 |
+
|
530 |
+
case 26:
|
531 |
+
$patterns = array(6, 30, 58, 86, 114);
|
532 |
+
$ecBlocks = array(
|
533 |
+
new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2, 115)),
|
534 |
+
new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4, 47)),
|
535 |
+
new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6, 23)),
|
536 |
+
new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17)),
|
537 |
+
);
|
538 |
+
break;
|
539 |
+
|
540 |
+
case 27:
|
541 |
+
$patterns = array(6, 34, 62, 90, 118);
|
542 |
+
$ecBlocks = array(
|
543 |
+
new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4, 123)),
|
544 |
+
new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3, 46)),
|
545 |
+
new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26, 24)),
|
546 |
+
new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16)),
|
547 |
+
);
|
548 |
+
break;
|
549 |
+
|
550 |
+
case 28:
|
551 |
+
$patterns = array(6, 26, 50, 74, 98, 122);
|
552 |
+
$ecBlocks = array(
|
553 |
+
new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10, 118)),
|
554 |
+
new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23, 46)),
|
555 |
+
new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31, 25)),
|
556 |
+
new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16)),
|
557 |
+
);
|
558 |
+
break;
|
559 |
+
|
560 |
+
case 29:
|
561 |
+
$patterns = array(6, 30, 54, 78, 102, 126);
|
562 |
+
$ecBlocks = array(
|
563 |
+
new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7, 117)),
|
564 |
+
new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7, 46)),
|
565 |
+
new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37, 24)),
|
566 |
+
new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16)),
|
567 |
+
);
|
568 |
+
break;
|
569 |
+
|
570 |
+
case 30:
|
571 |
+
$patterns = array(6, 26, 52, 78, 104, 130);
|
572 |
+
$ecBlocks = array(
|
573 |
+
new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10, 116)),
|
574 |
+
new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10, 48)),
|
575 |
+
new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25, 25)),
|
576 |
+
new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16)),
|
577 |
+
);
|
578 |
+
break;
|
579 |
+
|
580 |
+
case 31:
|
581 |
+
$patterns = array(6, 30, 56, 82, 108, 134);
|
582 |
+
$ecBlocks = array(
|
583 |
+
new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3, 116)),
|
584 |
+
new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29, 47)),
|
585 |
+
new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1, 25)),
|
586 |
+
new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16)),
|
587 |
+
);
|
588 |
+
break;
|
589 |
+
|
590 |
+
case 32:
|
591 |
+
$patterns = array(6, 34, 60, 86, 112, 138);
|
592 |
+
$ecBlocks = array(
|
593 |
+
new EcBlocks(30, new EcBlock(17, 115)),
|
594 |
+
new EcBlocks(28, new EcBlock(10, 46), new EcBlock(23, 47)),
|
595 |
+
new EcBlocks(30, new EcBlock(10, 24), new EcBlock(35, 25)),
|
596 |
+
new EcBlocks(30, new EcBlock(19, 15), new EcBlock(35, 16)),
|
597 |
+
);
|
598 |
+
break;
|
599 |
+
|
600 |
+
case 33:
|
601 |
+
$patterns = array(6, 30, 58, 86, 114, 142);
|
602 |
+
$ecBlocks = array(
|
603 |
+
new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1, 116)),
|
604 |
+
new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21, 47)),
|
605 |
+
new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19, 25)),
|
606 |
+
new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16)),
|
607 |
+
);
|
608 |
+
break;
|
609 |
+
|
610 |
+
case 34:
|
611 |
+
$patterns = array(6, 34, 62, 90, 118, 146);
|
612 |
+
$ecBlocks = array(
|
613 |
+
new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6, 116)),
|
614 |
+
new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23, 47)),
|
615 |
+
new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7, 25)),
|
616 |
+
new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17)),
|
617 |
+
);
|
618 |
+
break;
|
619 |
+
|
620 |
+
case 35:
|
621 |
+
$patterns = array(6, 30, 54, 78, 102, 126, 150);
|
622 |
+
$ecBlocks = array(
|
623 |
+
new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7, 122)),
|
624 |
+
new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26, 48)),
|
625 |
+
new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14, 25)),
|
626 |
+
new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16)),
|
627 |
+
);
|
628 |
+
break;
|
629 |
+
|
630 |
+
case 36:
|
631 |
+
$patterns = array(6, 24, 50, 76, 102, 128, 154);
|
632 |
+
$ecBlocks = array(
|
633 |
+
new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14, 122)),
|
634 |
+
new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34, 48)),
|
635 |
+
new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10, 25)),
|
636 |
+
new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16)),
|
637 |
+
);
|
638 |
+
break;
|
639 |
+
|
640 |
+
case 37:
|
641 |
+
$patterns = array(6, 28, 54, 80, 106, 132, 158);
|
642 |
+
$ecBlocks = array(
|
643 |
+
new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4, 123)),
|
644 |
+
new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14, 47)),
|
645 |
+
new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10, 25)),
|
646 |
+
new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16)),
|
647 |
+
);
|
648 |
+
break;
|
649 |
+
|
650 |
+
case 38:
|
651 |
+
$patterns = array(6, 32, 58, 84, 110, 136, 162);
|
652 |
+
$ecBlocks = array(
|
653 |
+
new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18, 123)),
|
654 |
+
new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32, 47)),
|
655 |
+
new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14, 25)),
|
656 |
+
new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16)),
|
657 |
+
);
|
658 |
+
break;
|
659 |
+
|
660 |
+
case 39:
|
661 |
+
$patterns = array(6, 26, 54, 82, 110, 138, 166);
|
662 |
+
$ecBlocks = array(
|
663 |
+
new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4, 118)),
|
664 |
+
new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7, 48)),
|
665 |
+
new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22, 25)),
|
666 |
+
new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16)),
|
667 |
+
);
|
668 |
+
break;
|
669 |
+
|
670 |
+
case 40:
|
671 |
+
$patterns = array(6, 30, 58, 86, 114, 142, 170);
|
672 |
+
$ecBlocks = array(
|
673 |
+
new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6, 119)),
|
674 |
+
new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31, 48)),
|
675 |
+
new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34, 25)),
|
676 |
+
new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16)),
|
677 |
+
);
|
678 |
+
break;
|
679 |
+
}
|
680 |
+
|
681 |
+
self::$versions[$versionNumber - 1] = new self(
|
682 |
+
$versionNumber,
|
683 |
+
SplFixedArray::fromArray($patterns, false),
|
684 |
+
SplFixedArray::fromArray($ecBlocks, false)
|
685 |
+
);
|
686 |
+
}
|
687 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Encoder;
|
11 |
+
|
12 |
+
use SplFixedArray;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Block pair.
|
16 |
+
*/
|
17 |
+
class BlockPair
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Data bytes in the block.
|
21 |
+
*
|
22 |
+
* @var SplFixedArray
|
23 |
+
*/
|
24 |
+
protected $dataBytes;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Error correction bytes in the block.
|
28 |
+
*
|
29 |
+
* @var SplFixedArray
|
30 |
+
*/
|
31 |
+
protected $errorCorrectionBytes;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Creates a new block pair.
|
35 |
+
*
|
36 |
+
* @param SplFixedArray $data
|
37 |
+
* @param SplFixedArray $errorCorrection
|
38 |
+
*/
|
39 |
+
public function __construct(SplFixedArray $data, SplFixedArray $errorCorrection)
|
40 |
+
{
|
41 |
+
$this->dataBytes = $data;
|
42 |
+
$this->errorCorrectionBytes = $errorCorrection;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Gets the data bytes.
|
47 |
+
*
|
48 |
+
* @return SplFixedArray
|
49 |
+
*/
|
50 |
+
public function getDataBytes()
|
51 |
+
{
|
52 |
+
return $this->dataBytes;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Gets the error correction bytes.
|
57 |
+
*
|
58 |
+
* @return SplFixedArray
|
59 |
+
*/
|
60 |
+
public function getErrorCorrectionBytes()
|
61 |
+
{
|
62 |
+
return $this->errorCorrectionBytes;
|
63 |
+
}
|
64 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Encoder;
|
11 |
+
|
12 |
+
use SplFixedArray;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Byte matrix.
|
16 |
+
*/
|
17 |
+
class ByteMatrix
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Bytes in the matrix, represented as array.
|
21 |
+
*
|
22 |
+
* @var SplFixedArray
|
23 |
+
*/
|
24 |
+
protected $bytes;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Width of the matrix.
|
28 |
+
*
|
29 |
+
* @var integer
|
30 |
+
*/
|
31 |
+
protected $width;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Height of the matrix.
|
35 |
+
*
|
36 |
+
* @var integer
|
37 |
+
*/
|
38 |
+
protected $height;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Creates a new byte matrix.
|
42 |
+
*
|
43 |
+
* @param integer $width
|
44 |
+
* @param integer $height
|
45 |
+
*/
|
46 |
+
public function __construct($width, $height)
|
47 |
+
{
|
48 |
+
$this->height = $height;
|
49 |
+
$this->width = $width;
|
50 |
+
$this->bytes = new SplFixedArray($height);
|
51 |
+
|
52 |
+
for ($y = 0; $y < $height; $y++) {
|
53 |
+
$this->bytes[$y] = new SplFixedArray($width);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Gets the width of the matrix.
|
59 |
+
*
|
60 |
+
* @return integer
|
61 |
+
*/
|
62 |
+
public function getWidth()
|
63 |
+
{
|
64 |
+
return $this->width;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Gets the height of the matrix.
|
69 |
+
*
|
70 |
+
* @return integer
|
71 |
+
*/
|
72 |
+
public function getHeight()
|
73 |
+
{
|
74 |
+
return $this->height;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Gets the internal representation of the matrix.
|
79 |
+
*
|
80 |
+
* @return SplFixedArray
|
81 |
+
*/
|
82 |
+
public function getArray()
|
83 |
+
{
|
84 |
+
return $this->bytes;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Gets the byte for a specific position.
|
89 |
+
*
|
90 |
+
* @param integer $x
|
91 |
+
* @param integer $y
|
92 |
+
* @return integer
|
93 |
+
*/
|
94 |
+
public function get($x, $y)
|
95 |
+
{
|
96 |
+
return $this->bytes[$y][$x];
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Sets the byte for a specific position.
|
101 |
+
*
|
102 |
+
* @param integer $x
|
103 |
+
* @param integer $y
|
104 |
+
* @param integer $value
|
105 |
+
* @return void
|
106 |
+
*/
|
107 |
+
public function set($x, $y, $value)
|
108 |
+
{
|
109 |
+
$this->bytes[$y][$x] = (int) $value;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Clears the matrix with a specific value.
|
114 |
+
*
|
115 |
+
* @param integer $value
|
116 |
+
* @return void
|
117 |
+
*/
|
118 |
+
public function clear($value)
|
119 |
+
{
|
120 |
+
for ($y = 0; $y < $this->height; $y++) {
|
121 |
+
for ($x = 0; $x < $this->width; $x++) {
|
122 |
+
$this->bytes[$y][$x] = $value;
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Returns a string representation of the matrix.
|
129 |
+
*
|
130 |
+
* @return string
|
131 |
+
*/
|
132 |
+
public function __toString()
|
133 |
+
{
|
134 |
+
$result = '';
|
135 |
+
|
136 |
+
for ($y = 0; $y < $this->height; $y++) {
|
137 |
+
for ($x = 0; $x < $this->width; $x++) {
|
138 |
+
switch ($this->bytes[$y][$x]) {
|
139 |
+
case 0:
|
140 |
+
$result .= ' 0';
|
141 |
+
break;
|
142 |
+
|
143 |
+
case 1:
|
144 |
+
$result .= ' 1';
|
145 |
+
break;
|
146 |
+
|
147 |
+
default:
|
148 |
+
$result .= ' ';
|
149 |
+
break;
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
$result .= "\n";
|
154 |
+
}
|
155 |
+
|
156 |
+
return $result;
|
157 |
+
}
|
158 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php
ADDED
@@ -0,0 +1,687 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Encoder;
|
11 |
+
|
12 |
+
use BaconQrCode\Common\BitArray;
|
13 |
+
use BaconQrCode\Common\CharacterSetEci;
|
14 |
+
use BaconQrCode\Common\ErrorCorrectionLevel;
|
15 |
+
use BaconQrCode\Common\Mode;
|
16 |
+
use BaconQrCode\Common\ReedSolomonCodec;
|
17 |
+
use BaconQrCode\Common\Version;
|
18 |
+
use BaconQrCode\Exception;
|
19 |
+
use SplFixedArray;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Encoder.
|
23 |
+
*/
|
24 |
+
class Encoder
|
25 |
+
{
|
26 |
+
/**
|
27 |
+
* Default byte encoding.
|
28 |
+
*/
|
29 |
+
const DEFAULT_BYTE_MODE_ECODING = 'ISO-8859-1';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The original table is defined in the table 5 of JISX0510:2004 (p.19).
|
33 |
+
*
|
34 |
+
* @var array
|
35 |
+
*/
|
36 |
+
protected static $alphanumericTable = array(
|
37 |
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f
|
38 |
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f
|
39 |
+
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f
|
40 |
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f
|
41 |
+
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f
|
42 |
+
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
|
43 |
+
);
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Codec cache.
|
47 |
+
*
|
48 |
+
* @var array
|
49 |
+
*/
|
50 |
+
protected static $codecs = array();
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Encodes "content" with the error correction level "ecLevel".
|
54 |
+
*
|
55 |
+
* @param string $content
|
56 |
+
* @param ErrorCorrectionLevel $ecLevel
|
57 |
+
* @param ? $hints
|
58 |
+
* @return QrCode
|
59 |
+
*/
|
60 |
+
public static function encode($content, ErrorCorrectionLevel $ecLevel, $encoding = self::DEFAULT_BYTE_MODE_ECODING)
|
61 |
+
{
|
62 |
+
// Pick an encoding mode appropriate for the content. Note that this
|
63 |
+
// will not attempt to use multiple modes / segments even if that were
|
64 |
+
// more efficient. Would be nice.
|
65 |
+
$mode = self::chooseMode($content, $encoding);
|
66 |
+
|
67 |
+
// This will store the header information, like mode and length, as well
|
68 |
+
// as "header" segments like an ECI segment.
|
69 |
+
$headerBits = new BitArray();
|
70 |
+
|
71 |
+
// Append ECI segment if applicable
|
72 |
+
if ($mode->get() === Mode::BYTE && $encoding !== self::DEFAULT_BYTE_MODE_ECODING) {
|
73 |
+
$eci = CharacterSetEci::getCharacterSetEciByName($encoding);
|
74 |
+
|
75 |
+
if ($eci !== null) {
|
76 |
+
self::appendEci($eci, $headerBits);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
// (With ECI in place,) Write the mode marker
|
81 |
+
self::appendModeInfo($mode, $headerBits);
|
82 |
+
|
83 |
+
// Collect data within the main segment, separately, to count its size
|
84 |
+
// if needed. Don't add it to main payload yet.
|
85 |
+
$dataBits = new BitArray();
|
86 |
+
self::appendBytes($content, $mode, $dataBits, $encoding);
|
87 |
+
|
88 |
+
// Hard part: need to know version to know how many bits length takes.
|
89 |
+
// But need to know how many bits it takes to know version. First we
|
90 |
+
// take a guess at version by assuming version will be the minimum, 1:
|
91 |
+
$provisionalBitsNeeded = $headerBits->getSize()
|
92 |
+
+ $mode->getCharacterCountBits(Version::getVersionForNumber(1))
|
93 |
+
+ $dataBits->getSize();
|
94 |
+
$provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel);
|
95 |
+
|
96 |
+
// Use that guess to calculate the right version. I am still not sure
|
97 |
+
// this works in 100% of cases.
|
98 |
+
$bitsNeeded = $headerBits->getSize()
|
99 |
+
+ $mode->getCharacterCountBits($provisionalVersion)
|
100 |
+
+ $dataBits->getSize();
|
101 |
+
$version = self::chooseVersion($bitsNeeded, $ecLevel);
|
102 |
+
|
103 |
+
$headerAndDataBits = new BitArray();
|
104 |
+
$headerAndDataBits->appendBitArray($headerBits);
|
105 |
+
|
106 |
+
// Find "length" of main segment and write it.
|
107 |
+
$numLetters = ($mode->get() === Mode::BYTE ? $dataBits->getSizeInBytes() : strlen($content));
|
108 |
+
self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits);
|
109 |
+
|
110 |
+
// Put data together into the overall payload.
|
111 |
+
$headerAndDataBits->appendBitArray($dataBits);
|
112 |
+
$ecBlocks = $version->getEcBlocksForLevel($ecLevel);
|
113 |
+
$numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords();
|
114 |
+
|
115 |
+
// Terminate the bits properly.
|
116 |
+
self::terminateBits($numDataBytes, $headerAndDataBits);
|
117 |
+
|
118 |
+
// Interleave data bits with error correction code.
|
119 |
+
$finalBits = self::interleaveWithEcBytes(
|
120 |
+
$headerAndDataBits,
|
121 |
+
$version->getTotalCodewords(),
|
122 |
+
$numDataBytes,
|
123 |
+
$ecBlocks->getNumBlocks()
|
124 |
+
);
|
125 |
+
|
126 |
+
$qrCode = new QrCode();
|
127 |
+
$qrCode->setErrorCorrectionLevel($ecLevel);
|
128 |
+
$qrCode->setMode($mode);
|
129 |
+
$qrCode->setVersion($version);
|
130 |
+
|
131 |
+
// Choose the mask pattern and set to "qrCode".
|
132 |
+
$dimension = $version->getDimensionForVersion();
|
133 |
+
$matrix = new ByteMatrix($dimension, $dimension);
|
134 |
+
$maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix);
|
135 |
+
$qrCode->setMaskPattern($maskPattern);
|
136 |
+
|
137 |
+
// Build the matrix and set it to "qrCode".
|
138 |
+
MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix);
|
139 |
+
$qrCode->setMatrix($matrix);
|
140 |
+
|
141 |
+
return $qrCode;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Gets the alphanumeric code for a byte.
|
146 |
+
*
|
147 |
+
* @param string|integer $code
|
148 |
+
* @return integer
|
149 |
+
*/
|
150 |
+
protected static function getAlphanumericCode($code)
|
151 |
+
{
|
152 |
+
$code = (is_string($code) ? ord($code) : $code);
|
153 |
+
|
154 |
+
if (isset(self::$alphanumericTable[$code])) {
|
155 |
+
return self::$alphanumericTable[$code];
|
156 |
+
}
|
157 |
+
|
158 |
+
return -1;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Chooses the best mode for a given content.
|
163 |
+
*
|
164 |
+
* @param string $content
|
165 |
+
* @param string $encoding
|
166 |
+
* @return Mode
|
167 |
+
*/
|
168 |
+
protected static function chooseMode($content, $encoding = null)
|
169 |
+
{
|
170 |
+
if (strcasecmp($encoding, 'SHIFT-JIS') === 0) {
|
171 |
+
return self::isOnlyDoubleByteKanji($content) ? new Mode(Mode::KANJI) : new Mode(Mode::BYTE);
|
172 |
+
}
|
173 |
+
|
174 |
+
$hasNumeric = false;
|
175 |
+
$hasAlphanumeric = false;
|
176 |
+
$contentLength = strlen($content);
|
177 |
+
|
178 |
+
for ($i = 0; $i < $contentLength; $i++) {
|
179 |
+
$char = $content[$i];
|
180 |
+
|
181 |
+
if (ctype_digit($char)) {
|
182 |
+
$hasNumeric = true;
|
183 |
+
} elseif (self::getAlphanumericCode($char) !== -1) {
|
184 |
+
$hasAlphanumeric = true;
|
185 |
+
} else {
|
186 |
+
return new Mode(Mode::BYTE);
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
if ($hasAlphanumeric) {
|
191 |
+
return new Mode(Mode::ALPHANUMERIC);
|
192 |
+
} elseif ($hasNumeric) {
|
193 |
+
return new Mode(Mode::NUMERIC);
|
194 |
+
}
|
195 |
+
|
196 |
+
return new Mode(Mode::BYTE);
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Calculates the mask penalty for a matrix.
|
201 |
+
*
|
202 |
+
* @param ByteMatrix $matrix
|
203 |
+
* @return integer
|
204 |
+
*/
|
205 |
+
protected static function calculateMaskPenalty(ByteMatrix $matrix)
|
206 |
+
{
|
207 |
+
return (
|
208 |
+
MaskUtil::applyMaskPenaltyRule1($matrix)
|
209 |
+
+ MaskUtil::applyMaskPenaltyRule2($matrix)
|
210 |
+
+ MaskUtil::applyMaskPenaltyRule3($matrix)
|
211 |
+
+ MaskUtil::applyMaskPenaltyRule4($matrix)
|
212 |
+
);
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Chooses the best mask pattern for a matrix.
|
217 |
+
*
|
218 |
+
* @param BitArray $bits
|
219 |
+
* @param ErrorCorrectionLevel $ecLevel
|
220 |
+
* @param Version $version
|
221 |
+
* @param ByteMatrix $matrix
|
222 |
+
* @return integer
|
223 |
+
*/
|
224 |
+
protected static function chooseMaskPattern(
|
225 |
+
BitArray $bits,
|
226 |
+
ErrorCorrectionLevel $ecLevel,
|
227 |
+
Version $version,
|
228 |
+
ByteMatrix $matrix
|
229 |
+
) {
|
230 |
+
$minPenality = PHP_INT_MAX;
|
231 |
+
$bestMaskPattern = -1;
|
232 |
+
|
233 |
+
for ($maskPattern = 0; $maskPattern < QrCode::NUM_MASK_PATTERNS; $maskPattern++) {
|
234 |
+
MatrixUtil::buildMatrix($bits, $ecLevel, $version, $maskPattern, $matrix);
|
235 |
+
$penalty = self::calculateMaskPenalty($matrix);
|
236 |
+
|
237 |
+
if ($penalty < $minPenality) {
|
238 |
+
$minPenality = $penalty;
|
239 |
+
$bestMaskPattern = $maskPattern;
|
240 |
+
}
|
241 |
+
}
|
242 |
+
|
243 |
+
return $bestMaskPattern;
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Chooses the best version for the input.
|
248 |
+
*
|
249 |
+
* @param integer $numInputBits
|
250 |
+
* @param ErrorCorrectionLevel $ecLevel
|
251 |
+
* @return Version
|
252 |
+
* @throws Exception\WriterException
|
253 |
+
*/
|
254 |
+
protected static function chooseVersion($numInputBits, ErrorCorrectionLevel $ecLevel)
|
255 |
+
{
|
256 |
+
for ($versionNum = 1; $versionNum <= 40; $versionNum++) {
|
257 |
+
$version = Version::getVersionForNumber($versionNum);
|
258 |
+
$numBytes = $version->getTotalCodewords();
|
259 |
+
|
260 |
+
$ecBlocks = $version->getEcBlocksForLevel($ecLevel);
|
261 |
+
$numEcBytes = $ecBlocks->getTotalEcCodewords();
|
262 |
+
|
263 |
+
$numDataBytes = $numBytes - $numEcBytes;
|
264 |
+
$totalInputBytes = intval(($numInputBits + 8) / 8);
|
265 |
+
|
266 |
+
if ($numDataBytes >= $totalInputBytes) {
|
267 |
+
return $version;
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
throw new Exception\WriterException('Data too big');
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Terminates the bits in a bit array.
|
276 |
+
*
|
277 |
+
* @param integer $numDataBytes
|
278 |
+
* @param BitArray $bits
|
279 |
+
* @throws Exception\WriterException
|
280 |
+
*/
|
281 |
+
protected static function terminateBits($numDataBytes, BitArray $bits)
|
282 |
+
{
|
283 |
+
$capacity = $numDataBytes << 3;
|
284 |
+
|
285 |
+
if ($bits->getSize() > $capacity) {
|
286 |
+
throw new Exception\WriterException('Data bits cannot fit in the QR code');
|
287 |
+
}
|
288 |
+
|
289 |
+
for ($i = 0; $i < 4 && $bits->getSize() < $capacity; $i++) {
|
290 |
+
$bits->appendBit(false);
|
291 |
+
}
|
292 |
+
|
293 |
+
$numBitsInLastByte = $bits->getSize() & 0x7;
|
294 |
+
|
295 |
+
if ($numBitsInLastByte > 0) {
|
296 |
+
for ($i = $numBitsInLastByte; $i < 8; $i++) {
|
297 |
+
$bits->appendBit(false);
|
298 |
+
}
|
299 |
+
}
|
300 |
+
|
301 |
+
$numPaddingBytes = $numDataBytes - $bits->getSizeInBytes();
|
302 |
+
|
303 |
+
for ($i = 0; $i < $numPaddingBytes; $i++) {
|
304 |
+
$bits->appendBits(($i & 0x1) === 0 ? 0xec : 0x11, 8);
|
305 |
+
}
|
306 |
+
|
307 |
+
if ($bits->getSize() !== $capacity) {
|
308 |
+
throw new Exception\WriterException('Bits size does not equal capacity');
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Gets number of data- and EC bytes for a block ID.
|
314 |
+
*
|
315 |
+
* @param integer $numTotalBytes
|
316 |
+
* @param integer $numDataBytes
|
317 |
+
* @param integer $numRsBlocks
|
318 |
+
* @param integer $blockId
|
319 |
+
* @return array
|
320 |
+
* @throws Exception\WriterException
|
321 |
+
*/
|
322 |
+
protected static function getNumDataBytesAndNumEcBytesForBlockId(
|
323 |
+
$numTotalBytes,
|
324 |
+
$numDataBytes,
|
325 |
+
$numRsBlocks,
|
326 |
+
$blockId
|
327 |
+
) {
|
328 |
+
if ($blockId >= $numRsBlocks) {
|
329 |
+
throw new Exception\WriterException('Block ID too large');
|
330 |
+
}
|
331 |
+
|
332 |
+
$numRsBlocksInGroup2 = $numTotalBytes % $numRsBlocks;
|
333 |
+
$numRsBlocksInGroup1 = $numRsBlocks - $numRsBlocksInGroup2;
|
334 |
+
$numTotalBytesInGroup1 = intval($numTotalBytes / $numRsBlocks);
|
335 |
+
$numTotalBytesInGroup2 = $numTotalBytesInGroup1 + 1;
|
336 |
+
$numDataBytesInGroup1 = intval($numDataBytes / $numRsBlocks);
|
337 |
+
$numDataBytesInGroup2 = $numDataBytesInGroup1 + 1;
|
338 |
+
$numEcBytesInGroup1 = $numTotalBytesInGroup1 - $numDataBytesInGroup1;
|
339 |
+
$numEcBytesInGroup2 = $numTotalBytesInGroup2 - $numDataBytesInGroup2;
|
340 |
+
|
341 |
+
if ($numEcBytesInGroup1 !== $numEcBytesInGroup2) {
|
342 |
+
throw new Exception\WriterException('EC bytes mismatch');
|
343 |
+
}
|
344 |
+
|
345 |
+
if ($numRsBlocks !== $numRsBlocksInGroup1 + $numRsBlocksInGroup2) {
|
346 |
+
throw new Exception\WriterException('RS blocks mismatch');
|
347 |
+
}
|
348 |
+
|
349 |
+
if ($numTotalBytes !==
|
350 |
+
(($numDataBytesInGroup1 + $numEcBytesInGroup1) * $numRsBlocksInGroup1)
|
351 |
+
+ (($numDataBytesInGroup2 + $numEcBytesInGroup2) * $numRsBlocksInGroup2)
|
352 |
+
) {
|
353 |
+
throw new Exception\WriterException('Total bytes mismatch');
|
354 |
+
}
|
355 |
+
|
356 |
+
if ($blockId < $numRsBlocksInGroup1) {
|
357 |
+
return array($numDataBytesInGroup1, $numEcBytesInGroup1);
|
358 |
+
} else {
|
359 |
+
return array($numDataBytesInGroup2, $numEcBytesInGroup2);
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Interleaves data with EC bytes.
|
365 |
+
*
|
366 |
+
* @param BitArray $bits
|
367 |
+
* @param integer $numTotalBytes
|
368 |
+
* @param integer $numDataBytes
|
369 |
+
* @param integer $numRsBlocks
|
370 |
+
* @return BitArray
|
371 |
+
* @throws Exception\WriterException
|
372 |
+
*/
|
373 |
+
protected static function interleaveWithEcBytes(BitArray $bits, $numTotalBytes, $numDataBytes, $numRsBlocks)
|
374 |
+
{
|
375 |
+
if ($bits->getSizeInBytes() !== $numDataBytes) {
|
376 |
+
throw new Exception\WriterException('Number of bits and data bytes does not match');
|
377 |
+
}
|
378 |
+
|
379 |
+
$dataBytesOffset = 0;
|
380 |
+
$maxNumDataBytes = 0;
|
381 |
+
$maxNumEcBytes = 0;
|
382 |
+
|
383 |
+
$blocks = new SplFixedArray($numRsBlocks);
|
384 |
+
|
385 |
+
for ($i = 0; $i < $numRsBlocks; $i++) {
|
386 |
+
list($numDataBytesInBlock, $numEcBytesInBlock) = self::getNumDataBytesAndNumEcBytesForBlockId(
|
387 |
+
$numTotalBytes,
|
388 |
+
$numDataBytes,
|
389 |
+
$numRsBlocks,
|
390 |
+
$i
|
391 |
+
);
|
392 |
+
|
393 |
+
$size = $numDataBytesInBlock;
|
394 |
+
$dataBytes = $bits->toBytes(8 * $dataBytesOffset, $size);
|
395 |
+
$ecBytes = self::generateEcBytes($dataBytes, $numEcBytesInBlock);
|
396 |
+
$blocks[$i] = new BlockPair($dataBytes, $ecBytes);
|
397 |
+
|
398 |
+
$maxNumDataBytes = max($maxNumDataBytes, $size);
|
399 |
+
$maxNumEcBytes = max($maxNumEcBytes, count($ecBytes));
|
400 |
+
$dataBytesOffset += $numDataBytesInBlock;
|
401 |
+
}
|
402 |
+
|
403 |
+
if ($numDataBytes !== $dataBytesOffset) {
|
404 |
+
throw new Exception\WriterException('Data bytes does not match offset');
|
405 |
+
}
|
406 |
+
|
407 |
+
$result = new BitArray();
|
408 |
+
|
409 |
+
for ($i = 0; $i < $maxNumDataBytes; $i++) {
|
410 |
+
foreach ($blocks as $block) {
|
411 |
+
$dataBytes = $block->getDataBytes();
|
412 |
+
|
413 |
+
if ($i < count($dataBytes)) {
|
414 |
+
$result->appendBits($dataBytes[$i], 8);
|
415 |
+
}
|
416 |
+
}
|
417 |
+
}
|
418 |
+
|
419 |
+
for ($i = 0; $i < $maxNumEcBytes; $i++) {
|
420 |
+
foreach ($blocks as $block) {
|
421 |
+
$ecBytes = $block->getErrorCorrectionBytes();
|
422 |
+
|
423 |
+
if ($i < count($ecBytes)) {
|
424 |
+
$result->appendBits($ecBytes[$i], 8);
|
425 |
+
}
|
426 |
+
}
|
427 |
+
}
|
428 |
+
|
429 |
+
if ($numTotalBytes !== $result->getSizeInBytes()) {
|
430 |
+
throw new Exception\WriterException('Interleaving error: ' . $numTotalBytes . ' and ' . $result->getSizeInBytes() . ' differ');
|
431 |
+
}
|
432 |
+
|
433 |
+
return $result;
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Generates EC bytes for given data.
|
438 |
+
*
|
439 |
+
* @param SplFixedArray $dataBytes
|
440 |
+
* @param integer $numEcBytesInBlock
|
441 |
+
* @return SplFixedArray
|
442 |
+
*/
|
443 |
+
protected static function generateEcBytes(SplFixedArray $dataBytes, $numEcBytesInBlock)
|
444 |
+
{
|
445 |
+
$numDataBytes = count($dataBytes);
|
446 |
+
$toEncode = new SplFixedArray($numDataBytes + $numEcBytesInBlock);
|
447 |
+
|
448 |
+
for ($i = 0; $i < $numDataBytes; $i++) {
|
449 |
+
$toEncode[$i] = $dataBytes[$i] & 0xff;
|
450 |
+
}
|
451 |
+
|
452 |
+
$ecBytes = new SplFixedArray($numEcBytesInBlock);
|
453 |
+
$codec = self::getCodec($numDataBytes, $numEcBytesInBlock);
|
454 |
+
$codec->encode($toEncode, $ecBytes);
|
455 |
+
|
456 |
+
return $ecBytes;
|
457 |
+
}
|
458 |
+
|
459 |
+
/**
|
460 |
+
* Gets an RS codec and caches it.
|
461 |
+
*
|
462 |
+
* @param integer $numDataBytes
|
463 |
+
* @param integer $numEcBytesInBlock
|
464 |
+
* @return ReedSolomonCodec
|
465 |
+
*/
|
466 |
+
protected static function getCodec($numDataBytes, $numEcBytesInBlock)
|
467 |
+
{
|
468 |
+
$cacheId = $numDataBytes . '-' . $numEcBytesInBlock;
|
469 |
+
|
470 |
+
if (!isset(self::$codecs[$cacheId])) {
|
471 |
+
self::$codecs[$cacheId] = new ReedSolomonCodec(
|
472 |
+
8,
|
473 |
+
0x11d,
|
474 |
+
0,
|
475 |
+
1,
|
476 |
+
$numEcBytesInBlock,
|
477 |
+
255 - $numDataBytes - $numEcBytesInBlock
|
478 |
+
);
|
479 |
+
}
|
480 |
+
|
481 |
+
return self::$codecs[$cacheId];
|
482 |
+
}
|
483 |
+
|
484 |
+
/**
|
485 |
+
* Appends mode information to a bit array.
|
486 |
+
*
|
487 |
+
* @param Mode $mode
|
488 |
+
* @param BitArray $bits
|
489 |
+
* @return void
|
490 |
+
*/
|
491 |
+
protected static function appendModeInfo(Mode $mode, BitArray $bits)
|
492 |
+
{
|
493 |
+
$bits->appendBits($mode->get(), 4);
|
494 |
+
}
|
495 |
+
|
496 |
+
/**
|
497 |
+
* Appends length information to a bit array.
|
498 |
+
*
|
499 |
+
* @param integer $numLetters
|
500 |
+
* @param Version $version
|
501 |
+
* @param Mode $mode
|
502 |
+
* @param BitArray $bits
|
503 |
+
* @return void
|
504 |
+
* @throws Exception\WriterException
|
505 |
+
*/
|
506 |
+
protected static function appendLengthInfo($numLetters, Version $version, Mode $mode, BitArray $bits)
|
507 |
+
{
|
508 |
+
$numBits = $mode->getCharacterCountBits($version);
|
509 |
+
|
510 |
+
if ($numLetters >= (1 << $numBits)) {
|
511 |
+
throw new Exception\WriterException($numLetters . ' is bigger than ' . ((1 << $numBits) - 1));
|
512 |
+
}
|
513 |
+
|
514 |
+
$bits->appendBits($numLetters, $numBits);
|
515 |
+
}
|
516 |
+
|
517 |
+
/**
|
518 |
+
* Appends bytes to a bit array in a specific mode.
|
519 |
+
*
|
520 |
+
* @param stirng $content
|
521 |
+
* @param Mode $mode
|
522 |
+
* @param BitArray $bits
|
523 |
+
* @param string $encoding
|
524 |
+
* @return void
|
525 |
+
* @throws Exception\WriterException
|
526 |
+
*/
|
527 |
+
protected static function appendBytes($content, Mode $mode, BitArray $bits, $encoding)
|
528 |
+
{
|
529 |
+
switch ($mode->get()) {
|
530 |
+
case Mode::NUMERIC:
|
531 |
+
self::appendNumericBytes($content, $bits);
|
532 |
+
break;
|
533 |
+
|
534 |
+
case Mode::ALPHANUMERIC:
|
535 |
+
self::appendAlphanumericBytes($content, $bits);
|
536 |
+
break;
|
537 |
+
|
538 |
+
case Mode::BYTE:
|
539 |
+
self::append8BitBytes($content, $bits, $encoding);
|
540 |
+
break;
|
541 |
+
|
542 |
+
case Mode::KANJI:
|
543 |
+
self::appendKanjiBytes($content, $bits);
|
544 |
+
break;
|
545 |
+
|
546 |
+
default:
|
547 |
+
throw new Exception\WriterException('Invalid mode: ' . $mode->get());
|
548 |
+
}
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Appends numeric bytes to a bit array.
|
553 |
+
*
|
554 |
+
* @param string $content
|
555 |
+
* @param BitArray $bits
|
556 |
+
* @return void
|
557 |
+
*/
|
558 |
+
protected static function appendNumericBytes($content, BitArray $bits)
|
559 |
+
{
|
560 |
+
$length = strlen($content);
|
561 |
+
$i = 0;
|
562 |
+
|
563 |
+
while ($i < $length) {
|
564 |
+
$num1 = (int) $content[$i];
|
565 |
+
|
566 |
+
if ($i + 2 < $length) {
|
567 |
+
// Encode three numeric letters in ten bits.
|
568 |
+
$num2 = (int) $content[$i + 1];
|
569 |
+
$num3 = (int) $content[$i + 2];
|
570 |
+
$bits->appendBits($num1 * 100 + $num2 * 10 + $num3, 10);
|
571 |
+
$i += 3;
|
572 |
+
} elseif ($i + 1 < $length) {
|
573 |
+
// Encode two numeric letters in seven bits.
|
574 |
+
$num2 = (int) $content[$i + 1];
|
575 |
+
$bits->appendBits($num1 * 10 + $num2, 7);
|
576 |
+
$i += 2;
|
577 |
+
} else {
|
578 |
+
// Encode one numeric letter in four bits.
|
579 |
+
$bits->appendBits($num1, 4);
|
580 |
+
$i++;
|
581 |
+
}
|
582 |
+
}
|
583 |
+
}
|
584 |
+
|
585 |
+
/**
|
586 |
+
* Appends alpha-numeric bytes to a bit array.
|
587 |
+
*
|
588 |
+
* @param string $content
|
589 |
+
* @param BitArray $bits
|
590 |
+
* @return void
|
591 |
+
*/
|
592 |
+
protected static function appendAlphanumericBytes($content, BitArray $bits)
|
593 |
+
{
|
594 |
+
$length = strlen($content);
|
595 |
+
$i = 0;
|
596 |
+
|
597 |
+
while ($i < $length) {
|
598 |
+
if (-1 === ($code1 = self::getAlphanumericCode($content[$i]))) {
|
599 |
+
throw new Exception\WriterException('Invalid alphanumeric code');
|
600 |
+
}
|
601 |
+
|
602 |
+
if ($i + 1 < $length) {
|
603 |
+
if (-1 === ($code2 = self::getAlphanumericCode($content[$i + 1]))) {
|
604 |
+
throw new Exception\WriterException('Invalid alphanumeric code');
|
605 |
+
}
|
606 |
+
|
607 |
+
// Encode two alphanumeric letters in 11 bits.
|
608 |
+
$bits->appendBits($code1 * 45 + $code2, 11);
|
609 |
+
$i += 2;
|
610 |
+
} else {
|
611 |
+
// Encode one alphanumeric letter in six bits.
|
612 |
+
$bits->appendBits($code1, 6);
|
613 |
+
$i++;
|
614 |
+
}
|
615 |
+
}
|
616 |
+
}
|
617 |
+
|
618 |
+
/**
|
619 |
+
* Appends regular 8-bit bytes to a bit array.
|
620 |
+
*
|
621 |
+
* @param string $content
|
622 |
+
* @param BitArray $bits
|
623 |
+
* @return void
|
624 |
+
*/
|
625 |
+
protected static function append8BitBytes($content, BitArray $bits, $encoding)
|
626 |
+
{
|
627 |
+
if (false === ($bytes = @iconv('utf-8', $encoding, $content))) {
|
628 |
+
throw new Exception\WriterException('Could not encode content to ' . $encoding);
|
629 |
+
}
|
630 |
+
|
631 |
+
$length = strlen($bytes);
|
632 |
+
|
633 |
+
for ($i = 0; $i < $length; $i++) {
|
634 |
+
$bits->appendBits(ord($bytes[$i]), 8);
|
635 |
+
}
|
636 |
+
}
|
637 |
+
|
638 |
+
/**
|
639 |
+
* Appends KANJI bytes to a bit array.
|
640 |
+
*
|
641 |
+
* @param string $content
|
642 |
+
* @param BitArray $bits
|
643 |
+
* @return void
|
644 |
+
*/
|
645 |
+
protected static function appendKanjiBytes($content, BitArray $bits)
|
646 |
+
{
|
647 |
+
if (strlen($content) % 2 > 0) {
|
648 |
+
// We just do a simple length check here. The for loop will check
|
649 |
+
// individual characters.
|
650 |
+
throw new Exception\WriterException('Content does not seem to be encoded in SHIFT-JIS');
|
651 |
+
}
|
652 |
+
|
653 |
+
$length = strlen($content);
|
654 |
+
|
655 |
+
for ($i = 0; $i < $length; $i += 2) {
|
656 |
+
$byte1 = ord($content[$i]) & 0xff;
|
657 |
+
$byte2 = ord($content[$i + 1]) & 0xff;
|
658 |
+
$code = ($byte1 << 8) | $byte2;
|
659 |
+
|
660 |
+
if ($code >= 0x8140 && $code <= 0x9ffc) {
|
661 |
+
$subtracted = $code - 0x8140;
|
662 |
+
} elseif ($code >= 0xe040 && $code <= 0xebbf) {
|
663 |
+
$subtracted = $code - 0xc140;
|
664 |
+
} else {
|
665 |
+
throw new Exception\WriterException('Invalid byte sequence');
|
666 |
+
}
|
667 |
+
|
668 |
+
$encoded = (($subtracted >> 8) * 0xc0) + ($subtracted & 0xff);
|
669 |
+
|
670 |
+
$bits->appendBits($encoded, 13);
|
671 |
+
}
|
672 |
+
}
|
673 |
+
|
674 |
+
/**
|
675 |
+
* Appends ECI information to a bit array.
|
676 |
+
*
|
677 |
+
* @param CharacterSetEci $eci
|
678 |
+
* @param BitArray $bits
|
679 |
+
* @return void
|
680 |
+
*/
|
681 |
+
protected static function appendEci(CharacterSetEci $eci, BitArray $bits)
|
682 |
+
{
|
683 |
+
$mode = new Mode(Mode::ECI);
|
684 |
+
$bits->appendBits($mode->get(), 4);
|
685 |
+
$bits->appendBits($eci->get(), 8);
|
686 |
+
}
|
687 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php
ADDED
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Encoder;
|
11 |
+
|
12 |
+
use BaconQrCode\Common\BitUtils;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Mask utility.
|
16 |
+
*/
|
17 |
+
class MaskUtil
|
18 |
+
{
|
19 |
+
/**#@+
|
20 |
+
* Penalty weights from section 6.8.2.1
|
21 |
+
*/
|
22 |
+
const N1 = 3;
|
23 |
+
const N2 = 3;
|
24 |
+
const N3 = 40;
|
25 |
+
const N4 = 10;
|
26 |
+
/**#@-*/
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Applies mask penalty rule 1 and returns the penalty.
|
30 |
+
*
|
31 |
+
* Finds repetitive cells with the same color and gives penalty to them.
|
32 |
+
* Example: 00000 or 11111.
|
33 |
+
*
|
34 |
+
* @param ByteMatrix $matrix
|
35 |
+
* @return integer
|
36 |
+
*/
|
37 |
+
public static function applyMaskPenaltyRule1(ByteMatrix $matrix)
|
38 |
+
{
|
39 |
+
return (
|
40 |
+
self::applyMaskPenaltyRule1Internal($matrix, true)
|
41 |
+
+ self::applyMaskPenaltyRule1Internal($matrix, false)
|
42 |
+
);
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Applies mask penalty rule 2 and returns the penalty.
|
47 |
+
*
|
48 |
+
* Finds 2x2 blocks with the same color and gives penalty to them. This is
|
49 |
+
* actually equivalent to the spec's rule, which is to find MxN blocks and
|
50 |
+
* give a penalty proportional to (M-1)x(N-1), because this is the number of
|
51 |
+
* 2x2 blocks inside such a block.
|
52 |
+
*
|
53 |
+
* @param ByteMatrix $matrix
|
54 |
+
* @return integer
|
55 |
+
*/
|
56 |
+
public static function applyMaskPenaltyRule2(ByteMatrix $matrix)
|
57 |
+
{
|
58 |
+
$penalty = 0;
|
59 |
+
$array = $matrix->getArray();
|
60 |
+
$width = $matrix->getWidth();
|
61 |
+
$height = $matrix->getHeight();
|
62 |
+
|
63 |
+
for ($y = 0; $y < $height - 1; $y++) {
|
64 |
+
for ($x = 0; $x < $width - 1; $x++) {
|
65 |
+
$value = $array[$y][$x];
|
66 |
+
|
67 |
+
if ($value === $array[$y][$x + 1] && $value === $array[$y + 1][$x] && $value === $array[$y + 1][$x + 1]) {
|
68 |
+
$penalty++;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
return self::N2 * $penalty;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Applies mask penalty rule 3 and returns the penalty.
|
78 |
+
*
|
79 |
+
* Finds consecutive cells of 00001011101 or 10111010000, and gives penalty
|
80 |
+
* to them. If we find patterns like 000010111010000, we give penalties
|
81 |
+
* twice (i.e. 40 * 2).
|
82 |
+
*
|
83 |
+
* @param ByteMatrix $matrix
|
84 |
+
* @return integer
|
85 |
+
*/
|
86 |
+
public static function applyMaskPenaltyRule3(ByteMatrix $matrix)
|
87 |
+
{
|
88 |
+
$penalty = 0;
|
89 |
+
$array = $matrix->getArray();
|
90 |
+
$width = $matrix->getWidth();
|
91 |
+
$height = $matrix->getHeight();
|
92 |
+
|
93 |
+
for ($y = 0; $y < $height; $y++) {
|
94 |
+
for ($x = 0; $x < $width; $x++) {
|
95 |
+
if (
|
96 |
+
$x + 6 < $width
|
97 |
+
&& $array[$y][$x] === 1
|
98 |
+
&& $array[$y][$x + 1] === 0
|
99 |
+
&& $array[$y][$x + 2] === 1
|
100 |
+
&& $array[$y][$x + 3] === 1
|
101 |
+
&& $array[$y][$x + 4] === 1
|
102 |
+
&& $array[$y][$x + 5] === 0
|
103 |
+
&& $array[$y][$x + 6] === 1
|
104 |
+
&& (
|
105 |
+
(
|
106 |
+
$x + 10 < $width
|
107 |
+
&& $array[$y][$x + 7] === 0
|
108 |
+
&& $array[$y][$x + 8] === 0
|
109 |
+
&& $array[$y][$x + 9] === 0
|
110 |
+
&& $array[$y][$x + 10] === 0
|
111 |
+
)
|
112 |
+
|| (
|
113 |
+
$x - 4 >= 0
|
114 |
+
&& $array[$y][$x - 1] === 0
|
115 |
+
&& $array[$y][$x - 2] === 0
|
116 |
+
&& $array[$y][$x - 3] === 0
|
117 |
+
&& $array[$y][$x - 4] === 0
|
118 |
+
)
|
119 |
+
)
|
120 |
+
) {
|
121 |
+
$penalty += self::N3;
|
122 |
+
}
|
123 |
+
|
124 |
+
if (
|
125 |
+
$y + 6 < $height
|
126 |
+
&& $array[$y][$x] === 1
|
127 |
+
&& $array[$y + 1][$x] === 0
|
128 |
+
&& $array[$y + 2][$x] === 1
|
129 |
+
&& $array[$y + 3][$x] === 1
|
130 |
+
&& $array[$y + 4][$x] === 1
|
131 |
+
&& $array[$y + 5][$x] === 0
|
132 |
+
&& $array[$y + 6][$x] === 1
|
133 |
+
&& (
|
134 |
+
(
|
135 |
+
$y + 10 < $height
|
136 |
+
&& $array[$y + 7][$x] === 0
|
137 |
+
&& $array[$y + 8][$x] === 0
|
138 |
+
&& $array[$y + 9][$x] === 0
|
139 |
+
&& $array[$y + 10][$x] === 0
|
140 |
+
)
|
141 |
+
|| (
|
142 |
+
$y - 4 >= 0
|
143 |
+
&& $array[$y - 1][$x] === 0
|
144 |
+
&& $array[$y - 2][$x] === 0
|
145 |
+
&& $array[$y - 3][$x] === 0
|
146 |
+
&& $array[$y - 4][$x] === 0
|
147 |
+
)
|
148 |
+
)
|
149 |
+
) {
|
150 |
+
$penalty += self::N3;
|
151 |
+
}
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
return $penalty;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Applies mask penalty rule 4 and returns the penalty.
|
160 |
+
*
|
161 |
+
* Calculates the ratio of dark cells and gives penalty if the ratio is far
|
162 |
+
* from 50%. It gives 10 penalty for 5% distance.
|
163 |
+
*
|
164 |
+
* @param ByteMatrix $matrix
|
165 |
+
* @return integer
|
166 |
+
*/
|
167 |
+
public static function applyMaskPenaltyRule4(ByteMatrix $matrix)
|
168 |
+
{
|
169 |
+
$numDarkCells = 0;
|
170 |
+
|
171 |
+
$array = $matrix->getArray();
|
172 |
+
$width = $matrix->getWidth();
|
173 |
+
$height = $matrix->getHeight();
|
174 |
+
|
175 |
+
for ($y = 0; $y < $height; $y++) {
|
176 |
+
$arrayY = $array[$y];
|
177 |
+
|
178 |
+
for ($x = 0; $x < $width; $x++) {
|
179 |
+
if ($arrayY[$x] === 1) {
|
180 |
+
$numDarkCells++;
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
$numTotalCells = $height * $width;
|
186 |
+
$darkRatio = $numDarkCells / $numTotalCells;
|
187 |
+
$fixedPercentVariances = (int) (abs($darkRatio - 0.5) * 20);
|
188 |
+
|
189 |
+
return $fixedPercentVariances * self::N4;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Returns the mask bit for "getMaskPattern" at "x" and "y".
|
194 |
+
*
|
195 |
+
* See 8.8 of JISX0510:2004 for mask pattern conditions.
|
196 |
+
*
|
197 |
+
* @param integer $maskPattern
|
198 |
+
* @param integer $x
|
199 |
+
* @param integer $y
|
200 |
+
* @return integer
|
201 |
+
* @throws Exception\InvalidArgumentException
|
202 |
+
*/
|
203 |
+
public static function getDataMaskBit($maskPattern, $x, $y)
|
204 |
+
{
|
205 |
+
switch ($maskPattern) {
|
206 |
+
case 0:
|
207 |
+
$intermediate = ($y + $x) & 0x1;
|
208 |
+
break;
|
209 |
+
|
210 |
+
case 1:
|
211 |
+
$intermediate = $y & 0x1;
|
212 |
+
break;
|
213 |
+
|
214 |
+
case 2:
|
215 |
+
$intermediate = $x % 3;
|
216 |
+
break;
|
217 |
+
|
218 |
+
case 3:
|
219 |
+
$intermediate = ($y + $x) % 3;
|
220 |
+
break;
|
221 |
+
|
222 |
+
case 4:
|
223 |
+
$intermediate = (BitUtils::unsignedRightShift($y, 1) + ($x / 3)) & 0x1;
|
224 |
+
break;
|
225 |
+
|
226 |
+
case 5:
|
227 |
+
$temp = $y * $x;
|
228 |
+
$intermediate = ($temp & 0x1) + ($temp % 3);
|
229 |
+
break;
|
230 |
+
|
231 |
+
case 6:
|
232 |
+
$temp = $y * $x;
|
233 |
+
$intermediate = (($temp & 0x1) + ($temp % 3)) & 0x1;
|
234 |
+
break;
|
235 |
+
|
236 |
+
case 7:
|
237 |
+
$temp = $y * $x;
|
238 |
+
$intermediate = (($temp % 3) + (($y + $x) & 0x1)) & 0x1;
|
239 |
+
break;
|
240 |
+
|
241 |
+
default:
|
242 |
+
throw new Exception\InvalidArgumentException('Invalid mask pattern: ' . $maskPattern);
|
243 |
+
}
|
244 |
+
|
245 |
+
return $intermediate === 0;
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Helper function for applyMaskPenaltyRule1.
|
250 |
+
*
|
251 |
+
* We need this for doing this calculation in both vertical and horizontal
|
252 |
+
* orders respectively.
|
253 |
+
*
|
254 |
+
* @param ByteMatrix $matrix
|
255 |
+
* @param boolean $isHorizontal
|
256 |
+
* @return integer
|
257 |
+
*/
|
258 |
+
protected static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, $isHorizontal)
|
259 |
+
{
|
260 |
+
$penalty = 0;
|
261 |
+
$iLimit = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth();
|
262 |
+
$jLimit = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight();
|
263 |
+
$array = $matrix->getArray();
|
264 |
+
|
265 |
+
for ($i = 0; $i < $iLimit; $i++) {
|
266 |
+
$numSameBitCells = 0;
|
267 |
+
$prevBit = -1;
|
268 |
+
|
269 |
+
for ($j = 0; $j < $jLimit; $j++) {
|
270 |
+
$bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i];
|
271 |
+
|
272 |
+
if ($bit === $prevBit) {
|
273 |
+
$numSameBitCells++;
|
274 |
+
} else {
|
275 |
+
if ($numSameBitCells >= 5) {
|
276 |
+
$penalty += self::N1 + ($numSameBitCells - 5);
|
277 |
+
}
|
278 |
+
|
279 |
+
$numSameBitCells = 1;
|
280 |
+
$prevBit = $bit;
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
if ($numSameBitCells >= 5) {
|
285 |
+
$penalty += self::N1 + ($numSameBitCells - 5);
|
286 |
+
}
|
287 |
+
}
|
288 |
+
|
289 |
+
return $penalty;
|
290 |
+
}
|
291 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php
ADDED
@@ -0,0 +1,580 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Encoder;
|
11 |
+
|
12 |
+
use BaconQrCode\Common\BitArray;
|
13 |
+
use BaconQrCode\Common\ErrorCorrectionLevel;
|
14 |
+
use BaconQrCode\Common\Version;
|
15 |
+
use BaconQrCode\Exception;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Matrix utility.
|
19 |
+
*/
|
20 |
+
class MatrixUtil
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Position detection pattern.
|
24 |
+
*
|
25 |
+
* @var array
|
26 |
+
*/
|
27 |
+
protected static $positionDetectionPattern = array(
|
28 |
+
array(1, 1, 1, 1, 1, 1, 1),
|
29 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
30 |
+
array(1, 0, 1, 1, 1, 0, 1),
|
31 |
+
array(1, 0, 1, 1, 1, 0, 1),
|
32 |
+
array(1, 0, 1, 1, 1, 0, 1),
|
33 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
34 |
+
array(1, 1, 1, 1, 1, 1, 1),
|
35 |
+
);
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Position adjustment pattern.
|
39 |
+
*
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
protected static $positionAdjustmentPattern = array(
|
43 |
+
array(1, 1, 1, 1, 1),
|
44 |
+
array(1, 0, 0, 0, 1),
|
45 |
+
array(1, 0, 1, 0, 1),
|
46 |
+
array(1, 0, 0, 0, 1),
|
47 |
+
array(1, 1, 1, 1, 1),
|
48 |
+
);
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Coordinates for position adjustment patterns for each version.
|
52 |
+
*
|
53 |
+
* @var array
|
54 |
+
*/
|
55 |
+
protected static $positionAdjustmentPatternCoordinateTable = array(
|
56 |
+
array(null, null, null, null, null, null, null), // Version 1
|
57 |
+
array( 6, 18, null, null, null, null, null), // Version 2
|
58 |
+
array( 6, 22, null, null, null, null, null), // Version 3
|
59 |
+
array( 6, 26, null, null, null, null, null), // Version 4
|
60 |
+
array( 6, 30, null, null, null, null, null), // Version 5
|
61 |
+
array( 6, 34, null, null, null, null, null), // Version 6
|
62 |
+
array( 6, 22, 38, null, null, null, null), // Version 7
|
63 |
+
array( 6, 24, 42, null, null, null, null), // Version 8
|
64 |
+
array( 6, 26, 46, null, null, null, null), // Version 9
|
65 |
+
array( 6, 28, 50, null, null, null, null), // Version 10
|
66 |
+
array( 6, 30, 54, null, null, null, null), // Version 11
|
67 |
+
array( 6, 32, 58, null, null, null, null), // Version 12
|
68 |
+
array( 6, 34, 62, null, null, null, null), // Version 13
|
69 |
+
array( 6, 26, 46, 66, null, null, null), // Version 14
|
70 |
+
array( 6, 26, 48, 70, null, null, null), // Version 15
|
71 |
+
array( 6, 26, 50, 74, null, null, null), // Version 16
|
72 |
+
array( 6, 30, 54, 78, null, null, null), // Version 17
|
73 |
+
array( 6, 30, 56, 82, null, null, null), // Version 18
|
74 |
+
array( 6, 30, 58, 86, null, null, null), // Version 19
|
75 |
+
array( 6, 34, 62, 90, null, null, null), // Version 20
|
76 |
+
array( 6, 28, 50, 72, 94, null, null), // Version 21
|
77 |
+
array( 6, 26, 50, 74, 98, null, null), // Version 22
|
78 |
+
array( 6, 30, 54, 78, 102, null, null), // Version 23
|
79 |
+
array( 6, 28, 54, 80, 106, null, null), // Version 24
|
80 |
+
array( 6, 32, 58, 84, 110, null, null), // Version 25
|
81 |
+
array( 6, 30, 58, 86, 114, null, null), // Version 26
|
82 |
+
array( 6, 34, 62, 90, 118, null, null), // Version 27
|
83 |
+
array( 6, 26, 50, 74, 98, 122, null), // Version 28
|
84 |
+
array( 6, 30, 54, 78, 102, 126, null), // Version 29
|
85 |
+
array( 6, 26, 52, 78, 104, 130, null), // Version 30
|
86 |
+
array( 6, 30, 56, 82, 108, 134, null), // Version 31
|
87 |
+
array( 6, 34, 60, 86, 112, 138, null), // Version 32
|
88 |
+
array( 6, 30, 58, 86, 114, 142, null), // Version 33
|
89 |
+
array( 6, 34, 62, 90, 118, 146, null), // Version 34
|
90 |
+
array( 6, 30, 54, 78, 102, 126, 150), // Version 35
|
91 |
+
array( 6, 24, 50, 76, 102, 128, 154), // Version 36
|
92 |
+
array( 6, 28, 54, 80, 106, 132, 158), // Version 37
|
93 |
+
array( 6, 32, 58, 84, 110, 136, 162), // Version 38
|
94 |
+
array( 6, 26, 54, 82, 110, 138, 166), // Version 39
|
95 |
+
array( 6, 30, 58, 86, 114, 142, 170), // Version 40
|
96 |
+
);
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Type information coordinates.
|
100 |
+
*
|
101 |
+
* @var array
|
102 |
+
*/
|
103 |
+
protected static $typeInfoCoordinates = array(
|
104 |
+
array(8, 0),
|
105 |
+
array(8, 1),
|
106 |
+
array(8, 2),
|
107 |
+
array(8, 3),
|
108 |
+
array(8, 4),
|
109 |
+
array(8, 5),
|
110 |
+
array(8, 7),
|
111 |
+
array(8, 8),
|
112 |
+
array(7, 8),
|
113 |
+
array(5, 8),
|
114 |
+
array(4, 8),
|
115 |
+
array(3, 8),
|
116 |
+
array(2, 8),
|
117 |
+
array(1, 8),
|
118 |
+
array(0, 8),
|
119 |
+
);
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Version information polynomial.
|
123 |
+
*
|
124 |
+
* @var integer
|
125 |
+
*/
|
126 |
+
protected static $versionInfoPoly = 0x1f25;
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Type information polynomial.
|
130 |
+
*
|
131 |
+
* @var integer
|
132 |
+
*/
|
133 |
+
protected static $typeInfoPoly = 0x537;
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Type information mask pattern.
|
137 |
+
*
|
138 |
+
* @var integer
|
139 |
+
*/
|
140 |
+
protected static $typeInfoMaskPattern = 0x5412;
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Clears a given matrix.
|
144 |
+
*
|
145 |
+
* @param ByteMatrix $matrix
|
146 |
+
* @return void
|
147 |
+
*/
|
148 |
+
public static function clearMatrix(ByteMatrix $matrix)
|
149 |
+
{
|
150 |
+
$matrix->clear(-1);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Builds a complete matrix.
|
155 |
+
*
|
156 |
+
* @param BitArray $dataBits
|
157 |
+
* @param ErrorCorrectionLevel $level
|
158 |
+
* @param Version $version
|
159 |
+
* @param integer $maskPattern
|
160 |
+
* @param ByteMatrix $matrix
|
161 |
+
* @return void
|
162 |
+
*/
|
163 |
+
public static function buildMatrix(
|
164 |
+
BitArray $dataBits,
|
165 |
+
ErrorCorrectionLevel $level,
|
166 |
+
Version $version,
|
167 |
+
$maskPattern,
|
168 |
+
ByteMatrix $matrix
|
169 |
+
) {
|
170 |
+
self::clearMatrix($matrix);
|
171 |
+
self::embedBasicPatterns($version, $matrix);
|
172 |
+
self::embedTypeInfo($level, $maskPattern, $matrix);
|
173 |
+
self::maybeEmbedVersionInfo($version, $matrix);
|
174 |
+
self::embedDataBits($dataBits, $maskPattern, $matrix);
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Embeds type information into a matrix.
|
179 |
+
*
|
180 |
+
* @param ErrorCorrectionLevel $level
|
181 |
+
* @param integer $maskPattern
|
182 |
+
* @param ByteMatrix $matrix
|
183 |
+
* @return void
|
184 |
+
*/
|
185 |
+
protected static function embedTypeInfo(ErrorCorrectionLevel $level, $maskPattern, ByteMatrix $matrix)
|
186 |
+
{
|
187 |
+
$typeInfoBits = new BitArray();
|
188 |
+
self::makeTypeInfoBits($level, $maskPattern, $typeInfoBits);
|
189 |
+
|
190 |
+
$typeInfoBitsSize = $typeInfoBits->getSize();
|
191 |
+
|
192 |
+
for ($i = 0; $i < $typeInfoBitsSize; $i++) {
|
193 |
+
$bit = $typeInfoBits->get($typeInfoBitsSize - 1 - $i);
|
194 |
+
|
195 |
+
$x1 = self::$typeInfoCoordinates[$i][0];
|
196 |
+
$y1 = self::$typeInfoCoordinates[$i][1];
|
197 |
+
|
198 |
+
$matrix->set($x1, $y1, $bit);
|
199 |
+
|
200 |
+
if ($i < 8) {
|
201 |
+
$x2 = $matrix->getWidth() - $i - 1;
|
202 |
+
$y2 = 8;
|
203 |
+
} else {
|
204 |
+
$x2 = 8;
|
205 |
+
$y2 = $matrix->getHeight() - 7 + ($i - 8);
|
206 |
+
}
|
207 |
+
|
208 |
+
$matrix->set($x2, $y2, $bit);
|
209 |
+
}
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Generates type information bits and appends them to a bit array.
|
214 |
+
*
|
215 |
+
* @param ErrorCorrectionLevel $level
|
216 |
+
* @param integer $maskPattern
|
217 |
+
* @param BitArray $bits
|
218 |
+
* @return void
|
219 |
+
* @throws Exception\RuntimeException
|
220 |
+
*/
|
221 |
+
protected static function makeTypeInfoBits(ErrorCorrectionLevel $level, $maskPattern, BitArray $bits)
|
222 |
+
{
|
223 |
+
$typeInfo = ($level->get() << 3) | $maskPattern;
|
224 |
+
$bits->appendBits($typeInfo, 5);
|
225 |
+
|
226 |
+
$bchCode = self::calculateBchCode($typeInfo, self::$typeInfoPoly);
|
227 |
+
$bits->appendBits($bchCode, 10);
|
228 |
+
|
229 |
+
$maskBits = new BitArray();
|
230 |
+
$maskBits->appendBits(self::$typeInfoMaskPattern, 15);
|
231 |
+
$bits->xorBits($maskBits);
|
232 |
+
|
233 |
+
if ($bits->getSize() !== 15) {
|
234 |
+
throw new Exception\RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
|
235 |
+
}
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Embeds version information if required.
|
240 |
+
*
|
241 |
+
* @param Version $version
|
242 |
+
* @param ByteMatrix $matrix
|
243 |
+
* @return void
|
244 |
+
*/
|
245 |
+
protected static function maybeEmbedVersionInfo(Version $version, ByteMatrix $matrix)
|
246 |
+
{
|
247 |
+
if ($version->getVersionNumber() < 7) {
|
248 |
+
return;
|
249 |
+
}
|
250 |
+
|
251 |
+
$versionInfoBits = new BitArray();
|
252 |
+
self::makeVersionInfoBits($version, $versionInfoBits);
|
253 |
+
|
254 |
+
$bitIndex = 6 * 3 - 1;
|
255 |
+
|
256 |
+
for ($i = 0; $i < 6; $i++) {
|
257 |
+
for ($j = 0; $j < 3; $j++) {
|
258 |
+
$bit = $versionInfoBits->get($bitIndex);
|
259 |
+
$bitIndex--;
|
260 |
+
|
261 |
+
$matrix->set($i, $matrix->getHeight() - 11 + $j, $bit);
|
262 |
+
$matrix->set($matrix->getHeight() - 11 + $j, $i, $bit);
|
263 |
+
}
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Generates version information bits and appends them to a bit array.
|
269 |
+
*
|
270 |
+
* @param Version $version
|
271 |
+
* @param BitArray $bits
|
272 |
+
* @return void
|
273 |
+
* @throws Exception\RuntimeException
|
274 |
+
*/
|
275 |
+
protected static function makeVersionInfoBits(Version $version, BitArray $bits)
|
276 |
+
{
|
277 |
+
$bits->appendBits($version->getVersionNumber(), 6);
|
278 |
+
|
279 |
+
$bchCode = self::calculateBchCode($version->getVersionNumber(), self::$versionInfoPoly);
|
280 |
+
$bits->appendBits($bchCode, 12);
|
281 |
+
|
282 |
+
if ($bits->getSize() !== 18) {
|
283 |
+
throw new Exception\RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
|
284 |
+
}
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* Calculates the BHC code for a value and a polynomial.
|
289 |
+
*
|
290 |
+
* @param integer $value
|
291 |
+
* @param integer $poly
|
292 |
+
* @return integer
|
293 |
+
*/
|
294 |
+
protected static function calculateBchCode($value, $poly)
|
295 |
+
{
|
296 |
+
$msbSetInPoly = self::findMsbSet($poly);
|
297 |
+
$value <<= $msbSetInPoly - 1;
|
298 |
+
|
299 |
+
while (self::findMsbSet($value) >= $msbSetInPoly) {
|
300 |
+
$value ^= $poly << (self::findMsbSet($value) - $msbSetInPoly);
|
301 |
+
}
|
302 |
+
|
303 |
+
return $value;
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Finds and MSB set.
|
308 |
+
*
|
309 |
+
* @param integer $value
|
310 |
+
* @return integer
|
311 |
+
*/
|
312 |
+
protected static function findMsbSet($value)
|
313 |
+
{
|
314 |
+
$numDigits = 0;
|
315 |
+
|
316 |
+
while ($value !== 0) {
|
317 |
+
$value >>= 1;
|
318 |
+
$numDigits++;
|
319 |
+
}
|
320 |
+
|
321 |
+
return $numDigits;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Embeds basic patterns into a matrix.
|
326 |
+
*
|
327 |
+
* @param Version $version
|
328 |
+
* @param ByteMatrix $matrix
|
329 |
+
* @return void
|
330 |
+
*/
|
331 |
+
protected static function embedBasicPatterns(Version $version, ByteMatrix $matrix)
|
332 |
+
{
|
333 |
+
self::embedPositionDetectionPatternsAndSeparators($matrix);
|
334 |
+
self::embedDarkDotAtLeftBottomCorner($matrix);
|
335 |
+
self::maybeEmbedPositionAdjustmentPatterns($version, $matrix);
|
336 |
+
self::embedTimingPatterns($matrix);
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Embeds position detection patterns and separators into a byte matrix.
|
341 |
+
*
|
342 |
+
* @param ByteMatrix $matrix
|
343 |
+
* @return void
|
344 |
+
*/
|
345 |
+
protected static function embedPositionDetectionPatternsAndSeparators(ByteMatrix $matrix)
|
346 |
+
{
|
347 |
+
$pdpWidth = count(self::$positionDetectionPattern[0]);
|
348 |
+
|
349 |
+
self::embedPositionDetectionPattern(0, 0, $matrix);
|
350 |
+
self::embedPositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix);
|
351 |
+
self::embedPositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix);
|
352 |
+
|
353 |
+
$hspWidth = 8;
|
354 |
+
|
355 |
+
self::embedHorizontalSeparationPattern(0, $hspWidth - 1, $matrix);
|
356 |
+
self::embedHorizontalSeparationPattern($matrix->getWidth() - $hspWidth, $hspWidth - 1, $matrix);
|
357 |
+
self::embedHorizontalSeparationPattern(0, $matrix->getWidth() - $hspWidth, $matrix);
|
358 |
+
|
359 |
+
$vspSize = 7;
|
360 |
+
|
361 |
+
self::embedVerticalSeparationPattern($vspSize, 0, $matrix);
|
362 |
+
self::embedVerticalSeparationPattern($matrix->getHeight() - $vspSize - 1, 0, $matrix);
|
363 |
+
self::embedVerticalSeparationPattern($vspSize, $matrix->getHeight() - $vspSize, $matrix);
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* Embeds a single position detection pattern into a byte matrix.
|
368 |
+
*
|
369 |
+
* @param integer $xStart
|
370 |
+
* @param integer $yStart
|
371 |
+
* @param ByteMatrix $matrix
|
372 |
+
* @return void
|
373 |
+
*/
|
374 |
+
protected static function embedPositionDetectionPattern($xStart, $yStart, ByteMatrix $matrix)
|
375 |
+
{
|
376 |
+
for ($y = 0; $y < 7; $y++) {
|
377 |
+
for ($x = 0; $x < 7; $x++) {
|
378 |
+
$matrix->set($xStart + $x, $yStart + $y, self::$positionDetectionPattern[$y][$x]);
|
379 |
+
}
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
/**
|
384 |
+
* Embeds a single horizontal separation pattern.
|
385 |
+
*
|
386 |
+
* @param integer $xStart
|
387 |
+
* @param integer $yStart
|
388 |
+
* @param ByteMatrix $matrix
|
389 |
+
* @return void
|
390 |
+
* @throws Exception\RuntimeException
|
391 |
+
*/
|
392 |
+
protected static function embedHorizontalSeparationPattern($xStart, $yStart, ByteMatrix $matrix)
|
393 |
+
{
|
394 |
+
for ($x = 0; $x < 8; $x++) {
|
395 |
+
if ($matrix->get($xStart + $x, $yStart) !== -1) {
|
396 |
+
throw new Exception\RuntimeException('Byte already set');
|
397 |
+
}
|
398 |
+
|
399 |
+
$matrix->set($xStart + $x, $yStart, 0);
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Embeds a single vertical separation pattern.
|
405 |
+
*
|
406 |
+
* @param integer $xStart
|
407 |
+
* @param integer $yStart
|
408 |
+
* @param ByteMatrix $matrix
|
409 |
+
* @return void
|
410 |
+
* @throws Exception\RuntimeException
|
411 |
+
*/
|
412 |
+
protected static function embedVerticalSeparationPattern($xStart, $yStart, ByteMatrix $matrix)
|
413 |
+
{
|
414 |
+
for ($y = 0; $y < 7; $y++) {
|
415 |
+
if ($matrix->get($xStart, $yStart + $y) !== -1) {
|
416 |
+
throw new Exception\RuntimeException('Byte already set');
|
417 |
+
}
|
418 |
+
|
419 |
+
$matrix->set($xStart, $yStart + $y, 0);
|
420 |
+
}
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Embeds a dot at the left bottom corner.
|
425 |
+
*
|
426 |
+
* @param ByteMatrix $matrix
|
427 |
+
* @return void
|
428 |
+
* @throws Exception\RuntimeException
|
429 |
+
*/
|
430 |
+
protected static function embedDarkDotAtLeftBottomCorner(ByteMatrix $matrix)
|
431 |
+
{
|
432 |
+
if ($matrix->get(8, $matrix->getHeight() - 8) === 0) {
|
433 |
+
throw new Exception\RuntimeException('Byte already set to 0');
|
434 |
+
}
|
435 |
+
|
436 |
+
$matrix->set(8, $matrix->getHeight() - 8, 1);
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Embeds position adjustment patterns if required.
|
441 |
+
*
|
442 |
+
* @param Version $version
|
443 |
+
* @param ByteMatrix $matrix
|
444 |
+
* @return void
|
445 |
+
*/
|
446 |
+
protected static function maybeEmbedPositionAdjustmentPatterns(Version $version, ByteMatrix $matrix)
|
447 |
+
{
|
448 |
+
if ($version->getVersionNumber() < 2) {
|
449 |
+
return;
|
450 |
+
}
|
451 |
+
|
452 |
+
$index = $version->getVersionNumber() - 1;
|
453 |
+
|
454 |
+
$coordinates = self::$positionAdjustmentPatternCoordinateTable[$index];
|
455 |
+
$numCoordinates = count($coordinates);
|
456 |
+
|
457 |
+
for ($i = 0; $i < $numCoordinates; $i++) {
|
458 |
+
for ($j = 0; $j < $numCoordinates; $j++) {
|
459 |
+
$y = $coordinates[$i];
|
460 |
+
$x = $coordinates[$j];
|
461 |
+
|
462 |
+
if ($x === null || $y === null) {
|
463 |
+
continue;
|
464 |
+
}
|
465 |
+
|
466 |
+
if ($matrix->get($x, $y) === -1) {
|
467 |
+
self::embedPositionAdjustmentPattern($x - 2, $y - 2, $matrix);
|
468 |
+
}
|
469 |
+
}
|
470 |
+
}
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* Embeds a single position adjustment pattern.
|
475 |
+
*
|
476 |
+
* @param integer $xStart
|
477 |
+
* @param intger $yStart
|
478 |
+
* @param ByteMatrix $matrix
|
479 |
+
* @return void
|
480 |
+
*/
|
481 |
+
protected static function embedPositionAdjustmentPattern($xStart, $yStart, ByteMatrix $matrix)
|
482 |
+
{
|
483 |
+
for ($y = 0; $y < 5; $y++) {
|
484 |
+
for ($x = 0; $x < 5; $x++) {
|
485 |
+
$matrix->set($xStart + $x, $yStart + $y, self::$positionAdjustmentPattern[$y][$x]);
|
486 |
+
}
|
487 |
+
}
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* Embeds timing patterns into a matrix.
|
492 |
+
*
|
493 |
+
* @param ByteMatrix $matrix
|
494 |
+
* @return void
|
495 |
+
*/
|
496 |
+
protected static function embedTimingPatterns(ByteMatrix $matrix)
|
497 |
+
{
|
498 |
+
$matrixWidth = $matrix->getWidth();
|
499 |
+
|
500 |
+
for ($i = 8; $i < $matrixWidth - 8; $i++) {
|
501 |
+
$bit = ($i + 1) % 2;
|
502 |
+
|
503 |
+
if ($matrix->get($i, 6) === -1) {
|
504 |
+
$matrix->set($i, 6, $bit);
|
505 |
+
}
|
506 |
+
|
507 |
+
if ($matrix->get(6, $i) === -1) {
|
508 |
+
$matrix->set(6, $i, $bit);
|
509 |
+
}
|
510 |
+
}
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Embeds "dataBits" using "getMaskPattern".
|
515 |
+
*
|
516 |
+
* For debugging purposes, it skips masking process if "getMaskPattern" is
|
517 |
+
* -1. See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
|
518 |
+
*
|
519 |
+
* @param BitArray $dataBits
|
520 |
+
* @param integer $maskPattern
|
521 |
+
* @param ByteMatrix $matrix
|
522 |
+
* @return void
|
523 |
+
* @throws Exception\WriterException
|
524 |
+
*/
|
525 |
+
protected static function embedDataBits(BitArray $dataBits, $maskPattern, ByteMatrix $matrix)
|
526 |
+
{
|
527 |
+
$bitIndex = 0;
|
528 |
+
$direction = -1;
|
529 |
+
|
530 |
+
// Start from the right bottom cell.
|
531 |
+
$x = $matrix->getWidth() - 1;
|
532 |
+
$y = $matrix->getHeight() - 1;
|
533 |
+
|
534 |
+
while ($x > 0) {
|
535 |
+
// Skip vertical timing pattern.
|
536 |
+
if ($x === 6) {
|
537 |
+
$x--;
|
538 |
+
}
|
539 |
+
|
540 |
+
while ($y >= 0 && $y < $matrix->getHeight()) {
|
541 |
+
for ($i = 0; $i < 2; $i++) {
|
542 |
+
$xx = $x - $i;
|
543 |
+
|
544 |
+
// Skip the cell if it's not empty.
|
545 |
+
if ($matrix->get($xx, $y) !== -1) {
|
546 |
+
continue;
|
547 |
+
}
|
548 |
+
|
549 |
+
if ($bitIndex < $dataBits->getSize()) {
|
550 |
+
$bit = $dataBits->get($bitIndex);
|
551 |
+
$bitIndex++;
|
552 |
+
} else {
|
553 |
+
// Padding bit. If there is no bit left, we'll fill the
|
554 |
+
// left cells with 0, as described in 8.4.9 of
|
555 |
+
// JISX0510:2004 (p. 24).
|
556 |
+
$bit = false;
|
557 |
+
}
|
558 |
+
|
559 |
+
// Skip masking if maskPattern is -1.
|
560 |
+
if ($maskPattern !== -1 && MaskUtil::getDataMaskBit($maskPattern, $xx, $y)) {
|
561 |
+
$bit = !$bit;
|
562 |
+
}
|
563 |
+
|
564 |
+
$matrix->set($xx, $y, $bit);
|
565 |
+
}
|
566 |
+
|
567 |
+
$y += $direction;
|
568 |
+
}
|
569 |
+
|
570 |
+
$direction = -$direction;
|
571 |
+
$y += $direction;
|
572 |
+
$x -= 2;
|
573 |
+
}
|
574 |
+
|
575 |
+
// All bits should be consumed
|
576 |
+
if ($bitIndex !== $dataBits->getSize()) {
|
577 |
+
throw new Exception\WriterException('Not all bits consumed (' . $bitIndex . ' out of ' . $dataBits->getSize() .')');
|
578 |
+
}
|
579 |
+
}
|
580 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php
ADDED
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Encoder;
|
11 |
+
|
12 |
+
use BaconQrCode\Common\ErrorCorrectionLevel;
|
13 |
+
use BaconQrCode\Common\Mode;
|
14 |
+
use BaconQrCode\Common\Version;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* QR code.
|
18 |
+
*/
|
19 |
+
class QrCode
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* Number of possible mask patterns.
|
23 |
+
*/
|
24 |
+
const NUM_MASK_PATTERNS = 8;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Mode of the QR code.
|
28 |
+
*
|
29 |
+
* @var Mode
|
30 |
+
*/
|
31 |
+
protected $mode;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* EC level of the QR code.
|
35 |
+
*
|
36 |
+
* @var ErrorCorrectionLevel
|
37 |
+
*/
|
38 |
+
protected $errorCorrectionLevel;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Version of the QR code.
|
42 |
+
*
|
43 |
+
* @var Version
|
44 |
+
*/
|
45 |
+
protected $version;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Mask pattern of the QR code.
|
49 |
+
*
|
50 |
+
* @var integer
|
51 |
+
*/
|
52 |
+
protected $maskPattern = -1;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Matrix of the QR code.
|
56 |
+
*
|
57 |
+
* @var ByteMatrix
|
58 |
+
*/
|
59 |
+
protected $matrix;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Gets the mode.
|
63 |
+
*
|
64 |
+
* @return Mode
|
65 |
+
*/
|
66 |
+
public function getMode()
|
67 |
+
{
|
68 |
+
return $this->mode;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Sets the mode.
|
73 |
+
*
|
74 |
+
* @param Mode $mode
|
75 |
+
* @return void
|
76 |
+
*/
|
77 |
+
public function setMode(Mode $mode)
|
78 |
+
{
|
79 |
+
$this->mode = $mode;
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Gets the EC level.
|
84 |
+
*
|
85 |
+
* @return ErrorCorrectionLevel
|
86 |
+
*/
|
87 |
+
public function getErrorCorrectionLevel()
|
88 |
+
{
|
89 |
+
return $this->errorCorrectionLevel;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Sets the EC level.
|
94 |
+
*
|
95 |
+
* @param ErrorCorrectionLevel $errorCorrectionLevel
|
96 |
+
* @return void
|
97 |
+
*/
|
98 |
+
public function setErrorCorrectionLevel(ErrorCorrectionLevel $errorCorrectionLevel)
|
99 |
+
{
|
100 |
+
$this->errorCorrectionLevel = $errorCorrectionLevel;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Gets the version.
|
105 |
+
*
|
106 |
+
* @return Version
|
107 |
+
*/
|
108 |
+
public function getVersion()
|
109 |
+
{
|
110 |
+
return $this->version;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Sets the version.
|
115 |
+
*
|
116 |
+
* @param Version $version
|
117 |
+
* @return void
|
118 |
+
*/
|
119 |
+
public function setVersion(Version $version)
|
120 |
+
{
|
121 |
+
$this->version = $version;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Gets the mask pattern.
|
126 |
+
*
|
127 |
+
* @return integer
|
128 |
+
*/
|
129 |
+
public function getMaskPattern()
|
130 |
+
{
|
131 |
+
return $this->maskPattern;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Sets the mask pattern.
|
136 |
+
*
|
137 |
+
* @param integer $maskPattern
|
138 |
+
* @return void
|
139 |
+
*/
|
140 |
+
public function setMaskPattern($maskPattern)
|
141 |
+
{
|
142 |
+
$this->maskPattern = $maskPattern;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Gets the matrix.
|
147 |
+
*
|
148 |
+
* @return ByteMatrix
|
149 |
+
*/
|
150 |
+
public function getMatrix()
|
151 |
+
{
|
152 |
+
return $this->matrix;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Sets the matrix.
|
157 |
+
*
|
158 |
+
* @param ByteMatrix $matrix
|
159 |
+
* @return void
|
160 |
+
*/
|
161 |
+
public function setMatrix(ByteMatrix $matrix)
|
162 |
+
{
|
163 |
+
$this->matrix = $matrix;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Validates whether a mask pattern is valid.
|
168 |
+
*
|
169 |
+
* @param integer $maskPattern
|
170 |
+
* @return boolean
|
171 |
+
*/
|
172 |
+
public static function isValidMaskPattern($maskPattern)
|
173 |
+
{
|
174 |
+
return $maskPattern > 0 && $maskPattern < self::NUM_MASK_PATTERNS;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Returns a string representation of the QR code.
|
179 |
+
*
|
180 |
+
* @return string
|
181 |
+
*/
|
182 |
+
public function __toString()
|
183 |
+
{
|
184 |
+
$result = "<<\n"
|
185 |
+
. " mode: " . $this->mode . "\n"
|
186 |
+
. " ecLevel: " . $this->errorCorrectionLevel . "\n"
|
187 |
+
. " version: " . $this->version . "\n"
|
188 |
+
. " maskPattern: " . $this->maskPattern . "\n";
|
189 |
+
|
190 |
+
if ($this->matrix === null) {
|
191 |
+
$result .= " matrix: null\n";
|
192 |
+
} else {
|
193 |
+
$result .= " matrix:\n";
|
194 |
+
$result .= $this->matrix;
|
195 |
+
}
|
196 |
+
|
197 |
+
$result .= ">>\n";
|
198 |
+
|
199 |
+
return $result;
|
200 |
+
}
|
201 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Exception;
|
11 |
+
|
12 |
+
interface ExceptionInterface
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Exception;
|
11 |
+
|
12 |
+
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Exception;
|
11 |
+
|
12 |
+
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Exception;
|
11 |
+
|
12 |
+
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Exception;
|
11 |
+
|
12 |
+
class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Exception;
|
11 |
+
|
12 |
+
class WriterException extends \RuntimeException implements ExceptionInterface
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Color;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* CMYK color.
|
16 |
+
*/
|
17 |
+
class Cmyk implements ColorInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Cyan value.
|
21 |
+
*
|
22 |
+
* @var integer
|
23 |
+
*/
|
24 |
+
protected $cyan;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Magenta value.
|
28 |
+
*
|
29 |
+
* @var integer
|
30 |
+
*/
|
31 |
+
protected $magenta;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Yellow value.
|
35 |
+
*
|
36 |
+
* @var integer
|
37 |
+
*/
|
38 |
+
protected $yellow;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Black value.
|
42 |
+
*
|
43 |
+
* @var integer
|
44 |
+
*/
|
45 |
+
protected $black;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Creates a new CMYK color.
|
49 |
+
*
|
50 |
+
* @param integer $cyan
|
51 |
+
* @param integer $magenta
|
52 |
+
* @param integer $yellow
|
53 |
+
* @param integer $black
|
54 |
+
*/
|
55 |
+
public function __construct($cyan, $magenta, $yellow, $black)
|
56 |
+
{
|
57 |
+
if ($cyan < 0 || $cyan > 100) {
|
58 |
+
throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100');
|
59 |
+
}
|
60 |
+
|
61 |
+
if ($magenta < 0 || $magenta > 100) {
|
62 |
+
throw new Exception\InvalidArgumentException('Magenta must be between 0 and 100');
|
63 |
+
}
|
64 |
+
|
65 |
+
if ($yellow < 0 || $yellow > 100) {
|
66 |
+
throw new Exception\InvalidArgumentException('Yellow must be between 0 and 100');
|
67 |
+
}
|
68 |
+
|
69 |
+
if ($black < 0 || $black > 100) {
|
70 |
+
throw new Exception\InvalidArgumentException('Black must be between 0 and 100');
|
71 |
+
}
|
72 |
+
|
73 |
+
$this->cyan = (int) $cyan;
|
74 |
+
$this->magenta = (int) $magenta;
|
75 |
+
$this->yellow = (int) $yellow;
|
76 |
+
$this->black = (int) $black;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns the cyan value.
|
81 |
+
*
|
82 |
+
* @return integer
|
83 |
+
*/
|
84 |
+
public function getCyan()
|
85 |
+
{
|
86 |
+
return $this->cyan;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Returns the magenta value.
|
91 |
+
*
|
92 |
+
* @return integer
|
93 |
+
*/
|
94 |
+
public function getMagenta()
|
95 |
+
{
|
96 |
+
return $this->magenta;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Returns the yellow value.
|
101 |
+
*
|
102 |
+
* @return integer
|
103 |
+
*/
|
104 |
+
public function getYellow()
|
105 |
+
{
|
106 |
+
return $this->yellow;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Returns the black value.
|
111 |
+
*
|
112 |
+
* @return integer
|
113 |
+
*/
|
114 |
+
public function getBlack()
|
115 |
+
{
|
116 |
+
return $this->black;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* toRgb(): defined by ColorInterface.
|
121 |
+
*
|
122 |
+
* @see ColorInterface::toRgb()
|
123 |
+
* @return Rgb
|
124 |
+
*/
|
125 |
+
public function toRgb()
|
126 |
+
{
|
127 |
+
$k = $this->black / 100;
|
128 |
+
$c = (-$k * $this->cyan + $k * 100 + $this->cyan) / 100;
|
129 |
+
$m = (-$k * $this->magenta + $k * 100 + $this->magenta) / 100;
|
130 |
+
$y = (-$k * $this->yellow + $k * 100 + $this->yellow) / 100;
|
131 |
+
|
132 |
+
return new Rgb(
|
133 |
+
-$c * 255 + 255,
|
134 |
+
-$m * 255 + 255,
|
135 |
+
-$y * 255 + 255
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* toCmyk(): defined by ColorInterface.
|
141 |
+
*
|
142 |
+
* @see ColorInterface::toCmyk()
|
143 |
+
* @return Cmyk
|
144 |
+
*/
|
145 |
+
public function toCmyk()
|
146 |
+
{
|
147 |
+
return $this;
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* toGray(): defined by ColorInterface.
|
152 |
+
*
|
153 |
+
* @see ColorInterface::toGray()
|
154 |
+
* @return Gray
|
155 |
+
*/
|
156 |
+
public function toGray()
|
157 |
+
{
|
158 |
+
return $this->toRgb()->toGray();
|
159 |
+
}
|
160 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Color;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Color interface.
|
14 |
+
*/
|
15 |
+
interface ColorInterface
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* Converts the color to RGB.
|
19 |
+
*
|
20 |
+
* @return Rgb
|
21 |
+
*/
|
22 |
+
public function toRgb();
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Converts the color to CMYK.
|
26 |
+
*
|
27 |
+
* @return Cmyk
|
28 |
+
*/
|
29 |
+
public function toCmyk();
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Converts the color to gray.
|
33 |
+
*
|
34 |
+
* @return Gray
|
35 |
+
*/
|
36 |
+
public function toGray();
|
37 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Color;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Gray color.
|
16 |
+
*/
|
17 |
+
class Gray implements ColorInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Gray value.
|
21 |
+
*
|
22 |
+
* @var integer
|
23 |
+
*/
|
24 |
+
protected $gray;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Creates a new gray color.
|
28 |
+
*
|
29 |
+
* A low gray value means black, while a high value means white.
|
30 |
+
*
|
31 |
+
* @param integer $gray
|
32 |
+
*/
|
33 |
+
public function __construct($gray)
|
34 |
+
{
|
35 |
+
if ($gray < 0 || $gray > 100) {
|
36 |
+
throw new Exception\InvalidArgumentException('Gray must be between 0 and 100');
|
37 |
+
}
|
38 |
+
|
39 |
+
$this->gray = (int) $gray;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Returns the gray value.
|
44 |
+
*
|
45 |
+
* @return integer
|
46 |
+
*/
|
47 |
+
public function getGray()
|
48 |
+
{
|
49 |
+
return $this->gray;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* toRgb(): defined by ColorInterface.
|
54 |
+
*
|
55 |
+
* @see ColorInterface::toRgb()
|
56 |
+
* @return Rgb
|
57 |
+
*/
|
58 |
+
public function toRgb()
|
59 |
+
{
|
60 |
+
return new Rgb($this->gray * 2.55, $this->gray * 2.55, $this->gray * 2.55);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* toCmyk(): defined by ColorInterface.
|
65 |
+
*
|
66 |
+
* @see ColorInterface::toCmyk()
|
67 |
+
* @return Cmyk
|
68 |
+
*/
|
69 |
+
public function toCmyk()
|
70 |
+
{
|
71 |
+
return new Cmyk(0, 0, 0, 100 - $this->gray);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* toGray(): defined by ColorInterface.
|
76 |
+
*
|
77 |
+
* @see ColorInterface::toGray()
|
78 |
+
* @return Gray
|
79 |
+
*/
|
80 |
+
public function toGray()
|
81 |
+
{
|
82 |
+
return $this;
|
83 |
+
}
|
84 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Color;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* RGB color.
|
16 |
+
*/
|
17 |
+
class Rgb implements ColorInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Red value.
|
21 |
+
*
|
22 |
+
* @var integer
|
23 |
+
*/
|
24 |
+
protected $red;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Green value.
|
28 |
+
*
|
29 |
+
* @var integer
|
30 |
+
*/
|
31 |
+
protected $green;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Blue value.
|
35 |
+
*
|
36 |
+
* @var integer
|
37 |
+
*/
|
38 |
+
protected $blue;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Creates a new RGB color.
|
42 |
+
*
|
43 |
+
* @param integer $red
|
44 |
+
* @param integer $green
|
45 |
+
* @param integer $blue
|
46 |
+
*/
|
47 |
+
public function __construct($red, $green, $blue)
|
48 |
+
{
|
49 |
+
if ($red < 0 || $red > 255) {
|
50 |
+
throw new Exception\InvalidArgumentException('Red must be between 0 and 255');
|
51 |
+
}
|
52 |
+
|
53 |
+
if ($green < 0 || $green > 255) {
|
54 |
+
throw new Exception\InvalidArgumentException('Green must be between 0 and 255');
|
55 |
+
}
|
56 |
+
|
57 |
+
if ($blue < 0 || $blue > 255) {
|
58 |
+
throw new Exception\InvalidArgumentException('Blue must be between 0 and 255');
|
59 |
+
}
|
60 |
+
|
61 |
+
$this->red = (int) $red;
|
62 |
+
$this->green = (int) $green;
|
63 |
+
$this->blue = (int) $blue;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Returns the red value.
|
68 |
+
*
|
69 |
+
* @return integer
|
70 |
+
*/
|
71 |
+
public function getRed()
|
72 |
+
{
|
73 |
+
return $this->red;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Returns the green value.
|
78 |
+
*
|
79 |
+
* @return integer
|
80 |
+
*/
|
81 |
+
public function getGreen()
|
82 |
+
{
|
83 |
+
return $this->green;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Returns the blue value.
|
88 |
+
*
|
89 |
+
* @return integer
|
90 |
+
*/
|
91 |
+
public function getBlue()
|
92 |
+
{
|
93 |
+
return $this->blue;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Returns a hexadecimal string representation of the RGB value.
|
98 |
+
*
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function __toString()
|
102 |
+
{
|
103 |
+
return sprintf('%02x%02x%02x', $this->red, $this->green, $this->blue);
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* toRgb(): defined by ColorInterface.
|
108 |
+
*
|
109 |
+
* @see ColorInterface::toRgb()
|
110 |
+
* @return Rgb
|
111 |
+
*/
|
112 |
+
public function toRgb()
|
113 |
+
{
|
114 |
+
return $this;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* toCmyk(): defined by ColorInterface.
|
119 |
+
*
|
120 |
+
* @see ColorInterface::toCmyk()
|
121 |
+
* @return Cmyk
|
122 |
+
*/
|
123 |
+
public function toCmyk()
|
124 |
+
{
|
125 |
+
$c = 1 - ($this->red / 255);
|
126 |
+
$m = 1 - ($this->green / 255);
|
127 |
+
$y = 1 - ($this->blue / 255);
|
128 |
+
$k = min($c, $m, $y);
|
129 |
+
|
130 |
+
return new Cmyk(
|
131 |
+
100 * ($c - $k) / (1 - $k),
|
132 |
+
100 * ($m - $k) / (1 - $k),
|
133 |
+
100 * ($y - $k) / (1 - $k),
|
134 |
+
100 * $k
|
135 |
+
);
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* toGray(): defined by ColorInterface.
|
140 |
+
*
|
141 |
+
* @see ColorInterface::toGray()
|
142 |
+
* @return Gray
|
143 |
+
*/
|
144 |
+
public function toGray()
|
145 |
+
{
|
146 |
+
return new Gray(($this->red * 0.21 + $this->green * 0.71 + $this->blue * 0.07) / 2.55);
|
147 |
+
}
|
148 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php
ADDED
@@ -0,0 +1,338 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image;
|
11 |
+
|
12 |
+
use BaconQrCode\Encoder\QrCode;
|
13 |
+
use BaconQrCode\Renderer\Color;
|
14 |
+
use BaconQrCode\Renderer\Image\Decorator\DecoratorInterface;
|
15 |
+
use BaconQrCode\Exception;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Image renderer, supporting multiple backends.
|
19 |
+
*/
|
20 |
+
abstract class AbstractRenderer implements RendererInterface
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Margin around the QR code, also known as quiet zone.
|
24 |
+
*
|
25 |
+
* @var integer
|
26 |
+
*/
|
27 |
+
protected $margin = 4;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Requested width of the rendered image.
|
31 |
+
*
|
32 |
+
* @var integer
|
33 |
+
*/
|
34 |
+
protected $width = 0;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Requested height of the rendered image.
|
38 |
+
*
|
39 |
+
* @var integer
|
40 |
+
*/
|
41 |
+
protected $height = 0;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Whether dimensions should be rounded down.
|
45 |
+
*
|
46 |
+
* @var boolean
|
47 |
+
*/
|
48 |
+
protected $roundDimensions = true;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Final width of the image.
|
52 |
+
*
|
53 |
+
* @var integer
|
54 |
+
*/
|
55 |
+
protected $finalWidth;
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Final height of the image.
|
59 |
+
*
|
60 |
+
* @var integer
|
61 |
+
*/
|
62 |
+
protected $finalHeight;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Size of each individual block.
|
66 |
+
*
|
67 |
+
* @var integer
|
68 |
+
*/
|
69 |
+
protected $blockSize;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Background color.
|
73 |
+
*
|
74 |
+
* @var Color\ColorInterface
|
75 |
+
*/
|
76 |
+
protected $backgroundColor;
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Whether dimensions should be rounded down
|
80 |
+
*
|
81 |
+
* @var boolean
|
82 |
+
*/
|
83 |
+
protected $floorToClosestDimension;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Foreground color.
|
87 |
+
*
|
88 |
+
* @var Color\ColorInterface
|
89 |
+
*/
|
90 |
+
protected $foregroundColor;
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Decorators used on QR codes.
|
94 |
+
*
|
95 |
+
* @var array
|
96 |
+
*/
|
97 |
+
protected $decorators = array();
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Sets the margin around the QR code.
|
101 |
+
*
|
102 |
+
* @param integer $margin
|
103 |
+
* @return AbstractRenderer
|
104 |
+
* @throws Exception\InvalidArgumentException
|
105 |
+
*/
|
106 |
+
public function setMargin($margin)
|
107 |
+
{
|
108 |
+
if ($margin < 0) {
|
109 |
+
throw new Exception\InvalidArgumentException('Margin must be equal to greater than 0');
|
110 |
+
}
|
111 |
+
|
112 |
+
$this->margin = (int) $margin;
|
113 |
+
return $this;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Gets the margin around the QR code.
|
118 |
+
*
|
119 |
+
* @return integer
|
120 |
+
*/
|
121 |
+
public function getMargin()
|
122 |
+
{
|
123 |
+
return $this->margin;
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Sets the height around the renderd image.
|
128 |
+
*
|
129 |
+
* If the width is smaller than the matrix width plus padding, the renderer
|
130 |
+
* will automatically use that as the width instead of the specified one.
|
131 |
+
*
|
132 |
+
* @param integer $width
|
133 |
+
* @return AbstractRenderer
|
134 |
+
*/
|
135 |
+
public function setWidth($width)
|
136 |
+
{
|
137 |
+
$this->width = (int) $width;
|
138 |
+
return $this;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Gets the width of the rendered image.
|
143 |
+
*
|
144 |
+
* @return integer
|
145 |
+
*/
|
146 |
+
public function getWidth()
|
147 |
+
{
|
148 |
+
return $this->width;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Sets the height around the renderd image.
|
153 |
+
*
|
154 |
+
* If the height is smaller than the matrix height plus padding, the
|
155 |
+
* renderer will automatically use that as the height instead of the
|
156 |
+
* specified one.
|
157 |
+
*
|
158 |
+
* @param integer $height
|
159 |
+
* @return AbstractRenderer
|
160 |
+
*/
|
161 |
+
public function setHeight($height)
|
162 |
+
{
|
163 |
+
$this->height = (int) $height;
|
164 |
+
return $this;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Gets the height around the rendered image.
|
169 |
+
*
|
170 |
+
* @return integer
|
171 |
+
*/
|
172 |
+
public function getHeight()
|
173 |
+
{
|
174 |
+
return $this->height;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Sets whether dimensions should be rounded down.
|
179 |
+
*
|
180 |
+
* @param boolean $flag
|
181 |
+
* @return AbstractRenderer
|
182 |
+
*/
|
183 |
+
public function setRoundDimensions($flag)
|
184 |
+
{
|
185 |
+
$this->floorToClosestDimension = $flag;
|
186 |
+
return $this;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Gets whether dimensions should be rounded down.
|
191 |
+
*
|
192 |
+
* @return boolean
|
193 |
+
*/
|
194 |
+
public function shouldRoundDimensions()
|
195 |
+
{
|
196 |
+
return $this->floorToClosestDimension;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Sets background color.
|
201 |
+
*
|
202 |
+
* @param Color\ColorInterface $color
|
203 |
+
* @return AbstractRenderer
|
204 |
+
*/
|
205 |
+
public function setBackgroundColor(Color\ColorInterface $color)
|
206 |
+
{
|
207 |
+
$this->backgroundColor = $color;
|
208 |
+
return $this;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Gets background color.
|
213 |
+
*
|
214 |
+
* @return Color\ColorInterface
|
215 |
+
*/
|
216 |
+
public function getBackgroundColor()
|
217 |
+
{
|
218 |
+
if ($this->backgroundColor === null) {
|
219 |
+
$this->backgroundColor = new Color\Gray(100);
|
220 |
+
}
|
221 |
+
|
222 |
+
return $this->backgroundColor;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Sets foreground color.
|
227 |
+
*
|
228 |
+
* @param Color\ColorInterface $color
|
229 |
+
* @return AbstractRenderer
|
230 |
+
*/
|
231 |
+
public function setForegroundColor(Color\ColorInterface $color)
|
232 |
+
{
|
233 |
+
$this->foregroundColor = $color;
|
234 |
+
return $this;
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Gets foreground color.
|
239 |
+
*
|
240 |
+
* @return Color\ColorInterface
|
241 |
+
*/
|
242 |
+
public function getForegroundColor()
|
243 |
+
{
|
244 |
+
if ($this->foregroundColor === null) {
|
245 |
+
$this->foregroundColor = new Color\Gray(0);
|
246 |
+
}
|
247 |
+
|
248 |
+
return $this->foregroundColor;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Adds a decorator to the renderer.
|
253 |
+
*
|
254 |
+
* @param DecoratorInterface $decorator
|
255 |
+
* @return AbstractRenderer
|
256 |
+
*/
|
257 |
+
public function addDecorator(DecoratorInterface $decorator)
|
258 |
+
{
|
259 |
+
$this->decorators[] = $decorator;
|
260 |
+
return $this;
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* render(): defined by RendererInterface.
|
265 |
+
*
|
266 |
+
* @see RendererInterface::render()
|
267 |
+
* @param QrCode $qrCode
|
268 |
+
* @return string
|
269 |
+
*/
|
270 |
+
public function render(QrCode $qrCode)
|
271 |
+
{
|
272 |
+
$input = $qrCode->getMatrix();
|
273 |
+
$inputWidth = $input->getWidth();
|
274 |
+
$inputHeight = $input->getHeight();
|
275 |
+
$qrWidth = $inputWidth + ($this->getMargin() << 1);
|
276 |
+
$qrHeight = $inputHeight + ($this->getMargin() << 1);
|
277 |
+
$outputWidth = max($this->getWidth(), $qrWidth);
|
278 |
+
$outputHeight = max($this->getHeight(), $qrHeight);
|
279 |
+
$multiple = (int) min($outputWidth / $qrWidth, $outputHeight / $qrHeight);
|
280 |
+
|
281 |
+
if ($this->shouldRoundDimensions()) {
|
282 |
+
$outputWidth -= $outputWidth % $multiple;
|
283 |
+
$outputHeight -= $outputHeight % $multiple;
|
284 |
+
}
|
285 |
+
|
286 |
+
// Padding includes both the quiet zone and the extra white pixels to
|
287 |
+
// accommodate the requested dimensions. For example, if input is 25x25
|
288 |
+
// the QR will be 33x33 including the quiet zone. If the requested size
|
289 |
+
// is 200x160, the multiple will be 4, for a QR of 132x132. These will
|
290 |
+
// handle all the padding from 100x100 (the actual QR) up to 200x160.
|
291 |
+
$leftPadding = (int) (($outputWidth - ($inputWidth * $multiple)) / 2);
|
292 |
+
$topPadding = (int) (($outputHeight - ($inputHeight * $multiple)) / 2);
|
293 |
+
|
294 |
+
// Store calculated parameters
|
295 |
+
$this->finalWidth = $outputWidth;
|
296 |
+
$this->finalHeight = $outputHeight;
|
297 |
+
$this->blockSize = $multiple;
|
298 |
+
|
299 |
+
$this->init();
|
300 |
+
$this->addColor('background', $this->getBackgroundColor());
|
301 |
+
$this->addColor('foreground', $this->getForegroundColor());
|
302 |
+
$this->drawBackground('background');
|
303 |
+
|
304 |
+
foreach ($this->decorators as $decorator) {
|
305 |
+
$decorator->preProcess(
|
306 |
+
$qrCode,
|
307 |
+
$this,
|
308 |
+
$outputWidth,
|
309 |
+
$outputHeight,
|
310 |
+
$leftPadding,
|
311 |
+
$topPadding,
|
312 |
+
$multiple
|
313 |
+
);
|
314 |
+
}
|
315 |
+
|
316 |
+
for ($inputY = 0, $outputY = $topPadding; $inputY < $inputHeight; $inputY++, $outputY += $multiple) {
|
317 |
+
for ($inputX = 0, $outputX = $leftPadding; $inputX < $inputWidth; $inputX++, $outputX += $multiple) {
|
318 |
+
if ($input->get($inputX, $inputY) === 1) {
|
319 |
+
$this->drawBlock($outputX, $outputY, 'foreground');
|
320 |
+
}
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
foreach ($this->decorators as $decorator) {
|
325 |
+
$decorator->postProcess(
|
326 |
+
$qrCode,
|
327 |
+
$this,
|
328 |
+
$outputWidth,
|
329 |
+
$outputHeight,
|
330 |
+
$leftPadding,
|
331 |
+
$topPadding,
|
332 |
+
$multiple
|
333 |
+
);
|
334 |
+
}
|
335 |
+
|
336 |
+
return $this->getByteStream();
|
337 |
+
}
|
338 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image\Decorator;
|
11 |
+
|
12 |
+
use BaconQrCode\Encoder\QrCode;
|
13 |
+
use BaconQrCode\Renderer\Image\RendererInterface;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Decorator interface.
|
17 |
+
*/
|
18 |
+
interface DecoratorInterface
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Pre-process a QR code.
|
22 |
+
*
|
23 |
+
* @param QrCode $qrCode
|
24 |
+
* @param RendererInterface $renderer
|
25 |
+
* @param integer $outputWidth
|
26 |
+
* @param integer $outputHeight
|
27 |
+
* @param integer $leftPadding
|
28 |
+
* @param integer $topPadding
|
29 |
+
* @param integer $multiple
|
30 |
+
* @return void
|
31 |
+
*/
|
32 |
+
public function preProcess(
|
33 |
+
QrCode $qrCode,
|
34 |
+
RendererInterface $renderer,
|
35 |
+
$outputWidth,
|
36 |
+
$outputHeight,
|
37 |
+
$leftPadding,
|
38 |
+
$topPadding,
|
39 |
+
$multiple
|
40 |
+
);
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Post-process a QR code.
|
44 |
+
*
|
45 |
+
* @param QrCode $qrCode
|
46 |
+
* @param RendererInterface $renderer
|
47 |
+
* @param integer $outputWidth
|
48 |
+
* @param integer $outputHeight
|
49 |
+
* @param integer $leftPadding
|
50 |
+
* @param integer $topPadding
|
51 |
+
* @param integer $multiple
|
52 |
+
* @return void
|
53 |
+
*/
|
54 |
+
public function postProcess(
|
55 |
+
QrCode $qrCode,
|
56 |
+
RendererInterface $renderer,
|
57 |
+
$outputWidth,
|
58 |
+
$outputHeight,
|
59 |
+
$leftPadding,
|
60 |
+
$topPadding,
|
61 |
+
$multiple
|
62 |
+
);
|
63 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php
ADDED
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image\Decorator;
|
11 |
+
|
12 |
+
use BaconQrCode\Encoder\QrCode;
|
13 |
+
use BaconQrCode\Renderer\Image\RendererInterface;
|
14 |
+
use BaconQrCode\Renderer\Color;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Finder pattern decorator.
|
18 |
+
*/
|
19 |
+
class FinderPattern implements DecoratorInterface
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* @var Color\ColorInterface
|
23 |
+
*/
|
24 |
+
protected $innerColor;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @varColor\ColorInterface
|
28 |
+
*/
|
29 |
+
protected $outerColor;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Outer position detection pattern.
|
33 |
+
*
|
34 |
+
* @var array
|
35 |
+
*/
|
36 |
+
protected static $outerPositionDetectionPattern = array(
|
37 |
+
array(1, 1, 1, 1, 1, 1, 1),
|
38 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
39 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
40 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
41 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
42 |
+
array(1, 0, 0, 0, 0, 0, 1),
|
43 |
+
array(1, 1, 1, 1, 1, 1, 1),
|
44 |
+
);
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Inner position detection pattern.
|
48 |
+
*
|
49 |
+
* @var array
|
50 |
+
*/
|
51 |
+
protected static $innerPositionDetectionPattern = array(
|
52 |
+
array(0, 0, 0, 0, 0, 0, 0),
|
53 |
+
array(0, 0, 0, 0, 0, 0, 0),
|
54 |
+
array(0, 0, 1, 1, 1, 0, 0),
|
55 |
+
array(0, 0, 1, 1, 1, 0, 0),
|
56 |
+
array(0, 0, 1, 1, 1, 0, 0),
|
57 |
+
array(0, 0, 0, 0, 0, 0, 0),
|
58 |
+
array(0, 0, 0, 0, 0, 0, 0),
|
59 |
+
);
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Sets outer color.
|
63 |
+
*
|
64 |
+
* @param Color\ColorInterface $color
|
65 |
+
* @return FinderPattern
|
66 |
+
*/
|
67 |
+
public function setOuterColor(Color\ColorInterface $color)
|
68 |
+
{
|
69 |
+
$this->outerColor = $color;
|
70 |
+
return $this;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Gets outer color.
|
75 |
+
*
|
76 |
+
* @return Color\ColorInterface
|
77 |
+
*/
|
78 |
+
public function getOuterColor()
|
79 |
+
{
|
80 |
+
if ($this->outerColor === null) {
|
81 |
+
$this->outerColor = new Color\Gray(100);
|
82 |
+
}
|
83 |
+
|
84 |
+
return $this->outerColor;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Sets inner color.
|
89 |
+
*
|
90 |
+
* @param Color\ColorInterface $color
|
91 |
+
* @return FinderPattern
|
92 |
+
*/
|
93 |
+
public function setInnerColor(Color\ColorInterface $color)
|
94 |
+
{
|
95 |
+
$this->innerColor = $color;
|
96 |
+
return $this;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Gets inner color.
|
101 |
+
*
|
102 |
+
* @return Color\ColorInterface
|
103 |
+
*/
|
104 |
+
public function getInnerColor()
|
105 |
+
{
|
106 |
+
if ($this->innerColor === null) {
|
107 |
+
$this->innerColor = new Color\Gray(0);
|
108 |
+
}
|
109 |
+
|
110 |
+
return $this->innerColor;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* preProcess(): defined by DecoratorInterface.
|
115 |
+
*
|
116 |
+
* @see DecoratorInterface::preProcess()
|
117 |
+
* @param QrCode $qrCode
|
118 |
+
* @param RendererInterface $renderer
|
119 |
+
* @param integer $outputWidth
|
120 |
+
* @param integer $outputHeight
|
121 |
+
* @param integer $leftPadding
|
122 |
+
* @param integer $topPadding
|
123 |
+
* @param integer $multiple
|
124 |
+
* @return void
|
125 |
+
*/
|
126 |
+
public function preProcess(
|
127 |
+
QrCode $qrCode,
|
128 |
+
RendererInterface $renderer,
|
129 |
+
$outputWidth,
|
130 |
+
$outputHeight,
|
131 |
+
$leftPadding,
|
132 |
+
$topPadding,
|
133 |
+
$multiple
|
134 |
+
) {
|
135 |
+
$matrix = $qrCode->getMatrix();
|
136 |
+
$positions = array(
|
137 |
+
array(0, 0),
|
138 |
+
array($matrix->getWidth() - 7, 0),
|
139 |
+
array(0, $matrix->getHeight() - 7),
|
140 |
+
);
|
141 |
+
|
142 |
+
foreach (self::$outerPositionDetectionPattern as $y => $row) {
|
143 |
+
foreach ($row as $x => $isSet) {
|
144 |
+
foreach ($positions as $position) {
|
145 |
+
$matrix->set($x + $position[0], $y + $position[1], 0);
|
146 |
+
}
|
147 |
+
}
|
148 |
+
}
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* postProcess(): defined by DecoratorInterface.
|
153 |
+
*
|
154 |
+
* @see DecoratorInterface::postProcess()
|
155 |
+
*
|
156 |
+
* @param QrCode $qrCode
|
157 |
+
* @param RendererInterface $renderer
|
158 |
+
* @param integer $outputWidth
|
159 |
+
* @param integer $outputHeight
|
160 |
+
* @param integer $leftPadding
|
161 |
+
* @param integer $topPadding
|
162 |
+
* @param integer $multiple
|
163 |
+
* @return void
|
164 |
+
*/
|
165 |
+
public function postProcess(
|
166 |
+
QrCode $qrCode,
|
167 |
+
RendererInterface $renderer,
|
168 |
+
$outputWidth,
|
169 |
+
$outputHeight,
|
170 |
+
$leftPadding,
|
171 |
+
$topPadding,
|
172 |
+
$multiple
|
173 |
+
) {
|
174 |
+
$matrix = $qrCode->getMatrix();
|
175 |
+
$positions = array(
|
176 |
+
array(0, 0),
|
177 |
+
array($matrix->getWidth() - 7, 0),
|
178 |
+
array(0, $matrix->getHeight() - 7),
|
179 |
+
);
|
180 |
+
|
181 |
+
$renderer->addColor('finder-outer', $this->getOuterColor());
|
182 |
+
$renderer->addColor('finder-inner', $this->getInnerColor());
|
183 |
+
|
184 |
+
foreach (self::$outerPositionDetectionPattern as $y => $row) {
|
185 |
+
foreach ($row as $x => $isOuterSet) {
|
186 |
+
$isInnerSet = self::$innerPositionDetectionPattern[$y][$x];
|
187 |
+
|
188 |
+
if ($isOuterSet) {
|
189 |
+
foreach ($positions as $position) {
|
190 |
+
$renderer->drawBlock(
|
191 |
+
$leftPadding + $x * $multiple + $position[0] * $multiple,
|
192 |
+
$topPadding + $y * $multiple + $position[1] * $multiple,
|
193 |
+
'finder-outer'
|
194 |
+
);
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
if ($isInnerSet) {
|
199 |
+
foreach ($positions as $position) {
|
200 |
+
$renderer->drawBlock(
|
201 |
+
$leftPadding + $x * $multiple + $position[0] * $multiple,
|
202 |
+
$topPadding + $y * $multiple + $position[1] * $multiple,
|
203 |
+
'finder-inner'
|
204 |
+
);
|
205 |
+
}
|
206 |
+
}
|
207 |
+
}
|
208 |
+
}
|
209 |
+
}
|
210 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php
ADDED
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image;
|
11 |
+
|
12 |
+
use BaconQrCode\Renderer\Color\ColorInterface;
|
13 |
+
use BaconQrCode\Renderer\Color\Rgb;
|
14 |
+
use BaconQrCode\Renderer\Color\Cmyk;
|
15 |
+
use BaconQrCode\Renderer\Color\Gray;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* EPS backend.
|
19 |
+
*/
|
20 |
+
class Eps extends AbstractRenderer
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* EPS string.
|
24 |
+
*
|
25 |
+
* @var string
|
26 |
+
*/
|
27 |
+
protected $eps;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Colors used for drawing.
|
31 |
+
*
|
32 |
+
* @var array
|
33 |
+
*/
|
34 |
+
protected $colors = array();
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Current color.
|
38 |
+
*
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected $currentColor;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* init(): defined by RendererInterface.
|
45 |
+
*
|
46 |
+
* @see ImageRendererInterface::init()
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
+
public function init()
|
50 |
+
{
|
51 |
+
$this->eps = "%!PS-Adobe-3.0 EPSF-3.0\n"
|
52 |
+
. "%%BoundingBox: 0 0 " . $this->finalWidth . " " . $this->finalHeight . "\n"
|
53 |
+
. "/F { rectfill } def\n";
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* addColor(): defined by RendererInterface.
|
58 |
+
*
|
59 |
+
* @see ImageRendererInterface::addColor()
|
60 |
+
* @param string $id
|
61 |
+
* @param ColorInterface $color
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
+
public function addColor($id, ColorInterface $color)
|
65 |
+
{
|
66 |
+
if (
|
67 |
+
!$color instanceof Rgb
|
68 |
+
&& !$color instanceof Cmyk
|
69 |
+
&& !$color instanceof Gray
|
70 |
+
) {
|
71 |
+
$color = $color->toCmyk();
|
72 |
+
}
|
73 |
+
|
74 |
+
$this->colors[$id] = $color;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* drawBackground(): defined by RendererInterface.
|
79 |
+
*
|
80 |
+
* @see ImageRendererInterface::drawBackground()
|
81 |
+
* @param string $colorId
|
82 |
+
* @return void
|
83 |
+
*/
|
84 |
+
public function drawBackground($colorId)
|
85 |
+
{
|
86 |
+
$this->setColor($colorId);
|
87 |
+
$this->eps .= "0 0 " . $this->finalWidth . " " . $this->finalHeight . " F\n";
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* drawBlock(): defined by RendererInterface.
|
92 |
+
*
|
93 |
+
* @see ImageRendererInterface::drawBlock()
|
94 |
+
* @param integer $x
|
95 |
+
* @param integer $y
|
96 |
+
* @param string $colorId
|
97 |
+
* @return void
|
98 |
+
*/
|
99 |
+
public function drawBlock($x, $y, $colorId)
|
100 |
+
{
|
101 |
+
$this->setColor($colorId);
|
102 |
+
$this->eps .= $x . " " . ($this->finalHeight - $y - $this->blockSize) . " " . $this->blockSize . " " . $this->blockSize . " F\n";
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* getByteStream(): defined by RendererInterface.
|
107 |
+
*
|
108 |
+
* @see ImageRendererInterface::getByteStream()
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
public function getByteStream()
|
112 |
+
{
|
113 |
+
return $this->eps;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Sets color to use.
|
118 |
+
*
|
119 |
+
* @param string $colorId
|
120 |
+
* @return void
|
121 |
+
*/
|
122 |
+
protected function setColor($colorId)
|
123 |
+
{
|
124 |
+
if ($colorId !== $this->currentColor) {
|
125 |
+
$color = $this->colors[$colorId];
|
126 |
+
|
127 |
+
if ($color instanceof Rgb) {
|
128 |
+
$this->eps .= sprintf(
|
129 |
+
"%F %F %F setrgbcolor\n",
|
130 |
+
$color->getRed() / 100,
|
131 |
+
$color->getGreen() / 100,
|
132 |
+
$color->getBlue() / 100
|
133 |
+
);
|
134 |
+
} elseif ($color instanceof Cmyk) {
|
135 |
+
$this->eps .= sprintf(
|
136 |
+
"%F %F %F %F setcmykcolor\n",
|
137 |
+
$color->getCyan() / 100,
|
138 |
+
$color->getMagenta() / 100,
|
139 |
+
$color->getYellow() / 100,
|
140 |
+
$color->getBlack() / 100
|
141 |
+
);
|
142 |
+
} elseif ($color instanceof Gray) {
|
143 |
+
$this->eps .= sprintf(
|
144 |
+
"%F setgray\n",
|
145 |
+
$color->getGray() / 100
|
146 |
+
);
|
147 |
+
}
|
148 |
+
|
149 |
+
$this->currentColor = $colorId;
|
150 |
+
}
|
151 |
+
}
|
152 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
use BaconQrCode\Renderer\Color\ColorInterface;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* PNG backend.
|
17 |
+
*/
|
18 |
+
class Png extends AbstractRenderer
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Image resource used when drawing.
|
22 |
+
*
|
23 |
+
* @var resource
|
24 |
+
*/
|
25 |
+
protected $image;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Colors used for drawing.
|
29 |
+
*
|
30 |
+
* @var array
|
31 |
+
*/
|
32 |
+
protected $colors = array();
|
33 |
+
|
34 |
+
/**
|
35 |
+
* init(): defined by RendererInterface.
|
36 |
+
*
|
37 |
+
* @see ImageRendererInterface::init()
|
38 |
+
* @return void
|
39 |
+
*/
|
40 |
+
public function init()
|
41 |
+
{
|
42 |
+
$this->image = imagecreatetruecolor($this->finalWidth, $this->finalHeight);
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* addColor(): defined by RendererInterface.
|
47 |
+
*
|
48 |
+
* @see ImageRendererInterface::addColor()
|
49 |
+
* @param string $id
|
50 |
+
* @param ColorInterface $color
|
51 |
+
* @return void
|
52 |
+
* @throws Exception\RuntimeException
|
53 |
+
*/
|
54 |
+
public function addColor($id, ColorInterface $color)
|
55 |
+
{
|
56 |
+
if ($this->image === null) {
|
57 |
+
throw new Exception\RuntimeException('Colors can only be added after init');
|
58 |
+
}
|
59 |
+
|
60 |
+
$color = $color->toRgb();
|
61 |
+
|
62 |
+
$this->colors[$id] = imagecolorallocate(
|
63 |
+
$this->image,
|
64 |
+
$color->getRed(),
|
65 |
+
$color->getGreen(),
|
66 |
+
$color->getBlue()
|
67 |
+
);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* drawBackground(): defined by RendererInterface.
|
72 |
+
*
|
73 |
+
* @see ImageRendererInterface::drawBackground()
|
74 |
+
* @param string $colorId
|
75 |
+
* @return void
|
76 |
+
*/
|
77 |
+
public function drawBackground($colorId)
|
78 |
+
{
|
79 |
+
imagefill($this->image, 0, 0, $this->colors[$colorId]);
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* drawBlock(): defined by RendererInterface.
|
84 |
+
*
|
85 |
+
* @see ImageRendererInterface::drawBlock()
|
86 |
+
* @param integer $x
|
87 |
+
* @param integer $y
|
88 |
+
* @param string $colorId
|
89 |
+
* @return void
|
90 |
+
*/
|
91 |
+
public function drawBlock($x, $y, $colorId)
|
92 |
+
{
|
93 |
+
imagefilledrectangle(
|
94 |
+
$this->image,
|
95 |
+
$x,
|
96 |
+
$y,
|
97 |
+
$x + $this->blockSize - 1,
|
98 |
+
$y + $this->blockSize - 1,
|
99 |
+
$this->colors[$colorId]
|
100 |
+
);
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* getByteStream(): defined by RendererInterface.
|
105 |
+
*
|
106 |
+
* @see ImageRendererInterface::getByteStream()
|
107 |
+
* @return string
|
108 |
+
*/
|
109 |
+
public function getByteStream()
|
110 |
+
{
|
111 |
+
ob_start();
|
112 |
+
imagepng($this->image);
|
113 |
+
return ob_get_clean();
|
114 |
+
}
|
115 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image;
|
11 |
+
|
12 |
+
use BaconQrCode\Renderer\Color\ColorInterface;
|
13 |
+
use BaconQrCode\Renderer\RendererInterface as GeneralRendererInterface;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Renderer interface.
|
17 |
+
*/
|
18 |
+
interface RendererInterface extends GeneralRendererInterface
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* Initiates the drawing area.
|
22 |
+
*
|
23 |
+
* @return void
|
24 |
+
*/
|
25 |
+
public function init();
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Adds a color to the drawing area.
|
29 |
+
*
|
30 |
+
* @param string $id
|
31 |
+
* @param ColorInterface $color
|
32 |
+
* @return void
|
33 |
+
*/
|
34 |
+
public function addColor($id, ColorInterface $color);
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Draws the background.
|
38 |
+
*
|
39 |
+
* @param string $colorId
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
public function drawBackground($colorId);
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Draws a block at a specified position.
|
46 |
+
*
|
47 |
+
* @param integer $x
|
48 |
+
* @param integer $y
|
49 |
+
* @param string $colorId
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
+
public function drawBlock($x, $y, $colorId);
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Returns the byte stream representing the QR code.
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function getByteStream();
|
60 |
+
|
61 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Image;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
use BaconQrCode\Renderer\Color\ColorInterface;
|
14 |
+
use SimpleXMLElement;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* SVG backend.
|
18 |
+
*/
|
19 |
+
class Svg extends AbstractRenderer
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* SVG resource.
|
23 |
+
*
|
24 |
+
* @var SimpleXMLElement
|
25 |
+
*/
|
26 |
+
protected $svg;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Colors used for drawing.
|
30 |
+
*
|
31 |
+
* @var array
|
32 |
+
*/
|
33 |
+
protected $colors = array();
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Prototype IDs.
|
37 |
+
*
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
protected $prototypeIds = array();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* init(): defined by RendererInterface.
|
44 |
+
*
|
45 |
+
* @see ImageRendererInterface::init()
|
46 |
+
* @return void
|
47 |
+
*/
|
48 |
+
public function init()
|
49 |
+
{
|
50 |
+
$this->svg = new SimpleXMLElement(
|
51 |
+
'<?xml version="1.0" encoding="UTF-8"?>'
|
52 |
+
. '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"/>'
|
53 |
+
);
|
54 |
+
$this->svg->addAttribute('version', '1.1');
|
55 |
+
$this->svg->addAttribute('width', $this->finalWidth . 'px');
|
56 |
+
$this->svg->addAttribute('height', $this->finalHeight . 'px');
|
57 |
+
$this->svg->addAttribute('viewBox', '0 0 ' . $this->finalWidth . ' ' . $this->finalHeight);
|
58 |
+
$this->svg->addChild('defs');
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* addColor(): defined by RendererInterface.
|
63 |
+
*
|
64 |
+
* @see ImageRendererInterface::addColor()
|
65 |
+
* @param string $id
|
66 |
+
* @param ColorInterface $color
|
67 |
+
* @return void
|
68 |
+
* @throws Exception\InvalidArgumentException
|
69 |
+
*/
|
70 |
+
public function addColor($id, ColorInterface $color)
|
71 |
+
{
|
72 |
+
$this->colors[$id] = (string) $color->toRgb();
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* drawBackground(): defined by RendererInterface.
|
77 |
+
*
|
78 |
+
* @see ImageRendererInterface::drawBackground()
|
79 |
+
* @param string $colorId
|
80 |
+
* @return void
|
81 |
+
*/
|
82 |
+
public function drawBackground($colorId)
|
83 |
+
{
|
84 |
+
$rect = $this->svg->addChild('rect');
|
85 |
+
$rect->addAttribute('x', 0);
|
86 |
+
$rect->addAttribute('y', 0);
|
87 |
+
$rect->addAttribute('width', $this->finalWidth);
|
88 |
+
$rect->addAttribute('height', $this->finalHeight);
|
89 |
+
$rect->addAttribute('fill', '#' . $this->colors[$colorId]);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* drawBlock(): defined by RendererInterface.
|
94 |
+
*
|
95 |
+
* @see ImageRendererInterface::drawBlock()
|
96 |
+
* @param integer $x
|
97 |
+
* @param integer $y
|
98 |
+
* @param string $colorId
|
99 |
+
* @return void
|
100 |
+
*/
|
101 |
+
public function drawBlock($x, $y, $colorId)
|
102 |
+
{
|
103 |
+
$use = $this->svg->addChild('use');
|
104 |
+
$use->addAttribute('x', $x);
|
105 |
+
$use->addAttribute('y', $y);
|
106 |
+
$use->addAttribute(
|
107 |
+
'xlink:href',
|
108 |
+
$this->getRectPrototypeId($colorId),
|
109 |
+
'http://www.w3.org/1999/xlink'
|
110 |
+
);
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* getByteStream(): defined by RendererInterface.
|
115 |
+
*
|
116 |
+
* @see ImageRendererInterface::getByteStream()
|
117 |
+
* @return string
|
118 |
+
*/
|
119 |
+
public function getByteStream()
|
120 |
+
{
|
121 |
+
return $this->svg->asXML();
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Get the prototype ID for a color.
|
126 |
+
*
|
127 |
+
* @param integer $colorId
|
128 |
+
* @return string
|
129 |
+
*/
|
130 |
+
protected function getRectPrototypeId($colorId)
|
131 |
+
{
|
132 |
+
if (!isset($this->prototypeIds[$colorId])) {
|
133 |
+
$id = 'r' . dechex(count($this->prototypeIds));
|
134 |
+
|
135 |
+
$rect = $this->svg->defs->addChild('rect');
|
136 |
+
$rect->addAttribute('id', $id);
|
137 |
+
$rect->addAttribute('width', $this->blockSize);
|
138 |
+
$rect->addAttribute('height', $this->blockSize);
|
139 |
+
$rect->addAttribute('fill', '#' . $this->colors[$colorId]);
|
140 |
+
|
141 |
+
$this->prototypeIds[$colorId] = '#' . $id;
|
142 |
+
}
|
143 |
+
|
144 |
+
return $this->prototypeIds[$colorId];
|
145 |
+
}
|
146 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer;
|
11 |
+
|
12 |
+
use BaconQrCode\Encoder\QrCode;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Renderer interface.
|
16 |
+
*/
|
17 |
+
interface RendererInterface
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Renders a QR code.
|
21 |
+
*
|
22 |
+
* @param QrCode $qrCode
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
+
public function render(QrCode $qrCode);
|
26 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Text;
|
11 |
+
|
12 |
+
use BaconQrCode\Encoder\QrCode;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Html renderer.
|
16 |
+
*/
|
17 |
+
class Html extends Plain
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* HTML CSS class attribute value.
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected $class = '';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* HTML CSS style definition for the code element.
|
28 |
+
*
|
29 |
+
* @var string
|
30 |
+
*/
|
31 |
+
protected $style = 'font-family: monospace; line-height: 0.65em; letter-spacing: -1px';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Set CSS class name.
|
35 |
+
*
|
36 |
+
* @param string $class
|
37 |
+
*/
|
38 |
+
public function setClass($class)
|
39 |
+
{
|
40 |
+
$this->class = $class;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Get CSS class name.
|
45 |
+
*
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
+
public function getClass()
|
49 |
+
{
|
50 |
+
return $this->class;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Set CSS style value.
|
55 |
+
*
|
56 |
+
* @param string $style
|
57 |
+
*/
|
58 |
+
public function setStyle($style)
|
59 |
+
{
|
60 |
+
$this->style = $style;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Get CSS style value.
|
65 |
+
*
|
66 |
+
* @return string
|
67 |
+
*/
|
68 |
+
public function getStyle()
|
69 |
+
{
|
70 |
+
return $this->style;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* render(): defined by RendererInterface.
|
75 |
+
*
|
76 |
+
* @see RendererInterface::render()
|
77 |
+
* @param QrCode $qrCode
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public function render(QrCode $qrCode)
|
81 |
+
{
|
82 |
+
$textCode = parent::render($qrCode);
|
83 |
+
|
84 |
+
$result = '<pre'
|
85 |
+
. ' style="' . htmlspecialchars($this->style, ENT_QUOTES, 'utf-8') . '"'
|
86 |
+
. ' class="' . htmlspecialchars($this->class, ENT_QUOTES, 'utf-8') . '"'
|
87 |
+
. '>' . $textCode . '</pre>';
|
88 |
+
|
89 |
+
return $result;
|
90 |
+
}
|
91 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode\Renderer\Text;
|
11 |
+
|
12 |
+
use BaconQrCode\Exception;
|
13 |
+
use BaconQrCode\Encoder\QrCode;
|
14 |
+
use BaconQrCode\Renderer\RendererInterface;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Plaintext renderer.
|
18 |
+
*/
|
19 |
+
class Plain implements RendererInterface
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* Margin around the QR code, also known as quiet zone.
|
23 |
+
*
|
24 |
+
* @var integer
|
25 |
+
*/
|
26 |
+
protected $margin = 1;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Char used for full block.
|
30 |
+
*
|
31 |
+
* UTF-8 FULL BLOCK (U+2588)
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
* @link http://www.fileformat.info/info/unicode/char/2588/index.htm
|
35 |
+
*/
|
36 |
+
protected $fullBlock = "\xE2\x96\x88";
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Char used for empty space
|
40 |
+
*
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
protected $emptyBlock = ' ';
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Set char used as full block (occupied space, "black").
|
47 |
+
*
|
48 |
+
* @param string $fullBlock
|
49 |
+
*/
|
50 |
+
public function setFullBlock($fullBlock)
|
51 |
+
{
|
52 |
+
$this->fullBlock = $fullBlock;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Get char used as full block (occupied space, "black").
|
57 |
+
*
|
58 |
+
* @return string
|
59 |
+
*/
|
60 |
+
public function getFullBlock()
|
61 |
+
{
|
62 |
+
return $this->fullBlock;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Set char used as empty block (empty space, "white").
|
67 |
+
*
|
68 |
+
* @param string $emptyBlock
|
69 |
+
*/
|
70 |
+
public function setEmptyBlock($emptyBlock)
|
71 |
+
{
|
72 |
+
$this->emptyBlock = $emptyBlock;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Get char used as empty block (empty space, "white").
|
77 |
+
*
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public function getEmptyBlock()
|
81 |
+
{
|
82 |
+
return $this->emptyBlock;
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Sets the margin around the QR code.
|
87 |
+
*
|
88 |
+
* @param integer $margin
|
89 |
+
* @return AbstractRenderer
|
90 |
+
* @throws Exception\InvalidArgumentException
|
91 |
+
*/
|
92 |
+
public function setMargin($margin)
|
93 |
+
{
|
94 |
+
if ($margin < 0) {
|
95 |
+
throw new Exception\InvalidArgumentException('Margin must be equal to greater than 0');
|
96 |
+
}
|
97 |
+
|
98 |
+
$this->margin = (int) $margin;
|
99 |
+
|
100 |
+
return $this;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Gets the margin around the QR code.
|
105 |
+
*
|
106 |
+
* @return integer
|
107 |
+
*/
|
108 |
+
public function getMargin()
|
109 |
+
{
|
110 |
+
return $this->margin;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* render(): defined by RendererInterface.
|
115 |
+
*
|
116 |
+
* @see RendererInterface::render()
|
117 |
+
* @param QrCode $qrCode
|
118 |
+
* @return string
|
119 |
+
*/
|
120 |
+
public function render(QrCode $qrCode)
|
121 |
+
{
|
122 |
+
$result = '';
|
123 |
+
$matrix = $qrCode->getMatrix();
|
124 |
+
$width = $matrix->getWidth();
|
125 |
+
|
126 |
+
// Top margin
|
127 |
+
for ($x = 0; $x < $this->margin; $x++) {
|
128 |
+
$result .= str_repeat($this->emptyBlock, $width + 2 * $this->margin)."\n";
|
129 |
+
}
|
130 |
+
|
131 |
+
// Body
|
132 |
+
$array = $matrix->getArray();
|
133 |
+
|
134 |
+
foreach ($array as $row) {
|
135 |
+
$result .= str_repeat($this->emptyBlock, $this->margin); // left margin
|
136 |
+
foreach ($row as $byte) {
|
137 |
+
$result .= $byte ? $this->fullBlock : $this->emptyBlock;
|
138 |
+
}
|
139 |
+
$result .= str_repeat($this->emptyBlock, $this->margin); // right margin
|
140 |
+
$result .= "\n";
|
141 |
+
}
|
142 |
+
|
143 |
+
// Bottom margin
|
144 |
+
for ($x = 0; $x < $this->margin; $x++) {
|
145 |
+
$result .= str_repeat($this->emptyBlock, $width + 2 * $this->margin)."\n";
|
146 |
+
}
|
147 |
+
|
148 |
+
return $result;
|
149 |
+
}
|
150 |
+
}
|
src/lib/vendor/bacon/bacon-qr-code/src/BaconQrCode/Writer.php
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* BaconQrCode
|
4 |
+
*
|
5 |
+
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
6 |
+
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
7 |
+
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace BaconQrCode;
|
11 |
+
|
12 |
+
use BaconQrCode\Common\ErrorCorrectionLevel;
|
13 |
+
use BaconQrCode\Encoder\Encoder;
|
14 |
+
use BaconQrCode\Exception;
|
15 |
+
use BaconQrCode\Renderer\RendererInterface;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* QR code writer.
|
19 |
+
*/
|
20 |
+
class Writer
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* Renderer instance.
|
24 |
+
*
|
25 |
+
* @var RendererInterface
|
26 |
+
*/
|
27 |
+
protected $renderer;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Creates a new writer with a specific renderer.
|
31 |
+
*
|
32 |
+
* @param RendererInterface $renderer
|
33 |
+
*/
|
34 |
+
public function __construct(RendererInterface $renderer)
|
35 |
+
{
|
36 |
+
$this->renderer = $renderer;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Sets the renderer used to create a byte stream.
|
41 |
+
*
|
42 |
+
* @param RendererInterface $renderer
|
43 |
+
* @return Writer
|
44 |
+
*/
|
45 |
+
public function setRenderer(RendererInterface $renderer)
|
46 |
+
{
|
47 |
+
$this->renderer = $renderer;
|
48 |
+
return $this;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Gets the renderer used to create a byte stream.
|
53 |
+
*
|
54 |
+
* @return RendererInterface
|
55 |
+
*/
|
56 |
+
public function getRenderer()
|
57 |
+
{
|
58 |
+
return $this->renderer;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Writes QR code and returns it as string.
|
63 |
+
*
|
64 |
+
* Content is a string which *should* be encoded in UTF-8, in case there are
|
65 |
+
* non ASCII-characters present.
|
66 |
+
*
|
67 |
+
* @param string $content
|
68 |
+
* @param string $encoding
|
69 |
+
* @param integer $ecLevel
|
70 |
+
* @return string
|
71 |
+
* @throws Exception\InvalidArgumentException
|
72 |
+
*/
|
73 |
+
public function writeString(
|
74 |
+
$content,
|
75 |
+
$encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
|
76 |
+
$ecLevel = ErrorCorrectionLevel::L
|
77 |
+
) {
|
78 |
+
if (strlen($content) === 0) {
|
79 |
+
throw new Exception\InvalidArgumentException('Found empty contents');
|
80 |
+
}
|
81 |
+
|
82 |
+
$qrCode = Encoder::encode($content, new ErrorCorrectionLevel($ecLevel), $encoding);
|
83 |
+
|
84 |
+
return $this->getRenderer()->render($qrCode);
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Writes QR code to a file.
|
89 |
+
*
|
90 |
+
* @see Writer::writeString()
|
91 |
+
* @param string $content
|
92 |
+
* @param string $filename
|
93 |
+
* @param string $encoding
|
94 |
+
* @param integer $ecLevel
|
95 |
+
* @return void
|
96 |
+
*/
|
97 |
+
public function writeFile(
|
98 |
+
$content,
|
99 |
+
$filename,
|
100 |
+
$encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
|
101 |
+
$ecLevel = ErrorCorrectionLevel::L
|
102 |
+
) {
|
103 |
+
file_put_contents($filename, $this->writeString($content, $encoding, $ecLevel));
|
104 |
+
}
|
105 |
+
}
|
src/lib/vendor/composer/autoload_classmap.php
CHANGED
@@ -6,6 +6,45 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
'Base32\\Base32' => $vendorDir . '/christian-riesen/base32/src/Base32.php',
|
10 |
'Carbon\\Carbon' => $vendorDir . '/nesbot/carbon/src/Carbon/Carbon.php',
|
11 |
'Carbon\\CarbonInterval' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
|
@@ -23,11 +62,40 @@ return array(
|
|
23 |
'Dolondro\\GoogleAuthenticator\\SecretFactory' => $vendorDir . '/dolondro/google-authenticator/src/SecretFactory.php',
|
24 |
'Elliotchance\\Iterator\\AbstractPagedIterator' => $vendorDir . '/elliotchance/iterator/src/Elliotchance/Iterator/AbstractPagedIterator.php',
|
25 |
'Elliotchance\\Iterator\\PagedIteratorTest' => $vendorDir . '/elliotchance/iterator/tests/Elliotchance/Iterator/PagedIteratorTest.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynProperties' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/DynProperties.php',
|
27 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynPropertiesClass' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/DynPropertiesClass.php',
|
28 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynamicProperties' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/DynamicProperties.php',
|
29 |
'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
|
30 |
'FernleafSystems\\Utilities\\Data\\CaptureOutput' => $vendorDir . '/fernleafsystems/utilities/src/Data/CaptureOutput.php',
|
|
|
31 |
'FernleafSystems\\Utilities\\Logic\\ExecOnce' => $vendorDir . '/fernleafsystems/utilities/src/Logic/ExecOnce.php',
|
32 |
'FernleafSystems\\Utilities\\Logic\\OneTimeExecute' => $vendorDir . '/fernleafsystems/utilities/src/Logic/OneTimeExecute.php',
|
33 |
'FernleafSystems\\Utilities\\Response' => $vendorDir . '/fernleafsystems/utilities/src/Response.php',
|
@@ -63,6 +131,7 @@ return array(
|
|
63 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Ajax\\Response' => $baseDir . '/src/Controller/Ajax/Response.php',
|
64 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Enqueue' => $baseDir . '/src/Controller/Assets/Enqueue.php',
|
65 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Paths' => $baseDir . '/src/Controller/Assets/Paths.php',
|
|
|
66 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Urls' => $baseDir . '/src/Controller/Assets/Urls.php',
|
67 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\ConfigVO' => $baseDir . '/src/Controller/Config/ConfigVO.php',
|
68 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\Ops\\LoadConfig' => $baseDir . '/src/Controller/Config/Ops/LoadConfig.php',
|
@@ -206,21 +275,33 @@ return array(
|
|
206 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Processor' => $baseDir . '/src/Modules/Autoupdates/Processor.php',
|
207 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Strings' => $baseDir . '/src/Modules/Autoupdates/Strings.php',
|
208 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\UI' => $baseDir . '/src/Modules/Autoupdates/UI.php',
|
|
|
209 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\AjaxHandler' => $baseDir . '/src/Modules/BaseShield/AjaxHandler.php',
|
210 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\ModCon' => $baseDir . '/src/Modules/BaseShield/ModCon.php',
|
211 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Options' => $baseDir . '/src/Modules/BaseShield/Options.php',
|
212 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Processor' => $baseDir . '/src/Modules/BaseShield/Processor.php',
|
213 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\UI' => $baseDir . '/src/Modules/BaseShield/UI.php',
|
214 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AdminNotices' => $baseDir . '/src/Modules/Base/AdminNotices.php',
|
|
|
215 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AjaxHandler' => $baseDir . '/src/Modules/Base/AjaxHandler.php',
|
|
|
216 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Debug' => $baseDir . '/src/Modules/Base/Debug.php',
|
217 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Insights\\OverviewCards' => $baseDir . '/src/Modules/Base/Insights/OverviewCards.php',
|
218 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Request\\FormParams' => $baseDir . '/src/Modules/Base/Lib/Request/FormParams.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\ModCon' => $baseDir . '/src/Modules/Base/ModCon.php',
|
220 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options' => $baseDir . '/src/Modules/Base/Options.php',
|
221 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options\\OptValueSanitize' => $baseDir . '/src/Modules/Base/Options/OptValueSanitize.php',
|
222 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Processor' => $baseDir . '/src/Modules/Base/Processor.php',
|
223 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Reporting' => $baseDir . '/src/Modules/Base/Reporting.php',
|
|
|
224 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Strings' => $baseDir . '/src/Modules/Base/Strings.php',
|
225 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\UI' => $baseDir . '/src/Modules/Base/UI.php',
|
226 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Upgrade' => $baseDir . '/src/Modules/Base/Upgrade.php',
|
@@ -408,14 +489,45 @@ return array(
|
|
408 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\BaseAddRemove' => $baseDir . '/src/Modules/IPs/WpCli/BaseAddRemove.php',
|
409 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Enumerate' => $baseDir . '/src/Modules/IPs/WpCli/Enumerate.php',
|
410 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => $baseDir . '/src/Modules/IPs/WpCli/Remove.php',
|
|
|
411 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => $baseDir . '/src/Modules/Insights/AjaxHandler.php',
|
412 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\OverviewCards' => $baseDir . '/src/Modules/Insights/Lib/OverviewCards.php',
|
413 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Requests\\DynamicPageLoader' => $baseDir . '/src/Modules/Insights/Lib/Requests/DynamicPageLoader.php',
|
414 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\SideMenuBuilder' => $baseDir . '/src/Modules/Insights/Lib/SideMenuBuilder.php',
|
|
|
415 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\ModCon' => $baseDir . '/src/Modules/Insights/ModCon.php',
|
416 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Options' => $baseDir . '/src/Modules/Insights/Options.php',
|
417 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Strings' => $baseDir . '/src/Modules/Insights/Strings.php',
|
418 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\UI' => $baseDir . '/src/Modules/Insights/UI.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
419 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\ApiActionInit' => $baseDir . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/ApiActionInit.php',
|
420 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Init' => $baseDir . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Init.php',
|
421 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Sync' => $baseDir . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Sync.php',
|
@@ -460,6 +572,8 @@ return array(
|
|
460 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Options' => $baseDir . '/src/Modules/Integrations/Options.php',
|
461 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Processor' => $baseDir . '/src/Modules/Integrations/Processor.php',
|
462 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Strings' => $baseDir . '/src/Modules/Integrations/Strings.php',
|
|
|
|
|
463 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AdminNotices' => $baseDir . '/src/Modules/License/AdminNotices.php',
|
464 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AjaxHandler' => $baseDir . '/src/Modules/License/AjaxHandler.php',
|
465 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\Lib\\LicenseEmails' => $baseDir . '/src/Modules/License/Lib/LicenseEmails.php',
|
@@ -510,11 +624,11 @@ return array(
|
|
510 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\LoginIntentPage' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php',
|
511 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaController' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php',
|
512 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaControllerConsumer' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaControllerConsumer.php',
|
|
|
513 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaSkip' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaSkip.php',
|
514 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Profiles\\
|
515 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\
|
516 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BaseProvider' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php',
|
517 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BaseProviderV2' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProviderV2.php',
|
518 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\Email' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Email.php',
|
519 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\GoogleAuth' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/GoogleAuth.php',
|
520 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\ProviderInterface' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/ProviderInterface.php',
|
@@ -604,8 +718,8 @@ return array(
|
|
604 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\Restrictions\\WpOptions' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/WpOptions.php',
|
605 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
|
606 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
|
607 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\ApplyLabels' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php',
|
608 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\BuildOptions' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php',
|
|
|
609 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => $baseDir . '/src/Modules/SecurityAdmin/ModCon.php',
|
610 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => $baseDir . '/src/Modules/SecurityAdmin/Options.php',
|
611 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => $baseDir . '/src/Modules/SecurityAdmin/Processor.php',
|
@@ -615,6 +729,7 @@ return array(
|
|
615 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminAdd' => $baseDir . '/src/Modules/SecurityAdmin/WpCli/AdminAdd.php',
|
616 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminRemove' => $baseDir . '/src/Modules/SecurityAdmin/WpCli/AdminRemove.php',
|
617 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\Pin' => $baseDir . '/src/Modules/SecurityAdmin/WpCli/Pin.php',
|
|
|
618 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\Ops\\Terminate' => $baseDir . '/src/Modules/Sessions/Lib/Ops/Terminate.php',
|
619 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\SessionController' => $baseDir . '/src/Modules/Sessions/Lib/SessionController.php',
|
620 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\ModCon' => $baseDir . '/src/Modules/Sessions/ModCon.php',
|
@@ -774,6 +889,10 @@ return array(
|
|
774 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\ScanWpv' => $baseDir . '/src/Tables/Build/ScanWpv.php',
|
775 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => $baseDir . '/src/Tables/Build/Sessions.php',
|
776 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Traffic' => $baseDir . '/src/Tables/Build/Traffic.php',
|
|
|
|
|
|
|
|
|
777 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpCliTable/AuditTrail.php',
|
778 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\Base' => $baseDir . '/src/Tables/Render/WpCliTable/Base.php',
|
779 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => $baseDir . '/src/Tables/Render/WpListTable/AdminNotes.php',
|
@@ -921,7 +1040,6 @@ return array(
|
|
921 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Base.php',
|
922 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
|
923 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
|
924 |
-
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Lookup.php',
|
925 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\BaseIP' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php',
|
926 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\FindSourceFromIp' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php',
|
927 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\IpID' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/IpID.php',
|
@@ -978,6 +1096,7 @@ return array(
|
|
978 |
'LZCompressor\\LZString' => $vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor/LZString.php',
|
979 |
'LZCompressor\\LZUtil' => $vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil.php',
|
980 |
'LZCompressor\\LZUtil16' => $vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil16.php',
|
|
|
981 |
'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php',
|
982 |
'Pimple\\Exception\\ExpectedInvokableException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php',
|
983 |
'Pimple\\Exception\\FrozenServiceException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php',
|
@@ -1003,6 +1122,7 @@ return array(
|
|
1003 |
'Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php',
|
1004 |
'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php',
|
1005 |
'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php',
|
|
|
1006 |
'Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php',
|
1007 |
'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
|
1008 |
'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
|
@@ -1058,6 +1178,36 @@ return array(
|
|
1058 |
'ReCaptcha\\RequestMethod\\SocketPost' => $vendorDir . '/google/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php',
|
1059 |
'ReCaptcha\\RequestParameters' => $vendorDir . '/google/recaptcha/src/ReCaptcha/RequestParameters.php',
|
1060 |
'ReCaptcha\\Response' => $vendorDir . '/google/recaptcha/src/ReCaptcha/Response.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1061 |
'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => $vendorDir . '/symfony/translation/Catalogue/AbstractOperation.php',
|
1062 |
'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => $vendorDir . '/symfony/translation/Catalogue/MergeOperation.php',
|
1063 |
'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => $vendorDir . '/symfony/translation/Catalogue/OperationInterface.php',
|
@@ -1527,6 +1677,64 @@ return array(
|
|
1527 |
'ZxcvbnPhp\\Scorer' => $vendorDir . '/fernleafsystems/zxcvbn-php/src/Scorer.php',
|
1528 |
'ZxcvbnPhp\\TimeEstimator' => $vendorDir . '/fernleafsystems/zxcvbn-php/src/TimeEstimator.php',
|
1529 |
'ZxcvbnPhp\\Zxcvbn' => $vendorDir . '/fernleafsystems/zxcvbn-php/src/Zxcvbn.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1530 |
'u2flib_server\\Error' => $baseDir . '/custom/U2F/Yubico/U2F.php',
|
1531 |
'u2flib_server\\RegisterRequest' => $baseDir . '/custom/U2F/Yubico/U2F.php',
|
1532 |
'u2flib_server\\Registration' => $baseDir . '/custom/U2F/Yubico/U2F.php',
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
+
'BaconQrCode\\Common\\AbstractEnum' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php',
|
10 |
+
'BaconQrCode\\Common\\BitArray' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php',
|
11 |
+
'BaconQrCode\\Common\\BitMatrix' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php',
|
12 |
+
'BaconQrCode\\Common\\BitUtils' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php',
|
13 |
+
'BaconQrCode\\Common\\CharacterSetEci' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php',
|
14 |
+
'BaconQrCode\\Common\\EcBlock' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php',
|
15 |
+
'BaconQrCode\\Common\\EcBlocks' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php',
|
16 |
+
'BaconQrCode\\Common\\ErrorCorrectionLevel' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php',
|
17 |
+
'BaconQrCode\\Common\\FormatInformation' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php',
|
18 |
+
'BaconQrCode\\Common\\Mode' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php',
|
19 |
+
'BaconQrCode\\Common\\ReedSolomonCodec' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php',
|
20 |
+
'BaconQrCode\\Common\\Version' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php',
|
21 |
+
'BaconQrCode\\Encoder\\BlockPair' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php',
|
22 |
+
'BaconQrCode\\Encoder\\ByteMatrix' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php',
|
23 |
+
'BaconQrCode\\Encoder\\Encoder' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php',
|
24 |
+
'BaconQrCode\\Encoder\\MaskUtil' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php',
|
25 |
+
'BaconQrCode\\Encoder\\MatrixUtil' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php',
|
26 |
+
'BaconQrCode\\Encoder\\QrCode' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php',
|
27 |
+
'BaconQrCode\\Exception\\ExceptionInterface' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php',
|
28 |
+
'BaconQrCode\\Exception\\InvalidArgumentException' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php',
|
29 |
+
'BaconQrCode\\Exception\\OutOfBoundsException' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php',
|
30 |
+
'BaconQrCode\\Exception\\RuntimeException' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php',
|
31 |
+
'BaconQrCode\\Exception\\UnexpectedValueException' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php',
|
32 |
+
'BaconQrCode\\Exception\\WriterException' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php',
|
33 |
+
'BaconQrCode\\Renderer\\Color\\Cmyk' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php',
|
34 |
+
'BaconQrCode\\Renderer\\Color\\ColorInterface' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php',
|
35 |
+
'BaconQrCode\\Renderer\\Color\\Gray' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php',
|
36 |
+
'BaconQrCode\\Renderer\\Color\\Rgb' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php',
|
37 |
+
'BaconQrCode\\Renderer\\Image\\AbstractRenderer' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php',
|
38 |
+
'BaconQrCode\\Renderer\\Image\\Decorator\\DecoratorInterface' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php',
|
39 |
+
'BaconQrCode\\Renderer\\Image\\Decorator\\FinderPattern' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php',
|
40 |
+
'BaconQrCode\\Renderer\\Image\\Eps' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php',
|
41 |
+
'BaconQrCode\\Renderer\\Image\\Png' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php',
|
42 |
+
'BaconQrCode\\Renderer\\Image\\RendererInterface' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php',
|
43 |
+
'BaconQrCode\\Renderer\\Image\\Svg' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php',
|
44 |
+
'BaconQrCode\\Renderer\\RendererInterface' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php',
|
45 |
+
'BaconQrCode\\Renderer\\Text\\Html' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php',
|
46 |
+
'BaconQrCode\\Renderer\\Text\\Plain' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php',
|
47 |
+
'BaconQrCode\\Writer' => $vendorDir . '/bacon/bacon-qr-code/src/BaconQrCode/Writer.php',
|
48 |
'Base32\\Base32' => $vendorDir . '/christian-riesen/base32/src/Base32.php',
|
49 |
'Carbon\\Carbon' => $vendorDir . '/nesbot/carbon/src/Carbon/Carbon.php',
|
50 |
'Carbon\\CarbonInterval' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
|
62 |
'Dolondro\\GoogleAuthenticator\\SecretFactory' => $vendorDir . '/dolondro/google-authenticator/src/SecretFactory.php',
|
63 |
'Elliotchance\\Iterator\\AbstractPagedIterator' => $vendorDir . '/elliotchance/iterator/src/Elliotchance/Iterator/AbstractPagedIterator.php',
|
64 |
'Elliotchance\\Iterator\\PagedIteratorTest' => $vendorDir . '/elliotchance/iterator/tests/Elliotchance/Iterator/PagedIteratorTest.php',
|
65 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\Controller\\QrCodeController' => $vendorDir . '/endroid/qr-code/src/Bundle/QrCodeBundle/Controller/QrCodeController.php',
|
66 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\DependencyInjection\\Compiler\\WriterRegistryCompilerPass' => $vendorDir . '/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Compiler/WriterRegistryCompilerPass.php',
|
67 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\DependencyInjection\\Configuration' => $vendorDir . '/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Configuration.php',
|
68 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\DependencyInjection\\EndroidQrCodeExtension' => $vendorDir . '/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/EndroidQrCodeExtension.php',
|
69 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\EndroidQrCodeBundle' => $vendorDir . '/endroid/qr-code/src/Bundle/QrCodeBundle/EndroidQrCodeBundle.php',
|
70 |
+
'Endroid\\QrCode\\ErrorCorrectionLevel' => $vendorDir . '/endroid/qr-code/src/ErrorCorrectionLevel.php',
|
71 |
+
'Endroid\\QrCode\\Exception\\InvalidPathException' => $vendorDir . '/endroid/qr-code/src/Exception/InvalidPathException.php',
|
72 |
+
'Endroid\\QrCode\\Exception\\InvalidWriterException' => $vendorDir . '/endroid/qr-code/src/Exception/InvalidWriterException.php',
|
73 |
+
'Endroid\\QrCode\\Exception\\MissingFunctionException' => $vendorDir . '/endroid/qr-code/src/Exception/MissingFunctionException.php',
|
74 |
+
'Endroid\\QrCode\\Exception\\QrCodeException' => $vendorDir . '/endroid/qr-code/src/Exception/QrCodeException.php',
|
75 |
+
'Endroid\\QrCode\\Exception\\UnsupportedExtensionException' => $vendorDir . '/endroid/qr-code/src/Exception/UnsupportedExtensionException.php',
|
76 |
+
'Endroid\\QrCode\\Exception\\ValidationException' => $vendorDir . '/endroid/qr-code/src/Exception/ValidationException.php',
|
77 |
+
'Endroid\\QrCode\\Factory\\QrCodeFactory' => $vendorDir . '/endroid/qr-code/src/Factory/QrCodeFactory.php',
|
78 |
+
'Endroid\\QrCode\\LabelAlignment' => $vendorDir . '/endroid/qr-code/src/LabelAlignment.php',
|
79 |
+
'Endroid\\QrCode\\QrCode' => $vendorDir . '/endroid/qr-code/src/QrCode.php',
|
80 |
+
'Endroid\\QrCode\\QrCodeInterface' => $vendorDir . '/endroid/qr-code/src/QrCodeInterface.php',
|
81 |
+
'Endroid\\QrCode\\StaticWriterRegistry' => $vendorDir . '/endroid/qr-code/src/StaticWriterRegistry.php',
|
82 |
+
'Endroid\\QrCode\\Twig\\Extension\\QrCodeExtension' => $vendorDir . '/endroid/qr-code/src/Twig/Extension/QrCodeExtension.php',
|
83 |
+
'Endroid\\QrCode\\WriterRegistry' => $vendorDir . '/endroid/qr-code/src/WriterRegistry.php',
|
84 |
+
'Endroid\\QrCode\\WriterRegistryInterface' => $vendorDir . '/endroid/qr-code/src/WriterRegistryInterface.php',
|
85 |
+
'Endroid\\QrCode\\Writer\\AbstractBaconWriter' => $vendorDir . '/endroid/qr-code/src/Writer/AbstractBaconWriter.php',
|
86 |
+
'Endroid\\QrCode\\Writer\\AbstractWriter' => $vendorDir . '/endroid/qr-code/src/Writer/AbstractWriter.php',
|
87 |
+
'Endroid\\QrCode\\Writer\\BinaryWriter' => $vendorDir . '/endroid/qr-code/src/Writer/BinaryWriter.php',
|
88 |
+
'Endroid\\QrCode\\Writer\\DebugWriter' => $vendorDir . '/endroid/qr-code/src/Writer/DebugWriter.php',
|
89 |
+
'Endroid\\QrCode\\Writer\\EpsWriter' => $vendorDir . '/endroid/qr-code/src/Writer/EpsWriter.php',
|
90 |
+
'Endroid\\QrCode\\Writer\\PngWriter' => $vendorDir . '/endroid/qr-code/src/Writer/PngWriter.php',
|
91 |
+
'Endroid\\QrCode\\Writer\\SvgWriter' => $vendorDir . '/endroid/qr-code/src/Writer/SvgWriter.php',
|
92 |
+
'Endroid\\QrCode\\Writer\\WriterInterface' => $vendorDir . '/endroid/qr-code/src/Writer/WriterInterface.php',
|
93 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynProperties' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/DynProperties.php',
|
94 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynPropertiesClass' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/DynPropertiesClass.php',
|
95 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynamicProperties' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/DynamicProperties.php',
|
96 |
'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
|
97 |
'FernleafSystems\\Utilities\\Data\\CaptureOutput' => $vendorDir . '/fernleafsystems/utilities/src/Data/CaptureOutput.php',
|
98 |
+
'FernleafSystems\\Utilities\\Data\\Response\\StdResponse' => $vendorDir . '/fernleafsystems/utilities/src/Data/Response/StdResponse.php',
|
99 |
'FernleafSystems\\Utilities\\Logic\\ExecOnce' => $vendorDir . '/fernleafsystems/utilities/src/Logic/ExecOnce.php',
|
100 |
'FernleafSystems\\Utilities\\Logic\\OneTimeExecute' => $vendorDir . '/fernleafsystems/utilities/src/Logic/OneTimeExecute.php',
|
101 |
'FernleafSystems\\Utilities\\Response' => $vendorDir . '/fernleafsystems/utilities/src/Response.php',
|
131 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Ajax\\Response' => $baseDir . '/src/Controller/Ajax/Response.php',
|
132 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Enqueue' => $baseDir . '/src/Controller/Assets/Enqueue.php',
|
133 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Paths' => $baseDir . '/src/Controller/Assets/Paths.php',
|
134 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Svgs' => $baseDir . '/src/Controller/Assets/Svgs.php',
|
135 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Urls' => $baseDir . '/src/Controller/Assets/Urls.php',
|
136 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\ConfigVO' => $baseDir . '/src/Controller/Config/ConfigVO.php',
|
137 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\Ops\\LoadConfig' => $baseDir . '/src/Controller/Config/Ops/LoadConfig.php',
|
275 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Processor' => $baseDir . '/src/Modules/Autoupdates/Processor.php',
|
276 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Strings' => $baseDir . '/src/Modules/Autoupdates/Strings.php',
|
277 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\UI' => $baseDir . '/src/Modules/Autoupdates/UI.php',
|
278 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\AdminPage' => $baseDir . '/src/Modules/BaseShield/AdminPage.php',
|
279 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\AjaxHandler' => $baseDir . '/src/Modules/BaseShield/AjaxHandler.php',
|
280 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\ModCon' => $baseDir . '/src/Modules/BaseShield/ModCon.php',
|
281 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Options' => $baseDir . '/src/Modules/BaseShield/Options.php',
|
282 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Processor' => $baseDir . '/src/Modules/BaseShield/Processor.php',
|
283 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\UI' => $baseDir . '/src/Modules/BaseShield/UI.php',
|
284 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AdminNotices' => $baseDir . '/src/Modules/Base/AdminNotices.php',
|
285 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AdminPage' => $baseDir . '/src/Modules/Base/AdminPage.php',
|
286 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AjaxHandler' => $baseDir . '/src/Modules/Base/AjaxHandler.php',
|
287 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Common\\ExecOnceModConsumer' => $baseDir . '/src/Modules/Base/Common/ExecOnceModConsumer.php',
|
288 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Debug' => $baseDir . '/src/Modules/Base/Debug.php',
|
289 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Insights\\OverviewCards' => $baseDir . '/src/Modules/Base/Insights/OverviewCards.php',
|
290 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Request\\FormParams' => $baseDir . '/src/Modules/Base/Lib/Request/FormParams.php',
|
291 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\RequestVoConsumer' => $baseDir . '/src/Modules/Base/Lib/Rest/RequestVoConsumer.php',
|
292 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Request\\Process' => $baseDir . '/src/Modules/Base/Lib/Rest/Request/Process.php',
|
293 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Request\\RequestVO' => $baseDir . '/src/Modules/Base/Lib/Rest/Request/RequestVO.php',
|
294 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Route\\RestRouteConsumer' => $baseDir . '/src/Modules/Base/Lib/Rest/Route/RestRouteConsumer.php',
|
295 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Route\\RouteBase' => $baseDir . '/src/Modules/Base/Lib/Rest/Route/RouteBase.php',
|
296 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Route\\RouteCache' => $baseDir . '/src/Modules/Base/Lib/Rest/Route/RouteCache.php',
|
297 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Utility\\PreChecks' => $baseDir . '/src/Modules/Base/Lib/Rest/Utility/PreChecks.php',
|
298 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Utility\\RestLocker' => $baseDir . '/src/Modules/Base/Lib/Rest/Utility/RestLocker.php',
|
299 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\ModCon' => $baseDir . '/src/Modules/Base/ModCon.php',
|
300 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options' => $baseDir . '/src/Modules/Base/Options.php',
|
301 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options\\OptValueSanitize' => $baseDir . '/src/Modules/Base/Options/OptValueSanitize.php',
|
302 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Processor' => $baseDir . '/src/Modules/Base/Processor.php',
|
303 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Reporting' => $baseDir . '/src/Modules/Base/Reporting.php',
|
304 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\RestHandler' => $baseDir . '/src/Modules/Base/RestHandler.php',
|
305 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Strings' => $baseDir . '/src/Modules/Base/Strings.php',
|
306 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\UI' => $baseDir . '/src/Modules/Base/UI.php',
|
307 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Upgrade' => $baseDir . '/src/Modules/Base/Upgrade.php',
|
489 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\BaseAddRemove' => $baseDir . '/src/Modules/IPs/WpCli/BaseAddRemove.php',
|
490 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Enumerate' => $baseDir . '/src/Modules/IPs/WpCli/Enumerate.php',
|
491 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => $baseDir . '/src/Modules/IPs/WpCli/Remove.php',
|
492 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AdminPage' => $baseDir . '/src/Modules/Insights/AdminPage.php',
|
493 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => $baseDir . '/src/Modules/Insights/AjaxHandler.php',
|
494 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\OverviewCards' => $baseDir . '/src/Modules/Insights/Lib/OverviewCards.php',
|
495 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Requests\\DynamicPageLoader' => $baseDir . '/src/Modules/Insights/Lib/Requests/DynamicPageLoader.php',
|
496 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\SideMenuBuilder' => $baseDir . '/src/Modules/Insights/Lib/SideMenuBuilder.php',
|
497 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\SummaryCards' => $baseDir . '/src/Modules/Insights/Lib/SummaryCards.php',
|
498 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\ModCon' => $baseDir . '/src/Modules/Insights/ModCon.php',
|
499 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Options' => $baseDir . '/src/Modules/Insights/Options.php',
|
500 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Strings' => $baseDir . '/src/Modules/Insights/Strings.php',
|
501 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\UI' => $baseDir . '/src/Modules/Insights/UI.php',
|
502 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Common\\BaseBotDetectionController' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Common/BaseBotDetectionController.php',
|
503 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Common\\BaseHandler' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Common/BaseHandler.php',
|
504 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Base' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Base.php',
|
505 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\ContactForm7' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ContactForm7.php',
|
506 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\ElementorPro' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ElementorPro.php',
|
507 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\FluentForms' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FluentForms.php',
|
508 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\FormidableForms' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FormidableForms.php',
|
509 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Forminator' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Forminator.php',
|
510 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\GravityForms' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/GravityForms.php',
|
511 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Groundhogg' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Groundhogg.php',
|
512 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Helpers\\NinjaForms_ShieldSpamAction' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Helpers/NinjaForms_ShieldSpamAction.php',
|
513 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\KaliForms' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/KaliForms.php',
|
514 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\NinjaForms' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/NinjaForms.php',
|
515 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\WPForms' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WPForms.php',
|
516 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\WpForo' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WpForo.php',
|
517 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\SpamController' => $baseDir . '/src/Modules/Integrations/Lib/Bots/Spam/SpamController.php',
|
518 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\Base' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Base.php',
|
519 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\Buddypress' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Buddypress.php',
|
520 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\EasyDigitalDownloads' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/EasyDigitalDownloads.php',
|
521 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\LearnPress' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LearnPress.php',
|
522 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\LifterLMS' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LifterLMS.php',
|
523 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\MemberPress' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/MemberPress.php',
|
524 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\PaidMemberSubscriptions' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/PaidMemberSubscriptions.php',
|
525 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\ProfileBuilder' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/ProfileBuilder.php',
|
526 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\UltimateMember' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/UltimateMember.php',
|
527 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\WPMembers' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WPMembers.php',
|
528 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\WooCommerce' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WooCommerce.php',
|
529 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\WordPress' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WordPress.php',
|
530 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\UserFormsController' => $baseDir . '/src/Modules/Integrations/Lib/Bots/UserForms/UserFormsController.php',
|
531 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\ApiActionInit' => $baseDir . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/ApiActionInit.php',
|
532 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Init' => $baseDir . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Init.php',
|
533 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Sync' => $baseDir . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Sync.php',
|
572 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Options' => $baseDir . '/src/Modules/Integrations/Options.php',
|
573 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Processor' => $baseDir . '/src/Modules/Integrations/Processor.php',
|
574 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Strings' => $baseDir . '/src/Modules/Integrations/Strings.php',
|
575 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\UI' => $baseDir . '/src/Modules/Integrations/UI.php',
|
576 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Upgrade' => $baseDir . '/src/Modules/Integrations/Upgrade.php',
|
577 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AdminNotices' => $baseDir . '/src/Modules/License/AdminNotices.php',
|
578 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AjaxHandler' => $baseDir . '/src/Modules/License/AjaxHandler.php',
|
579 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\Lib\\LicenseEmails' => $baseDir . '/src/Modules/License/Lib/LicenseEmails.php',
|
624 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\LoginIntentPage' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php',
|
625 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaController' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php',
|
626 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaControllerConsumer' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaControllerConsumer.php',
|
627 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaProfilesController' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaProfilesController.php',
|
628 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaSkip' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaSkip.php',
|
629 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Profiles\\RenderCustomForms' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/RenderCustomForms.php',
|
630 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BackupCodes' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BackupCodes.php',
|
631 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BaseProvider' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php',
|
|
|
632 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\Email' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Email.php',
|
633 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\GoogleAuth' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/GoogleAuth.php',
|
634 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\ProviderInterface' => $baseDir . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/ProviderInterface.php',
|
718 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\Restrictions\\WpOptions' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/WpOptions.php',
|
719 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
|
720 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => $baseDir . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
|
|
|
721 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\BuildOptions' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php',
|
722 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\WhitelabelController' => $baseDir . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/WhitelabelController.php',
|
723 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => $baseDir . '/src/Modules/SecurityAdmin/ModCon.php',
|
724 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => $baseDir . '/src/Modules/SecurityAdmin/Options.php',
|
725 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => $baseDir . '/src/Modules/SecurityAdmin/Processor.php',
|
729 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminAdd' => $baseDir . '/src/Modules/SecurityAdmin/WpCli/AdminAdd.php',
|
730 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminRemove' => $baseDir . '/src/Modules/SecurityAdmin/WpCli/AdminRemove.php',
|
731 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\Pin' => $baseDir . '/src/Modules/SecurityAdmin/WpCli/Pin.php',
|
732 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\Ops\\Retrieve' => $baseDir . '/src/Modules/Sessions/Lib/Ops/Retrieve.php',
|
733 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\Ops\\Terminate' => $baseDir . '/src/Modules/Sessions/Lib/Ops/Terminate.php',
|
734 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\SessionController' => $baseDir . '/src/Modules/Sessions/Lib/SessionController.php',
|
735 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\ModCon' => $baseDir . '/src/Modules/Sessions/ModCon.php',
|
889 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\ScanWpv' => $baseDir . '/src/Tables/Build/ScanWpv.php',
|
890 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => $baseDir . '/src/Tables/Build/Sessions.php',
|
891 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Traffic' => $baseDir . '/src/Tables/Build/Traffic.php',
|
892 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => $baseDir . '/src/Tables/Render/Common/BaseTable.php',
|
893 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\DataTable\\Base' => $baseDir . '/src/Tables/Render/DataTable/Base.php',
|
894 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\DataTable\\ScanBase' => $baseDir . '/src/Tables/Render/DataTable/ScanBase.php',
|
895 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\DataTable\\ScanWcf' => $baseDir . '/src/Tables/Render/DataTable/ScanWcf.php',
|
896 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => $baseDir . '/src/Tables/Render/WpCliTable/AuditTrail.php',
|
897 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\Base' => $baseDir . '/src/Tables/Render/WpCliTable/Base.php',
|
898 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => $baseDir . '/src/Tables/Render/WpListTable/AdminNotes.php',
|
1040 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Base' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Base.php',
|
1041 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
|
1042 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
|
|
|
1043 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\BaseIP' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php',
|
1044 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\FindSourceFromIp' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php',
|
1045 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\IpID' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/IpID.php',
|
1096 |
'LZCompressor\\LZString' => $vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor/LZString.php',
|
1097 |
'LZCompressor\\LZUtil' => $vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil.php',
|
1098 |
'LZCompressor\\LZUtil16' => $vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil16.php',
|
1099 |
+
'MyCLabs\\Enum\\Enum' => $vendorDir . '/myclabs/php-enum/src/Enum.php',
|
1100 |
'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php',
|
1101 |
'Pimple\\Exception\\ExpectedInvokableException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php',
|
1102 |
'Pimple\\Exception\\FrozenServiceException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php',
|
1122 |
'Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php',
|
1123 |
'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php',
|
1124 |
'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php',
|
1125 |
+
'QrReader' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/QrReader.php',
|
1126 |
'Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php',
|
1127 |
'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
|
1128 |
'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
|
1178 |
'ReCaptcha\\RequestMethod\\SocketPost' => $vendorDir . '/google/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php',
|
1179 |
'ReCaptcha\\RequestParameters' => $vendorDir . '/google/recaptcha/src/ReCaptcha/RequestParameters.php',
|
1180 |
'ReCaptcha\\Response' => $vendorDir . '/google/recaptcha/src/ReCaptcha/Response.php',
|
1181 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\AccessException' => $vendorDir . '/symfony/options-resolver/Exception/AccessException.php',
|
1182 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/options-resolver/Exception/ExceptionInterface.php',
|
1183 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/options-resolver/Exception/InvalidArgumentException.php',
|
1184 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException' => $vendorDir . '/symfony/options-resolver/Exception/InvalidOptionsException.php',
|
1185 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException' => $vendorDir . '/symfony/options-resolver/Exception/MissingOptionsException.php',
|
1186 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\NoSuchOptionException' => $vendorDir . '/symfony/options-resolver/Exception/NoSuchOptionException.php',
|
1187 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\OptionDefinitionException' => $vendorDir . '/symfony/options-resolver/Exception/OptionDefinitionException.php',
|
1188 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException' => $vendorDir . '/symfony/options-resolver/Exception/UndefinedOptionsException.php',
|
1189 |
+
'Symfony\\Component\\OptionsResolver\\Options' => $vendorDir . '/symfony/options-resolver/Options.php',
|
1190 |
+
'Symfony\\Component\\OptionsResolver\\OptionsResolver' => $vendorDir . '/symfony/options-resolver/OptionsResolver.php',
|
1191 |
+
'Symfony\\Component\\OptionsResolver\\OptionsResolverInterface' => $vendorDir . '/symfony/options-resolver/OptionsResolverInterface.php',
|
1192 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => $vendorDir . '/symfony/property-access/Exception/AccessException.php',
|
1193 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/property-access/Exception/ExceptionInterface.php',
|
1194 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/property-access/Exception/InvalidArgumentException.php',
|
1195 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => $vendorDir . '/symfony/property-access/Exception/InvalidPropertyPathException.php',
|
1196 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => $vendorDir . '/symfony/property-access/Exception/NoSuchIndexException.php',
|
1197 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => $vendorDir . '/symfony/property-access/Exception/NoSuchPropertyException.php',
|
1198 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/property-access/Exception/OutOfBoundsException.php',
|
1199 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => $vendorDir . '/symfony/property-access/Exception/RuntimeException.php',
|
1200 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/property-access/Exception/UnexpectedTypeException.php',
|
1201 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccess' => $vendorDir . '/symfony/property-access/PropertyAccess.php',
|
1202 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccessor' => $vendorDir . '/symfony/property-access/PropertyAccessor.php',
|
1203 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => $vendorDir . '/symfony/property-access/PropertyAccessorBuilder.php',
|
1204 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => $vendorDir . '/symfony/property-access/PropertyAccessorInterface.php',
|
1205 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPath' => $vendorDir . '/symfony/property-access/PropertyPath.php',
|
1206 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => $vendorDir . '/symfony/property-access/PropertyPathBuilder.php',
|
1207 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => $vendorDir . '/symfony/property-access/PropertyPathInterface.php',
|
1208 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => $vendorDir . '/symfony/property-access/PropertyPathIterator.php',
|
1209 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => $vendorDir . '/symfony/property-access/PropertyPathIteratorInterface.php',
|
1210 |
+
'Symfony\\Component\\PropertyAccess\\StringUtil' => $vendorDir . '/symfony/property-access/StringUtil.php',
|
1211 |
'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => $vendorDir . '/symfony/translation/Catalogue/AbstractOperation.php',
|
1212 |
'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => $vendorDir . '/symfony/translation/Catalogue/MergeOperation.php',
|
1213 |
'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => $vendorDir . '/symfony/translation/Catalogue/OperationInterface.php',
|
1677 |
'ZxcvbnPhp\\Scorer' => $vendorDir . '/fernleafsystems/zxcvbn-php/src/Scorer.php',
|
1678 |
'ZxcvbnPhp\\TimeEstimator' => $vendorDir . '/fernleafsystems/zxcvbn-php/src/TimeEstimator.php',
|
1679 |
'ZxcvbnPhp\\Zxcvbn' => $vendorDir . '/fernleafsystems/zxcvbn-php/src/Zxcvbn.php',
|
1680 |
+
'Zxing\\Binarizer' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/Binarizer.php',
|
1681 |
+
'Zxing\\BinaryBitmap' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/BinaryBitmap.php',
|
1682 |
+
'Zxing\\ChecksumException' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/ChecksumException.php',
|
1683 |
+
'Zxing\\Common\\BitArray' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/BitArray.php',
|
1684 |
+
'Zxing\\Common\\BitMatrix' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/BitMatrix.php',
|
1685 |
+
'Zxing\\Common\\BitSource' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/BitSource.php',
|
1686 |
+
'Zxing\\Common\\CharacterSetECI' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/CharacterSetEci.php',
|
1687 |
+
'Zxing\\Common\\CharacterSetEci\\AbstractEnum\\AbstractEnum' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/AbstractEnum.php',
|
1688 |
+
'Zxing\\Common\\DecoderResult' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/DecoderResult.php',
|
1689 |
+
'Zxing\\Common\\DefaultGridSampler' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/DefaultGridSampler.php',
|
1690 |
+
'Zxing\\Common\\DetectorResult' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/DetectorResult.php',
|
1691 |
+
'Zxing\\Common\\Detector\\MathUtils' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/detector/MathUtils.php',
|
1692 |
+
'Zxing\\Common\\Detector\\MonochromeRectangleDetector' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/detector/MonochromeRectangleDetector.php',
|
1693 |
+
'Zxing\\Common\\GlobalHistogramBinarizer' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/GlobalHistogramBinarizer.php',
|
1694 |
+
'Zxing\\Common\\GridSampler' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/GridSampler.php',
|
1695 |
+
'Zxing\\Common\\HybridBinarizer' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/HybridBinarizer.php',
|
1696 |
+
'Zxing\\Common\\PerspectiveTransform' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/PerspectiveTransform.php',
|
1697 |
+
'Zxing\\Common\\Reedsolomon\\GenericGF' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/GenericGF.php',
|
1698 |
+
'Zxing\\Common\\Reedsolomon\\GenericGFPoly' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/GenericGFPoly.php',
|
1699 |
+
'Zxing\\Common\\Reedsolomon\\ReedSolomonDecoder' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/ReedSolomonDecoder.php',
|
1700 |
+
'Zxing\\Common\\Reedsolomon\\ReedSolomonException' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/ReedSolomonException.php',
|
1701 |
+
'Zxing\\FormatException' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/FormatException.php',
|
1702 |
+
'Zxing\\GDLuminanceSource' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/GDLuminanceSource.php',
|
1703 |
+
'Zxing\\IMagickLuminanceSource' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/IMagickLuminanceSource.php',
|
1704 |
+
'Zxing\\LuminanceSource' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/LuminanceSource.php',
|
1705 |
+
'Zxing\\NotFoundException' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/NotFoundException.php',
|
1706 |
+
'Zxing\\PlanarYUVLuminanceSource' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/PlanarYUVLuminanceSource.php',
|
1707 |
+
'Zxing\\Qrcode\\Decoder\\BitMatrixParser' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/BitMatrixParser.php',
|
1708 |
+
'Zxing\\Qrcode\\Decoder\\DataBlock' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataBlock.php',
|
1709 |
+
'Zxing\\Qrcode\\Decoder\\DataMask' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1710 |
+
'Zxing\\Qrcode\\Decoder\\DataMask000' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1711 |
+
'Zxing\\Qrcode\\Decoder\\DataMask001' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1712 |
+
'Zxing\\Qrcode\\Decoder\\DataMask010' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1713 |
+
'Zxing\\Qrcode\\Decoder\\DataMask011' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1714 |
+
'Zxing\\Qrcode\\Decoder\\DataMask100' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1715 |
+
'Zxing\\Qrcode\\Decoder\\DataMask101' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1716 |
+
'Zxing\\Qrcode\\Decoder\\DataMask110' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1717 |
+
'Zxing\\Qrcode\\Decoder\\DataMask111' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1718 |
+
'Zxing\\Qrcode\\Decoder\\DecodedBitStreamParser' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DecodedBitStreamParser.php',
|
1719 |
+
'Zxing\\Qrcode\\Decoder\\Decoder' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Decoder.php',
|
1720 |
+
'Zxing\\Qrcode\\Decoder\\ECB' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Version.php',
|
1721 |
+
'Zxing\\Qrcode\\Decoder\\ECBlocks' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Version.php',
|
1722 |
+
'Zxing\\Qrcode\\Decoder\\ErrorCorrectionLevel' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/ErrorCorrectionLevel.php',
|
1723 |
+
'Zxing\\Qrcode\\Decoder\\FormatInformation' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/FormatInformation.php',
|
1724 |
+
'Zxing\\Qrcode\\Decoder\\Mode' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Mode.php',
|
1725 |
+
'Zxing\\Qrcode\\Decoder\\Version' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Version.php',
|
1726 |
+
'Zxing\\Qrcode\\Detector\\AlignmentPattern' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/AlignmentPattern.php',
|
1727 |
+
'Zxing\\Qrcode\\Detector\\AlignmentPatternFinder' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/AlignmentPatternFinder.php',
|
1728 |
+
'Zxing\\Qrcode\\Detector\\Detector' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/Detector.php',
|
1729 |
+
'Zxing\\Qrcode\\Detector\\FinderPattern' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/FinderPattern.php',
|
1730 |
+
'Zxing\\Qrcode\\Detector\\FinderPatternFinder' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/FinderPatternFinder.php',
|
1731 |
+
'Zxing\\Qrcode\\Detector\\FinderPatternInfo' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/FinderPatternInfo.php',
|
1732 |
+
'Zxing\\Qrcode\\QRCodeReader' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/QRCodeReader.php',
|
1733 |
+
'Zxing\\RGBLuminanceSource' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/RGBLuminanceSource.php',
|
1734 |
+
'Zxing\\Reader' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/Reader.php',
|
1735 |
+
'Zxing\\ReaderException' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/ReaderException.php',
|
1736 |
+
'Zxing\\Result' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/Result.php',
|
1737 |
+
'Zxing\\ResultPoint' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/ResultPoint.php',
|
1738 |
'u2flib_server\\Error' => $baseDir . '/custom/U2F/Yubico/U2F.php',
|
1739 |
'u2flib_server\\RegisterRequest' => $baseDir . '/custom/U2F/Yubico/U2F.php',
|
1740 |
'u2flib_server\\Registration' => $baseDir . '/custom/U2F/Yubico/U2F.php',
|
src/lib/vendor/composer/autoload_files.php
CHANGED
@@ -6,8 +6,9 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
-
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
10 |
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
|
|
|
|
11 |
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
12 |
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
|
13 |
'b14ca0bb4d408c293d6ea9b68f1b4abe' => $baseDir . '/functions/functions.php',
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
9 |
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
10 |
+
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
11 |
+
'626dcc41390ebdaa619faa02d99943b0' => $vendorDir . '/khanamiryan/qrcode-detector-decoder/lib/common/customFunctions.php',
|
12 |
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
13 |
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
|
14 |
'b14ca0bb4d408c293d6ea9b68f1b4abe' => $baseDir . '/functions/functions.php',
|
src/lib/vendor/composer/autoload_namespaces.php
CHANGED
@@ -9,5 +9,6 @@ return array(
|
|
9 |
'UpdateHelper\\' => array($vendorDir . '/kylekatarnls/update-helper/src'),
|
10 |
'Twig_' => array($vendorDir . '/twig/twig/lib'),
|
11 |
'Pimple' => array($vendorDir . '/pimple/pimple/src'),
|
|
|
12 |
'' => array($vendorDir . '/elliotchance/iterator/tests', $vendorDir . '/elliotchance/iterator/src'),
|
13 |
);
|
9 |
'UpdateHelper\\' => array($vendorDir . '/kylekatarnls/update-helper/src'),
|
10 |
'Twig_' => array($vendorDir . '/twig/twig/lib'),
|
11 |
'Pimple' => array($vendorDir . '/pimple/pimple/src'),
|
12 |
+
'BaconQrCode' => array($vendorDir . '/bacon/bacon-qr-code/src'),
|
13 |
'' => array($vendorDir . '/elliotchance/iterator/tests', $vendorDir . '/elliotchance/iterator/src'),
|
14 |
);
|
src/lib/vendor/composer/autoload_psr4.php
CHANGED
@@ -13,15 +13,19 @@ return array(
|
|
13 |
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
14 |
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
|
15 |
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
|
|
|
|
16 |
'ReCaptcha\\' => array($vendorDir . '/google/recaptcha/src/ReCaptcha'),
|
17 |
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
18 |
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
19 |
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
|
|
20 |
'LZCompressor\\' => array($vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor'),
|
21 |
'Html2Text\\' => array($vendorDir . '/soundasleep/html2text/src'),
|
22 |
'FernleafSystems\\Wordpress\\Services\\' => array($vendorDir . '/fernleafsystems/wordpress-services/src'),
|
23 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\' => array($baseDir . '/src'),
|
24 |
'FernleafSystems\\Utilities\\' => array($vendorDir . '/fernleafsystems/utilities/src'),
|
|
|
25 |
'Dolondro\\GoogleAuthenticator\\' => array($vendorDir . '/dolondro/google-authenticator/src'),
|
26 |
'Base32\\' => array($vendorDir . '/christian-riesen/base32/src'),
|
27 |
'' => array($vendorDir . '/nesbot/carbon/src'),
|
13 |
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
14 |
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
|
15 |
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
16 |
+
'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'),
|
17 |
+
'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'),
|
18 |
'ReCaptcha\\' => array($vendorDir . '/google/recaptcha/src/ReCaptcha'),
|
19 |
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
20 |
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
21 |
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
22 |
+
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
|
23 |
'LZCompressor\\' => array($vendorDir . '/nullpunkt/lz-string-php/src/LZCompressor'),
|
24 |
'Html2Text\\' => array($vendorDir . '/soundasleep/html2text/src'),
|
25 |
'FernleafSystems\\Wordpress\\Services\\' => array($vendorDir . '/fernleafsystems/wordpress-services/src'),
|
26 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\' => array($baseDir . '/src'),
|
27 |
'FernleafSystems\\Utilities\\' => array($vendorDir . '/fernleafsystems/utilities/src'),
|
28 |
+
'Endroid\\QrCode\\' => array($vendorDir . '/endroid/qr-code/src'),
|
29 |
'Dolondro\\GoogleAuthenticator\\' => array($vendorDir . '/dolondro/google-authenticator/src'),
|
30 |
'Base32\\' => array($vendorDir . '/christian-riesen/base32/src'),
|
31 |
'' => array($vendorDir . '/nesbot/carbon/src'),
|
src/lib/vendor/composer/autoload_static.php
CHANGED
@@ -7,8 +7,9 @@ namespace Composer\Autoload;
|
|
7 |
class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
8 |
{
|
9 |
public static $files = array (
|
10 |
-
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
11 |
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
|
|
|
|
12 |
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
13 |
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
|
14 |
'b14ca0bb4d408c293d6ea9b68f1b4abe' => __DIR__ . '/../..' . '/functions/functions.php',
|
@@ -30,6 +31,8 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
30 |
'Symfony\\Polyfill\\Ctype\\' => 23,
|
31 |
'Symfony\\Component\\Yaml\\' => 23,
|
32 |
'Symfony\\Component\\Translation\\' => 30,
|
|
|
|
|
33 |
),
|
34 |
'R' =>
|
35 |
array (
|
@@ -41,6 +44,10 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
41 |
'Psr\\Container\\' => 14,
|
42 |
'Psr\\Cache\\' => 10,
|
43 |
),
|
|
|
|
|
|
|
|
|
44 |
'L' =>
|
45 |
array (
|
46 |
'LZCompressor\\' => 13,
|
@@ -55,6 +62,10 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
55 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\' => 40,
|
56 |
'FernleafSystems\\Utilities\\' => 26,
|
57 |
),
|
|
|
|
|
|
|
|
|
58 |
'D' =>
|
59 |
array (
|
60 |
'Dolondro\\GoogleAuthenticator\\' => 29,
|
@@ -94,6 +105,14 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
94 |
array (
|
95 |
0 => __DIR__ . '/..' . '/symfony/translation',
|
96 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
'ReCaptcha\\' =>
|
98 |
array (
|
99 |
0 => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha',
|
@@ -110,6 +129,10 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
110 |
array (
|
111 |
0 => __DIR__ . '/..' . '/psr/cache/src',
|
112 |
),
|
|
|
|
|
|
|
|
|
113 |
'LZCompressor\\' =>
|
114 |
array (
|
115 |
0 => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor',
|
@@ -130,6 +153,10 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
130 |
array (
|
131 |
0 => __DIR__ . '/..' . '/fernleafsystems/utilities/src',
|
132 |
),
|
|
|
|
|
|
|
|
|
133 |
'Dolondro\\GoogleAuthenticator\\' =>
|
134 |
array (
|
135 |
0 => __DIR__ . '/..' . '/dolondro/google-authenticator/src',
|
@@ -166,6 +193,13 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
166 |
0 => __DIR__ . '/..' . '/pimple/pimple/src',
|
167 |
),
|
168 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
);
|
170 |
|
171 |
public static $fallbackDirsPsr0 = array (
|
@@ -174,6 +208,45 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
174 |
);
|
175 |
|
176 |
public static $classMap = array (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
'Base32\\Base32' => __DIR__ . '/..' . '/christian-riesen/base32/src/Base32.php',
|
178 |
'Carbon\\Carbon' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Carbon.php',
|
179 |
'Carbon\\CarbonInterval' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
|
@@ -191,11 +264,40 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
191 |
'Dolondro\\GoogleAuthenticator\\SecretFactory' => __DIR__ . '/..' . '/dolondro/google-authenticator/src/SecretFactory.php',
|
192 |
'Elliotchance\\Iterator\\AbstractPagedIterator' => __DIR__ . '/..' . '/elliotchance/iterator/src/Elliotchance/Iterator/AbstractPagedIterator.php',
|
193 |
'Elliotchance\\Iterator\\PagedIteratorTest' => __DIR__ . '/..' . '/elliotchance/iterator/tests/Elliotchance/Iterator/PagedIteratorTest.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynProperties' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/DynProperties.php',
|
195 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynPropertiesClass' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/DynPropertiesClass.php',
|
196 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynamicProperties' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/DynamicProperties.php',
|
197 |
'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
|
198 |
'FernleafSystems\\Utilities\\Data\\CaptureOutput' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/CaptureOutput.php',
|
|
|
199 |
'FernleafSystems\\Utilities\\Logic\\ExecOnce' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Logic/ExecOnce.php',
|
200 |
'FernleafSystems\\Utilities\\Logic\\OneTimeExecute' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Logic/OneTimeExecute.php',
|
201 |
'FernleafSystems\\Utilities\\Response' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Response.php',
|
@@ -231,6 +333,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
231 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Ajax\\Response' => __DIR__ . '/../..' . '/src/Controller/Ajax/Response.php',
|
232 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Enqueue' => __DIR__ . '/../..' . '/src/Controller/Assets/Enqueue.php',
|
233 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Paths' => __DIR__ . '/../..' . '/src/Controller/Assets/Paths.php',
|
|
|
234 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Urls' => __DIR__ . '/../..' . '/src/Controller/Assets/Urls.php',
|
235 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\ConfigVO' => __DIR__ . '/../..' . '/src/Controller/Config/ConfigVO.php',
|
236 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\Ops\\LoadConfig' => __DIR__ . '/../..' . '/src/Controller/Config/Ops/LoadConfig.php',
|
@@ -374,21 +477,33 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
374 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Processor' => __DIR__ . '/../..' . '/src/Modules/Autoupdates/Processor.php',
|
375 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Strings' => __DIR__ . '/../..' . '/src/Modules/Autoupdates/Strings.php',
|
376 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\UI' => __DIR__ . '/../..' . '/src/Modules/Autoupdates/UI.php',
|
|
|
377 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/BaseShield/AjaxHandler.php',
|
378 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\ModCon' => __DIR__ . '/../..' . '/src/Modules/BaseShield/ModCon.php',
|
379 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Options' => __DIR__ . '/../..' . '/src/Modules/BaseShield/Options.php',
|
380 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Processor' => __DIR__ . '/../..' . '/src/Modules/BaseShield/Processor.php',
|
381 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\UI' => __DIR__ . '/../..' . '/src/Modules/BaseShield/UI.php',
|
382 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AdminNotices' => __DIR__ . '/../..' . '/src/Modules/Base/AdminNotices.php',
|
|
|
383 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Base/AjaxHandler.php',
|
|
|
384 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Debug' => __DIR__ . '/../..' . '/src/Modules/Base/Debug.php',
|
385 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/Base/Insights/OverviewCards.php',
|
386 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Request\\FormParams' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Request/FormParams.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Base/ModCon.php',
|
388 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options' => __DIR__ . '/../..' . '/src/Modules/Base/Options.php',
|
389 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options\\OptValueSanitize' => __DIR__ . '/../..' . '/src/Modules/Base/Options/OptValueSanitize.php',
|
390 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Processor' => __DIR__ . '/../..' . '/src/Modules/Base/Processor.php',
|
391 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Reporting' => __DIR__ . '/../..' . '/src/Modules/Base/Reporting.php',
|
|
|
392 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Strings' => __DIR__ . '/../..' . '/src/Modules/Base/Strings.php',
|
393 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\UI' => __DIR__ . '/../..' . '/src/Modules/Base/UI.php',
|
394 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Upgrade' => __DIR__ . '/../..' . '/src/Modules/Base/Upgrade.php',
|
@@ -576,14 +691,45 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
576 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\BaseAddRemove' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/BaseAddRemove.php',
|
577 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Enumerate' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/Enumerate.php',
|
578 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/Remove.php',
|
|
|
579 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Insights/AjaxHandler.php',
|
580 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/OverviewCards.php',
|
581 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Requests\\DynamicPageLoader' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Requests/DynamicPageLoader.php',
|
582 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\SideMenuBuilder' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/SideMenuBuilder.php',
|
|
|
583 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Insights/ModCon.php',
|
584 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Options' => __DIR__ . '/../..' . '/src/Modules/Insights/Options.php',
|
585 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Strings' => __DIR__ . '/../..' . '/src/Modules/Insights/Strings.php',
|
586 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\UI' => __DIR__ . '/../..' . '/src/Modules/Insights/UI.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
587 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\ApiActionInit' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/ApiActionInit.php',
|
588 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Init' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Init.php',
|
589 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Sync' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Sync.php',
|
@@ -628,6 +774,8 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
628 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Options' => __DIR__ . '/../..' . '/src/Modules/Integrations/Options.php',
|
629 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Processor' => __DIR__ . '/../..' . '/src/Modules/Integrations/Processor.php',
|
630 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Strings' => __DIR__ . '/../..' . '/src/Modules/Integrations/Strings.php',
|
|
|
|
|
631 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AdminNotices' => __DIR__ . '/../..' . '/src/Modules/License/AdminNotices.php',
|
632 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/License/AjaxHandler.php',
|
633 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\Lib\\LicenseEmails' => __DIR__ . '/../..' . '/src/Modules/License/Lib/LicenseEmails.php',
|
@@ -678,11 +826,11 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
678 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\LoginIntentPage' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php',
|
679 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaController' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php',
|
680 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaControllerConsumer.php',
|
|
|
681 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaSkip' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaSkip.php',
|
682 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Profiles\\
|
683 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\
|
684 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BaseProvider' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php',
|
685 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BaseProviderV2' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProviderV2.php',
|
686 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\Email' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Email.php',
|
687 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\GoogleAuth' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/GoogleAuth.php',
|
688 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\ProviderInterface' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/ProviderInterface.php',
|
@@ -772,8 +920,8 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
772 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\Restrictions\\WpOptions' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/WpOptions.php',
|
773 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
|
774 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
|
775 |
-
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\ApplyLabels' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/ApplyLabels.php',
|
776 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\BuildOptions' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php',
|
|
|
777 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/ModCon.php',
|
778 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Options.php',
|
779 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Processor.php',
|
@@ -783,6 +931,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
783 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminAdd' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/WpCli/AdminAdd.php',
|
784 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminRemove' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/WpCli/AdminRemove.php',
|
785 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\Pin' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/WpCli/Pin.php',
|
|
|
786 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\Ops\\Terminate' => __DIR__ . '/../..' . '/src/Modules/Sessions/Lib/Ops/Terminate.php',
|
787 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\SessionController' => __DIR__ . '/../..' . '/src/Modules/Sessions/Lib/SessionController.php',
|
788 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Sessions/ModCon.php',
|
@@ -942,6 +1091,10 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
942 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\ScanWpv' => __DIR__ . '/../..' . '/src/Tables/Build/ScanWpv.php',
|
943 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Build/Sessions.php',
|
944 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Traffic' => __DIR__ . '/../..' . '/src/Tables/Build/Traffic.php',
|
|
|
|
|
|
|
|
|
945 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/AuditTrail.php',
|
946 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\Base' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/Base.php',
|
947 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/AdminNotes.php',
|
@@ -1089,7 +1242,6 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
1089 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Base.php',
|
1090 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
|
1091 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
|
1092 |
-
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Lookup.php',
|
1093 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\BaseIP' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php',
|
1094 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\FindSourceFromIp' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php',
|
1095 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\IpID' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/IpID.php',
|
@@ -1146,6 +1298,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
1146 |
'LZCompressor\\LZString' => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor/LZString.php',
|
1147 |
'LZCompressor\\LZUtil' => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil.php',
|
1148 |
'LZCompressor\\LZUtil16' => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil16.php',
|
|
|
1149 |
'Pimple\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Container.php',
|
1150 |
'Pimple\\Exception\\ExpectedInvokableException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php',
|
1151 |
'Pimple\\Exception\\FrozenServiceException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php',
|
@@ -1171,6 +1324,7 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
1171 |
'Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php',
|
1172 |
'Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php',
|
1173 |
'Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php',
|
|
|
1174 |
'Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php',
|
1175 |
'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
|
1176 |
'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
|
@@ -1226,6 +1380,36 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
1226 |
'ReCaptcha\\RequestMethod\\SocketPost' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php',
|
1227 |
'ReCaptcha\\RequestParameters' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/RequestParameters.php',
|
1228 |
'ReCaptcha\\Response' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/Response.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1229 |
'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/AbstractOperation.php',
|
1230 |
'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/MergeOperation.php',
|
1231 |
'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => __DIR__ . '/..' . '/symfony/translation/Catalogue/OperationInterface.php',
|
@@ -1695,6 +1879,64 @@ class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
|
1695 |
'ZxcvbnPhp\\Scorer' => __DIR__ . '/..' . '/fernleafsystems/zxcvbn-php/src/Scorer.php',
|
1696 |
'ZxcvbnPhp\\TimeEstimator' => __DIR__ . '/..' . '/fernleafsystems/zxcvbn-php/src/TimeEstimator.php',
|
1697 |
'ZxcvbnPhp\\Zxcvbn' => __DIR__ . '/..' . '/fernleafsystems/zxcvbn-php/src/Zxcvbn.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1698 |
'u2flib_server\\Error' => __DIR__ . '/../..' . '/custom/U2F/Yubico/U2F.php',
|
1699 |
'u2flib_server\\RegisterRequest' => __DIR__ . '/../..' . '/custom/U2F/Yubico/U2F.php',
|
1700 |
'u2flib_server\\Registration' => __DIR__ . '/../..' . '/custom/U2F/Yubico/U2F.php',
|
7 |
class ComposerStaticInit4fc2c6daaffaf40b64b79b6d26830171
|
8 |
{
|
9 |
public static $files = array (
|
|
|
10 |
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
11 |
+
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
12 |
+
'626dcc41390ebdaa619faa02d99943b0' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/customFunctions.php',
|
13 |
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
14 |
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
|
15 |
'b14ca0bb4d408c293d6ea9b68f1b4abe' => __DIR__ . '/../..' . '/functions/functions.php',
|
31 |
'Symfony\\Polyfill\\Ctype\\' => 23,
|
32 |
'Symfony\\Component\\Yaml\\' => 23,
|
33 |
'Symfony\\Component\\Translation\\' => 30,
|
34 |
+
'Symfony\\Component\\PropertyAccess\\' => 33,
|
35 |
+
'Symfony\\Component\\OptionsResolver\\' => 34,
|
36 |
),
|
37 |
'R' =>
|
38 |
array (
|
44 |
'Psr\\Container\\' => 14,
|
45 |
'Psr\\Cache\\' => 10,
|
46 |
),
|
47 |
+
'M' =>
|
48 |
+
array (
|
49 |
+
'MyCLabs\\Enum\\' => 13,
|
50 |
+
),
|
51 |
'L' =>
|
52 |
array (
|
53 |
'LZCompressor\\' => 13,
|
62 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\' => 40,
|
63 |
'FernleafSystems\\Utilities\\' => 26,
|
64 |
),
|
65 |
+
'E' =>
|
66 |
+
array (
|
67 |
+
'Endroid\\QrCode\\' => 15,
|
68 |
+
),
|
69 |
'D' =>
|
70 |
array (
|
71 |
'Dolondro\\GoogleAuthenticator\\' => 29,
|
105 |
array (
|
106 |
0 => __DIR__ . '/..' . '/symfony/translation',
|
107 |
),
|
108 |
+
'Symfony\\Component\\PropertyAccess\\' =>
|
109 |
+
array (
|
110 |
+
0 => __DIR__ . '/..' . '/symfony/property-access',
|
111 |
+
),
|
112 |
+
'Symfony\\Component\\OptionsResolver\\' =>
|
113 |
+
array (
|
114 |
+
0 => __DIR__ . '/..' . '/symfony/options-resolver',
|
115 |
+
),
|
116 |
'ReCaptcha\\' =>
|
117 |
array (
|
118 |
0 => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha',
|
129 |
array (
|
130 |
0 => __DIR__ . '/..' . '/psr/cache/src',
|
131 |
),
|
132 |
+
'MyCLabs\\Enum\\' =>
|
133 |
+
array (
|
134 |
+
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
|
135 |
+
),
|
136 |
'LZCompressor\\' =>
|
137 |
array (
|
138 |
0 => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor',
|
153 |
array (
|
154 |
0 => __DIR__ . '/..' . '/fernleafsystems/utilities/src',
|
155 |
),
|
156 |
+
'Endroid\\QrCode\\' =>
|
157 |
+
array (
|
158 |
+
0 => __DIR__ . '/..' . '/endroid/qr-code/src',
|
159 |
+
),
|
160 |
'Dolondro\\GoogleAuthenticator\\' =>
|
161 |
array (
|
162 |
0 => __DIR__ . '/..' . '/dolondro/google-authenticator/src',
|
193 |
0 => __DIR__ . '/..' . '/pimple/pimple/src',
|
194 |
),
|
195 |
),
|
196 |
+
'B' =>
|
197 |
+
array (
|
198 |
+
'BaconQrCode' =>
|
199 |
+
array (
|
200 |
+
0 => __DIR__ . '/..' . '/bacon/bacon-qr-code/src',
|
201 |
+
),
|
202 |
+
),
|
203 |
);
|
204 |
|
205 |
public static $fallbackDirsPsr0 = array (
|
208 |
);
|
209 |
|
210 |
public static $classMap = array (
|
211 |
+
'BaconQrCode\\Common\\AbstractEnum' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php',
|
212 |
+
'BaconQrCode\\Common\\BitArray' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php',
|
213 |
+
'BaconQrCode\\Common\\BitMatrix' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php',
|
214 |
+
'BaconQrCode\\Common\\BitUtils' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php',
|
215 |
+
'BaconQrCode\\Common\\CharacterSetEci' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php',
|
216 |
+
'BaconQrCode\\Common\\EcBlock' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php',
|
217 |
+
'BaconQrCode\\Common\\EcBlocks' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php',
|
218 |
+
'BaconQrCode\\Common\\ErrorCorrectionLevel' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php',
|
219 |
+
'BaconQrCode\\Common\\FormatInformation' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php',
|
220 |
+
'BaconQrCode\\Common\\Mode' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php',
|
221 |
+
'BaconQrCode\\Common\\ReedSolomonCodec' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php',
|
222 |
+
'BaconQrCode\\Common\\Version' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php',
|
223 |
+
'BaconQrCode\\Encoder\\BlockPair' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php',
|
224 |
+
'BaconQrCode\\Encoder\\ByteMatrix' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php',
|
225 |
+
'BaconQrCode\\Encoder\\Encoder' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php',
|
226 |
+
'BaconQrCode\\Encoder\\MaskUtil' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php',
|
227 |
+
'BaconQrCode\\Encoder\\MatrixUtil' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php',
|
228 |
+
'BaconQrCode\\Encoder\\QrCode' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php',
|
229 |
+
'BaconQrCode\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php',
|
230 |
+
'BaconQrCode\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php',
|
231 |
+
'BaconQrCode\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php',
|
232 |
+
'BaconQrCode\\Exception\\RuntimeException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php',
|
233 |
+
'BaconQrCode\\Exception\\UnexpectedValueException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php',
|
234 |
+
'BaconQrCode\\Exception\\WriterException' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php',
|
235 |
+
'BaconQrCode\\Renderer\\Color\\Cmyk' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php',
|
236 |
+
'BaconQrCode\\Renderer\\Color\\ColorInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php',
|
237 |
+
'BaconQrCode\\Renderer\\Color\\Gray' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php',
|
238 |
+
'BaconQrCode\\Renderer\\Color\\Rgb' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php',
|
239 |
+
'BaconQrCode\\Renderer\\Image\\AbstractRenderer' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php',
|
240 |
+
'BaconQrCode\\Renderer\\Image\\Decorator\\DecoratorInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php',
|
241 |
+
'BaconQrCode\\Renderer\\Image\\Decorator\\FinderPattern' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php',
|
242 |
+
'BaconQrCode\\Renderer\\Image\\Eps' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php',
|
243 |
+
'BaconQrCode\\Renderer\\Image\\Png' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php',
|
244 |
+
'BaconQrCode\\Renderer\\Image\\RendererInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php',
|
245 |
+
'BaconQrCode\\Renderer\\Image\\Svg' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php',
|
246 |
+
'BaconQrCode\\Renderer\\RendererInterface' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php',
|
247 |
+
'BaconQrCode\\Renderer\\Text\\Html' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php',
|
248 |
+
'BaconQrCode\\Renderer\\Text\\Plain' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php',
|
249 |
+
'BaconQrCode\\Writer' => __DIR__ . '/..' . '/bacon/bacon-qr-code/src/BaconQrCode/Writer.php',
|
250 |
'Base32\\Base32' => __DIR__ . '/..' . '/christian-riesen/base32/src/Base32.php',
|
251 |
'Carbon\\Carbon' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/Carbon.php',
|
252 |
'Carbon\\CarbonInterval' => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
|
264 |
'Dolondro\\GoogleAuthenticator\\SecretFactory' => __DIR__ . '/..' . '/dolondro/google-authenticator/src/SecretFactory.php',
|
265 |
'Elliotchance\\Iterator\\AbstractPagedIterator' => __DIR__ . '/..' . '/elliotchance/iterator/src/Elliotchance/Iterator/AbstractPagedIterator.php',
|
266 |
'Elliotchance\\Iterator\\PagedIteratorTest' => __DIR__ . '/..' . '/elliotchance/iterator/tests/Elliotchance/Iterator/PagedIteratorTest.php',
|
267 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\Controller\\QrCodeController' => __DIR__ . '/..' . '/endroid/qr-code/src/Bundle/QrCodeBundle/Controller/QrCodeController.php',
|
268 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\DependencyInjection\\Compiler\\WriterRegistryCompilerPass' => __DIR__ . '/..' . '/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Compiler/WriterRegistryCompilerPass.php',
|
269 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Configuration.php',
|
270 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\DependencyInjection\\EndroidQrCodeExtension' => __DIR__ . '/..' . '/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/EndroidQrCodeExtension.php',
|
271 |
+
'Endroid\\QrCode\\Bundle\\QrCodeBundle\\EndroidQrCodeBundle' => __DIR__ . '/..' . '/endroid/qr-code/src/Bundle/QrCodeBundle/EndroidQrCodeBundle.php',
|
272 |
+
'Endroid\\QrCode\\ErrorCorrectionLevel' => __DIR__ . '/..' . '/endroid/qr-code/src/ErrorCorrectionLevel.php',
|
273 |
+
'Endroid\\QrCode\\Exception\\InvalidPathException' => __DIR__ . '/..' . '/endroid/qr-code/src/Exception/InvalidPathException.php',
|
274 |
+
'Endroid\\QrCode\\Exception\\InvalidWriterException' => __DIR__ . '/..' . '/endroid/qr-code/src/Exception/InvalidWriterException.php',
|
275 |
+
'Endroid\\QrCode\\Exception\\MissingFunctionException' => __DIR__ . '/..' . '/endroid/qr-code/src/Exception/MissingFunctionException.php',
|
276 |
+
'Endroid\\QrCode\\Exception\\QrCodeException' => __DIR__ . '/..' . '/endroid/qr-code/src/Exception/QrCodeException.php',
|
277 |
+
'Endroid\\QrCode\\Exception\\UnsupportedExtensionException' => __DIR__ . '/..' . '/endroid/qr-code/src/Exception/UnsupportedExtensionException.php',
|
278 |
+
'Endroid\\QrCode\\Exception\\ValidationException' => __DIR__ . '/..' . '/endroid/qr-code/src/Exception/ValidationException.php',
|
279 |
+
'Endroid\\QrCode\\Factory\\QrCodeFactory' => __DIR__ . '/..' . '/endroid/qr-code/src/Factory/QrCodeFactory.php',
|
280 |
+
'Endroid\\QrCode\\LabelAlignment' => __DIR__ . '/..' . '/endroid/qr-code/src/LabelAlignment.php',
|
281 |
+
'Endroid\\QrCode\\QrCode' => __DIR__ . '/..' . '/endroid/qr-code/src/QrCode.php',
|
282 |
+
'Endroid\\QrCode\\QrCodeInterface' => __DIR__ . '/..' . '/endroid/qr-code/src/QrCodeInterface.php',
|
283 |
+
'Endroid\\QrCode\\StaticWriterRegistry' => __DIR__ . '/..' . '/endroid/qr-code/src/StaticWriterRegistry.php',
|
284 |
+
'Endroid\\QrCode\\Twig\\Extension\\QrCodeExtension' => __DIR__ . '/..' . '/endroid/qr-code/src/Twig/Extension/QrCodeExtension.php',
|
285 |
+
'Endroid\\QrCode\\WriterRegistry' => __DIR__ . '/..' . '/endroid/qr-code/src/WriterRegistry.php',
|
286 |
+
'Endroid\\QrCode\\WriterRegistryInterface' => __DIR__ . '/..' . '/endroid/qr-code/src/WriterRegistryInterface.php',
|
287 |
+
'Endroid\\QrCode\\Writer\\AbstractBaconWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/AbstractBaconWriter.php',
|
288 |
+
'Endroid\\QrCode\\Writer\\AbstractWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/AbstractWriter.php',
|
289 |
+
'Endroid\\QrCode\\Writer\\BinaryWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/BinaryWriter.php',
|
290 |
+
'Endroid\\QrCode\\Writer\\DebugWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/DebugWriter.php',
|
291 |
+
'Endroid\\QrCode\\Writer\\EpsWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/EpsWriter.php',
|
292 |
+
'Endroid\\QrCode\\Writer\\PngWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/PngWriter.php',
|
293 |
+
'Endroid\\QrCode\\Writer\\SvgWriter' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/SvgWriter.php',
|
294 |
+
'Endroid\\QrCode\\Writer\\WriterInterface' => __DIR__ . '/..' . '/endroid/qr-code/src/Writer/WriterInterface.php',
|
295 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynProperties' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/DynProperties.php',
|
296 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynPropertiesClass' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/DynPropertiesClass.php',
|
297 |
'FernleafSystems\\Utilities\\Data\\Adapter\\DynamicProperties' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/DynamicProperties.php',
|
298 |
'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
|
299 |
'FernleafSystems\\Utilities\\Data\\CaptureOutput' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/CaptureOutput.php',
|
300 |
+
'FernleafSystems\\Utilities\\Data\\Response\\StdResponse' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Response/StdResponse.php',
|
301 |
'FernleafSystems\\Utilities\\Logic\\ExecOnce' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Logic/ExecOnce.php',
|
302 |
'FernleafSystems\\Utilities\\Logic\\OneTimeExecute' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Logic/OneTimeExecute.php',
|
303 |
'FernleafSystems\\Utilities\\Response' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Response.php',
|
333 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Ajax\\Response' => __DIR__ . '/../..' . '/src/Controller/Ajax/Response.php',
|
334 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Enqueue' => __DIR__ . '/../..' . '/src/Controller/Assets/Enqueue.php',
|
335 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Paths' => __DIR__ . '/../..' . '/src/Controller/Assets/Paths.php',
|
336 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Svgs' => __DIR__ . '/../..' . '/src/Controller/Assets/Svgs.php',
|
337 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Assets\\Urls' => __DIR__ . '/../..' . '/src/Controller/Assets/Urls.php',
|
338 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\ConfigVO' => __DIR__ . '/../..' . '/src/Controller/Config/ConfigVO.php',
|
339 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Controller\\Config\\Ops\\LoadConfig' => __DIR__ . '/../..' . '/src/Controller/Config/Ops/LoadConfig.php',
|
477 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Processor' => __DIR__ . '/../..' . '/src/Modules/Autoupdates/Processor.php',
|
478 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\Strings' => __DIR__ . '/../..' . '/src/Modules/Autoupdates/Strings.php',
|
479 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Autoupdates\\UI' => __DIR__ . '/../..' . '/src/Modules/Autoupdates/UI.php',
|
480 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\AdminPage' => __DIR__ . '/../..' . '/src/Modules/BaseShield/AdminPage.php',
|
481 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/BaseShield/AjaxHandler.php',
|
482 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\ModCon' => __DIR__ . '/../..' . '/src/Modules/BaseShield/ModCon.php',
|
483 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Options' => __DIR__ . '/../..' . '/src/Modules/BaseShield/Options.php',
|
484 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\Processor' => __DIR__ . '/../..' . '/src/Modules/BaseShield/Processor.php',
|
485 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\BaseShield\\UI' => __DIR__ . '/../..' . '/src/Modules/BaseShield/UI.php',
|
486 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AdminNotices' => __DIR__ . '/../..' . '/src/Modules/Base/AdminNotices.php',
|
487 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AdminPage' => __DIR__ . '/../..' . '/src/Modules/Base/AdminPage.php',
|
488 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Base/AjaxHandler.php',
|
489 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Common\\ExecOnceModConsumer' => __DIR__ . '/../..' . '/src/Modules/Base/Common/ExecOnceModConsumer.php',
|
490 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Debug' => __DIR__ . '/../..' . '/src/Modules/Base/Debug.php',
|
491 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Insights\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/Base/Insights/OverviewCards.php',
|
492 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Request\\FormParams' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Request/FormParams.php',
|
493 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\RequestVoConsumer' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/RequestVoConsumer.php',
|
494 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Request\\Process' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Request/Process.php',
|
495 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Request\\RequestVO' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Request/RequestVO.php',
|
496 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Route\\RestRouteConsumer' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Route/RestRouteConsumer.php',
|
497 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Route\\RouteBase' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Route/RouteBase.php',
|
498 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Route\\RouteCache' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Route/RouteCache.php',
|
499 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Utility\\PreChecks' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Utility/PreChecks.php',
|
500 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Lib\\Rest\\Utility\\RestLocker' => __DIR__ . '/../..' . '/src/Modules/Base/Lib/Rest/Utility/RestLocker.php',
|
501 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Base/ModCon.php',
|
502 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options' => __DIR__ . '/../..' . '/src/Modules/Base/Options.php',
|
503 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Options\\OptValueSanitize' => __DIR__ . '/../..' . '/src/Modules/Base/Options/OptValueSanitize.php',
|
504 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Processor' => __DIR__ . '/../..' . '/src/Modules/Base/Processor.php',
|
505 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Reporting' => __DIR__ . '/../..' . '/src/Modules/Base/Reporting.php',
|
506 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\RestHandler' => __DIR__ . '/../..' . '/src/Modules/Base/RestHandler.php',
|
507 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Strings' => __DIR__ . '/../..' . '/src/Modules/Base/Strings.php',
|
508 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\UI' => __DIR__ . '/../..' . '/src/Modules/Base/UI.php',
|
509 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Base\\Upgrade' => __DIR__ . '/../..' . '/src/Modules/Base/Upgrade.php',
|
691 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\BaseAddRemove' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/BaseAddRemove.php',
|
692 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Enumerate' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/Enumerate.php',
|
693 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\IPs\\WpCli\\Remove' => __DIR__ . '/../..' . '/src/Modules/IPs/WpCli/Remove.php',
|
694 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AdminPage' => __DIR__ . '/../..' . '/src/Modules/Insights/AdminPage.php',
|
695 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/Insights/AjaxHandler.php',
|
696 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\OverviewCards' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/OverviewCards.php',
|
697 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\Requests\\DynamicPageLoader' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/Requests/DynamicPageLoader.php',
|
698 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\SideMenuBuilder' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/SideMenuBuilder.php',
|
699 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Lib\\SummaryCards' => __DIR__ . '/../..' . '/src/Modules/Insights/Lib/SummaryCards.php',
|
700 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Insights/ModCon.php',
|
701 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Options' => __DIR__ . '/../..' . '/src/Modules/Insights/Options.php',
|
702 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\Strings' => __DIR__ . '/../..' . '/src/Modules/Insights/Strings.php',
|
703 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Insights\\UI' => __DIR__ . '/../..' . '/src/Modules/Insights/UI.php',
|
704 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Common\\BaseBotDetectionController' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Common/BaseBotDetectionController.php',
|
705 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Common\\BaseHandler' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Common/BaseHandler.php',
|
706 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Base' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Base.php',
|
707 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\ContactForm7' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ContactForm7.php',
|
708 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\ElementorPro' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/ElementorPro.php',
|
709 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\FluentForms' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FluentForms.php',
|
710 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\FormidableForms' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/FormidableForms.php',
|
711 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Forminator' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Forminator.php',
|
712 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\GravityForms' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/GravityForms.php',
|
713 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Groundhogg' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Groundhogg.php',
|
714 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\Helpers\\NinjaForms_ShieldSpamAction' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/Helpers/NinjaForms_ShieldSpamAction.php',
|
715 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\KaliForms' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/KaliForms.php',
|
716 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\NinjaForms' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/NinjaForms.php',
|
717 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\WPForms' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WPForms.php',
|
718 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\Handlers\\WpForo' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/Handlers/WpForo.php',
|
719 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\Spam\\SpamController' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/Spam/SpamController.php',
|
720 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\Base' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Base.php',
|
721 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\Buddypress' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/Buddypress.php',
|
722 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\EasyDigitalDownloads' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/EasyDigitalDownloads.php',
|
723 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\LearnPress' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LearnPress.php',
|
724 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\LifterLMS' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/LifterLMS.php',
|
725 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\MemberPress' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/MemberPress.php',
|
726 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\PaidMemberSubscriptions' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/PaidMemberSubscriptions.php',
|
727 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\ProfileBuilder' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/ProfileBuilder.php',
|
728 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\UltimateMember' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/UltimateMember.php',
|
729 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\WPMembers' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WPMembers.php',
|
730 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\WooCommerce' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WooCommerce.php',
|
731 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\Handlers\\WordPress' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/Handlers/WordPress.php',
|
732 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\Bots\\UserForms\\UserFormsController' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/Bots/UserForms/UserFormsController.php',
|
733 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\ApiActionInit' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/ApiActionInit.php',
|
734 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Init' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Init.php',
|
735 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Lib\\MainWP\\Client\\Actions\\Sync' => __DIR__ . '/../..' . '/src/Modules/Integrations/Lib/MainWP/Client/Actions/Sync.php',
|
774 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Options' => __DIR__ . '/../..' . '/src/Modules/Integrations/Options.php',
|
775 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Processor' => __DIR__ . '/../..' . '/src/Modules/Integrations/Processor.php',
|
776 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Strings' => __DIR__ . '/../..' . '/src/Modules/Integrations/Strings.php',
|
777 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\UI' => __DIR__ . '/../..' . '/src/Modules/Integrations/UI.php',
|
778 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Integrations\\Upgrade' => __DIR__ . '/../..' . '/src/Modules/Integrations/Upgrade.php',
|
779 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AdminNotices' => __DIR__ . '/../..' . '/src/Modules/License/AdminNotices.php',
|
780 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\AjaxHandler' => __DIR__ . '/../..' . '/src/Modules/License/AjaxHandler.php',
|
781 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\License\\Lib\\LicenseEmails' => __DIR__ . '/../..' . '/src/Modules/License/Lib/LicenseEmails.php',
|
826 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\LoginIntentPage' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/LoginIntentPage.php',
|
827 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaController' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaController.php',
|
828 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaControllerConsumer.php',
|
829 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaProfilesController' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaProfilesController.php',
|
830 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\MfaSkip' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/MfaSkip.php',
|
831 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Profiles\\RenderCustomForms' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Profiles/RenderCustomForms.php',
|
832 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BackupCodes' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BackupCodes.php',
|
833 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\BaseProvider' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/BaseProvider.php',
|
|
|
834 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\Email' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/Email.php',
|
835 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\GoogleAuth' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/GoogleAuth.php',
|
836 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\LoginGuard\\Lib\\TwoFactor\\Provider\\ProviderInterface' => __DIR__ . '/../..' . '/src/Modules/LoginGuard/Lib/TwoFactor/Provider/ProviderInterface.php',
|
920 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\Restrictions\\WpOptions' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/Restrictions/WpOptions.php',
|
921 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\SecurityAdminController' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/SecurityAdminController.php',
|
922 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\SecurityAdmin\\VerifySecurityAdminList' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/SecurityAdmin/VerifySecurityAdminList.php',
|
|
|
923 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\BuildOptions' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/BuildOptions.php',
|
924 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Lib\\WhiteLabel\\WhitelabelController' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Lib/WhiteLabel/WhitelabelController.php',
|
925 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\ModCon' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/ModCon.php',
|
926 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Options' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Options.php',
|
927 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\Processor' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/Processor.php',
|
931 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminAdd' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/WpCli/AdminAdd.php',
|
932 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\AdminRemove' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/WpCli/AdminRemove.php',
|
933 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\SecurityAdmin\\WpCli\\Pin' => __DIR__ . '/../..' . '/src/Modules/SecurityAdmin/WpCli/Pin.php',
|
934 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\Ops\\Retrieve' => __DIR__ . '/../..' . '/src/Modules/Sessions/Lib/Ops/Retrieve.php',
|
935 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\Ops\\Terminate' => __DIR__ . '/../..' . '/src/Modules/Sessions/Lib/Ops/Terminate.php',
|
936 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\Lib\\SessionController' => __DIR__ . '/../..' . '/src/Modules/Sessions/Lib/SessionController.php',
|
937 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\Sessions\\ModCon' => __DIR__ . '/../..' . '/src/Modules/Sessions/ModCon.php',
|
1091 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\ScanWpv' => __DIR__ . '/../..' . '/src/Tables/Build/ScanWpv.php',
|
1092 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Sessions' => __DIR__ . '/../..' . '/src/Tables/Build/Sessions.php',
|
1093 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Build\\Traffic' => __DIR__ . '/../..' . '/src/Tables/Build/Traffic.php',
|
1094 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\Common\\BaseTable' => __DIR__ . '/../..' . '/src/Tables/Render/Common/BaseTable.php',
|
1095 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\DataTable\\Base' => __DIR__ . '/../..' . '/src/Tables/Render/DataTable/Base.php',
|
1096 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\DataTable\\ScanBase' => __DIR__ . '/../..' . '/src/Tables/Render/DataTable/ScanBase.php',
|
1097 |
+
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\DataTable\\ScanWcf' => __DIR__ . '/../..' . '/src/Tables/Render/DataTable/ScanWcf.php',
|
1098 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\AuditTrail' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/AuditTrail.php',
|
1099 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpCliTable\\Base' => __DIR__ . '/../..' . '/src/Tables/Render/WpCliTable/Base.php',
|
1100 |
'FernleafSystems\\Wordpress\\Plugin\\Shield\\Tables\\Render\\WpListTable\\AdminNotes' => __DIR__ . '/../..' . '/src/Tables/Render/WpListTable/AdminNotes.php',
|
1242 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Base' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Base.php',
|
1243 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Lookup' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Lookup.php',
|
1244 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Licenses\\Keyless\\Ping' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Licenses/Keyless/Ping.php',
|
|
|
1245 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\BaseIP' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/BaseIP.php',
|
1246 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\FindSourceFromIp' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/FindSourceFromIp.php',
|
1247 |
'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\IpID' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/IpID.php',
|
1298 |
'LZCompressor\\LZString' => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor/LZString.php',
|
1299 |
'LZCompressor\\LZUtil' => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil.php',
|
1300 |
'LZCompressor\\LZUtil16' => __DIR__ . '/..' . '/nullpunkt/lz-string-php/src/LZCompressor/LZUtil16.php',
|
1301 |
+
'MyCLabs\\Enum\\Enum' => __DIR__ . '/..' . '/myclabs/php-enum/src/Enum.php',
|
1302 |
'Pimple\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Container.php',
|
1303 |
'Pimple\\Exception\\ExpectedInvokableException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php',
|
1304 |
'Pimple\\Exception\\FrozenServiceException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php',
|
1324 |
'Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerExceptionInterface.php',
|
1325 |
'Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php',
|
1326 |
'Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php',
|
1327 |
+
'QrReader' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/QrReader.php',
|
1328 |
'Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php',
|
1329 |
'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php',
|
1330 |
'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php',
|
1380 |
'ReCaptcha\\RequestMethod\\SocketPost' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php',
|
1381 |
'ReCaptcha\\RequestParameters' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/RequestParameters.php',
|
1382 |
'ReCaptcha\\Response' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/Response.php',
|
1383 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/AccessException.php',
|
1384 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/ExceptionInterface.php',
|
1385 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/InvalidArgumentException.php',
|
1386 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/InvalidOptionsException.php',
|
1387 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\MissingOptionsException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/MissingOptionsException.php',
|
1388 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\NoSuchOptionException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/NoSuchOptionException.php',
|
1389 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\OptionDefinitionException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/OptionDefinitionException.php',
|
1390 |
+
'Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException' => __DIR__ . '/..' . '/symfony/options-resolver/Exception/UndefinedOptionsException.php',
|
1391 |
+
'Symfony\\Component\\OptionsResolver\\Options' => __DIR__ . '/..' . '/symfony/options-resolver/Options.php',
|
1392 |
+
'Symfony\\Component\\OptionsResolver\\OptionsResolver' => __DIR__ . '/..' . '/symfony/options-resolver/OptionsResolver.php',
|
1393 |
+
'Symfony\\Component\\OptionsResolver\\OptionsResolverInterface' => __DIR__ . '/..' . '/symfony/options-resolver/OptionsResolverInterface.php',
|
1394 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\AccessException' => __DIR__ . '/..' . '/symfony/property-access/Exception/AccessException.php',
|
1395 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/property-access/Exception/ExceptionInterface.php',
|
1396 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidArgumentException.php',
|
1397 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\InvalidPropertyPathException' => __DIR__ . '/..' . '/symfony/property-access/Exception/InvalidPropertyPathException.php',
|
1398 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchIndexException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchIndexException.php',
|
1399 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException' => __DIR__ . '/..' . '/symfony/property-access/Exception/NoSuchPropertyException.php',
|
1400 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/symfony/property-access/Exception/OutOfBoundsException.php',
|
1401 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/RuntimeException.php',
|
1402 |
+
'Symfony\\Component\\PropertyAccess\\Exception\\UnexpectedTypeException' => __DIR__ . '/..' . '/symfony/property-access/Exception/UnexpectedTypeException.php',
|
1403 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccess' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccess.php',
|
1404 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccessor' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessor.php',
|
1405 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccessorBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorBuilder.php',
|
1406 |
+
'Symfony\\Component\\PropertyAccess\\PropertyAccessorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyAccessorInterface.php',
|
1407 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPath' => __DIR__ . '/..' . '/symfony/property-access/PropertyPath.php',
|
1408 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathBuilder' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathBuilder.php',
|
1409 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathInterface.php',
|
1410 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathIterator' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIterator.php',
|
1411 |
+
'Symfony\\Component\\PropertyAccess\\PropertyPathIteratorInterface' => __DIR__ . '/..' . '/symfony/property-access/PropertyPathIteratorInterface.php',
|
1412 |
+
'Symfony\\Component\\PropertyAccess\\StringUtil' => __DIR__ . '/..' . '/symfony/property-access/StringUtil.php',
|
1413 |
'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/AbstractOperation.php',
|
1414 |
'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => __DIR__ . '/..' . '/symfony/translation/Catalogue/MergeOperation.php',
|
1415 |
'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => __DIR__ . '/..' . '/symfony/translation/Catalogue/OperationInterface.php',
|
1879 |
'ZxcvbnPhp\\Scorer' => __DIR__ . '/..' . '/fernleafsystems/zxcvbn-php/src/Scorer.php',
|
1880 |
'ZxcvbnPhp\\TimeEstimator' => __DIR__ . '/..' . '/fernleafsystems/zxcvbn-php/src/TimeEstimator.php',
|
1881 |
'ZxcvbnPhp\\Zxcvbn' => __DIR__ . '/..' . '/fernleafsystems/zxcvbn-php/src/Zxcvbn.php',
|
1882 |
+
'Zxing\\Binarizer' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/Binarizer.php',
|
1883 |
+
'Zxing\\BinaryBitmap' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/BinaryBitmap.php',
|
1884 |
+
'Zxing\\ChecksumException' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/ChecksumException.php',
|
1885 |
+
'Zxing\\Common\\BitArray' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/BitArray.php',
|
1886 |
+
'Zxing\\Common\\BitMatrix' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/BitMatrix.php',
|
1887 |
+
'Zxing\\Common\\BitSource' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/BitSource.php',
|
1888 |
+
'Zxing\\Common\\CharacterSetECI' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/CharacterSetEci.php',
|
1889 |
+
'Zxing\\Common\\CharacterSetEci\\AbstractEnum\\AbstractEnum' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/AbstractEnum.php',
|
1890 |
+
'Zxing\\Common\\DecoderResult' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/DecoderResult.php',
|
1891 |
+
'Zxing\\Common\\DefaultGridSampler' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/DefaultGridSampler.php',
|
1892 |
+
'Zxing\\Common\\DetectorResult' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/DetectorResult.php',
|
1893 |
+
'Zxing\\Common\\Detector\\MathUtils' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/detector/MathUtils.php',
|
1894 |
+
'Zxing\\Common\\Detector\\MonochromeRectangleDetector' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/detector/MonochromeRectangleDetector.php',
|
1895 |
+
'Zxing\\Common\\GlobalHistogramBinarizer' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/GlobalHistogramBinarizer.php',
|
1896 |
+
'Zxing\\Common\\GridSampler' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/GridSampler.php',
|
1897 |
+
'Zxing\\Common\\HybridBinarizer' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/HybridBinarizer.php',
|
1898 |
+
'Zxing\\Common\\PerspectiveTransform' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/PerspectiveTransform.php',
|
1899 |
+
'Zxing\\Common\\Reedsolomon\\GenericGF' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/GenericGF.php',
|
1900 |
+
'Zxing\\Common\\Reedsolomon\\GenericGFPoly' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/GenericGFPoly.php',
|
1901 |
+
'Zxing\\Common\\Reedsolomon\\ReedSolomonDecoder' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/ReedSolomonDecoder.php',
|
1902 |
+
'Zxing\\Common\\Reedsolomon\\ReedSolomonException' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/common/reedsolomon/ReedSolomonException.php',
|
1903 |
+
'Zxing\\FormatException' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/FormatException.php',
|
1904 |
+
'Zxing\\GDLuminanceSource' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/GDLuminanceSource.php',
|
1905 |
+
'Zxing\\IMagickLuminanceSource' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/IMagickLuminanceSource.php',
|
1906 |
+
'Zxing\\LuminanceSource' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/LuminanceSource.php',
|
1907 |
+
'Zxing\\NotFoundException' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/NotFoundException.php',
|
1908 |
+
'Zxing\\PlanarYUVLuminanceSource' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/PlanarYUVLuminanceSource.php',
|
1909 |
+
'Zxing\\Qrcode\\Decoder\\BitMatrixParser' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/BitMatrixParser.php',
|
1910 |
+
'Zxing\\Qrcode\\Decoder\\DataBlock' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataBlock.php',
|
1911 |
+
'Zxing\\Qrcode\\Decoder\\DataMask' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1912 |
+
'Zxing\\Qrcode\\Decoder\\DataMask000' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1913 |
+
'Zxing\\Qrcode\\Decoder\\DataMask001' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1914 |
+
'Zxing\\Qrcode\\Decoder\\DataMask010' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1915 |
+
'Zxing\\Qrcode\\Decoder\\DataMask011' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1916 |
+
'Zxing\\Qrcode\\Decoder\\DataMask100' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1917 |
+
'Zxing\\Qrcode\\Decoder\\DataMask101' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1918 |
+
'Zxing\\Qrcode\\Decoder\\DataMask110' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1919 |
+
'Zxing\\Qrcode\\Decoder\\DataMask111' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DataMask.php',
|
1920 |
+
'Zxing\\Qrcode\\Decoder\\DecodedBitStreamParser' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/DecodedBitStreamParser.php',
|
1921 |
+
'Zxing\\Qrcode\\Decoder\\Decoder' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Decoder.php',
|
1922 |
+
'Zxing\\Qrcode\\Decoder\\ECB' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Version.php',
|
1923 |
+
'Zxing\\Qrcode\\Decoder\\ECBlocks' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Version.php',
|
1924 |
+
'Zxing\\Qrcode\\Decoder\\ErrorCorrectionLevel' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/ErrorCorrectionLevel.php',
|
1925 |
+
'Zxing\\Qrcode\\Decoder\\FormatInformation' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/FormatInformation.php',
|
1926 |
+
'Zxing\\Qrcode\\Decoder\\Mode' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Mode.php',
|
1927 |
+
'Zxing\\Qrcode\\Decoder\\Version' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/decoder/Version.php',
|
1928 |
+
'Zxing\\Qrcode\\Detector\\AlignmentPattern' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/AlignmentPattern.php',
|
1929 |
+
'Zxing\\Qrcode\\Detector\\AlignmentPatternFinder' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/AlignmentPatternFinder.php',
|
1930 |
+
'Zxing\\Qrcode\\Detector\\Detector' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/Detector.php',
|
1931 |
+
'Zxing\\Qrcode\\Detector\\FinderPattern' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/FinderPattern.php',
|
1932 |
+
'Zxing\\Qrcode\\Detector\\FinderPatternFinder' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/FinderPatternFinder.php',
|
1933 |
+
'Zxing\\Qrcode\\Detector\\FinderPatternInfo' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/detector/FinderPatternInfo.php',
|
1934 |
+
'Zxing\\Qrcode\\QRCodeReader' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/qrcode/QRCodeReader.php',
|
1935 |
+
'Zxing\\RGBLuminanceSource' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/RGBLuminanceSource.php',
|
1936 |
+
'Zxing\\Reader' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/Reader.php',
|
1937 |
+
'Zxing\\ReaderException' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/ReaderException.php',
|
1938 |
+
'Zxing\\Result' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/Result.php',
|
1939 |
+
'Zxing\\ResultPoint' => __DIR__ . '/..' . '/khanamiryan/qrcode-detector-decoder/lib/ResultPoint.php',
|
1940 |
'u2flib_server\\Error' => __DIR__ . '/../..' . '/custom/U2F/Yubico/U2F.php',
|
1941 |
'u2flib_server\\RegisterRequest' => __DIR__ . '/../..' . '/custom/U2F/Yubico/U2F.php',
|
1942 |
'u2flib_server\\Registration' => __DIR__ . '/../..' . '/custom/U2F/Yubico/U2F.php',
|
src/lib/vendor/dolondro/google-authenticator/src/GoogleAuthenticator.php
CHANGED
@@ -140,11 +140,12 @@ class GoogleAuthenticator
|
|
140 |
/**
|
141 |
* @param $string1
|
142 |
* @param $string2
|
|
|
143 |
* @return bool
|
144 |
*/
|
145 |
protected function isEqual($string1, $string2)
|
146 |
{
|
147 |
-
return substr_count($string1 ^ $string2, "\0") * 2 === strlen($string1
|
148 |
}
|
149 |
|
150 |
/**
|
140 |
/**
|
141 |
* @param $string1
|
142 |
* @param $string2
|
143 |
+
*
|
144 |
* @return bool
|
145 |
*/
|
146 |
protected function isEqual($string1, $string2)
|
147 |
{
|
148 |
+
return substr_count($string1 ^ $string2, "\0") * 2 === strlen($string1.$string2);
|
149 |
}
|
150 |
|
151 |
/**
|
src/lib/vendor/dolondro/google-authenticator/src/QrImageGenerator/EndroidQrImageGenerator.php
CHANGED
@@ -8,14 +8,16 @@ use Endroid\QrCode\QrCode;
|
|
8 |
class EndroidQrImageGenerator implements QrImageGeneratorInterface
|
9 |
{
|
10 |
protected $size;
|
|
|
11 |
|
12 |
-
public function __construct($size = 200)
|
13 |
{
|
14 |
if (!is_numeric($size)) {
|
15 |
throw new \InvalidArgumentException("Size is required to be numeric");
|
16 |
}
|
17 |
|
18 |
$this->size = $size;
|
|
|
19 |
}
|
20 |
|
21 |
public function generateUri(Secret $secret)
|
@@ -23,7 +25,7 @@ class EndroidQrImageGenerator implements QrImageGeneratorInterface
|
|
23 |
$qrCode = new QrCode($secret->getUri());
|
24 |
$qrCode->setSize($this->size);
|
25 |
|
26 |
-
$qrCode->setWriterByName(
|
27 |
|
28 |
return $qrCode->writeDataUri();
|
29 |
}
|
8 |
class EndroidQrImageGenerator implements QrImageGeneratorInterface
|
9 |
{
|
10 |
protected $size;
|
11 |
+
protected $writer;
|
12 |
|
13 |
+
public function __construct($size = 200, $writer = 'png')
|
14 |
{
|
15 |
if (!is_numeric($size)) {
|
16 |
throw new \InvalidArgumentException("Size is required to be numeric");
|
17 |
}
|
18 |
|
19 |
$this->size = $size;
|
20 |
+
$this->writer = $writer;
|
21 |
}
|
22 |
|
23 |
public function generateUri(Secret $secret)
|
25 |
$qrCode = new QrCode($secret->getUri());
|
26 |
$qrCode->setSize($this->size);
|
27 |
|
28 |
+
$qrCode->setWriterByName($this->writer);
|
29 |
|
30 |
return $qrCode->writeDataUri();
|
31 |
}
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Controller/QrCodeController.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Bundle\QrCodeBundle\Controller;
|
11 |
+
|
12 |
+
use Endroid\QrCode\Factory\QrCodeFactory;
|
13 |
+
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
14 |
+
use Symfony\Component\HttpFoundation\Response;
|
15 |
+
use Symfony\Component\HttpFoundation\Request;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* QR code controller.
|
19 |
+
*/
|
20 |
+
class QrCodeController extends Controller
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* @param Request $request
|
24 |
+
* @param string $text
|
25 |
+
* @param string $extension
|
26 |
+
*
|
27 |
+
* @return Response
|
28 |
+
*/
|
29 |
+
public function generateAction(Request $request, $text, $extension)
|
30 |
+
{
|
31 |
+
$options = $request->query->all();
|
32 |
+
|
33 |
+
$qrCode = $this->getQrCodeFactory()->create($text, $options);
|
34 |
+
$qrCode->setWriterByExtension($extension);
|
35 |
+
|
36 |
+
return new Response($qrCode->writeString(), Response::HTTP_OK, ['Content-Type' => $qrCode->getContentType()]);
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @return Response
|
41 |
+
*/
|
42 |
+
public function twigFunctionsAction()
|
43 |
+
{
|
44 |
+
if (!$this->has('twig')) {
|
45 |
+
throw new \LogicException('You can not use the "@Template" annotation if the Twig Bundle is not available.');
|
46 |
+
}
|
47 |
+
|
48 |
+
$param = [
|
49 |
+
'message' => 'QR Code',
|
50 |
+
];
|
51 |
+
|
52 |
+
$renderedView = $this->get('twig')->render('@EndroidQrCode/QrCode/twigFunctions.html.twig', $param);
|
53 |
+
|
54 |
+
return new Response($renderedView, Response::HTTP_OK);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @return QrCodeFactory
|
59 |
+
*/
|
60 |
+
protected function getQrCodeFactory()
|
61 |
+
{
|
62 |
+
return $this->get('endroid.qrcode.factory');
|
63 |
+
}
|
64 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Compiler/WriterRegistryCompilerPass.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Bundle\QrCodeBundle\DependencyInjection\Compiler;
|
11 |
+
|
12 |
+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
13 |
+
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
14 |
+
use Symfony\Component\DependencyInjection\Reference;
|
15 |
+
|
16 |
+
class WriterRegistryCompilerPass implements CompilerPassInterface
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* {@inheritdoc}
|
20 |
+
*/
|
21 |
+
public function process(ContainerBuilder $container)
|
22 |
+
{
|
23 |
+
if (!$container->has('endroid.qrcode.writer_registry')) {
|
24 |
+
return;
|
25 |
+
}
|
26 |
+
|
27 |
+
$writerRegistryDefinition = $container->findDefinition('endroid.qrcode.writer_registry');
|
28 |
+
|
29 |
+
$taggedServices = $container->findTaggedServiceIds('endroid.qrcode.writer');
|
30 |
+
foreach ($taggedServices as $id => $tags) {
|
31 |
+
foreach ($tags as $attributes) {
|
32 |
+
$writerRegistryDefinition->addMethodCall('addWriter', [new Reference($id), isset($attributes['set_as_default']) && $attributes['set_as_default']]);
|
33 |
+
}
|
34 |
+
}
|
35 |
+
}
|
36 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/Configuration.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Bundle\QrCodeBundle\DependencyInjection;
|
11 |
+
|
12 |
+
use Endroid\QrCode\ErrorCorrectionLevel;
|
13 |
+
use Endroid\QrCode\LabelAlignment;
|
14 |
+
use Predis\Response\Error;
|
15 |
+
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
16 |
+
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
17 |
+
|
18 |
+
class Configuration implements ConfigurationInterface
|
19 |
+
{
|
20 |
+
public function getConfigTreeBuilder()
|
21 |
+
{
|
22 |
+
$treeBuilder = new TreeBuilder();
|
23 |
+
|
24 |
+
$treeBuilder
|
25 |
+
->root('endroid_qr_code')
|
26 |
+
->children()
|
27 |
+
->scalarNode('writer')->end()
|
28 |
+
->integerNode('size')->min(0)->end()
|
29 |
+
->integerNode('margin')->min(0)->end()
|
30 |
+
->scalarNode('encoding')->defaultValue('UTF-8')->end()
|
31 |
+
->scalarNode('error_correction_level')
|
32 |
+
->validate()
|
33 |
+
->ifNotInArray(ErrorCorrectionLevel::toArray())
|
34 |
+
->thenInvalid('Invalid error correction level %s')
|
35 |
+
->end()
|
36 |
+
->end()
|
37 |
+
->arrayNode('foreground_color')
|
38 |
+
->children()
|
39 |
+
->scalarNode('r')->isRequired()->end()
|
40 |
+
->scalarNode('g')->isRequired()->end()
|
41 |
+
->scalarNode('b')->isRequired()->end()
|
42 |
+
->end()
|
43 |
+
->end()
|
44 |
+
->arrayNode('background_color')
|
45 |
+
->children()
|
46 |
+
->scalarNode('r')->isRequired()->end()
|
47 |
+
->scalarNode('g')->isRequired()->end()
|
48 |
+
->scalarNode('b')->isRequired()->end()
|
49 |
+
->end()
|
50 |
+
->end()
|
51 |
+
->scalarNode('logo_path')->end()
|
52 |
+
->integerNode('logo_width')->end()
|
53 |
+
->scalarNode('label')->end()
|
54 |
+
->integerNode('label_font_size')->end()
|
55 |
+
->scalarNode('label_font_path')->end()
|
56 |
+
->scalarNode('label_alignment')
|
57 |
+
->validate()
|
58 |
+
->ifNotInArray(LabelAlignment::toArray())
|
59 |
+
->thenInvalid('Invalid label alignment %s')
|
60 |
+
->end()
|
61 |
+
->end()
|
62 |
+
->arrayNode('label_margin')
|
63 |
+
->children()
|
64 |
+
->scalarNode('t')->end()
|
65 |
+
->scalarNode('r')->end()
|
66 |
+
->scalarNode('b')->end()
|
67 |
+
->scalarNode('l')->end()
|
68 |
+
->end()
|
69 |
+
->end()
|
70 |
+
->booleanNode('validate_result')->end()
|
71 |
+
->end()
|
72 |
+
->end()
|
73 |
+
;
|
74 |
+
|
75 |
+
return $treeBuilder;
|
76 |
+
}
|
77 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/DependencyInjection/EndroidQrCodeExtension.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Bundle\QrCodeBundle\DependencyInjection;
|
11 |
+
|
12 |
+
use Symfony\Component\Config\Definition\Processor;
|
13 |
+
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
14 |
+
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
15 |
+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
|
16 |
+
use Symfony\Component\Config\FileLocator;
|
17 |
+
|
18 |
+
class EndroidQrCodeExtension extends Extension
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* {@inheritdoc}
|
22 |
+
*/
|
23 |
+
public function load(array $configs, ContainerBuilder $container)
|
24 |
+
{
|
25 |
+
$processor = new Processor();
|
26 |
+
$config = $processor->processConfiguration(new Configuration(), $configs);
|
27 |
+
|
28 |
+
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
29 |
+
$loader->load('services.yml');
|
30 |
+
|
31 |
+
$factoryDefinition = $container->getDefinition('endroid.qrcode.factory');
|
32 |
+
$factoryDefinition->replaceArgument(0, $config);
|
33 |
+
}
|
34 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/EndroidQrCodeBundle.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Bundle\QrCodeBundle;
|
11 |
+
|
12 |
+
use Endroid\QrCode\Bundle\QrCodeBundle\DependencyInjection\Compiler\WriterRegistryCompilerPass;
|
13 |
+
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
14 |
+
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
15 |
+
|
16 |
+
class EndroidQrCodeBundle extends Bundle
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* {@inheritdoc}
|
20 |
+
*/
|
21 |
+
public function build(ContainerBuilder $container)
|
22 |
+
{
|
23 |
+
parent::build($container);
|
24 |
+
|
25 |
+
$container->addCompilerPass(new WriterRegistryCompilerPass());
|
26 |
+
}
|
27 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Resources/config/routing.yml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
endroid_qrcode_generate:
|
2 |
+
path: /{text}.{extension}
|
3 |
+
requirements:
|
4 |
+
text: "[\\w\\W]+"
|
5 |
+
defaults:
|
6 |
+
_controller: EndroidQrCodeBundle:QrCode:generate
|
7 |
+
|
8 |
+
endroid_qrcode_twig_functions:
|
9 |
+
path: /twig
|
10 |
+
defaults:
|
11 |
+
_controller: EndroidQrCodeBundle:QrCode:twigFunctions
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Resources/config/services.yml
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
services:
|
2 |
+
endroid.qrcode.factory:
|
3 |
+
class: Endroid\QrCode\Factory\QrCodeFactory
|
4 |
+
arguments: [ null, '@endroid.qrcode.writer_registry' ]
|
5 |
+
endroid.qrcode.twig.extension:
|
6 |
+
class: Endroid\QrCode\Twig\Extension\QrCodeExtension
|
7 |
+
arguments: [ '@endroid.qrcode.factory', '@router']
|
8 |
+
tags:
|
9 |
+
- { name: twig.extension }
|
10 |
+
endroid.qrcode.writer_registry:
|
11 |
+
class: Endroid\QrCode\WriterRegistry
|
12 |
+
endroid.qrcode.writer.binary_writer:
|
13 |
+
class: Endroid\QrCode\Writer\BinaryWriter
|
14 |
+
tags:
|
15 |
+
- { name: endroid.qrcode.writer }
|
16 |
+
endroid.qrcode.writer.debug_writer:
|
17 |
+
class: Endroid\QrCode\Writer\DebugWriter
|
18 |
+
tags:
|
19 |
+
- { name: endroid.qrcode.writer }
|
20 |
+
endroid.qrcode.writer.eps_writer:
|
21 |
+
class: Endroid\QrCode\Writer\EpsWriter
|
22 |
+
tags:
|
23 |
+
- { name: endroid.qrcode.writer }
|
24 |
+
endroid.qrcode.writer.png_writer:
|
25 |
+
class: Endroid\QrCode\Writer\PngWriter
|
26 |
+
tags:
|
27 |
+
- { name: endroid.qrcode.writer, set_as_default: true }
|
28 |
+
endroid.qrcode.writer.svg_writer:
|
29 |
+
class: Endroid\QrCode\Writer\SvgWriter
|
30 |
+
tags:
|
31 |
+
- { name: endroid.qrcode.writer }
|
src/lib/vendor/endroid/qr-code/src/Bundle/QrCodeBundle/Resources/views/QrCode/twigFunctions.html.twig
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<img src="{{ qrcode_path(message) }}" />
|
2 |
+
<img src="{{ qrcode_url(message, { writer: 'svg' }) }}" />
|
3 |
+
<img src="{{ qrcode_data_uri(message, { writer: 'svg', size: 150 }) }}" />
|
src/lib/vendor/endroid/qr-code/src/ErrorCorrectionLevel.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode;
|
11 |
+
|
12 |
+
use MyCLabs\Enum\Enum;
|
13 |
+
|
14 |
+
class ErrorCorrectionLevel extends Enum
|
15 |
+
{
|
16 |
+
const LOW = 'low';
|
17 |
+
const MEDIUM = 'medium';
|
18 |
+
const QUARTILE = 'quartile';
|
19 |
+
const HIGH = 'high';
|
20 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Exception/InvalidPathException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Exception;
|
11 |
+
|
12 |
+
class InvalidPathException extends QrCodeException
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Exception/InvalidWriterException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Exception;
|
11 |
+
|
12 |
+
class InvalidWriterException extends QrCodeException
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Exception/MissingFunctionException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Exception;
|
11 |
+
|
12 |
+
class MissingFunctionException extends QrCodeException
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Exception/QrCodeException.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Exception;
|
11 |
+
|
12 |
+
use Exception;
|
13 |
+
|
14 |
+
abstract class QrCodeException extends Exception
|
15 |
+
{
|
16 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Exception/UnsupportedExtensionException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Exception;
|
11 |
+
|
12 |
+
class UnsupportedExtensionException extends QrCodeException
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Exception/ValidationException.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Exception;
|
11 |
+
|
12 |
+
class ValidationException extends QrCodeException
|
13 |
+
{
|
14 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Factory/QrCodeFactory.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Factory;
|
11 |
+
|
12 |
+
use Endroid\QrCode\QrCode;
|
13 |
+
use Endroid\QrCode\WriterRegistryInterface;
|
14 |
+
use Symfony\Component\OptionsResolver\OptionsResolver;
|
15 |
+
use Symfony\Component\PropertyAccess\PropertyAccess;
|
16 |
+
|
17 |
+
class QrCodeFactory
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* @var array
|
21 |
+
*/
|
22 |
+
protected $definedOptions = [
|
23 |
+
'writer',
|
24 |
+
'size',
|
25 |
+
'margin',
|
26 |
+
'foreground_color',
|
27 |
+
'background_color',
|
28 |
+
'encoding',
|
29 |
+
'error_correction_level',
|
30 |
+
'logo_path',
|
31 |
+
'logo_width',
|
32 |
+
'label',
|
33 |
+
'label_font_size',
|
34 |
+
'label_font_path',
|
35 |
+
'label_alignment',
|
36 |
+
'label_margin',
|
37 |
+
'validate_result',
|
38 |
+
];
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var array
|
42 |
+
*/
|
43 |
+
protected $defaultOptions;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @var WriterRegistryInterface
|
47 |
+
*/
|
48 |
+
protected $writerRegistry;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var OptionsResolver
|
52 |
+
*/
|
53 |
+
protected $optionsResolver;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @param array $defaultOptions
|
57 |
+
* @param WriterRegistryInterface $writerRegistry
|
58 |
+
*/
|
59 |
+
public function __construct(array $defaultOptions = [], WriterRegistryInterface $writerRegistry = null)
|
60 |
+
{
|
61 |
+
$this->defaultOptions = $defaultOptions;
|
62 |
+
$this->writerRegistry = $writerRegistry;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @param string $text
|
67 |
+
* @param array $options
|
68 |
+
*
|
69 |
+
* @return QrCode
|
70 |
+
*/
|
71 |
+
public function create($text = '', array $options = [])
|
72 |
+
{
|
73 |
+
$options = $this->getOptionsResolver()->resolve($options);
|
74 |
+
$accessor = PropertyAccess::createPropertyAccessor();
|
75 |
+
|
76 |
+
$qrCode = new QrCode($text);
|
77 |
+
|
78 |
+
if ($this->writerRegistry instanceof WriterRegistryInterface) {
|
79 |
+
$qrCode->setWriterRegistry($this->writerRegistry);
|
80 |
+
}
|
81 |
+
|
82 |
+
foreach ($this->definedOptions as $option) {
|
83 |
+
if (isset($options[$option])) {
|
84 |
+
if ('writer' === $option) {
|
85 |
+
$options['writer_by_name'] = $options[$option];
|
86 |
+
$option = 'writer_by_name';
|
87 |
+
}
|
88 |
+
$accessor->setValue($qrCode, $option, $options[$option]);
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
return $qrCode;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @return OptionsResolver
|
97 |
+
*/
|
98 |
+
protected function getOptionsResolver()
|
99 |
+
{
|
100 |
+
if (!$this->optionsResolver instanceof OptionsResolver) {
|
101 |
+
$this->optionsResolver = $this->createOptionsResolver();
|
102 |
+
}
|
103 |
+
|
104 |
+
return $this->optionsResolver;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @return OptionsResolver
|
109 |
+
*/
|
110 |
+
protected function createOptionsResolver()
|
111 |
+
{
|
112 |
+
$optionsResolver = new OptionsResolver();
|
113 |
+
$optionsResolver
|
114 |
+
->setDefaults($this->defaultOptions)
|
115 |
+
->setDefined($this->definedOptions)
|
116 |
+
;
|
117 |
+
|
118 |
+
return $optionsResolver;
|
119 |
+
}
|
120 |
+
}
|
src/lib/vendor/endroid/qr-code/src/LabelAlignment.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode;
|
11 |
+
|
12 |
+
use MyCLabs\Enum\Enum;
|
13 |
+
|
14 |
+
class LabelAlignment extends Enum
|
15 |
+
{
|
16 |
+
const LEFT = 'left';
|
17 |
+
const CENTER = 'center';
|
18 |
+
const RIGHT = 'right';
|
19 |
+
}
|
src/lib/vendor/endroid/qr-code/src/QrCode.php
ADDED
@@ -0,0 +1,591 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode;
|
11 |
+
|
12 |
+
use Endroid\QrCode\Exception\InvalidPathException;
|
13 |
+
use Endroid\QrCode\Exception\InvalidWriterException;
|
14 |
+
use Endroid\QrCode\Exception\UnsupportedExtensionException;
|
15 |
+
use Endroid\QrCode\Writer\WriterInterface;
|
16 |
+
|
17 |
+
class QrCode implements QrCodeInterface
|
18 |
+
{
|
19 |
+
const LABEL_FONT_PATH_DEFAULT = __DIR__.'/../assets/noto_sans.otf';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected $text;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var int
|
28 |
+
*/
|
29 |
+
protected $size = 300;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var int
|
33 |
+
*/
|
34 |
+
protected $margin = 10;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
protected $foregroundColor = [
|
40 |
+
'r' => 0,
|
41 |
+
'g' => 0,
|
42 |
+
'b' => 0,
|
43 |
+
];
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @var array
|
47 |
+
*/
|
48 |
+
protected $backgroundColor = [
|
49 |
+
'r' => 255,
|
50 |
+
'g' => 255,
|
51 |
+
'b' => 255,
|
52 |
+
];
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @var string
|
56 |
+
*/
|
57 |
+
protected $encoding = 'UTF-8';
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @var ErrorCorrectionLevel
|
61 |
+
*/
|
62 |
+
protected $errorCorrectionLevel;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $logoPath;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @var int
|
71 |
+
*/
|
72 |
+
protected $logoWidth;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @var string
|
76 |
+
*/
|
77 |
+
protected $label;
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @var int
|
81 |
+
*/
|
82 |
+
protected $labelFontSize = 16;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @var string
|
86 |
+
*/
|
87 |
+
protected $labelFontPath = self::LABEL_FONT_PATH_DEFAULT;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @var LabelAlignment
|
91 |
+
*/
|
92 |
+
protected $labelAlignment;
|
93 |
+
|
94 |
+
/**
|
95 |
+
* @var array
|
96 |
+
*/
|
97 |
+
protected $labelMargin = [
|
98 |
+
't' => 0,
|
99 |
+
'r' => 10,
|
100 |
+
'b' => 10,
|
101 |
+
'l' => 10,
|
102 |
+
];
|
103 |
+
|
104 |
+
/**
|
105 |
+
* @var WriterRegistryInterface
|
106 |
+
*/
|
107 |
+
protected $writerRegistry;
|
108 |
+
|
109 |
+
/**
|
110 |
+
* @var WriterInterface
|
111 |
+
*/
|
112 |
+
protected $writer;
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @var bool
|
116 |
+
*/
|
117 |
+
protected $validateResult = false;
|
118 |
+
|
119 |
+
/**
|
120 |
+
* @param string $text
|
121 |
+
*/
|
122 |
+
public function __construct($text = '')
|
123 |
+
{
|
124 |
+
$this->text = $text;
|
125 |
+
|
126 |
+
$this->errorCorrectionLevel = new ErrorCorrectionLevel(ErrorCorrectionLevel::LOW);
|
127 |
+
$this->labelAlignment = new LabelAlignment(LabelAlignment::CENTER);
|
128 |
+
|
129 |
+
$this->writerRegistry = new StaticWriterRegistry();
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @param string $text
|
134 |
+
*
|
135 |
+
* @return $this
|
136 |
+
*/
|
137 |
+
public function setText($text)
|
138 |
+
{
|
139 |
+
$this->text = $text;
|
140 |
+
|
141 |
+
return $this;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* {@inheritdoc}
|
146 |
+
*/
|
147 |
+
public function getText()
|
148 |
+
{
|
149 |
+
return $this->text;
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* @param int $size
|
154 |
+
*
|
155 |
+
* @return $this
|
156 |
+
*/
|
157 |
+
public function setSize($size)
|
158 |
+
{
|
159 |
+
$this->size = $size;
|
160 |
+
|
161 |
+
return $this;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* {@inheritdoc}
|
166 |
+
*/
|
167 |
+
public function getSize()
|
168 |
+
{
|
169 |
+
return $this->size;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* @param int $margin
|
174 |
+
*
|
175 |
+
* @return $this
|
176 |
+
*/
|
177 |
+
public function setMargin($margin)
|
178 |
+
{
|
179 |
+
$this->margin = $margin;
|
180 |
+
|
181 |
+
return $this;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* {@inheritdoc}
|
186 |
+
*/
|
187 |
+
public function getMargin()
|
188 |
+
{
|
189 |
+
return $this->margin;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* @param array $foregroundColor
|
194 |
+
*
|
195 |
+
* @return $this
|
196 |
+
*/
|
197 |
+
public function setForegroundColor($foregroundColor)
|
198 |
+
{
|
199 |
+
$this->foregroundColor = $foregroundColor;
|
200 |
+
|
201 |
+
return $this;
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* {@inheritdoc}
|
206 |
+
*/
|
207 |
+
public function getForegroundColor()
|
208 |
+
{
|
209 |
+
return $this->foregroundColor;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* @param array $backgroundColor
|
214 |
+
*
|
215 |
+
* @return $this
|
216 |
+
*/
|
217 |
+
public function setBackgroundColor($backgroundColor)
|
218 |
+
{
|
219 |
+
$this->backgroundColor = $backgroundColor;
|
220 |
+
|
221 |
+
return $this;
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* {@inheritdoc}
|
226 |
+
*/
|
227 |
+
public function getBackgroundColor()
|
228 |
+
{
|
229 |
+
return $this->backgroundColor;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* @param string $encoding
|
234 |
+
*
|
235 |
+
* @return $this
|
236 |
+
*/
|
237 |
+
public function setEncoding($encoding)
|
238 |
+
{
|
239 |
+
$this->encoding = $encoding;
|
240 |
+
|
241 |
+
return $this;
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* {@inheritdoc}
|
246 |
+
*/
|
247 |
+
public function getEncoding()
|
248 |
+
{
|
249 |
+
return $this->encoding;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* @param string $errorCorrectionLevel
|
254 |
+
*
|
255 |
+
* @return $this
|
256 |
+
*/
|
257 |
+
public function setErrorCorrectionLevel($errorCorrectionLevel)
|
258 |
+
{
|
259 |
+
$this->errorCorrectionLevel = new ErrorCorrectionLevel($errorCorrectionLevel);
|
260 |
+
|
261 |
+
return $this;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* {@inheritdoc}
|
266 |
+
*/
|
267 |
+
public function getErrorCorrectionLevel()
|
268 |
+
{
|
269 |
+
return $this->errorCorrectionLevel->getValue();
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* @param string $logoPath
|
274 |
+
*
|
275 |
+
* @return $this
|
276 |
+
*
|
277 |
+
* @throws InvalidPathException
|
278 |
+
*/
|
279 |
+
public function setLogoPath($logoPath)
|
280 |
+
{
|
281 |
+
$logoPath = realpath($logoPath);
|
282 |
+
|
283 |
+
if (!is_file($logoPath)) {
|
284 |
+
throw new InvalidPathException('Invalid logo path: '.$logoPath);
|
285 |
+
}
|
286 |
+
|
287 |
+
$this->logoPath = $logoPath;
|
288 |
+
|
289 |
+
return $this;
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* {@inheritdoc}
|
294 |
+
*/
|
295 |
+
public function getLogoPath()
|
296 |
+
{
|
297 |
+
return $this->logoPath;
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* @param int $logoWidth
|
302 |
+
*
|
303 |
+
* @return $this
|
304 |
+
*/
|
305 |
+
public function setLogoWidth($logoWidth)
|
306 |
+
{
|
307 |
+
$this->logoWidth = $logoWidth;
|
308 |
+
|
309 |
+
return $this;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* {@inheritdoc}
|
314 |
+
*/
|
315 |
+
public function getLogoWidth()
|
316 |
+
{
|
317 |
+
return $this->logoWidth;
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* @param string $label
|
322 |
+
* @param int $labelFontSize
|
323 |
+
* @param string $labelFontPath
|
324 |
+
* @param string $labelAlignment
|
325 |
+
* @param array $labelMargin
|
326 |
+
*
|
327 |
+
* @return $this
|
328 |
+
*/
|
329 |
+
public function setLabel($label, $labelFontSize = null, $labelFontPath = null, $labelAlignment = null, $labelMargin = null)
|
330 |
+
{
|
331 |
+
$this->label = $label;
|
332 |
+
|
333 |
+
if (null !== $labelFontSize) {
|
334 |
+
$this->setLabelFontSize($labelFontSize);
|
335 |
+
}
|
336 |
+
|
337 |
+
if (null !== $labelFontPath) {
|
338 |
+
$this->setLabelFontPath($labelFontPath);
|
339 |
+
}
|
340 |
+
|
341 |
+
if (null !== $labelAlignment) {
|
342 |
+
$this->setLabelAlignment($labelAlignment);
|
343 |
+
}
|
344 |
+
|
345 |
+
if (null !== $labelMargin) {
|
346 |
+
$this->setLabelMargin($labelMargin);
|
347 |
+
}
|
348 |
+
|
349 |
+
return $this;
|
350 |
+
}
|
351 |
+
|
352 |
+
/**
|
353 |
+
* {@inheritdoc}
|
354 |
+
*/
|
355 |
+
public function getLabel()
|
356 |
+
{
|
357 |
+
return $this->label;
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* @param int $labelFontSize
|
362 |
+
*
|
363 |
+
* @return $this
|
364 |
+
*/
|
365 |
+
public function setLabelFontSize($labelFontSize)
|
366 |
+
{
|
367 |
+
$this->labelFontSize = $labelFontSize;
|
368 |
+
|
369 |
+
return $this;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* {@inheritdoc}
|
374 |
+
*/
|
375 |
+
public function getLabelFontSize()
|
376 |
+
{
|
377 |
+
return $this->labelFontSize;
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* @param string $labelFontPath
|
382 |
+
*
|
383 |
+
* @return $this
|
384 |
+
*
|
385 |
+
* @throws InvalidPathException
|
386 |
+
*/
|
387 |
+
public function setLabelFontPath($labelFontPath)
|
388 |
+
{
|
389 |
+
$labelFontPath = realpath($labelFontPath);
|
390 |
+
|
391 |
+
if (!is_file($labelFontPath)) {
|
392 |
+
throw new InvalidPathException('Invalid label font path: '.$labelFontPath);
|
393 |
+
}
|
394 |
+
|
395 |
+
$this->labelFontPath = $labelFontPath;
|
396 |
+
|
397 |
+
return $this;
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* {@inheritdoc}
|
402 |
+
*/
|
403 |
+
public function getLabelFontPath()
|
404 |
+
{
|
405 |
+
return $this->labelFontPath;
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* @param string $labelAlignment
|
410 |
+
*
|
411 |
+
* @return $this
|
412 |
+
*/
|
413 |
+
public function setLabelAlignment($labelAlignment)
|
414 |
+
{
|
415 |
+
$this->labelAlignment = new LabelAlignment($labelAlignment);
|
416 |
+
|
417 |
+
return $this;
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
* {@inheritdoc}
|
422 |
+
*/
|
423 |
+
public function getLabelAlignment()
|
424 |
+
{
|
425 |
+
return $this->labelAlignment->getValue();
|
426 |
+
}
|
427 |
+
|
428 |
+
/**
|
429 |
+
* @param int[] $labelMargin
|
430 |
+
*
|
431 |
+
* @return $this
|
432 |
+
*/
|
433 |
+
public function setLabelMargin(array $labelMargin)
|
434 |
+
{
|
435 |
+
$this->labelMargin = array_merge($this->labelMargin, $labelMargin);
|
436 |
+
|
437 |
+
return $this;
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* {@inheritdoc}
|
442 |
+
*/
|
443 |
+
public function getLabelMargin()
|
444 |
+
{
|
445 |
+
return $this->labelMargin;
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* @param WriterRegistryInterface $writerRegistry
|
450 |
+
*
|
451 |
+
* @return $this
|
452 |
+
*/
|
453 |
+
public function setWriterRegistry(WriterRegistryInterface $writerRegistry)
|
454 |
+
{
|
455 |
+
$this->writerRegistry = $writerRegistry;
|
456 |
+
|
457 |
+
return $this;
|
458 |
+
}
|
459 |
+
|
460 |
+
/**
|
461 |
+
* @param WriterInterface $writer
|
462 |
+
*
|
463 |
+
* @return $this
|
464 |
+
*/
|
465 |
+
public function setWriter(WriterInterface $writer)
|
466 |
+
{
|
467 |
+
$this->writer = $writer;
|
468 |
+
|
469 |
+
return $this;
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
* @param WriterInterface $name
|
474 |
+
*
|
475 |
+
* @return WriterInterface
|
476 |
+
*/
|
477 |
+
public function getWriter($name = null)
|
478 |
+
{
|
479 |
+
if (!is_null($name)) {
|
480 |
+
return $this->writerRegistry->getWriter($name);
|
481 |
+
}
|
482 |
+
|
483 |
+
if ($this->writer instanceof WriterInterface) {
|
484 |
+
return $this->writer;
|
485 |
+
}
|
486 |
+
|
487 |
+
return $this->writerRegistry->getDefaultWriter();
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* @param string $name
|
492 |
+
*
|
493 |
+
* @return $this
|
494 |
+
*
|
495 |
+
* @throws InvalidWriterException
|
496 |
+
*/
|
497 |
+
public function setWriterByName($name)
|
498 |
+
{
|
499 |
+
$this->writer = $this->writerRegistry->getWriter($name);
|
500 |
+
|
501 |
+
return $this;
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* @param string $path
|
506 |
+
*
|
507 |
+
* @return $this
|
508 |
+
*/
|
509 |
+
public function setWriterByPath($path)
|
510 |
+
{
|
511 |
+
$extension = pathinfo($path, PATHINFO_EXTENSION);
|
512 |
+
|
513 |
+
$this->setWriterByExtension($extension);
|
514 |
+
|
515 |
+
return $this;
|
516 |
+
}
|
517 |
+
|
518 |
+
/**
|
519 |
+
* @param string $extension
|
520 |
+
*
|
521 |
+
* @return $this
|
522 |
+
*
|
523 |
+
* @throws UnsupportedExtensionException
|
524 |
+
*/
|
525 |
+
public function setWriterByExtension($extension)
|
526 |
+
{
|
527 |
+
foreach ($this->writerRegistry->getWriters() as $writer) {
|
528 |
+
if ($writer->supportsExtension($extension)) {
|
529 |
+
$this->writer = $writer;
|
530 |
+
|
531 |
+
return $this;
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
throw new UnsupportedExtensionException('Missing writer for extension "'.$extension.'"');
|
536 |
+
}
|
537 |
+
|
538 |
+
/**
|
539 |
+
* @param bool $validateResult
|
540 |
+
*
|
541 |
+
* @return $this
|
542 |
+
*/
|
543 |
+
public function setValidateResult($validateResult)
|
544 |
+
{
|
545 |
+
$this->validateResult = $validateResult;
|
546 |
+
|
547 |
+
return $this;
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* {@inheritdoc}
|
552 |
+
*/
|
553 |
+
public function getValidateResult()
|
554 |
+
{
|
555 |
+
return $this->validateResult;
|
556 |
+
}
|
557 |
+
|
558 |
+
/**
|
559 |
+
* @return string
|
560 |
+
*/
|
561 |
+
public function writeString()
|
562 |
+
{
|
563 |
+
return $this->getWriter()->writeString($this);
|
564 |
+
}
|
565 |
+
|
566 |
+
/**
|
567 |
+
* @return string
|
568 |
+
*/
|
569 |
+
public function writeDataUri()
|
570 |
+
{
|
571 |
+
return $this->getWriter()->writeDataUri($this);
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* @param string $path
|
576 |
+
*/
|
577 |
+
public function writeFile($path)
|
578 |
+
{
|
579 |
+
return $this->getWriter()->writeFile($this, $path);
|
580 |
+
}
|
581 |
+
|
582 |
+
/**
|
583 |
+
* @return string
|
584 |
+
*
|
585 |
+
* @throws InvalidWriterException
|
586 |
+
*/
|
587 |
+
public function getContentType()
|
588 |
+
{
|
589 |
+
return $this->getWriter()->getContentType();
|
590 |
+
}
|
591 |
+
}
|
src/lib/vendor/endroid/qr-code/src/QrCodeInterface.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode;
|
11 |
+
|
12 |
+
interface QrCodeInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public function getText();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @return int
|
21 |
+
*/
|
22 |
+
public function getSize();
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @return int
|
26 |
+
*/
|
27 |
+
public function getMargin();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return int[]
|
31 |
+
*/
|
32 |
+
public function getForegroundColor();
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return int[]
|
36 |
+
*/
|
37 |
+
public function getBackgroundColor();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @return string
|
41 |
+
*/
|
42 |
+
public function getEncoding();
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @return string
|
46 |
+
*/
|
47 |
+
public function getErrorCorrectionLevel();
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @return string
|
51 |
+
*/
|
52 |
+
public function getLogoPath();
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @return int
|
56 |
+
*/
|
57 |
+
public function getLogoWidth();
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
public function getLabel();
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @return string
|
66 |
+
*/
|
67 |
+
public function getLabelFontPath();
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @return int
|
71 |
+
*/
|
72 |
+
public function getLabelFontSize();
|
73 |
+
|
74 |
+
/**
|
75 |
+
* @return string
|
76 |
+
*/
|
77 |
+
public function getLabelAlignment();
|
78 |
+
|
79 |
+
/**
|
80 |
+
* @return int[]
|
81 |
+
*/
|
82 |
+
public function getLabelMargin();
|
83 |
+
|
84 |
+
/**
|
85 |
+
* @return bool
|
86 |
+
*/
|
87 |
+
public function getValidateResult();
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @param WriterRegistryInterface $writerRegistry
|
91 |
+
*
|
92 |
+
* @return mixed
|
93 |
+
*/
|
94 |
+
public function setWriterRegistry(WriterRegistryInterface $writerRegistry);
|
95 |
+
}
|
src/lib/vendor/endroid/qr-code/src/StaticWriterRegistry.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode;
|
11 |
+
|
12 |
+
use Endroid\QrCode\Writer\BinaryWriter;
|
13 |
+
use Endroid\QrCode\Writer\DebugWriter;
|
14 |
+
use Endroid\QrCode\Writer\EpsWriter;
|
15 |
+
use Endroid\QrCode\Writer\PngWriter;
|
16 |
+
use Endroid\QrCode\Writer\SvgWriter;
|
17 |
+
|
18 |
+
class StaticWriterRegistry extends WriterRegistry
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* {@inheritdoc}
|
22 |
+
*/
|
23 |
+
public function __construct()
|
24 |
+
{
|
25 |
+
parent::__construct();
|
26 |
+
|
27 |
+
$this->loadWriters();
|
28 |
+
}
|
29 |
+
|
30 |
+
protected function loadWriters()
|
31 |
+
{
|
32 |
+
if (count($this->writers) > 0) {
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
$this->addWriter(new BinaryWriter());
|
37 |
+
$this->addWriter(new DebugWriter());
|
38 |
+
$this->addWriter(new EpsWriter());
|
39 |
+
$this->addWriter(new PngWriter(), true);
|
40 |
+
$this->addWriter(new SvgWriter());
|
41 |
+
}
|
42 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Twig/Extension/QrCodeExtension.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Twig\Extension;
|
11 |
+
|
12 |
+
use Endroid\QrCode\Exception\UnsupportedExtensionException;
|
13 |
+
use Endroid\QrCode\Factory\QrCodeFactory;
|
14 |
+
use Endroid\QrCode\WriterRegistryInterface;
|
15 |
+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
16 |
+
use Symfony\Component\Routing\RouterInterface;
|
17 |
+
use Twig_Extension;
|
18 |
+
use Twig_SimpleFunction;
|
19 |
+
|
20 |
+
class QrCodeExtension extends Twig_Extension
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* @var QrCodeFactory
|
24 |
+
*/
|
25 |
+
protected $qrCodeFactory;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var RouterInterface
|
29 |
+
*/
|
30 |
+
protected $router;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @param QrCodeFactory $qrCodeFactory
|
34 |
+
* @param RouterInterface $router
|
35 |
+
* @param WriterRegistryInterface $writerRegistry
|
36 |
+
*/
|
37 |
+
public function __construct(QrCodeFactory $qrCodeFactory, RouterInterface $router)
|
38 |
+
{
|
39 |
+
$this->qrCodeFactory = $qrCodeFactory;
|
40 |
+
$this->router = $router;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* {@inheritdoc}
|
45 |
+
*/
|
46 |
+
public function getFunctions()
|
47 |
+
{
|
48 |
+
return [
|
49 |
+
new Twig_SimpleFunction('qrcode_path', [$this, 'qrCodePathFunction']),
|
50 |
+
new Twig_SimpleFunction('qrcode_url', [$this, 'qrCodeUrlFunction']),
|
51 |
+
new Twig_SimpleFunction('qrcode_data_uri', [$this, 'qrCodeDataUriFunction']),
|
52 |
+
];
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @param string $text
|
57 |
+
* @param array $options
|
58 |
+
*
|
59 |
+
* @return string
|
60 |
+
*/
|
61 |
+
public function qrcodeUrlFunction($text, array $options = [])
|
62 |
+
{
|
63 |
+
return $this->getQrCodeReference($text, $options, UrlGeneratorInterface::ABSOLUTE_URL);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @param string $text
|
68 |
+
* @param array $options
|
69 |
+
*
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public function qrCodePathFunction($text, array $options = [])
|
73 |
+
{
|
74 |
+
return $this->getQrCodeReference($text, $options, UrlGeneratorInterface::ABSOLUTE_PATH);
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* @param string $text
|
79 |
+
* @param array $options
|
80 |
+
* @param int $referenceType
|
81 |
+
*
|
82 |
+
* @return string
|
83 |
+
*/
|
84 |
+
public function getQrCodeReference($text, array $options = [], $referenceType)
|
85 |
+
{
|
86 |
+
$qrCode = $this->qrCodeFactory->create($text, $options);
|
87 |
+
$supportedExtensions = $qrCode->getWriter()->getSupportedExtensions();
|
88 |
+
|
89 |
+
$options['text'] = $text;
|
90 |
+
$options['extension'] = current($supportedExtensions);
|
91 |
+
|
92 |
+
return $this->router->generate('endroid_qrcode_generate', $options, $referenceType);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @param string $text
|
97 |
+
* @param array $options
|
98 |
+
*
|
99 |
+
* @return string
|
100 |
+
*
|
101 |
+
* @throws UnsupportedExtensionException
|
102 |
+
*/
|
103 |
+
public function qrcodeDataUriFunction($text, array $options = [])
|
104 |
+
{
|
105 |
+
$qrCode = $this->qrCodeFactory->create($text, $options);
|
106 |
+
|
107 |
+
return $qrCode->writeDataUri();
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @return string
|
112 |
+
*/
|
113 |
+
public function getName()
|
114 |
+
{
|
115 |
+
return 'qrcode';
|
116 |
+
}
|
117 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Writer/AbstractBaconWriter.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Writer;
|
11 |
+
|
12 |
+
use BaconQrCode\Renderer\Color\Rgb;
|
13 |
+
|
14 |
+
abstract class AbstractBaconWriter extends AbstractWriter
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* @param array $color
|
18 |
+
*
|
19 |
+
* @return Rgb
|
20 |
+
*/
|
21 |
+
protected function convertColor(array $color)
|
22 |
+
{
|
23 |
+
$color = new Rgb($color['r'], $color['g'], $color['b']);
|
24 |
+
|
25 |
+
return $color;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @param string $errorCorrectionLevel
|
30 |
+
*
|
31 |
+
* @return string
|
32 |
+
*/
|
33 |
+
protected function convertErrorCorrectionLevel($errorCorrectionLevel)
|
34 |
+
{
|
35 |
+
$name = strtoupper(substr($errorCorrectionLevel, 0, 1));
|
36 |
+
$errorCorrectionLevel = constant('BaconQrCode\Common\ErrorCorrectionLevel::'.$name);
|
37 |
+
|
38 |
+
return $errorCorrectionLevel;
|
39 |
+
}
|
40 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Writer/AbstractWriter.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Writer;
|
11 |
+
|
12 |
+
use Endroid\QrCode\QrCodeInterface;
|
13 |
+
use ReflectionClass;
|
14 |
+
|
15 |
+
abstract class AbstractWriter implements WriterInterface
|
16 |
+
{
|
17 |
+
/**
|
18 |
+
* {@inheritdoc}
|
19 |
+
*/
|
20 |
+
public function writeDataUri(QrCodeInterface $qrCode)
|
21 |
+
{
|
22 |
+
$dataUri = 'data:'.$this->getContentType().';base64,'.base64_encode($this->writeString($qrCode));
|
23 |
+
|
24 |
+
return $dataUri;
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* {@inheritdoc}
|
29 |
+
*/
|
30 |
+
public function writeFile(QrCodeInterface $qrCode, $path)
|
31 |
+
{
|
32 |
+
$string = $this->writeString($qrCode);
|
33 |
+
file_put_contents($path, $string);
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* {@inheritdoc}
|
38 |
+
*/
|
39 |
+
public static function supportsExtension($extension)
|
40 |
+
{
|
41 |
+
return in_array($extension, static::getSupportedExtensions());
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* {@inheritdoc}
|
46 |
+
*/
|
47 |
+
public static function getSupportedExtensions()
|
48 |
+
{
|
49 |
+
return [];
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* {@inheritdoc}
|
54 |
+
*/
|
55 |
+
public function getName()
|
56 |
+
{
|
57 |
+
$reflectionClass = new ReflectionClass($this);
|
58 |
+
$className = $reflectionClass->getShortName();
|
59 |
+
$name = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', str_replace('Writer', '', $className)));
|
60 |
+
|
61 |
+
return $name;
|
62 |
+
}
|
63 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Writer/BinaryWriter.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Writer;
|
11 |
+
|
12 |
+
use Endroid\QrCode\QrCodeInterface;
|
13 |
+
|
14 |
+
class BinaryWriter extends AbstractWriter
|
15 |
+
{
|
16 |
+
/**
|
17 |
+
* {@inheritdoc}
|
18 |
+
*/
|
19 |
+
public function writeString(QrCodeInterface $qrCode)
|
20 |
+
{
|
21 |
+
$string = '
|
22 |
+
0001010101
|
23 |
+
0001010101
|
24 |
+
1000101010
|
25 |
+
0001010101
|
26 |
+
0101010101
|
27 |
+
0001010101
|
28 |
+
0001010101
|
29 |
+
0001010101
|
30 |
+
0001010101
|
31 |
+
1000101010
|
32 |
+
';
|
33 |
+
|
34 |
+
return $string;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* {@inheritdoc}
|
39 |
+
*/
|
40 |
+
public static function getContentType()
|
41 |
+
{
|
42 |
+
return 'text/plain';
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* {@inheritdoc}
|
47 |
+
*/
|
48 |
+
public static function getSupportedExtensions()
|
49 |
+
{
|
50 |
+
return ['bin', 'txt'];
|
51 |
+
}
|
52 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Writer/DebugWriter.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Writer;
|
11 |
+
|
12 |
+
use Endroid\QrCode\QrCodeInterface;
|
13 |
+
use ReflectionClass;
|
14 |
+
use Exception;
|
15 |
+
|
16 |
+
class DebugWriter extends AbstractWriter
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
* {@inheritdoc}
|
20 |
+
*/
|
21 |
+
public function writeString(QrCodeInterface $qrCode)
|
22 |
+
{
|
23 |
+
$data = [];
|
24 |
+
|
25 |
+
$reflectionClass = new ReflectionClass($qrCode);
|
26 |
+
foreach ($reflectionClass->getMethods() as $method) {
|
27 |
+
$methodName = $method->getShortName();
|
28 |
+
if (0 === strpos($methodName, 'get') && 0 == $method->getNumberOfParameters()) {
|
29 |
+
$value = $qrCode->{$methodName}();
|
30 |
+
if (is_array($value) && !is_object(current($value))) {
|
31 |
+
$value = '['.implode(', ', $value).']';
|
32 |
+
} elseif (is_bool($value)) {
|
33 |
+
$value = $value ? 'true' : 'false';
|
34 |
+
} elseif (is_string($value)) {
|
35 |
+
$value = '"'.$value.'"';
|
36 |
+
} elseif (is_null($value)) {
|
37 |
+
$value = 'null';
|
38 |
+
}
|
39 |
+
try {
|
40 |
+
$data[] = $methodName.': '.$value;
|
41 |
+
} catch (Exception $exception) {
|
42 |
+
}
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
$string = implode(" \n", $data);
|
47 |
+
|
48 |
+
return $string;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* {@inheritdoc}
|
53 |
+
*/
|
54 |
+
public static function getContentType()
|
55 |
+
{
|
56 |
+
return 'text/plain';
|
57 |
+
}
|
58 |
+
}
|
src/lib/vendor/endroid/qr-code/src/Writer/EpsWriter.php
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
* (c) Jeroen van den Enden <info@endroid.nl>
|
5 |
+
*
|
6 |
+
* This source file is subject to the MIT license that is bundled
|
7 |
+
* with this source code in the file LICENSE.
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace Endroid\QrCode\Writer;
|
11 |
+
|
12 |
+
use BaconQrCode\Renderer\Image\Eps;
|
13 |
+
use BaconQrCode\Writer;
|
14 |
+
use Endroid\QrCode\QrCodeInterface;
|
15 |
+
|
16 |
+
class EpsWriter extends AbstractBaconWriter
|
17 |
+
{
|
18 |
+
/**
|
19 |
+
|