diff --git a/.github/ISSUE_TEMPLATE/1_bug_report.yml b/.github/ISSUE_TEMPLATE/1_bug_report.yml index d8e1c50..6201e46 100644 --- a/.github/ISSUE_TEMPLATE/1_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1_bug_report.yml @@ -23,7 +23,7 @@ body: attributes: label: IconCaptcha version description: Please specify the version of the package that you are using. - placeholder: "e.g. 4.0.3" + placeholder: "e.g. 4.0.4" validations: required: true - type: input @@ -31,7 +31,7 @@ body: attributes: label: PHP version description: Please specify the version of PHP you are using. - placeholder: e.g. 8.2.0 + placeholder: e.g. 8.4.0 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/2_blank_issue.yml b/.github/ISSUE_TEMPLATE/2_blank_issue.yml index 61da860..1ca415f 100644 --- a/.github/ISSUE_TEMPLATE/2_blank_issue.yml +++ b/.github/ISSUE_TEMPLATE/2_blank_issue.yml @@ -12,7 +12,7 @@ body: attributes: label: IconCaptcha version description: Please specify the version of the package that you are using. - placeholder: "e.g. 4.0.3" + placeholder: "e.g. 4.0.4" validations: required: true - type: input @@ -20,7 +20,7 @@ body: attributes: label: PHP version description: Please specify the version of PHP you are using. - placeholder: e.g. 8.2.0 + placeholder: e.g. 8.4.0 validations: required: true - type: textarea diff --git a/CHANGELOG.md b/CHANGELOG.md index f37e85a..6899ea8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes will be documented in this file. Only changes starting at IconCaptcha 2.0.2 have been recorded. +## 4.0.4 - January 23, 2025 +Release: [View tag 4.0.4](https://github.com/fabianwennink/IconCaptcha-PHP/releases/tag/4.0.4) + +### Fixed +- Fixed a compatibility issue with PHP 8.4 caused by a deprecation warning for "implicitly marked nullable parameters", which was breaking the code. + +For a full list of commits and changes, please refer to the [full commit changelog](https://github.com/fabianwennink/IconCaptcha-PHP/compare/4.0.3...4.0.4). + ## 4.0.3 - Dec 19, 2023 Release: [View tag 4.0.3](https://github.com/fabianwennink/IconCaptcha-PHP/releases/tag/4.0.3) diff --git a/README.md b/README.md index 6df9a68..593ec23 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@

- Version + Version Latest Version on Packagist License Support via PayPal diff --git a/assets/client/css/iconcaptcha.min.css b/assets/client/css/iconcaptcha.min.css index 29d5dee..a1af9ef 100644 --- a/assets/client/css/iconcaptcha.min.css +++ b/assets/client/css/iconcaptcha.min.css @@ -1,2 +1,2 @@ -/*! IconCaptcha v4.0.1 | (c) 2023, Fabian Wennink (fabianwennink.nl) | fabianwennink.nl/projects/IconCaptcha-Widget/license */ -.iconcaptcha-widget{position:relative;max-width:330px;min-height:50px;width:99%;height:auto;border-radius:8px;font-family:inherit;text-shadow:none;line-height:1;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}.iconcaptcha-widget a{text-decoration:none}.iconcaptcha-widget.iconcaptcha-init{-webkit-transition:background 150ms linear;transition:background 150ms linear}.iconcaptcha-widget.iconcaptcha-init:hover{-webkit-transition:background 150ms linear;transition:background 150ms linear}.iconcaptcha-widget.iconcaptcha-init:hover .iconcaptcha-modal__body-circle{opacity:.75;-webkit-transition:opacity .1s linear;transition:opacity .1s linear}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body{cursor:pointer}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body-circle{width:28px;height:28px;border-radius:100%;border:6px solid #52b3d9;position:absolute;top:13px;left:15px;-webkit-transition:opacity .1s linear;transition:opacity .1s linear;-webkit-animation:captcha-breathing 5s infinite linear;animation:captcha-breathing 5s infinite linear}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body-circle--speed{-webkit-animation-duration:2s;animation-duration:2s}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body-title,.iconcaptcha-widget.iconcaptcha-success .iconcaptcha-modal__body-title{font-size:15px;font-weight:bold;top:19px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:20px;padding-left:60px}.iconcaptcha-widget .iconcaptcha-modal{width:100%;display:block}.iconcaptcha-widget .iconcaptcha-modal__header{height:auto;padding:0 10px;display:block}.iconcaptcha-widget .iconcaptcha-modal__header span{padding:6px 0;display:block;text-align:center;font-size:11px;line-height:14px;font-weight:bold;cursor:default}.iconcaptcha-widget .iconcaptcha-modal__header span::-moz-selection{background:none !important}.iconcaptcha-widget .iconcaptcha-modal__header span::selection{background:none !important}.iconcaptcha-widget .iconcaptcha-modal__header span::-moz-selection{background:none !important}.iconcaptcha-widget .iconcaptcha-modal__body{display:block;overflow:hidden;position:relative;height:50px;min-height:50px;padding:2px 4px;text-align:center;-webkit-box-align:center;-webkit-box-pack:center;-webkit-box-sizing:initial;box-sizing:initial}.iconcaptcha-widget .iconcaptcha-modal__body-title{font-size:20px;font-weight:700;text-transform:uppercase;display:inline-block;width:100%;position:absolute;left:0;right:0;top:8px}.iconcaptcha-widget .iconcaptcha-modal__body-subtitle{font-size:12px;display:inline-block;width:100%;position:absolute;left:0;right:0;top:35px}.iconcaptcha-widget .iconcaptcha-modal__body-icons{position:relative;height:50px;background-repeat:no-repeat;background-position:50% 50%;z-index:1}.iconcaptcha-widget .iconcaptcha-modal__body-selection{position:absolute;left:0;top:2px;bottom:0;right:0;margin:2px 4px;z-index:999;cursor:none;height:50px}.iconcaptcha-widget .iconcaptcha-modal__body-selection>i{content:"";width:14px;height:14px;border-radius:100%;background:#52b3d9;position:absolute;display:none}.iconcaptcha-widget .iconcaptcha-modal__body-info{position:absolute;right:6px;bottom:4px;font-size:9px}.iconcaptcha-widget .iconcaptcha-modal__body-info:hover{text-decoration:underline}.iconcaptcha-widget .iconcaptcha-modal__body-icons,.iconcaptcha-widget .iconcaptcha-modal__body-selection{width:100%;max-width:320px;margin:0 auto}.iconcaptcha-widget .iconcaptcha-modal__body .captcha-loader{margin:auto;position:absolute;width:34px;height:34px;border-radius:100%;border:6px solid #52b3d9;z-index:10;top:0;left:0;bottom:0;right:0;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-animation:captcha-breathing 2s infinite ease-in-out;animation:captcha-breathing 2s infinite ease-in-out}.iconcaptcha-widget .iconcaptcha-modal__body.captcha-opacity>canvas:not(.captcha-loader){-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=15);-moz-opacity:.15;-khtml-opacity:.15;opacity:.15;cursor:default;pointer-events:none}.iconcaptcha-widget .iconcaptcha-modal__body.captcha-opacity>canvas:not(.captcha-loader):after,.iconcaptcha-widget .iconcaptcha-modal__body.captcha-opacity>canvas:not(.captcha-loader):hover:after{content:none}.iconcaptcha-widget .iconcaptcha-modal__body-checkmark{width:28px;height:28px;position:absolute;top:13px;left:15px}.iconcaptcha-widget .iconcaptcha-modal__footer{display:block !important;font-size:9px;padding:3px;cursor:default;text-align:center}.iconcaptcha-widget .iconcaptcha-modal__footer>span a{text-decoration:none;-webkit-transition:color .1s linear;transition:color .1s linear;text-align:center}.iconcaptcha-widget .iconcaptcha-modal__footer>span a:hover{-webkit-transition:color .1s linear;transition:color .1s linear}.iconcaptcha-widget .iconcaptcha-modal__footer--hide{visibility:hidden}.iconcaptcha-widget .iconcaptcha-modal__fields{display:none;visibility:hidden}.iconcaptcha-widget .iconcaptcha-modal__fields input[type=text]{display:none;visibility:hidden}.iconcaptcha-widget.iconcaptcha-theme-light{background:#fafafa;border:1px solid #d8d8d8}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__header{border-bottom:2px solid #d8d8d8}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__body-subtitle{color:#9e9e9e}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__footer{color:#a7a7a7;border-top:2px solid #d8d8d8;padding-top:6px;padding-bottom:5px}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__footer>span a{color:#448aff;text-transform:uppercase;font-weight:bold}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__footer>span a:hover{color:#74a8ff}.iconcaptcha-widget.iconcaptcha-theme-dark{background:#4c4c4c;border:1px solid #404040}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__header{border-bottom:2px solid #404040}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__header span{color:#dadada}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__body-subtitle{color:#b1b1b1}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__footer{color:#a7a7a7;border-top:2px solid #404040;padding-top:6px;padding-bottom:5px}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__footer>span a{color:#fff;text-transform:uppercase;font-weight:bold}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__footer>span a:hover{color:#f0f0f0}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-init:hover{background:#f1f1f1}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-init .iconcaptcha-modal__body-title{color:#464646}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__header span{color:#1d1d1d}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__body-info a{color:#afafaf}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-success .iconcaptcha-modal__body-checkmark svg{stroke:#5bd25b}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-success .iconcaptcha-modal__body-title{color:#5bd25b}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-error .iconcaptcha-modal__body-title{color:#ef5858}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-init:hover{background:#454545}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-init .iconcaptcha-modal__body-title{color:#dadada}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__header span{color:#dadada}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__body-info a{color:#b1b1b1}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-success .iconcaptcha-modal__body-checkmark svg{stroke:#93d293}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-success .iconcaptcha-modal__body-title{color:#93d293}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-error .iconcaptcha-modal__body-title{color:#ef5858}.iconcaptcha-widget.iconcaptcha-success,.iconcaptcha-widget.iconcaptcha-error{cursor:default}.iconcaptcha-widget *{-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:antialiased}.iconcaptcha-widget *::-moz-selection{background:none !important}.iconcaptcha-widget *::selection{background:none !important}.iconcaptcha-widget *::-moz-selection{background:none !important}@-webkit-keyframes captcha-breathing{0%,100%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}25%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}50%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}75%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}}@keyframes captcha-breathing{0%,100%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}25%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}50%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}75%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}} \ No newline at end of file +/*! IconCaptcha v4.0.2 | (c) 2017-2025, Fabian Wennink (fabianwennink.nl) | fabianwennink.nl/projects/IconCaptcha-Widget/license */ +.iconcaptcha-widget{position:relative;max-width:330px;min-height:50px;width:99%;height:auto;border-radius:8px;font-family:inherit;text-shadow:none;line-height:1;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}.iconcaptcha-widget a{text-decoration:none}.iconcaptcha-widget.iconcaptcha-init{-webkit-transition:background 150ms linear;transition:background 150ms linear}.iconcaptcha-widget.iconcaptcha-init:hover{-webkit-transition:background 150ms linear;transition:background 150ms linear}.iconcaptcha-widget.iconcaptcha-init:hover .iconcaptcha-modal__body-circle{opacity:.75;-webkit-transition:opacity .1s linear;transition:opacity .1s linear}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body{cursor:pointer}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body-circle{width:28px;height:28px;border-radius:100%;border:6px solid #52b3d9;position:absolute;top:13px;left:15px;-webkit-transition:opacity .1s linear;transition:opacity .1s linear;-webkit-animation:captcha-breathing 5s infinite linear;animation:captcha-breathing 5s infinite linear}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body-circle--speed{-webkit-animation-duration:2s;animation-duration:2s}.iconcaptcha-widget.iconcaptcha-init .iconcaptcha-modal__body-title,.iconcaptcha-widget.iconcaptcha-success .iconcaptcha-modal__body-title{font-size:15px;font-weight:bold;top:19px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:20px;padding-left:60px}.iconcaptcha-widget .iconcaptcha-modal{width:100%;display:block}.iconcaptcha-widget .iconcaptcha-modal__header{height:auto;padding:0 10px;display:block}.iconcaptcha-widget .iconcaptcha-modal__header span{padding:6px 0;display:block;text-align:center;font-size:11px;line-height:14px;font-weight:bold;cursor:default}.iconcaptcha-widget .iconcaptcha-modal__header span::-moz-selection{background:none !important}.iconcaptcha-widget .iconcaptcha-modal__header span::selection{background:none !important}.iconcaptcha-widget .iconcaptcha-modal__header span::-moz-selection{background:none !important}.iconcaptcha-widget .iconcaptcha-modal__body{display:block;overflow:hidden;position:relative;height:50px;padding:2px 4px;text-align:center;-webkit-box-align:center;-webkit-box-pack:center;-webkit-box-sizing:initial;box-sizing:initial}.iconcaptcha-widget .iconcaptcha-modal__body-title{font-size:20px;font-weight:700;text-transform:uppercase;display:inline-block;width:100%;position:absolute;left:0;right:0;top:8px}.iconcaptcha-widget .iconcaptcha-modal__body-subtitle{font-size:12px;display:inline-block;width:100%;position:absolute;left:0;right:0;top:35px}.iconcaptcha-widget .iconcaptcha-modal__body-icons{position:relative;height:50px;background-repeat:no-repeat;background-position:50% 50%;z-index:1}.iconcaptcha-widget .iconcaptcha-modal__body-selection{position:absolute;left:0;top:2px;bottom:0;right:0;margin:2px 4px;z-index:999;cursor:none;height:50px}.iconcaptcha-widget .iconcaptcha-modal__body-selection>i{content:"";width:14px;height:14px;border-radius:100%;background:#52b3d9;position:absolute;display:none}.iconcaptcha-widget .iconcaptcha-modal__body-info{position:absolute;right:6px;bottom:4px;font-size:9px}.iconcaptcha-widget .iconcaptcha-modal__body-info:hover{text-decoration:underline}.iconcaptcha-widget .iconcaptcha-modal__body-icons,.iconcaptcha-widget .iconcaptcha-modal__body-selection{width:100%;max-width:320px;margin:0 auto}.iconcaptcha-widget .iconcaptcha-modal__body .captcha-loader{margin:auto;position:absolute;width:34px;height:34px;border-radius:100%;border:6px solid #52b3d9;z-index:10;top:0;left:0;bottom:0;right:0;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-animation:captcha-breathing 2s infinite ease-in-out;animation:captcha-breathing 2s infinite ease-in-out}.iconcaptcha-widget .iconcaptcha-modal__body.captcha-opacity>canvas:not(.captcha-loader){-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=15);-moz-opacity:.15;-khtml-opacity:.15;opacity:.15;cursor:default;pointer-events:none}.iconcaptcha-widget .iconcaptcha-modal__body.captcha-opacity>canvas:not(.captcha-loader):after,.iconcaptcha-widget .iconcaptcha-modal__body.captcha-opacity>canvas:not(.captcha-loader):hover:after{content:none}.iconcaptcha-widget .iconcaptcha-modal__body-checkmark{width:28px;height:28px;position:absolute;top:13px;left:15px}.iconcaptcha-widget .iconcaptcha-modal__footer{display:block !important;font-size:9px;padding:3px;cursor:default;text-align:center}.iconcaptcha-widget .iconcaptcha-modal__footer>span a{text-decoration:none;-webkit-transition:color .1s linear;transition:color .1s linear;text-align:center}.iconcaptcha-widget .iconcaptcha-modal__footer>span a:hover{-webkit-transition:color .1s linear;transition:color .1s linear}.iconcaptcha-widget .iconcaptcha-modal__footer--hide{visibility:hidden}.iconcaptcha-widget .iconcaptcha-modal__fields{display:none;visibility:hidden}.iconcaptcha-widget .iconcaptcha-modal__fields input[type=text]{display:none;visibility:hidden}.iconcaptcha-widget.iconcaptcha-theme-light{background:#fafafa;border:1px solid #d8d8d8}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__header{border-bottom:2px solid #d8d8d8}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__body-subtitle{color:#9e9e9e}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__footer{color:#a7a7a7;border-top:2px solid #d8d8d8;padding-top:6px;padding-bottom:5px}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__footer>span a{color:#448aff;text-transform:uppercase;font-weight:bold}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__footer>span a:hover{color:#74a8ff}.iconcaptcha-widget.iconcaptcha-theme-dark{background:#4c4c4c;border:1px solid #404040}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__header{border-bottom:2px solid #404040}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__header span{color:#dadada}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__body-subtitle{color:#b1b1b1}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__footer{color:#a7a7a7;border-top:2px solid #404040;padding-top:6px;padding-bottom:5px}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__footer>span a{color:#fff;text-transform:uppercase;font-weight:bold}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__footer>span a:hover{color:#f0f0f0}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-init:hover{background:#f1f1f1}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-init .iconcaptcha-modal__body-title{color:#464646}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__header span{color:#1d1d1d}.iconcaptcha-widget.iconcaptcha-theme-light .iconcaptcha-modal__body-info a{color:#afafaf}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-success .iconcaptcha-modal__body-checkmark svg{stroke:#5bd25b}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-success .iconcaptcha-modal__body-title{color:#5bd25b}.iconcaptcha-widget.iconcaptcha-theme-light.iconcaptcha-error .iconcaptcha-modal__body-title{color:#ef5858}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-init:hover{background:#454545}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-init .iconcaptcha-modal__body-title{color:#dadada}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__header span{color:#dadada}.iconcaptcha-widget.iconcaptcha-theme-dark .iconcaptcha-modal__body-info a{color:#b1b1b1}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-success .iconcaptcha-modal__body-checkmark svg{stroke:#93d293}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-success .iconcaptcha-modal__body-title{color:#93d293}.iconcaptcha-widget.iconcaptcha-theme-dark.iconcaptcha-error .iconcaptcha-modal__body-title{color:#ef5858}.iconcaptcha-widget.iconcaptcha-success,.iconcaptcha-widget.iconcaptcha-error{cursor:default}.iconcaptcha-widget *{-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:antialiased}.iconcaptcha-widget *::-moz-selection{background:none !important}.iconcaptcha-widget *::selection{background:none !important}.iconcaptcha-widget *::-moz-selection{background:none !important}@-webkit-keyframes captcha-breathing{0%,100%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}25%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}50%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}75%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}}@keyframes captcha-breathing{0%,100%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}25%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}50%{-webkit-transform:scale(1) translateZ(0);transform:scale(1) translateZ(0);border-color:#52b3d9}75%{-webkit-transform:scale(0.8) translateZ(0);transform:scale(0.8) translateZ(0);border-color:#41a2c7}} \ No newline at end of file diff --git a/assets/client/js/iconcaptcha.min.js b/assets/client/js/iconcaptcha.min.js index ab17013..71dd07c 100644 --- a/assets/client/js/iconcaptcha.min.js +++ b/assets/client/js/iconcaptcha.min.js @@ -1,2 +1,2 @@ -/*! IconCaptcha v4.0.1 | (c) 2023, Fabian Wennink (fabianwennink.nl) | fabianwennink.nl/projects/IconCaptcha-Widget/license */ -"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var IconCaptchaPolyfills=function(){var e={extend:function(e){e=e||{};for(var t=1;t=e.length?{done:!0}:{done:!1,value:e[a++]}},e:function(e){throw e},f:t}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,r=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){r=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(r)throw o}}}}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Map"===(n="Object"===n&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=new Array(t);nleast amount of times",correct:"Verification complete.",incorrect:{title:"Uh oh.",subtitle:"You've selected the wrong image."},timeout:{title:"Please wait.",subtitle:"You made too many incorrect selections."}}},k="https://www.fabianwennink.nl/projects/IconCaptcha",x="IconCaptcha by Fabian Wennink";e.$init=function(e,t){return n(this,e,t)},e.init=function(e,t){e=Array.from(document.querySelectorAll(e));return n(this,e,t)},e.reset=function(t){return void 0===this.instances?console.error("IconCaptcha has not yet been initialized. Cannot use 'reset' yet."):a(this.instances,function(e){void 0!==t&&e.id!==t||null!=e&&e.reset()}),this},e.bind=function(t,n){return void 0===this.instances?console.error("IconCaptcha has not yet been initialized. Cannot use 'bind' yet."):a(this.instances,function(e){e.element.addEventListener(t,n)}),this};var n=function(e,t,n){if(void 0===e.instances||!t.some(function(e){return null!==e.querySelector(".iconcaptcha-modal")})){void 0===e.instances&&(e.instances={});var a=IconCaptchaPolyfills.extend({},r,n||{}),o=Object.values(e.instances).length;e.instances[o]=[];for(var i=0;i","

","
","
".concat(i.locale.initialization.verify,"
"),"
",""],t=i.general.showCredits?"":"display: none",e.splice(4,0,"
"),"IconCaptcha ©"),"
"),l.classList.add("iconcaptcha-init"),l.classList.remove("iconcaptcha-error","iconcaptcha-success"),void(l.innerHTML=e.join(""));p||function(){var e=[];e.push("
","
","".concat(i.locale.header,""),"
","
","","
","","
","");for(var n=0,a=["wid","cid","hp"];n"))}e.push("
"),l.innerHTML=e.join(""),r=l.querySelector(".iconcaptcha-modal__body")}(),I(),i.security.loadingAnimationDuration&&0'),n=r.querySelector(".iconcaptcha-modal__body-selection > i"),function(e){for(var t in e._ic_listeners={click:function(e){var t,n,a;new Date-f<=i.security.interactionDelay||i.security.hoverProtection&&!y||(t=IconCaptchaPolyfills.offset(e.currentTarget),n=e.pageX-t.left,a=e.pageY-t.top,n&&a&&(r.classList.contains("captcha-opacity")||(IconCaptchaPolyfills.trigger(l,"selected",{captchaId:c}),i.security.loadingAnimationDuration&&0"),m(),IconCaptchaPolyfills.trigger(l,"refreshed",{captchaId:c})}function _(e,t){void 0!==e&&void 0!==t&&(h=!0,O(),e=Math.round(e),t=Math.round(t),n.style.display="none",t=T({widgetId:c,challengeId:a,action:"SELECTION",x:e,y:t,width:u,token:o}),IconCaptchaPolyfills.ajax({url:i.general.endpoint,type:"POST",headers:L(o),data:{payload:t},success:function(e){e=j(e);e.completed?w(e):C()},error:function(){return A(-1)}}))}function w(e){r.classList.remove("captcha-opacity"),D(l.querySelector(".iconcaptcha-modal__body-selection")),null!=e&&e.expiredAt&&(o=e.expiredAt-Date.now(),d=setTimeout(S,o));var t,n=_createForOfIteratorHelper(l.querySelectorAll(".iconcaptcha-modal__header, .iconcaptcha-modal__footer, .iconcaptcha-modal__body"));try{for(n.s();!(t=n.n()).done;){var a=t.value;a.parentNode.removeChild(a)}}catch(e){n.e(e)}finally{n.f()}l.classList.add("iconcaptcha-success");var e='
'+'
'.concat(i.locale.correct,"
")+'
'.concat('',"
"),o=i.general.showCredits?"":"display: none";e+="",e+="
",l.querySelector(".iconcaptcha-modal").innerHTML+=e,h=!1,IconCaptchaPolyfills.trigger(l,"success",{captchaId:c})}function C(e,t,n){n=!(2'.concat(e,"")+'
'.concat(t,"
"),h=!1,IconCaptchaPolyfills.trigger(l,"error",{captchaId:c}),n&&setTimeout(b,i.security.incorrectSelectionResetDelay)}function I(){r.classList.add("captcha-opacity"),r.insertAdjacentHTML("beforeend",'
')}function S(){a=void 0,s=p=!1,b(),IconCaptchaPolyfills.trigger(l,"invalidated",{captchaId:c})}function O(){null!==d&&(clearTimeout(d),d=null)}function A(e,t){switch(e){case"too-many-attempts":C(i.locale.timeout.title,i.locale.timeout.subtitle,!1);var n=l.querySelector(".iconcaptcha-modal__header");n.parentNode.removeChild(n),IconCaptchaPolyfills.trigger(l,"timeout",{captchaId:c}),setTimeout(S,t);break;case"invalid-form-token":P(!0,"Captcha form token is missing or incorrect.","A server request was made without including a captcha token, however this option is enabled.");break;default:P(!0,"An unexpected error occurred.","An unexpected error occurred while IconCaptcha performed an action.")}}function P(e,t,n){n=2=e.length?{done:!0}:{done:!1,value:e[a++]}},e:function(e){throw e},f:t}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,r=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){r=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(r)throw o}}}}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Map"===(n="Object"===n&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=new Array(t);nleast amount of times",correct:"Verification complete.",incorrect:{title:"Uh oh.",subtitle:"You've selected the wrong image."},timeout:{title:"Please wait.",subtitle:"You made too many incorrect selections."}}},q="https://www.fabianwennink.nl/projects/IconCaptcha/",k="IconCaptcha by Fabian Wennink",M=320,E=50;e.$init=function(e,t){return n(this,e,t)},e.init=function(e,t){e=Array.from(document.querySelectorAll(e));return n(this,e,t)},e.reset=function(t){return void 0===this.instances?console.error("IconCaptcha has not yet been initialized. Cannot use 'reset' yet."):a(this.instances,function(e){void 0!==t&&e.id!==t||null!=e&&e.reset()}),this},e.bind=function(t,n){return void 0===this.instances?console.error("IconCaptcha has not yet been initialized. Cannot use 'bind' yet."):a(this.instances,function(e){e.element.addEventListener(t,n)}),this};var n=function(e,t,n){if(void 0===e.instances||!t.some(function(e){return null!==e.querySelector(".iconcaptcha-modal")})){void 0===e.instances&&(e.instances={});var a=IconCaptchaPolyfills.extend({},r,n||{}),o=Object.values(e.instances).length;e.instances[o]=[];for(var i=0;i","
","
","
".concat(i.locale.initialization.verify,"
"),"
",""],t=i.general.showCredits?"":"display: none",e.splice(4,0,""),l.classList.add("iconcaptcha-init"),l.classList.remove("iconcaptcha-error","iconcaptcha-success"),void(l.innerHTML=e.join(""));p||function(){var e=[];e.push("
","
","".concat(i.locale.header,""),"
","
","","
","","
","");for(var n=0,a=["wid","cid","hp"];n"))}e.push("
"),l.innerHTML=e.join(""),r=l.querySelector(".iconcaptcha-modal__body")}(),C(),i.security.loadingAnimationDuration&&0'),n=r.querySelector(".iconcaptcha-modal__body-selection > i"),function(e){for(var t in e._ic_listeners={click:function(e){var t,n,a;new Date-f<=i.security.interactionDelay||i.security.hoverProtection&&!y||(t=IconCaptchaPolyfills.offset(e.currentTarget),n=e.pageX-t.left,a=e.pageY-t.top,n&&a&&(r.classList.contains("captcha-opacity")||(IconCaptchaPolyfills.trigger(l,"selected",{captchaId:c}),i.security.loadingAnimationDuration&&0"),m(),IconCaptchaPolyfills.trigger(l,"refreshed",{captchaId:c})}function _(e,t){void 0!==e&&void 0!==t&&(h=!0,O(),e=Math.round(e),t=Math.round(t),n.style.display="none",t=T({widgetId:c,challengeId:a,action:"SELECTION",x:e,y:t,width:u,token:o}),IconCaptchaPolyfills.ajax({url:i.general.endpoint,type:"POST",headers:L(o),data:{payload:t},success:function(e){e=j(e);e.completed?w(e):I()},error:function(){return A(-1)}}))}function w(e){r.classList.remove("captcha-opacity"),D(l.querySelector(".iconcaptcha-modal__body-selection")),null!=e&&e.expiredAt&&(o=e.expiredAt-Date.now(),d=setTimeout(S,o));var t,n=_createForOfIteratorHelper(l.querySelectorAll(".iconcaptcha-modal__header, .iconcaptcha-modal__footer, .iconcaptcha-modal__body"));try{for(n.s();!(t=n.n()).done;){var a=t.value;a.parentNode.removeChild(a)}}catch(e){n.e(e)}finally{n.f()}l.classList.add("iconcaptcha-success");var e='
'+'
'.concat(i.locale.correct,"
")+'
'.concat('',"
"),o=i.general.showCredits?"":"display: none";e+="",e+="
",l.querySelector(".iconcaptcha-modal").innerHTML+=e,h=!1,IconCaptchaPolyfills.trigger(l,"success",{captchaId:c})}function I(e,t,n){n=!(2'.concat(e,"")+'
'.concat(t,"
"),h=!1,IconCaptchaPolyfills.trigger(l,"error",{captchaId:c}),n&&setTimeout(b,i.security.incorrectSelectionResetDelay)}function C(){r.classList.add("captcha-opacity"),r.insertAdjacentHTML("beforeend",'
')}function S(){a=void 0,s=p=!1,b(),IconCaptchaPolyfills.trigger(l,"invalidated",{captchaId:c})}function O(){null!==d&&(clearTimeout(d),d=null)}function A(e,t){switch(e){case"too-many-attempts":I(i.locale.timeout.title,i.locale.timeout.subtitle,!1);var n=l.querySelector(".iconcaptcha-modal__header");n.parentNode.removeChild(n),IconCaptchaPolyfills.trigger(l,"timeout",{captchaId:c}),setTimeout(S,t);break;case"invalid-form-token":P(!0,"Captcha form token is missing or incorrect.","A server request was made without including a captcha token, however this option is enabled.");break;default:P(!0,"An unexpected error occurred.","An unexpected error occurred while IconCaptcha performed an action.")}}function P(e,t,n){n=2 - IconCaptcha v4.0.3 - By Fabian Wennink + IconCaptcha v4.0.4 - By Fabian Wennink @@ -38,7 +38,7 @@ diff --git a/examples/forms/ajax/ajax-submit.php b/examples/forms/ajax/ajax-submit.php index 4a4160d..872f3ce 100644 --- a/examples/forms/ajax/ajax-submit.php +++ b/examples/forms/ajax/ajax-submit.php @@ -25,7 +25,7 @@ if ($validation->success()) { echo 'Captcha: The form has been submitted!'; } else { - echo 'Captcha: Validation failed with error code:' . $validation->getErrorCode(); + echo 'Captcha: Validation failed with error code: ' . $validation->getErrorCode(); } } else { echo 'Captcha: No data posted!'; diff --git a/examples/forms/regular-form.php b/examples/forms/regular-form.php index 2bd1ceb..370d560 100644 --- a/examples/forms/regular-form.php +++ b/examples/forms/regular-form.php @@ -31,7 +31,7 @@ - IconCaptcha v4.0.3 - By Fabian Wennink + IconCaptcha v4.0.4 - By Fabian Wennink @@ -58,7 +58,7 @@ diff --git a/index.php b/index.php index daa905d..f6db410 100644 --- a/index.php +++ b/index.php @@ -1,7 +1,7 @@ - IconCaptcha v4.0.3 - By Fabian Wennink + IconCaptcha v4.0.4 - By Fabian Wennink @@ -20,7 +20,7 @@ diff --git a/src/Challenge/Challenge.php b/src/Challenge/Challenge.php index 828fb2a..5af7618 100644 --- a/src/Challenge/Challenge.php +++ b/src/Challenge/Challenge.php @@ -75,7 +75,7 @@ public function __construct($storage, array $options) * @param string $widgetId The widget identifier. * @param string|null $challengeId The challenge identifier. */ - public function initialize(string $widgetId, string $challengeId = null): Challenge + public function initialize(string $widgetId, ?string $challengeId = null): Challenge { // Get the visitor's current IP address. $ipAddress = Utils::getIpAddress($this->options['ipAddress']); diff --git a/src/Challenge/Hooks/InvalidHookException.php b/src/Challenge/Hooks/InvalidHookException.php index ba07bf4..538cff0 100644 --- a/src/Challenge/Hooks/InvalidHookException.php +++ b/src/Challenge/Hooks/InvalidHookException.php @@ -20,7 +20,7 @@ class InvalidHookException extends Exception * @param string $path The path of the non-existing file. * @inheritDoc */ - public function __construct(string $hook, string $message = null, int $code = 0, Throwable $previous = null) + public function __construct(string $hook, ?string $message = null, int $code = 0, ?Throwable $previous = null) { if ($message === null) { $message = "Hook \"$hook\" is invalid. A hook must be a class implementing the necessary interface."; diff --git a/src/Challenge/Image/AbstractImageGenerator.php b/src/Challenge/Image/AbstractImageGenerator.php index b1cff7f..0aaeed7 100644 --- a/src/Challenge/Image/AbstractImageGenerator.php +++ b/src/Challenge/Image/AbstractImageGenerator.php @@ -148,12 +148,10 @@ public function generate(string $iconPath, string $placeholderPath) } // Call the image generation hook, if provided. - $placeholder = Hook::call( + return Hook::call( 'generation', GenerationHookInterface::class, 'generate', $this->session, $this->options, $placeholder, $placeholder ); - - return $placeholder; } /** diff --git a/src/Challenge/ValidationResult.php b/src/Challenge/ValidationResult.php index 196ce9c..f3e8acf 100644 --- a/src/Challenge/ValidationResult.php +++ b/src/Challenge/ValidationResult.php @@ -25,7 +25,7 @@ final class ValidationResult * @param bool $success * @param string|null $errorCode */ - public function __construct(bool $success, string $errorCode = null) + public function __construct(bool $success, ?string $errorCode = null) { $this->success = $success; $this->errorCode = $errorCode; diff --git a/src/Challenge/Validator.php b/src/Challenge/Validator.php index 9f8d0b2..260139f 100644 --- a/src/Challenge/Validator.php +++ b/src/Challenge/Validator.php @@ -148,7 +148,7 @@ public function validate(array $request): ValidationResult * @return bool TRUE if the captcha session token matches the given tokens or if the token option is disabled, * FALSE if the captcha session token does not match the given tokens. */ - public function validateToken(string $payloadToken, string $headerToken = null): bool + public function validateToken(string $payloadToken, ?string $headerToken = null): bool { // Only validate if the token option is enabled. if (!empty($this->options['token'])) { diff --git a/src/Exceptions/FileNotFoundException.php b/src/Exceptions/FileNotFoundException.php index 12e5806..9453487 100644 --- a/src/Exceptions/FileNotFoundException.php +++ b/src/Exceptions/FileNotFoundException.php @@ -20,7 +20,7 @@ class FileNotFoundException extends Exception * @param string $path The path of the non-existing file. * @inheritDoc */ - public function __construct(string $path, string $message = null, int $code = 0, Throwable $previous = null) + public function __construct(string $path, ?string $message = null, int $code = 0, ?Throwable $previous = null) { if ($message === null) { $message = "File \"$path\" could not be found."; diff --git a/src/Request.php b/src/Request.php index 74ab44a..af9a71f 100644 --- a/src/Request.php +++ b/src/Request.php @@ -140,7 +140,7 @@ private function validateToken(array $payload): bool } /** - * Create a error message string for the token validation error. + * Create an error message string for the token validation error. */ private function tokenError(): void { diff --git a/src/Session/Drivers/KeyValueSession.php b/src/Session/Drivers/KeyValueSession.php index 0f49066..10a62f1 100644 --- a/src/Session/Drivers/KeyValueSession.php +++ b/src/Session/Drivers/KeyValueSession.php @@ -34,7 +34,7 @@ class KeyValueSession extends Session * @param string $widgetId The captcha widget identifier. * @param string|null $challengeId The captcha challenge identifier. */ - public function __construct(KeyValueStorageInterface $storage, array $options, string $ipAddress, string $widgetId, string $challengeId = null) + public function __construct(KeyValueStorageInterface $storage, array $options, string $ipAddress, string $widgetId, ?string $challengeId = null) { parent::__construct($options, $ipAddress, $widgetId, $challengeId); diff --git a/src/Session/Exceptions/SessionDataParsingFailedException.php b/src/Session/Exceptions/SessionDataParsingFailedException.php index 8e6736c..12025fa 100644 --- a/src/Session/Exceptions/SessionDataParsingFailedException.php +++ b/src/Session/Exceptions/SessionDataParsingFailedException.php @@ -21,7 +21,7 @@ class SessionDataParsingFailedException extends Exception * * @inheritDoc */ - public function __construct(Throwable $previous = null) + public function __construct(?Throwable $previous = null) { $message = 'Failed to parse the data of a SessionData instance.'; diff --git a/src/Session/Session.php b/src/Session/Session.php index ff83905..88fb06a 100644 --- a/src/Session/Session.php +++ b/src/Session/Session.php @@ -68,7 +68,7 @@ abstract class Session implements SessionInterface * @param string $widgetId The widget unique identifier. * @param string|null $challengeId The challenge unique identifier. */ - public function __construct(array $options, string $ipAddress, string $widgetId, string $challengeId = null) + public function __construct(array $options, string $ipAddress, string $widgetId, ?string $challengeId = null) { $this->options = $options; $this->maxIdentifierTries = (int)$options['options']['identifierTries']; diff --git a/src/Session/SessionFactory.php b/src/Session/SessionFactory.php index da2cdca..5b72618 100644 --- a/src/Session/SessionFactory.php +++ b/src/Session/SessionFactory.php @@ -29,7 +29,7 @@ class SessionFactory * @return PDOSession|KeyValueSession|SessionInterface|mixed The generated session instance. * @throws InvalidArgumentException If the configuration contains an invalid driver. */ - public static function create($storage, string $driver, array $options, string $ipAddress, string $widgetId, string $challengeId = null): SessionInterface + public static function create($storage, string $driver, array $options, string $ipAddress, string $widgetId, ?string $challengeId = null): SessionInterface { if (!isset($driver)) { throw new InvalidArgumentException('A session driver must be specified.'); diff --git a/src/Token/AbstractToken.php b/src/Token/AbstractToken.php index fe3128f..172ba77 100644 --- a/src/Token/AbstractToken.php +++ b/src/Token/AbstractToken.php @@ -57,7 +57,7 @@ protected function generate(): string * @param $headerToken string|null The token sent with the request as a header. Can be empty in certain requests. * @return bool TRUE if the token(s) match the stored token, FALSE if it/they don't. */ - protected function compareToken(string $storedToken, string $payloadToken, string $headerToken = null): bool + protected function compareToken(string $storedToken, string $payloadToken, ?string $headerToken = null): bool { // If the token is empty, the token was never requested. if (empty($storedToken)) { diff --git a/src/Token/IconCaptchaToken.php b/src/Token/IconCaptchaToken.php index ea329aa..fb31ee2 100644 --- a/src/Token/IconCaptchaToken.php +++ b/src/Token/IconCaptchaToken.php @@ -57,7 +57,7 @@ public function get(): string /** * @inheritDoc */ - public function validate(string $payloadToken, string $headerToken = null): bool + public function validate(string $payloadToken, ?string $headerToken = null): bool { $sessionToken = $this->retrieve(); diff --git a/src/Token/TokenInterface.php b/src/Token/TokenInterface.php index 125b4b0..f524819 100644 --- a/src/Token/TokenInterface.php +++ b/src/Token/TokenInterface.php @@ -36,5 +36,5 @@ public function get(): string; * value will be checked against the captcha token. * @return bool TRUE if the captcha token matches the given tokens, FALSE if it does not match. */ - public function validate(string $payloadToken, string $headerToken = null): bool; + public function validate(string $payloadToken, ?string $headerToken = null): bool; }