├── .github └── workflows │ ├── auto-close-issue.yml │ └── php.yml ├── .gitignore ├── .scrutinizer.yml ├── LICENSE ├── README.md ├── assets ├── dist │ ├── app-packed.css │ ├── app-packed.js │ └── app.css ├── package.json ├── src │ ├── images │ │ ├── favicon.ico │ │ ├── icon-clock_96x96.png │ │ ├── icon-secruity_96x96.png │ │ ├── icon-warning_96x96.png │ │ └── logo.png │ ├── js │ │ ├── app.js │ │ └── bootstrap.js │ └── sass │ │ ├── _background.scss │ │ ├── _bootstrap.scss │ │ ├── _dashboard.scss │ │ ├── _datatable.scss │ │ ├── _footer.scss │ │ ├── _functions.scss │ │ ├── _loading.scss │ │ ├── _main.scss │ │ ├── _menu.scss │ │ ├── _modal.scss │ │ ├── _radio-checkbox.scss │ │ ├── _responsive.scss │ │ ├── _setting-page.scss │ │ ├── _tab.scss │ │ ├── _toggle.scss │ │ ├── _typography.scss │ │ ├── _variables.scss │ │ ├── app.scss │ │ ├── config.rb │ │ └── index.html └── webpack.mix.js ├── autoload.php ├── bin ├── iptables_bridge.sh └── test.txt ├── composer.json ├── config.json ├── config.php ├── localization ├── en │ ├── core.php │ └── panel.php ├── zh │ ├── core.php │ └── panel.php └── zh_CN │ ├── core.php │ └── panel.php ├── phpcs.xml ├── phpunit.xml ├── src └── Firewall │ ├── Captcha │ ├── CaptchaInterface.php │ ├── CaptchaProvider.php │ ├── Csrf.php │ ├── Foundation.php │ ├── ImageCaptcha.php │ └── ReCaptcha.php │ ├── Component │ ├── AllowedTrait.php │ ├── ComponentProvider.php │ ├── DeniedTrait.php │ ├── Header.php │ ├── Ip.php │ ├── Rdns.php │ ├── TrustedBot.php │ └── UserAgent.php │ ├── Container.php │ ├── Driver │ ├── AbstractDriver.php │ ├── DriverInterface.php │ ├── DriverProvider.php │ ├── FileDriver.php │ ├── FileDriverTrait.php │ ├── MysqlDriver.php │ ├── RedisDriver.php │ ├── SqlDriverProvider.php │ ├── SqlDriverTrait.php │ └── SqliteDriver.php │ ├── Firewall.php │ ├── Firewall │ ├── Captcha │ │ ├── CaptchaFactory.php │ │ ├── ItemImage.php │ │ └── ItemRecaptcha.php │ ├── Driver │ │ ├── DriverFactory.php │ │ ├── ItemFileDriver.php │ │ ├── ItemMysqlDriver.php │ │ ├── ItemRedisDriver.php │ │ └── ItemSqliteDriver.php │ ├── Messenger │ │ ├── ItemLineNotify.php │ │ ├── ItemMailgun.php │ │ ├── ItemNativePhpMail.php │ │ ├── ItemRocketChat.php │ │ ├── ItemSendgrid.php │ │ ├── ItemSlack.php │ │ ├── ItemSlackWebhook.php │ │ ├── ItemSmtp.php │ │ ├── ItemTelegram.php │ │ ├── MessengerFactory.php │ │ └── MessengerTrait.php │ ├── SetupTrait.php │ └── XssProtectionTrait.php │ ├── FirewallTrait.php │ ├── Helpers.php │ ├── HttpFactory.php │ ├── HttpResolver.php │ ├── Integration │ ├── Bootstrap.php │ ├── CakePhp.php │ ├── CodeIgniter4.php │ ├── Laravel.php │ ├── Slim3.php │ ├── Slim4.php │ ├── ZendPsr15.php │ └── ZendPsr7.php │ ├── IpTrait.php │ ├── Kernel.php │ ├── Kernel │ ├── CaptchaTrait.php │ ├── ComponentTrait.php │ ├── DriverTrait.php │ ├── Enum.php │ ├── FilterTrait.php │ ├── MessengerTrait.php │ ├── RuleTrait.php │ ├── SessionTrait.php │ └── TemplateTrait.php │ ├── Log │ ├── ActionLogParsedCache.php │ ├── ActionLogParser.php │ ├── ActionLogger.php │ └── SessionLogger.php │ ├── Middleware │ ├── Header.php │ ├── HttpAuthentication.php │ └── UserAgent.php │ ├── Panel.php │ ├── Panel │ ├── Ajax.php │ ├── Asset.php │ ├── BaseController.php │ ├── Circle.php │ ├── ConfigMethodsTrait.php │ ├── CsrfTrait.php │ ├── DemoModeTrait.php │ ├── Home.php │ ├── Iptables.php │ ├── Report.php │ ├── Sandbox │ │ ├── LineNotify.php │ │ ├── Mailgun.php │ │ ├── NativePhpMail.php │ │ ├── RocketChat.php │ │ ├── Sendgrid.php │ │ ├── Slack.php │ │ ├── SlackWebhook.php │ │ ├── Smtp.php │ │ └── Telegram.php │ ├── Security.php │ ├── Setting.php │ └── User.php │ └── Session.php ├── templates ├── frontend │ ├── captcha.php │ ├── css │ │ └── default.php │ ├── login.php │ ├── rejection.php │ └── session_limitation.php └── panel │ ├── action_log_last_month.php │ ├── action_log_past_seven_days.php │ ├── action_log_this_month.php │ ├── action_log_today.php │ ├── action_log_yesterday.php │ ├── authentication.php │ ├── exclusion.php │ ├── ip_manager.php │ ├── iptables_manager.php │ ├── iptables_status.php │ ├── js │ ├── chart.php │ └── common.php │ ├── messenger.php │ ├── messenger │ ├── events.php │ ├── modules.php │ └── tab.php │ ├── operation_status.php │ ├── overview.php │ ├── setting.php │ ├── setting │ ├── admin_login.php │ ├── captchas.php │ ├── components.php │ ├── daemon.php │ ├── dialog_ui.php │ ├── filters.php │ ├── import_export.php │ └── tab.php │ ├── table_filter_logs.php │ ├── table_rules.php │ ├── table_sessions.php │ ├── template.php │ └── xss_protection.php └── tests ├── Firewall ├── BashScriptTest.php ├── Captcha │ ├── CsrfTest.php │ ├── FoundationTest.php │ ├── ImageCaptchaTest.php │ └── RecaptchaTest.php ├── Component │ ├── AllowTraitTest.php │ ├── DenyTraitTest.php │ ├── HeaderTest.php │ ├── IpTest.php │ ├── RdnsTest.php │ ├── TrustedBotTest.php │ └── UserAgentTest.php ├── ContainerTest.php ├── Driver │ ├── AbstractDriverTest.php │ ├── DriverProviderTest.php │ ├── FileDriverTest.php │ ├── MysqlDriverTest.php │ ├── RedisDriverTest.php │ ├── SqlDriverProviderTest.php │ └── SqliteDriverTest.php ├── Firewall │ └── Driver │ │ ├── DriverFactoryTest.php │ │ ├── ItemFileDriverTest.php │ │ ├── ItemMysqlDriverTest.php │ │ ├── ItemRedisDriverTest.php │ │ └── ItemSqliteDriverTest.php ├── FirewallTest.php ├── FirewallTraitTest.php ├── HttpResolverTest.php ├── IpTraitTest.php ├── KernelTest.php ├── Log │ ├── ActionLogParsedCacheTest.php │ ├── ActionLogParserTest.php │ └── ActionLoggerTest.php ├── Middleware │ ├── HeaderTest.php │ ├── UserAgentTest.php │ └── httpAuthenticationTest.php ├── Mock │ ├── MockMessenger.php │ ├── MockSaveConfig.php │ └── save_config_form_test.json ├── Panel │ ├── AjaxTest.php │ ├── AssetTest.php │ ├── BaseControllerTest.php │ ├── CircleTest.php │ ├── ConfigMethodsTraitTest.php │ ├── DemoModeTraitTest.php │ ├── HomeTest.php │ ├── IptablesTest.php │ ├── ReportTest.php │ ├── RouteTestTrait.php │ ├── SecurityTest.php │ ├── SettingTest.php │ └── UserTest.php ├── PanelTest.php ├── Security │ └── XssTest.php ├── SessionTest.php └── ShieldonTestCase.php ├── Fixture └── docker │ ├── Dockerfile │ └── entry-point.sh ├── bootstrap.php ├── config.json ├── config.php └── samples ├── action_logs ├── 20200203.log ├── 20200204.log ├── 20200205.log ├── 20200206.log ├── 20200207.log ├── 20200208.log ├── 20200209.log ├── 20200210.log ├── 20200211.log ├── 20200212.log ├── 20200213.log ├── 20200214.log ├── 20200215.log ├── 20200216.log ├── 20200217.log └── 20200218.log ├── json_files ├── invalid_json_format.json └── invalid_spec.json └── xss_bypass_list ├── test_list.txt ├── test_sample.jpg ├── test_sample_2.jpg └── test_sample_3.jpg /.github/workflows/auto-close-issue.yml: -------------------------------------------------------------------------------- 1 | name: Close Stale Issues 2 | on: 3 | schedule: 4 | - cron: "0 0 * * *" 5 | 6 | jobs: 7 | auto-close-issue: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Check for stale issues 11 | uses: actions/stale@v8 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.' 15 | stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 14 days.' 16 | close-issue-message: "This issue was closed because it has been inactive for 14 since being marked as stale." 17 | days-before-issue-stale: 60 18 | days-before-issue-close: 7 19 | days-before-pr-stale: 45 20 | days-before-pr-close: 14 21 | stale-issue-label: "stale" 22 | exempt-issue-labels: 'in-progress' 23 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ 2.x ] 6 | pull_request: 7 | branches: [ 2.x ] 8 | 9 | jobs: 10 | run: 11 | runs-on: ${{ matrix.operating-system }} 12 | strategy: 13 | matrix: 14 | operating-system: [ubuntu-latest] 15 | php-versions: ['7.4', '8.1', '8.2'] 16 | name: PHP ${{ matrix.php-versions }} 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Start MySQL service 22 | run: sudo service mysql start 23 | 24 | - name: MySQL - Create database. 25 | run: sudo mysql -uroot -proot -h 127.0.0.1 -e 'CREATE DATABASE shieldon_unittest;' 26 | 27 | - name: MySQL - Create user. 28 | run: sudo mysql -uroot -proot -h 127.0.0.1 -e "CREATE USER 'shieldon'@'localhost' IDENTIFIED WITH mysql_native_password BY 'taiwan';" 29 | 30 | - name: MySQL - Grant permission. 31 | run: sudo mysql -uroot -proot -h 127.0.0.1 -e "GRANT ALL ON shieldon_unittest.* TO 'shieldon'@'localhost';" 32 | 33 | - name: "Setup Redis" 34 | run: | 35 | sudo apt-get install -y redis-server 36 | sudo service redis-server start 37 | 38 | - name: "Setup PHP with Xdebug" 39 | uses: shivammathur/setup-php@v2 40 | with: 41 | php-version: ${{ matrix.php-versions }} 42 | extensions: mbstring, pdo, pdo_mysql, intl, zip, redis, ctype, json, gd 43 | coverage: xdebug 44 | 45 | - name: "Setup test directory" 46 | run: | 47 | sudo mkdir /home/runner/work/shieldon/shieldon/tmp 48 | sudo chmod 0777 /home/runner/work/shieldon/shieldon/tmp 49 | 50 | - name: "Install dependencies" 51 | run: | 52 | composer update --prefer-dist --no-interaction --no-suggest 53 | 54 | - name: "Run tests" 55 | run: | 56 | composer test 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.phar 3 | composer.lock 4 | phpunit.phar 5 | phpunit.log 6 | tests/report 7 | .DS_Store 8 | .php_cs.cache 9 | .hg 10 | .git 11 | .vscode 12 | tmp 13 | clover.xml 14 | .phpunit.result.cache 15 | bin/*.log 16 | test.sh 17 | assets/node_modules 18 | assets/package-lock.json 19 | assets/v8-compile-cache-0 20 | assets/npm* 21 | assets/mix-manifest.json 22 | assets/_webpack.config.js -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | paths: ["src/*"] 3 | excluded_paths: ["vendor/*", "tests/*"] 4 | 5 | checks: 6 | php: 7 | code_rating: true 8 | duplication: true 9 | 10 | tools: 11 | external_code_coverage: false 12 | 13 | build: 14 | environment: 15 | php: 16 | version: 7.3.0 17 | pecl_extensions: 18 | - redis 19 | mysql: true 20 | redis: true 21 | nodes: 22 | analysis: 23 | tests: 24 | override: 25 | - php-scrutinizer-run 26 | dependencies: 27 | before: 28 | - composer self-update 29 | - composer update --no-interaction --prefer-dist --no-progress --dev 30 | # Create DB for testing. 31 | - mysql -u root -e 'CREATE DATABASE shieldon_unittest;' 32 | - mysql -u root -e "CREATE USER 'shieldon'@'localhost' IDENTIFIED BY 'taiwan';" 33 | - mysql -u root -e "GRANT ALL ON shieldon_unittest.* TO 'shieldon'@'localhost';" 34 | tests: 35 | before: 36 | - 37 | command: composer test 38 | coverage: 39 | file: 'clover.xml' 40 | format: 'clover' -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Terry L. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.19", 14 | "cross-env": "^5.1", 15 | "laravel-mix": "^4.0.7", 16 | "lodash": "^4.17.13", 17 | "resolve-url-loader": "^2.3.1", 18 | "sass": "^1.15.2", 19 | "sass-loader": "^7.1.0", 20 | "vue-template-compiler": "^2.6.11" 21 | }, 22 | "dependencies": { 23 | "@fortawesome/fontawesome-free": "^5.14.0", 24 | "apexcharts": "^3.20.0", 25 | "bootstrap": "^4.5.0", 26 | "datatables.net": "^1.10.21", 27 | "datatables.net-responsive": "^2.2.5", 28 | "fibers": "^5.0.0", 29 | "fontawesome": "^5.6.3", 30 | "jquery": "^3.5.1", 31 | "popper.js": "^1.16.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /assets/src/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/assets/src/images/favicon.ico -------------------------------------------------------------------------------- /assets/src/images/icon-clock_96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/assets/src/images/icon-clock_96x96.png -------------------------------------------------------------------------------- /assets/src/images/icon-secruity_96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/assets/src/images/icon-secruity_96x96.png -------------------------------------------------------------------------------- /assets/src/images/icon-warning_96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/assets/src/images/icon-warning_96x96.png -------------------------------------------------------------------------------- /assets/src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/assets/src/images/logo.png -------------------------------------------------------------------------------- /assets/src/js/app.js: -------------------------------------------------------------------------------- 1 | require('./bootstrap'); 2 | -------------------------------------------------------------------------------- /assets/src/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | try { 4 | window.Popper = require('popper.js').default; 5 | window.$ = window.jQuery = require('jquery'); 6 | 7 | require('bootstrap'); 8 | } catch (e) {} 9 | 10 | require('@fortawesome/fontawesome-free/js/all.min.js'); 11 | require('datatables.net'); 12 | require('datatables.net-responsive'); 13 | 14 | window.ApexCharts = require('apexcharts'); 15 | -------------------------------------------------------------------------------- /assets/src/sass/_background.scss: -------------------------------------------------------------------------------- 1 | 2 | .bg-dot { 3 | background: #fff; 4 | background-image: radial-gradient(#dddddd 1%,rgba(0,0,0,0) 15%); 5 | background-size: 8px 8px; 6 | } 7 | 8 | .bg-glass { 9 | background: rgb(255,255,255); /* Old browsers */ 10 | background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6-15 */ 11 | background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10-25,Safari5.1-6 */ 12 | background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ 13 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f6f6f6',GradientType=0 ); 14 | } 15 | -------------------------------------------------------------------------------- /assets/src/sass/_footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | margin-top: 10px; 3 | text-align: center; 4 | 5 | .col-md-12 { 6 | color: #333; 7 | height: 30px; 8 | line-height: 30px; 9 | font-size: 12px; 10 | 11 | a { 12 | color: #000; 13 | font-weight: 500; 14 | } 15 | } 16 | 17 | @include media-breakpoint-down(md) { 18 | .col-md-12 { 19 | height: auto; 20 | line-height: 150%; 21 | padding: 10px; 22 | 23 | span { 24 | display: block; 25 | padding-bottom: 5px; 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /assets/src/sass/_functions.scss: -------------------------------------------------------------------------------- 1 | // Base functions to get safe web font 2 | 3 | @function get-base-font($key: "en") { 4 | @return map-get($font-family-base, $key); 5 | } 6 | 7 | @function get-title-font($key: "en") { 8 | @return map-get($font-family-title, $key); 9 | } 10 | 11 | @function get-heading-font($key: "en") { 12 | @return map-get($font-family-heading, $key); 13 | } -------------------------------------------------------------------------------- /assets/src/sass/_modal.scss: -------------------------------------------------------------------------------- 1 | .modal-lightbox { 2 | 3 | border-radius: 0; 4 | 5 | .icon-wrapper { 6 | text-align: center; 7 | display: block; 8 | width: 100%; 9 | } 10 | .icon-box { 11 | color: #fff; 12 | width: 95px; 13 | height: 95px; 14 | display: inline-block; 15 | border-radius: 50%; 16 | z-index: 9; 17 | border: 5px solid #fff; 18 | padding: 15px; 19 | text-align: center; 20 | 21 | .message-icon { 22 | font-size: 58px; 23 | margin: -2px 0 0 -2px; 24 | } 25 | } 26 | 27 | 28 | .modal-content { 29 | border: 0; 30 | border-radius: 0; 31 | } 32 | 33 | .modal-header { 34 | border-bottom: none; 35 | border-radius: 0; 36 | padding: 35px; 37 | 38 | &.success { 39 | background: #358a4e; 40 | } 41 | 42 | &.info { 43 | background: #0c8ec5; 44 | } 45 | 46 | &.danger { 47 | background: #a73232 48 | } 49 | 50 | .close { 51 | position: absolute; 52 | top: 10px; 53 | right: 10px; 54 | } 55 | } 56 | } 57 | 58 | .modal-dialog { 59 | justify-content: center; 60 | 61 | .modal-content { 62 | width: 100%; 63 | box-shadow: 0 3px 10px rgba(0,0,0,0.2); 64 | } 65 | } -------------------------------------------------------------------------------- /assets/src/sass/_setting-page.scss: -------------------------------------------------------------------------------- 1 | .so-setting-page { 2 | font-family: Helvetica, Arial, sans-serif !important; 3 | background-color: #f1f1f1; 4 | border: 0px #dddddd solid; 5 | padding: 10px; 6 | overflow: hidden; 7 | 8 | .section-title { 9 | position: relative; 10 | background-color: #ffffff; 11 | height: 50px; 12 | width: 100%; 13 | border: 1px #dddddd solid; 14 | 15 | h2 { 16 | line-height: 50px; 17 | font-size: 16px; 18 | padding: 0 10px; 19 | padding-left: 20px; 20 | color: #555; 21 | } 22 | 23 | &.sm { 24 | 25 | height: 40px; 26 | width: 100%; 27 | 28 | border: 1px #dddddd solid; 29 | 30 | h3 { 31 | line-height: 40px; 32 | padding: 0 10px; 33 | padding-left: 20px; 34 | font-size: 15px; 35 | font-family: "Lato", sans-serif; 36 | font-weight: bold; 37 | color: #333; 38 | } 39 | } 40 | } 41 | 42 | .toggle-container { 43 | position: absolute; 44 | top: -2px; 45 | right: 10px; 46 | display: inline-block; 47 | 48 | &.toggle-sm { 49 | top: 0; 50 | } 51 | } 52 | 53 | .section-body { 54 | background-color: #eeeeee; 55 | padding: 20px; 56 | border: 1px #dddddd solid; 57 | border-top: 0; 58 | margin-bottom: 20px; 59 | box-shadow: 0px 3px 3px -3px rgba(0, 0, 0, 0.1); 60 | 61 | &.sm { 62 | background-color: #fafafa; 63 | } 64 | } 65 | 66 | label { 67 | font-weight: bold; 68 | color: #666; 69 | } 70 | 71 | p { 72 | font-size: 13px; 73 | color: #777; 74 | } 75 | 76 | .setting-table { 77 | width: 100%; 78 | 79 | .r1 { 80 | width: 200px; 81 | font-weight: 600; 82 | color: #444; 83 | padding: 5px; 84 | } 85 | .r2 { 86 | width: calc(100% - 200px); 87 | padding: 5px; 88 | } 89 | } 90 | 91 | } 92 | 93 | 94 | 95 | .btn-enter { 96 | display: inline-block; 97 | padding: 3px 30px 5px 20px; 98 | margin: 0.5em; 99 | cursor: pointer; 100 | color: #ffffff; 101 | border-radius: 0.25em; 102 | background-color: #00b38a; 103 | box-shadow: 0 3px 10px rgba(0,0,0,0.2), inset 0 -3px 0 rgba(0,0,0,0.22); 104 | transition: 0.3s; 105 | user-select: none; 106 | font-size: 24px; 107 | line-height: 40px; 108 | 109 | &:hover { 110 | background: darken(#00b38a, 10%); 111 | color: darken(#ffffff, 10%); 112 | box-shadow: 0 3px 10px rgba(0,0,0,0.2), inset 0 -3px 0 rgba(0,0,0,0.32); 113 | } 114 | &:active { 115 | transform: translateY(2px); 116 | box-shadow: 0 3px 10px rgba(0,0,0,0.2), inset 0px -1px 0 rgba(0,0,0,0.22); 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /assets/src/sass/_tab.scss: -------------------------------------------------------------------------------- 1 | .so-tab { 2 | 3 | section { 4 | display: none; 5 | padding: 20px 0 0; 6 | border-top: 1px solid #ddd; 7 | } 8 | 9 | input.tab { 10 | display: none; 11 | } 12 | 13 | label.tab { 14 | display: inline-block; 15 | margin: 0 0 -1px; 16 | padding: 10px 18px; 17 | font-weight: 600; 18 | text-align: center; 19 | color: #999; 20 | border: 1px solid transparent; 21 | 22 | i { 23 | background-color: #555; 24 | color: #fff; 25 | width: 24px; 26 | height: 24px; 27 | line-height: 22px; 28 | text-align: center; 29 | font-size: 16px; 30 | margin-right: 15px; 31 | border-top: 1px solid #ddd; 32 | border-right: 1px solid #ddd; 33 | border-left: 1px solid #fff; 34 | border-bottom: 1px solid #fff; 35 | } 36 | } 37 | 38 | label.tab:hover { 39 | color: #888; 40 | cursor: pointer; 41 | } 42 | 43 | input.tab:checked + label { 44 | color: #555; 45 | border: 1px solid #ddd; 46 | border-top: 2px solid #1ABB9C; 47 | border-bottom: 1px solid #f1f1f1; 48 | 49 | i { 50 | border-top: 1px solid #46a593; 51 | border-right: 1px solid #46a593; 52 | background-color: #1ABB9C; 53 | } 54 | } 55 | 56 | #tab1:checked ~ #content1, 57 | #tab2:checked ~ #content2, 58 | #tab3:checked ~ #content3, 59 | #tab4:checked ~ #content4, 60 | #tab5:checked ~ #content5, 61 | #tab6:checked ~ #content6, 62 | #tab7:checked ~ #content7 { 63 | 64 | display: block; 65 | } 66 | 67 | @media screen and (max-width: 650px) { 68 | label { 69 | font-size: 0; 70 | } 71 | i { 72 | margin: 0; 73 | font-size: 18px; 74 | } 75 | } 76 | 77 | @media screen and (max-width: 400px) { 78 | label { 79 | padding: 15px; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /assets/src/sass/_typography.scss: -------------------------------------------------------------------------------- 1 | @each $lang-code in $supported-languages { 2 | :lang(#{$lang-code}) { 3 | 4 | * { 5 | font-family: get-base-font($lang-code) 6 | } 7 | 8 | h1, h2, h3, h4, h5, h6 { 9 | font-family: get-heading-font($lang-code); 10 | } 11 | 12 | .section-intro, #post-title, .site-info { 13 | font-family: get-title-font($lang-code); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /assets/src/sass/app.scss: -------------------------------------------------------------------------------- 1 | 2 | @import "bootstrap"; 3 | @import "variables"; 4 | 5 | @import "functions"; 6 | @import "typography"; 7 | @import "main"; 8 | @import "footer"; 9 | @import "dashboard"; 10 | @import "datatable"; 11 | @import "menu"; 12 | @import "tab"; 13 | @import "toggle"; 14 | @import "setting-page"; 15 | @import "background"; 16 | @import "radio-checkbox"; 17 | @import "responsive"; 18 | @import "loading"; 19 | @import "modal"; 20 | -------------------------------------------------------------------------------- /assets/src/sass/config.rb: -------------------------------------------------------------------------------- 1 | require 'compass/import-once/activate' 2 | # Require any additional compass plugins here. 3 | 4 | # Set this to the root of your project when deployed: 5 | http_path = "/" 6 | css_dir = "../css" 7 | sass_dir = "" 8 | images_dir = "../images" 9 | javascripts_dir = "../js" 10 | 11 | # You can select your preferred output style here (can be overridden via the command line): 12 | # output_style = :expanded or :nested or :compact or :compressed 13 | 14 | # To enable relative paths to assets via compass helper functions. Uncomment: 15 | # relative_assets = true 16 | 17 | # To disable debugging comments that display the original location of your selectors. Uncomment: 18 | line_comments = false 19 | 20 | output_style = :compressed 21 | 22 | # If you prefer the indented syntax, you might want to regenerate this 23 | # project again passing --syntax sass, or you can uncomment this: 24 | # preferred_syntax = :sass 25 | # and then run: 26 | # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass 27 | # 28 | Encoding.default_external = Encoding.find('utf-8') 29 | #require 'compass-normalize' 30 | 31 | cache = false -------------------------------------------------------------------------------- /assets/src/sass/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/assets/src/sass/index.html -------------------------------------------------------------------------------- /assets/webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('./src/js/app.js', './dist/app-packed.js') 15 | mix.sass('./src/sass/app.scss', './dist'); 16 | mix.styles([ 17 | 'node_modules/bootstrap/dist/css/bootstrap.min.css', 18 | './dist/app.css' 19 | ], './dist/app-packed.css'); 20 | -------------------------------------------------------------------------------- /autoload.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | /** 14 | * Register to PSR-4 autoloader. 15 | * 16 | * @return void 17 | */ 18 | function shieldon_firewall_register() 19 | { 20 | spl_autoload_register('shieldon_firewall_autoload', true, false); 21 | } 22 | 23 | /** 24 | * PSR-4 autoloader. 25 | * 26 | * @param string $className 27 | * 28 | * @return void 29 | */ 30 | function shieldon_firewall_autoload($className) 31 | { 32 | $prefix = 'Shieldon\\Firewall\\'; 33 | $dir = __DIR__ . '/src/Firewall'; 34 | 35 | if (0 === strpos($className, $prefix)) { 36 | $parts = explode('\\', substr($className, strlen($prefix))); 37 | $filepath = $dir . '/' . implode('/', $parts) . '.php'; 38 | 39 | if (is_file($filepath)) { 40 | include $filepath; 41 | } 42 | } 43 | } 44 | 45 | shieldon_firewall_register(); -------------------------------------------------------------------------------- /bin/test.txt: -------------------------------------------------------------------------------- 1 | add,4,33.33.33.33,28,23,tcp,deny 2 | add,6,2001:db8::a:74e6:b5f3:fe92:830e,124,23,all,allow 3 | add,6,2001:db8::a:74e6:b5f3:fe92:830e,126,25,tcp,allow -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shieldon/shieldon", 3 | "description": "Web application firewall for PHP.", 4 | "keywords": ["firewall", "web-application-firewall", "anti-scraping", "xss-filter", "xss-protection", "web-security", "www-authenticate"], 5 | "homepage": "https://github.com/terrylinooo/shieldon", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Terry Lin", 10 | "email": "contact@terryl.in", 11 | "homepage": "https://terryl.in", 12 | "role": "Developer" 13 | } 14 | ], 15 | "minimum-stability": "stable", 16 | "require": { 17 | "php": ">=7.1.0", 18 | "psr/http-factory": "*", 19 | "psr/http-message": "*", 20 | "shieldon/event-dispatcher": "^1", 21 | "shieldon/messenger": "^1", 22 | "shieldon/psr-http": "^1.2", 23 | "shieldon/web-security": "^1" 24 | }, 25 | "require-dev": { 26 | "phpunit/phpunit": "^8 || ^9 || ^10" 27 | }, 28 | "autoload": { 29 | "psr-4": { 30 | "Shieldon\\Firewall\\": "src/Firewall" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Shieldon\\FirewallTest\\": "tests/Firewall" 36 | } 37 | }, 38 | "config": { 39 | "process-timeout": 0, 40 | "sort-packages": true 41 | }, 42 | "scripts": { 43 | "test": "php vendor/phpunit/phpunit/phpunit", 44 | "test:docker:build": "docker build -t shieldon-test -f ./tests/Fixture/docker/Dockerfile .", 45 | "test:docker:run": "docker run --privileged --cap-add=NET_ADMIN -v .:/test-app --rm shieldon-test", 46 | "test:docker:ssh": "docker run --privileged --cap-add=NET_ADMIN -v .:/test-app -it --entrypoint /bin/bash shieldon-test " 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /localization/en/core.php: -------------------------------------------------------------------------------- 1 | 'Access Denied', 5 | 'deny_heading' => 'Access Denied', 6 | 'deny_message' => 'The IP address you are using has been blocked.', 7 | 'limit_title' => 'Please Queue', 8 | 'limit_heading' => 'Please Queue', 9 | 'limit_message' => 'This page is limiting the number of online users. Please wait for a moment.', 10 | 'stop_title' => 'Please Complete the CAPTCHA', 11 | 'stop_heading' => 'Unusual Behavior Detected', 12 | 'stop_message' => 'Please complete the CAPTCHA to confirm you are human.', 13 | 'stop_submit' => 'Submit', 14 | 'credit' => 'This website is protected by the {0} open source project.', 15 | 'lineup_info' => 'Number of users ahead of you: {0}', 16 | 'online_info' => 'Online users: {0}', 17 | 'keepalive_info' => 'Upon entry, each user has {0} seconds to view this page.', 18 | 'messenger_notification_subject' => 'Notification for IP: {0}!', 19 | 20 | // @since 0.1.7 21 | 'messenger_text_ip' => 'IP', 22 | 'messenger_text_rdns' => 'RDNS', 23 | 'messenger_text_time' => 'Time', 24 | 'messenger_text_timezone' => 'Timezone', 25 | 'messenger_text_cpu' => 'CPU Usage', 26 | 'messenger_text_memory' => 'Memory Usage', 27 | 'messenger_text_reason' => 'Reason', 28 | 'messenger_text_system' => 'System Status', 29 | 'messenger_text_reason_code_1' => 'Too many sessions.', 30 | 'messenger_text_reason_code_2' => 'Too many accesses.', 31 | 'messenger_text_reason_code_3' => 'Cannot create JS cookies.', 32 | 'messenger_text_reason_code_4' => 'Empty referrer.', 33 | 'messenger_text_reason_code_11' => 'Daily limit reached.', 34 | 'messenger_text_reason_code_12' => 'Hourly limit reached.', 35 | 'messenger_text_reason_code_13' => 'Minute limit reached.', 36 | 'messenger_text_reason_code_14' => 'Second limit reached.', 37 | 'messenger_text_handle' => 'Handle', 38 | 'messenger_text_handle_type_1' => 'This IP has been permanently banned for the current data cycle until data is reset.', // phpcs:ignore 39 | 'messenger_text_handle_type_2' => 'This IP has been added to iptables’ DROP list until the server is rebooted.', 40 | 'messenger_text_mail_subject' => 'Notification from Shieldon Firewall.', 41 | ]; 42 | -------------------------------------------------------------------------------- /localization/zh/core.php: -------------------------------------------------------------------------------- 1 | '禁止連線', 6 | 'deny_heading' => '禁止連線', 7 | 'deny_message' => '您的IP位址已被封鎖。', 8 | 'limit_title' => '請排隊', 9 | 'limit_heading' => '請排隊', 10 | 'limit_message' => '這個網站正限制在線瀏覽人數。請稍候。', 11 | 'stop_title' => '請解決 CAPTCHA 驗證', 12 | 'stop_heading' => '偵測到不尋常的行為', 13 | 'stop_message' => '請完成 CAPTCHA 驗證確認您是人類。', 14 | 'stop_submit' => '送出', 15 | 'credit' => '這個網站由 {0} 開源專案防護。', 16 | 'lineup_info' => '排在您之前的人數:{0}', 17 | 'online_info' => '線上人數:{0}', 18 | 'keepalive_info' => '在進入後,每位使用者有 {0} 秒鐘的時間可以檢視這個頁面。', 19 | 20 | // @since 0.1.7 21 | 'messenger_text_ip' => 'IP', 22 | 'messenger_text_rdns' => 'RDNS', 23 | 'messenger_text_time' => '時間', 24 | 'messenger_text_timezone' => '時區', 25 | 'messenger_text_cpu' => 'CPU 使用量', 26 | 'messenger_text_memory' => '記憶體使用量', 27 | 'messenger_text_reason' => '理由', 28 | 'messenger_text_system' => '系統狀態', 29 | 'messenger_text_reason_code_1' => '太多工作階段。', 30 | 'messenger_text_reason_code_2' => '太多連線。', 31 | 'messenger_text_reason_code_3' => '無法建立 JS Cookie。', 32 | 'messenger_text_reason_code_4' => '空的來源網址。', 33 | 'messenger_text_reason_code_11' => '達到每日限制。', 34 | 'messenger_text_reason_code_12' => '達到每小時限制。', 35 | 'messenger_text_reason_code_13' => '達到每分限制。', 36 | 'messenger_text_reason_code_14' => '達到每秒限制。', 37 | 'messenger_text_handle' => '處置', 38 | 'messenger_text_handle_type_1' => '這個 IP 已經在當前的資料週期被永久封鎖,直到重設資料週期為止。', 39 | 'messenger_text_handle_type_2' => '這個 IP 已經被放到 iptables 防火牆的 DROP 列表,直到伺服器重開機為止。', 40 | ]; 41 | -------------------------------------------------------------------------------- /localization/zh_CN/core.php: -------------------------------------------------------------------------------- 1 | '禁止连线', 6 | 'deny_heading' => '禁止连!', 7 | 'deny_message' => '您的IP位址已被封锁。', 8 | 'limit_title' => '请排队', 9 | 'limit_heading' => '请排队', 10 | 'limit_message' => '这个网站正限制在线浏览人数。请稍候。', 11 | 'stop_title' => '请解决 CAPTCHA 验证', 12 | 'stop_heading' => '偵測到不尋常的行為', 13 | 'stop_message' => '请完成 CAPTCHA 验证确认您是人类。', 14 | 'stop_submit' => '送出', 15 | 'credit' => '这个网站由 {0} 开源专案防护。', 16 | 'lineup_info' => '排在您之前的人数:{0}', 17 | 'online_info' => '在线人数:{0}', 18 | 'keepalive_info' => '在进入后,每位使用者有 {0} 秒钟的时间可以检视这个页面。', 19 | 20 | // @since 0.1.7 21 | 'messenger_text_ip' => 'IP', 22 | 'messenger_text_rdns' => 'RDNS', 23 | 'messenger_text_time' => '时间', 24 | 'messenger_text_timezone' => '时区', 25 | 'messenger_text_cpu' => 'CPU使用量', 26 | 'messenger_text_memory' => '记忆体使用量', 27 | 'messenger_text_reason' => '理由', 28 | 'messenger_text_system' => '系统状态', 29 | 'messenger_text_reason_code_1' => '太多工作阶段。', 30 | 'messenger_text_reason_code_2' => '太多连线。', 31 | 'messenger_text_reason_code_3' => '无法建立JS Cookie。', 32 | 'messenger_text_reason_code_4' => '空的来源网址。', 33 | 'messenger_text_reason_code_11' => '达到每日限制。', 34 | 'messenger_text_reason_code_12' => '达到每小时限制。', 35 | 'messenger_text_reason_code_13' => '达到每分限制。', 36 | 'messenger_text_reason_code_14' => '达到每秒限制。', 37 | 'messenger_text_handle' => '处置', 38 | 'messenger_text_handle_type_1' => '这个IP已经在当前的资料周期被永久封锁,直到重设资料周期为止。', 39 | 'messenger_text_handle_type_2' => '这个IP已经被放到iptables防火墙的DROP列表,直到伺服器重开机为止。', 40 | ]; 41 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | tests/Firewall/ 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | src/Firewall/ 22 | 23 | 24 | src/Firewall/Helpers.php 25 | src/Firewall/Integration/ 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Firewall/Captcha/CaptchaInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Captcha; 24 | 25 | /** 26 | * CaptchaInterface 27 | */ 28 | interface CaptchaInterface 29 | { 30 | /** 31 | * Response the result. 32 | * 33 | * @return bool 34 | */ 35 | public function response(): bool; 36 | 37 | /** 38 | * Output a required HTML. 39 | * 40 | * @return string 41 | */ 42 | public function form(): string; 43 | } 44 | -------------------------------------------------------------------------------- /src/Firewall/Captcha/CaptchaProvider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Captcha; 24 | 25 | /** 26 | * ComponentPrivider 27 | */ 28 | abstract class CaptchaProvider implements CaptchaInterface 29 | { 30 | /** 31 | * Constroctor. 32 | */ 33 | public function __construct() 34 | { 35 | } 36 | 37 | /** 38 | * Is denied? 39 | * 40 | * @return bool 41 | */ 42 | abstract public function response(): bool; 43 | 44 | /** 45 | * Unique deny status code. 46 | * 47 | * @return string 48 | */ 49 | abstract public function form(): string; 50 | } 51 | -------------------------------------------------------------------------------- /src/Firewall/Captcha/Csrf.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Captcha; 24 | 25 | use Shieldon\Firewall\Captcha\CaptchaProvider; 26 | 27 | /** 28 | * Add form fields for the CSRF features of some frameworks. 29 | */ 30 | class Csrf extends CaptchaProvider 31 | { 32 | /** 33 | * Form input name. 34 | * 35 | * @var string 36 | */ 37 | protected $name = ''; 38 | 39 | /** 40 | * Form input value. 41 | * 42 | * @var string 43 | */ 44 | protected $value = ''; 45 | 46 | /** 47 | * Constructor. 48 | * 49 | * It will implement default configuration settings here. 50 | * 51 | * @param array $config The field of the CSRF configuration. 52 | * 53 | * @return void 54 | */ 55 | public function __construct(array $config = []) 56 | { 57 | parent::__construct(); 58 | 59 | foreach ($config as $k => $v) { 60 | if (isset($this->{$k})) { 61 | $this->{$k} = $v; 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * Response the result. 68 | * 69 | * @return bool 70 | */ 71 | public function response(): bool 72 | { 73 | return true; 74 | } 75 | 76 | /** 77 | * Output a required HTML. 78 | * 79 | * @return string 80 | */ 81 | public function form(): string 82 | { 83 | $html = ''; 84 | 85 | return $html; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Firewall/Captcha/Foundation.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Captcha; 24 | 25 | use Shieldon\Firewall\Captcha\CaptchaProvider; 26 | 27 | use function Shieldon\Firewall\get_request; 28 | use function Shieldon\Firewall\unset_superglobal; 29 | 30 | /** 31 | * Basic form. 32 | */ 33 | class Foundation extends CaptchaProvider 34 | { 35 | /** 36 | * Constructor. 37 | * 38 | * It will implement default configuration settings here. 39 | * 40 | * @array $config 41 | * 42 | * @return void 43 | */ 44 | public function __construct() 45 | { 46 | parent::__construct(); 47 | } 48 | 49 | /** 50 | * Response the result. 51 | * 52 | * @return bool 53 | */ 54 | public function response(): bool 55 | { 56 | $postParams = get_request()->getParsedBody(); 57 | 58 | if (empty($postParams['shieldon_captcha'])) { 59 | return false; 60 | } 61 | 62 | $flag = false; 63 | 64 | if ($postParams['shieldon_captcha'] === 'ok') { 65 | $flag = true; 66 | } 67 | 68 | // Prevent detecting POST method on RESTful frameworks. 69 | unset_superglobal('shieldon_captcha', 'post'); 70 | 71 | return $flag; 72 | } 73 | 74 | /** 75 | * Output a required HTML. 76 | * 77 | * @return string 78 | */ 79 | public function form(): string 80 | { 81 | $html = ''; 82 | $html .= ''; 83 | 84 | return $html; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Firewall/Component/ComponentProvider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Component; 24 | 25 | /** 26 | * ComponentPrivider 27 | */ 28 | abstract class ComponentProvider 29 | { 30 | /** 31 | * It is really strict. 32 | * 33 | * @var bool 34 | */ 35 | protected $strictMode = false; 36 | 37 | /** 38 | * Enable strict mode. 39 | * 40 | * @param bool $bool Set true to enble strict mode, false to disable it overwise. 41 | * 42 | * @return void 43 | */ 44 | public function setStrict(bool $bool): void 45 | { 46 | $this->strictMode = $bool; 47 | } 48 | 49 | /** 50 | * Unique deny status code. 51 | * 52 | * @return int 53 | */ 54 | abstract public function getDenyStatusCode(): int; 55 | } 56 | -------------------------------------------------------------------------------- /src/Firewall/Container.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall; 24 | 25 | /** 26 | * This is a very, very simple container. 27 | * For storing Shieldon releated instances and variables.. 28 | */ 29 | class Container 30 | { 31 | /** 32 | * The container. 33 | * 34 | * @var array 35 | */ 36 | private static $instances = []; 37 | 38 | /** 39 | * Find an entry of the container by its identifier and returns it. 40 | * 41 | * @param string $id Identifier of the entry to look for. 42 | * 43 | * @return mixed Entry. 44 | */ 45 | public static function get(string $id) 46 | { 47 | if (self::has($id)) { 48 | return self::$instances[$id]; 49 | } 50 | 51 | return null; 52 | } 53 | 54 | /** 55 | * Return true if the container can return an entry for the given identifier. 56 | * Return false otherwise. 57 | * 58 | * @param string $id Identifier of the entry to look for. 59 | * 60 | * @return bool 61 | */ 62 | public static function has(string $id): bool 63 | { 64 | return isset(self::$instances[$id]); 65 | } 66 | 67 | /** 68 | * Set an entry into container. 69 | * 70 | * @param string $id Identifier of the entry to look for. 71 | * @param mixed $entry Entry. 72 | * @param bool $overwrite Overwrite it even exists. 73 | * 74 | * @return void 75 | */ 76 | public static function set(string $id, $entry, bool $overwrite = true): void 77 | { 78 | if (!self::has($id) || $overwrite) { 79 | self::$instances[$id] = $entry; 80 | } 81 | } 82 | 83 | /** 84 | * Unset an entry of the Container. 85 | * 86 | * @param string $id Identifier of the entry to look for. 87 | * 88 | * @return void 89 | */ 90 | public static function remove(string $id): void 91 | { 92 | if (self::has($id)) { 93 | self::$instances[$id] = null; 94 | unset(self::$instances[$id]); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Firewall/Driver/DriverInterface.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Driver; 24 | 25 | /** 26 | * Interface for Data drivers. 27 | */ 28 | interface DriverInterface 29 | { 30 | /** 31 | * Get an entry from the driver provider. 32 | * 33 | * @param string $ip The data id of the entry to fetch. 34 | * @param string $type The type of data table. accepts: filter | session | rule 35 | * 36 | * @return array The data or an empty array. 37 | */ 38 | public function get(string $ip, string $type = 'filter'): array; 39 | 40 | /** 41 | * Get all entries from the driver provider. 42 | * 43 | * @param string $type The type of data table. accepts: filter | session | rule 44 | * 45 | * @return array The data or an empty array. 46 | */ 47 | public function getAll(string $type = 'filter'): array; 48 | 49 | /** 50 | * Tests if an entry exists in the data. 51 | * 52 | * @param string $ip The IP address as well as the data id. 53 | * @param string $type The type of data table. accepts: filter | session | rule 54 | * 55 | * @return bool 56 | */ 57 | public function has(string $ip, string $type = 'filter'): bool; 58 | 59 | /** 60 | * Save data or replace old data to the new. 61 | * 62 | * @param string $ip The IP address as well as the data id. 63 | * @param array $data The data. 64 | * @param string $type The type of data table. accepts: filter | session | rule 65 | * @param int $expire The data will be deleted after expiring. 66 | * 67 | * @return bool 68 | */ 69 | public function save(string $ip, array $data, string $type = 'filter', int $expire = 0): bool; 70 | 71 | /** 72 | * Delete a data entry. 73 | * 74 | * @param string $ip The IP address as well as the data id. 75 | * @param string $type The type of data table. accepts: filter | session | rule 76 | * 77 | * @return bool true if the data entry is deleted successfully. 78 | * deleting a non-existing entry is considered successful. 79 | * return false overwise. 80 | */ 81 | public function delete(string $ip, string $type = 'filter'): bool; 82 | 83 | /** 84 | * Rebuild data table. 85 | * 86 | * @return bool 87 | */ 88 | public function rebuild(): bool; 89 | 90 | /** 91 | * Initial data tables. 92 | * 93 | * @param bool $dbCheck This is for creating data tables automatically 94 | * 95 | * @return void 96 | */ 97 | public function init(bool $dbCheck = true): void; 98 | } 99 | -------------------------------------------------------------------------------- /src/Firewall/Driver/MysqlDriver.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Driver; 24 | 25 | use Shieldon\Firewall\Driver\SqlDriverProvider; 26 | use PDO; 27 | 28 | /** 29 | * Mysql Driver. 30 | */ 31 | class MysqlDriver extends SqlDriverProvider 32 | { 33 | /** 34 | * Constructor. 35 | * 36 | * @param PDO $pdo The PDO instance. 37 | * @param bool $debug The option to enable debugging or not. 38 | * 39 | * @return void 40 | */ 41 | public function __construct(PDO $pdo, bool $debug = false) 42 | { 43 | parent::__construct($pdo, $debug); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Captcha/CaptchaFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Captcha; 24 | 25 | use Shieldon\Firewall\Captcha\CaptchaInterface; 26 | use function array_map; 27 | use function explode; 28 | use function implode; 29 | use function ucwords; 30 | 31 | /* 32 | * The factory creates driver instances. 33 | */ 34 | class CaptchaFactory 35 | { 36 | /** 37 | * Create a captcha instance. 38 | * 39 | * @param string $type The driver's type string. 40 | * @param array $setting The configuration of that driver. 41 | * 42 | * @return CaptchaInterface 43 | */ 44 | public static function getInstance(string $type, array $setting): CaptchaInterface 45 | { 46 | $className = '\Shieldon\Firewall\Firewall\Captcha\Item' . self::getCamelCase($type); 47 | 48 | return $className::get($setting); 49 | } 50 | 51 | /** 52 | * Check whether a messenger is available or not. 53 | * 54 | * @param array $setting The configuration of that messanger. 55 | * 56 | * @return bool 57 | */ 58 | public static function check(array $setting): bool 59 | { 60 | if (empty($setting['enable'])) { 61 | return false; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | /** 68 | * Covert string with dashes into camel-case string. 69 | * 70 | * @param string $string A string with dashes. 71 | * 72 | * @return string 73 | */ 74 | public static function getCamelCase(string $string = ''): string 75 | { 76 | $str = explode('-', $string); 77 | $str = implode( 78 | '', 79 | array_map( 80 | function ($word) { 81 | return ucwords($word); 82 | }, 83 | $str 84 | ) 85 | ); 86 | return $str; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Captcha/ItemImage.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Captcha; 24 | 25 | use Shieldon\Firewall\Captcha\CaptchaInterface; 26 | use Shieldon\Firewall\Captcha\ImageCaptcha; 27 | 28 | /** 29 | * Get File driver. 30 | */ 31 | class ItemImage 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that driver. 37 | * 38 | * @return CaptchaInterface 39 | */ 40 | public static function get(array $setting): CaptchaInterface 41 | { 42 | $type = $setting['config']['type'] ?? 'alnum'; 43 | $length = $setting['config']['length'] ?? 8; 44 | 45 | $imageCaptchaConfig = []; 46 | 47 | switch ($type) { 48 | case 'numeric': 49 | $imageCaptchaConfig['pool'] = '0123456789'; 50 | break; 51 | 52 | case 'alpha': 53 | $imageCaptchaConfig['pool'] = '0123456789abcdefghijklmnopqrstuvwxyz'; 54 | break; 55 | 56 | case 'alnum': 57 | default: 58 | $imageCaptchaConfig['pool'] = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 59 | } 60 | 61 | $imageCaptchaConfig['word_length'] = $length; 62 | 63 | return new ImageCaptcha($imageCaptchaConfig); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Captcha/ItemRecaptcha.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Captcha; 24 | 25 | use Shieldon\Firewall\Captcha\CaptchaInterface; 26 | use Shieldon\Firewall\Captcha\ReCaptcha; 27 | 28 | /** 29 | * Get File driver. 30 | */ 31 | class ItemRecaptcha 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that driver. 37 | * 38 | * @return CaptchaInterface 39 | */ 40 | public static function get(array $setting): CaptchaInterface 41 | { 42 | $recaptchaSetting = [ 43 | 'key' => $setting['config']['site_key'], 44 | 'secret' => $setting['config']['secret_key'], 45 | 'version' => $setting['config']['version'], 46 | 'lang' => $setting['config']['lang'], 47 | ]; 48 | 49 | return new ReCaptcha($recaptchaSetting); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Driver/DriverFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Driver; 24 | 25 | use Shieldon\Firewall\Driver\DriverInterface; 26 | use function array_map; 27 | use function explode; 28 | use function implode; 29 | use function ucwords; 30 | 31 | /* 32 | * The factory creates driver instances. 33 | */ 34 | class DriverFactory 35 | { 36 | /** 37 | * Create a driver instance. 38 | * 39 | * @param string $type The driver's type string. 40 | * @param array $setting The configuration of that driver. 41 | * 42 | * @return DriverInterface|null 43 | */ 44 | public static function getInstance(string $type, array $setting) 45 | { 46 | $className = '\Shieldon\Firewall\Firewall\Driver\Item' . self::getCamelCase($type) . 'Driver'; 47 | 48 | return $className::get($setting); 49 | } 50 | 51 | /** 52 | * Covert string with dashes into camel-case string. 53 | * 54 | * @param string $string A string with dashes. 55 | * 56 | * @return string 57 | */ 58 | public static function getCamelCase(string $string = ''): string 59 | { 60 | $str = explode('-', $string); 61 | $str = implode( 62 | '', 63 | array_map( 64 | function ($word) { 65 | return ucwords($word); 66 | }, 67 | $str 68 | ) 69 | ); 70 | return $str; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Driver/ItemFileDriver.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Driver; 24 | 25 | use Shieldon\Firewall\Driver\FileDriver; 26 | 27 | /** 28 | * Get File driver. 29 | */ 30 | class ItemFileDriver 31 | { 32 | /** 33 | * Initialize and get the instance. 34 | * 35 | * @param array $setting The configuration of that driver. 36 | * 37 | * @return FileDriver|null 38 | */ 39 | public static function get(array $setting) 40 | { 41 | $instance = null; 42 | 43 | if (empty($setting['directory_path'])) { 44 | return $instance; 45 | } 46 | 47 | $instance = new FileDriver($setting['directory_path']); 48 | 49 | return $instance; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Driver/ItemMysqlDriver.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Driver; 24 | 25 | use Shieldon\Firewall\Driver\MysqlDriver; 26 | use PDO; 27 | use PDOException; 28 | 29 | /** 30 | * Get MySQL driver. 31 | */ 32 | class ItemMysqlDriver 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that driver. 38 | * 39 | * @return MysqlDriver|null 40 | */ 41 | public static function get(array $setting) 42 | { 43 | $instance = null; 44 | 45 | try { 46 | $host = 'mysql' . 47 | ':host=' . $setting['host'] . 48 | ';dbname=' . $setting['dbname'] . 49 | ';charset=' . $setting['charset']; 50 | 51 | $user = (string) $setting['user']; 52 | $pass = (string) $setting['pass']; 53 | 54 | // Create a PDO instance. 55 | $pdoInstance = new PDO($host, $user, $pass); 56 | 57 | // Use MySQL data driver. 58 | $instance = new MysqlDriver($pdoInstance); 59 | 60 | // @codeCoverageIgnoreStart 61 | } catch (PDOException $e) { 62 | echo $e->getMessage(); 63 | } 64 | 65 | // @codeCoverageIgnoreEnd 66 | return $instance; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Driver/ItemRedisDriver.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Driver; 24 | 25 | use Shieldon\Firewall\Driver\RedisDriver; 26 | use Redis; 27 | use Exception; 28 | 29 | /** 30 | * Get Redis driver. 31 | */ 32 | class ItemRedisDriver 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that driver. 38 | * 39 | * @return RedisDriver|null 40 | */ 41 | public static function get(array $setting) 42 | { 43 | $instance = null; 44 | 45 | try { 46 | $host = '127.0.0.1'; 47 | $port = 6379; 48 | 49 | if (!empty($setting['host'])) { 50 | $host = $setting['host']; 51 | } 52 | 53 | if (!empty($setting['port'])) { 54 | $port = $setting['port']; 55 | } 56 | 57 | // Create a Redis instance. 58 | $redis = new Redis(); 59 | if (empty($setting['port'])) { 60 | $redis->connect($host); 61 | } else { 62 | $redis->connect($host, $port); 63 | } 64 | 65 | if (!empty($setting['auth'])) { 66 | // @codeCoverageIgnoreStart 67 | $redis->auth($setting['auth']); 68 | // @codeCoverageIgnoreEnd 69 | } 70 | 71 | // Use Redis data driver. 72 | $instance = new RedisDriver($redis); 73 | 74 | // @codeCoverageIgnoreStart 75 | } catch (Exception $e) { 76 | echo $e->getMessage(); 77 | } 78 | // @codeCoverageIgnoreEnd 79 | 80 | return $instance; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Driver/ItemSqliteDriver.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Driver; 24 | 25 | use Shieldon\Firewall\Driver\SqliteDriver; 26 | use PDO; 27 | use PDOException; 28 | 29 | /** 30 | * Get SQLite driver. 31 | */ 32 | class ItemSqliteDriver 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that driver. 38 | * 39 | * @return SqliteDriver|null 40 | */ 41 | public static function get(array $setting) 42 | { 43 | $instance = null; 44 | 45 | if (empty($setting['directory_path'])) { 46 | return null; 47 | } 48 | 49 | try { 50 | // Specify the sqlite file location. 51 | $sqliteLocation = $setting['directory_path'] . '/shieldon.sqlite3'; 52 | $pdoInstance = new PDO('sqlite:' . $sqliteLocation); 53 | $instance = new SqliteDriver($pdoInstance); 54 | 55 | // @codeCoverageIgnoreStart 56 | } catch (PDOException $e) { 57 | echo $e->getMessage(); 58 | } 59 | // @codeCoverageIgnoreEnd 60 | 61 | return $instance; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemLineNotify.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\LineNotify; 27 | 28 | /** 29 | * The get for Line Notify. 30 | */ 31 | class ItemLineNotify 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that messanger. 37 | * 38 | * @return MessengerInterface 39 | */ 40 | public static function get(array $setting): MessengerInterface 41 | { 42 | $accessToken = $setting['config']['access_token'] ?? ''; 43 | 44 | return new LineNotify($accessToken); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemMailgun.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\Mailgun; 27 | use function Shieldon\Firewall\__; 28 | 29 | /** 30 | * Get an item of messenger. It is Mailgun. 31 | */ 32 | class ItemMailgun 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that messanger. 38 | * 39 | * @return MessengerInterface 40 | */ 41 | public static function get(array $setting): MessengerInterface 42 | { 43 | $apiKey = $setting['config']['api_key'] ?? ''; 44 | $domain = $setting['config']['domain_name'] ?? ''; 45 | $sender = $setting['config']['sender'] ?? ''; 46 | $recipients = $setting['config']['recipients'] ?? []; 47 | 48 | $instance = new Mailgun($apiKey, $domain); 49 | $instance->setSubject(__('core', 'messenger_text_mail_subject')); 50 | $instance->addSender($sender); 51 | 52 | foreach ($recipients as $recipient) { 53 | $instance->addRecipient($recipient); 54 | } 55 | 56 | return $instance; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemNativePhpMail.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\Mail; 27 | use function Shieldon\Firewall\__; 28 | 29 | /** 30 | * The get for PHP native mail. 31 | */ 32 | class ItemNativePhpMail 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that messanger. 38 | * 39 | * @return MessengerInterface 40 | */ 41 | public static function get(array $setting): MessengerInterface 42 | { 43 | $sender = $setting['config']['sender'] ?? ''; 44 | $recipients = $setting['config']['recipients'] ?? []; 45 | 46 | $instance = new Mail(); 47 | $instance->setSubject(__('core', 'messenger_text_mail_subject')); 48 | $instance->addSender($sender); 49 | 50 | foreach ($recipients as $recipient) { 51 | $instance->addRecipient($recipient); 52 | } 53 | 54 | return $instance; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemRocketChat.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\RocketChat; 27 | 28 | /** 29 | * The get for RocketChat. 30 | */ 31 | class ItemRocketChat 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that messanger. 37 | * 38 | * @return MessengerInterface 39 | */ 40 | public static function get(array $setting): MessengerInterface 41 | { 42 | $serverUrl = $setting['config']['server_url'] ?? ''; 43 | $userId = $setting['config']['user_id'] ?? ''; 44 | $accessToken = $setting['config']['access_token'] ?? ''; 45 | $channel = $setting['config']['channel'] ?? ''; 46 | 47 | return new RocketChat($accessToken, $userId, $serverUrl, $channel); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemSendgrid.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\Sendgrid; 27 | use function Shieldon\Firewall\__; 28 | 29 | /** 30 | * The get for Sendgrid. 31 | */ 32 | class ItemSendgrid 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that messanger. 38 | * 39 | * @return MessengerInterface 40 | */ 41 | public static function get(array $setting): MessengerInterface 42 | { 43 | $apiKey = $setting['config']['api_key'] ?? ''; 44 | $sender = $setting['config']['sender'] ?? ''; 45 | $recipients = $setting['config']['recipients'] ?? []; 46 | 47 | $instance = new Sendgrid($apiKey); 48 | $instance->setSubject(__('core', 'messenger_text_mail_subject')); 49 | $instance->addSender($sender); 50 | 51 | foreach ($recipients as $recipient) { 52 | $instance->addRecipient($recipient); 53 | } 54 | 55 | return $instance; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemSlack.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\Slack; 27 | 28 | /** 29 | * The get for Slack. 30 | */ 31 | class ItemSlack 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that messanger. 37 | * 38 | * @return MessengerInterface 39 | */ 40 | public static function get(array $setting): MessengerInterface 41 | { 42 | $botToken = $setting['config']['bot_token'] ?? ''; 43 | $channel = $setting['config']['channel'] ?? ''; 44 | 45 | return new Slack($botToken, $channel); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemSlackWebhook.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\SlackWebhook; 27 | 28 | /** 29 | * The get for Slack Webhook. 30 | */ 31 | class ItemSlackWebhook 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that messanger. 37 | * 38 | * @return MessengerInterface 39 | */ 40 | public static function get(array $setting): MessengerInterface 41 | { 42 | $webhookUrl = $setting['config']['webhook_url'] ?? ''; 43 | 44 | return new SlackWebhook($webhookUrl); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemSmtp.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\Smtp; 27 | use function Shieldon\Firewall\__; 28 | 29 | /** 30 | * The get for SMTP. 31 | */ 32 | class ItemSmtp 33 | { 34 | /** 35 | * Initialize and get the instance. 36 | * 37 | * @param array $setting The configuration of that messanger. 38 | * 39 | * @return MessengerInterface 40 | */ 41 | public static function get(array $setting): MessengerInterface 42 | { 43 | $sender = $setting['config']['sender'] ?? ''; 44 | $recipients = $setting['config']['recipients'] ?? []; 45 | $host = $setting['config']['host'] ?? ''; 46 | $user = $setting['config']['user'] ?? ''; 47 | $pass = $setting['config']['pass'] ?? ''; 48 | $port = $setting['config']['port'] ?? ''; 49 | 50 | $instance = new Smtp($user, $pass, $host, (int) $port); 51 | $instance->setSubject(__('core', 'messenger_text_mail_subject')); 52 | $instance->addSender($sender); 53 | 54 | foreach ($recipients as $recipient) { 55 | $instance->addRecipient($recipient); 56 | } 57 | 58 | return $instance; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/ItemTelegram.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use Shieldon\Messenger\Telegram; 27 | 28 | /** 29 | * The get for Telegram. 30 | */ 31 | class ItemTelegram 32 | { 33 | /** 34 | * Initialize and get the instance. 35 | * 36 | * @param array $setting The configuration of that messanger. 37 | * 38 | * @return MessengerInterface 39 | */ 40 | public static function get(array $setting): MessengerInterface 41 | { 42 | $apiKey = $setting['config']['api_key'] ?? ''; 43 | $channel = $setting['config']['channel'] ?? ''; 44 | 45 | return new Telegram($apiKey, $channel); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Firewall/Firewall/Messenger/MessengerFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Firewall\Messenger; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use function array_map; 27 | use function explode; 28 | use function implode; 29 | use function ucwords; 30 | 31 | /* 32 | * The factory creates messenger instances. 33 | */ 34 | class MessengerFactory 35 | { 36 | /** 37 | * Create a messenger instance. 38 | * 39 | * @param string $messenger The messenger's ID string. 40 | * @param array $setting The configuration of that messanger. 41 | * 42 | * @return MessengerInterface 43 | */ 44 | public static function getInstance(string $messenger, array $setting): MessengerInterface 45 | { 46 | $className = '\Shieldon\Firewall\Firewall\Messenger\Item' . self::getCamelCase($messenger); 47 | 48 | return $className::get($setting); 49 | } 50 | 51 | /** 52 | * Check whether a messenger is available or not. 53 | * 54 | * @param array $setting The configuration of that messanger. 55 | * 56 | * @return bool 57 | */ 58 | public static function check(array $setting): bool 59 | { 60 | // If the settings is not set correctly. 61 | if (empty($setting['enable']) || empty($setting['confirm_test'])) { 62 | return false; 63 | } 64 | 65 | return true; 66 | } 67 | 68 | /** 69 | * Covert string with dashes into camel-case string. 70 | * 71 | * @param string $string A string with dashes. 72 | * 73 | * @return string 74 | */ 75 | public static function getCamelCase(string $string = ''): string 76 | { 77 | $str = explode('_', $string); 78 | $str = implode( 79 | '', 80 | array_map( 81 | function ($word) { 82 | return ucwords($word); 83 | }, 84 | $str 85 | ) 86 | ); 87 | return $str; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Firewall/HttpFactory.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall; 24 | 25 | use Shieldon\Firewall\Session; 26 | use Shieldon\Psr17\ResponseFactory; 27 | use Shieldon\Psr17\ServerRequestFactory; 28 | use Shieldon\Psr17\StreamFactory; 29 | use Shieldon\Psr7\Response; 30 | use Shieldon\Psr7\ServerRequest; 31 | use Shieldon\Psr7\Stream; 32 | 33 | /** 34 | * An object-oriented layer for the HTTP specification. 35 | */ 36 | class HttpFactory 37 | { 38 | /** 39 | * Create a server-side request. 40 | * 41 | * @return ServerRequest 42 | */ 43 | public static function createRequest(): ServerRequest 44 | { 45 | return ServerRequestFactory::fromGlobal(); 46 | } 47 | 48 | /** 49 | * Create a server-side response 50 | * 51 | * @return Response 52 | */ 53 | public static function createResponse(): Response 54 | { 55 | return ResponseFactory::fromNew(); 56 | } 57 | 58 | /** 59 | * Create a server-side response 60 | * 61 | * @return Stream 62 | */ 63 | public static function createStream(): Stream 64 | { 65 | return StreamFactory::fromNew(); 66 | } 67 | 68 | /** 69 | * Create a session by using Shieldon's Session driver. 70 | * 71 | * @param string $id Session ID 72 | * 73 | * @return Session 74 | */ 75 | public static function createSession($id = ''): Session 76 | { 77 | return new Session($id); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Firewall/HttpResolver.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall; 24 | 25 | use Psr\Http\Message\ResponseInterface; 26 | use function header; 27 | use function headers_sent; 28 | use function sprintf; 29 | use function stripos; 30 | 31 | /** 32 | * Display the final result. 33 | */ 34 | class HttpResolver 35 | { 36 | /** 37 | * Invoker. 38 | * 39 | * @param ResponseInterface $response The PSR-7 response. 40 | * @param bool $finally Terminate current PHP proccess if 41 | * this value is true. 42 | * @return void 43 | */ 44 | public function __invoke(ResponseInterface $response, $finally = true): void 45 | { 46 | if (!headers_sent()) { 47 | foreach ($response->getHeaders() as $key => $values) { 48 | $replace = stripos($key, 'Set-Cookie') === 0 ? false : true; 49 | foreach ($values as $value) { 50 | header(sprintf('%s: %s', $key, $value), $replace); 51 | $replace = false; 52 | } 53 | } 54 | 55 | header( 56 | sprintf( 57 | 'HTTP/%s %s %s', 58 | $response->getProtocolVersion(), 59 | $response->getStatusCode(), 60 | $response->getReasonPhrase() 61 | ), 62 | true, 63 | $response->getStatusCode() 64 | ); 65 | } 66 | 67 | echo $response->getBody()->getContents(); 68 | 69 | if ($finally && !defined('PHP_UNIT_TEST')) { 70 | // @codeCoverageIgnoreStart 71 | exit; 72 | // @codeCoverageIgnoreEnd 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Firewall/Integration/Bootstrap.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\Firewall\Integration; 14 | 15 | use Shieldon\Firewall\Container; 16 | use Shieldon\Firewall\Firewall; 17 | use Shieldon\Firewall\Panel; 18 | use Shieldon\Firewall\HttpResolver; 19 | use function dirname; 20 | use function strpos; 21 | 22 | /** 23 | * The easist way to implement Shieldon Firewall in your PHP project. 24 | * 25 | * [How to use] 26 | * 27 | * This class is supposed to be used in a very early stage of your code. 28 | * The position is right after Composer autoloader. 29 | * 30 | * [Example] 31 | * 32 | * require_once '../vendor/autoload.php'; 33 | * 34 | * $shieldon = new \Shieldon\Firewall\Intergration\Bootstrap(); 35 | * $shieldon->run(); 36 | * 37 | * [Note] 38 | * 39 | * If you use this approach on a PHP framework, make sure that the route 40 | * supports POST method, otherwise the CAPTCHA form will not work. 41 | */ 42 | class Bootstrap 43 | { 44 | /** 45 | * Constuctor. 46 | * 47 | * @param string $storage The absolute path of the storage where stores 48 | * Shieldon generated data. 49 | * @param string $requestUri The entry URL of Firewall Panel. 50 | * 51 | * @return void 52 | */ 53 | public function __construct(string $storage = '', string $requestUri = '') 54 | { 55 | // Prevent possible issues occur in CLI command line. 56 | if (isset($_SERVER['REQUEST_URI'])) { 57 | $serverRequestUri = $_SERVER['REQUEST_URI']; 58 | $scriptFilename = $_SERVER['SCRIPT_FILENAME']; 59 | 60 | if ('' === $storage) { 61 | // The storage folder should be placed above www-root for best security, 62 | // this folder must be writable. 63 | $storage = dirname($scriptFilename) . '/../shieldon_firewall'; 64 | } 65 | 66 | if ('' === $requestUri) { 67 | $requestUri = '/firewall/panel/'; 68 | } 69 | 70 | $firewall = new Firewall(); 71 | $firewall->configure($storage); 72 | $firewall->controlPanel($requestUri); 73 | 74 | if ($requestUri !== '' && 75 | strpos($serverRequestUri, $requestUri) === 0 76 | ) { 77 | // Get into the Firewall Panel. 78 | $panel = new Panel(); 79 | $panel->entry(); 80 | } 81 | } 82 | } 83 | 84 | /** 85 | * Start protecting your site. 86 | * 87 | * @return void 88 | */ 89 | public function run(): void 90 | { 91 | $firewall = Container::get('firewall'); 92 | 93 | $response = $firewall->run(); 94 | 95 | if ($response->getStatusCode() !== 200) { 96 | $httpResolver = new HttpResolver(); 97 | $httpResolver($response); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Firewall/Integration/CakePhp.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\Firewall\Integration; 14 | 15 | use Psr\Http\Message\ResponseInterface as Response; 16 | use Psr\Http\Message\ServerRequestInterface as Request; 17 | use Shieldon\Firewall\Firewall; 18 | use Shieldon\Firewall\HttpResolver; 19 | use Shieldon\Firewall\Captcha\Csrf; 20 | use const TMP; // CakePHP 21 | 22 | /** 23 | * CakePHP Middleware 24 | * 25 | * This middleware has been tested succesfully with CakePHP 3.8 26 | */ 27 | class CakePhp 28 | { 29 | /** 30 | * The absolute path of the storage where stores Shieldon generated data. 31 | * 32 | * @var string 33 | */ 34 | protected $storage; 35 | 36 | /** 37 | * The entry point of Shieldon Firewall's control panel. 38 | * 39 | * For example: https://yoursite.com/firewall/panel/ 40 | * Just use the path component of a URI. 41 | * 42 | * @var string 43 | */ 44 | protected $panelUri; 45 | 46 | /** 47 | * Constructor. 48 | * 49 | * @param string $storage See property `storage` explanation. 50 | * @param string $panelUri See property `panelUri` explanation. 51 | * 52 | * @return void 53 | */ 54 | public function __construct(string $storage = '', string $panelUri = '') 55 | { 56 | // The constant TMP is the path of CakePHP's tmp folder. 57 | // The Shieldon generated data is stored at that place. 58 | $this->storage = TMP . 'shieldon_firewall'; 59 | $this->panelUri = '/firewall/panel/'; 60 | 61 | if ('' !== $storage) { 62 | $this->storage = $storage; 63 | } 64 | 65 | if ('' !== $panelUri) { 66 | $this->panelUri = $panelUri; 67 | } 68 | } 69 | 70 | /** 71 | * Middleware invokable class. 72 | * 73 | * @param Request $request PSR7 request 74 | * @param Response $response PSR7 response 75 | * @param callable $next Next middleware 76 | * 77 | * @return Response 78 | */ 79 | public function __invoke(Request $request, Response $response, $next): Response 80 | { 81 | $firewall = new Firewall($request); 82 | $firewall->configure($this->storage); 83 | $firewall->controlPanel($this->panelUri); 84 | 85 | // Pass CSRF token to the Captcha form. 86 | // Note: The CsrfProtectionMiddleware was added in 3.5.0 87 | $firewall->getKernel()->setCaptcha( 88 | new Csrf([ 89 | 'name' => '_csrfToken', 90 | 'value' => $request->getParam('_csrfToken'), 91 | ]) 92 | ); 93 | 94 | $response = $firewall->run(); 95 | 96 | if ($response->getStatusCode() !== 200) { 97 | $httpResolver = new HttpResolver(); 98 | $httpResolver($response); 99 | } 100 | 101 | return $next($request, $response); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Firewall/Integration/Laravel.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\Firewall\Integration; 14 | 15 | use Psr\Http\Message\ServerRequestInterface as Request; 16 | use Shieldon\Firewall\Firewall; 17 | use Shieldon\Firewall\HttpResolver; 18 | use Shieldon\Firewall\Captcha\Csrf; 19 | use function storage_path; // Laravel 20 | use function csrf_token; // Laravel 21 | 22 | /** 23 | * Middleware for Laravel framework (5.x - 6.x) 24 | */ 25 | class Laravel 26 | { 27 | /** 28 | * The absolute path of the storage where stores Shieldon generated data. 29 | * 30 | * @var string 31 | */ 32 | protected $storage; 33 | 34 | /** 35 | * The entry point of Shieldon Firewall's control panel. 36 | * 37 | * For example: https://yoursite.com/firewall/panel/ 38 | * Just use the path component of a URI. 39 | * 40 | * @var string 41 | */ 42 | protected $panelUri; 43 | 44 | /** 45 | * Constructor. 46 | * 47 | * @param string $storage See property `storage` explanation. 48 | * @param string $panelUri See property `panelUri` explanation. 49 | * 50 | * @return void 51 | */ 52 | public function __construct(string $storage = '', string $panelUri = '') 53 | { 54 | // The Shieldon generated data is stored at that place. 55 | $this->storage = storage_path('shieldon_firewall'); 56 | $this->panelUri = '/firewall/panel/'; 57 | 58 | if ('' !== $storage) { 59 | $this->storage = $storage; 60 | } 61 | 62 | if ('' !== $panelUri) { 63 | $this->panelUri = $panelUri; 64 | } 65 | } 66 | 67 | /** 68 | * Handle an incoming request. 69 | * 70 | * @param Request $request The PSR-7 server request. 71 | * @param Closure $next The next middleware. 72 | * 73 | * @return mixed 74 | */ 75 | public function handle($request, Closure $next) 76 | { 77 | $firewall = new Firewall($request); 78 | $firewall->configure($this->storage); 79 | $firewall->controlPanel($this->panelUri); 80 | 81 | // Pass Laravel CSRF Token to Captcha form. 82 | $firewall->getKernel()->setCaptcha( 83 | new Csrf([ 84 | 'name' => '_token', 85 | 'value' => csrf_token(), 86 | ]) 87 | ); 88 | 89 | $response = $firewall->run(); 90 | 91 | if ($response->getStatusCode() !== 200) { 92 | $httpResolver = new HttpResolver(); 93 | $httpResolver($response); 94 | } 95 | 96 | return $next($request); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Firewall/Integration/Slim4.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\Firewall\Integration; 14 | 15 | use Psr\Http\Message\ResponseInterface as Response; 16 | use Psr\Http\Message\ServerRequestInterface as Request; 17 | use Psr\Http\Server\MiddlewareInterface as Middleware; 18 | use Psr\Http\Server\RequestHandlerInterface as RequestHandler; 19 | use Shieldon\Firewall\Firewall; 20 | use Shieldon\Firewall\HttpResolver; 21 | use Shieldon\Firewall\Captcha\Csrf; 22 | use function dirname; 23 | 24 | /** 25 | * Middleware for Slim 4 framework 26 | */ 27 | class Slim4 implements Middleware 28 | { 29 | /** 30 | * The absolute path of the storage where stores Shieldon generated data. 31 | * 32 | * @var string 33 | */ 34 | protected $storage; 35 | 36 | /** 37 | * The entry point of Shieldon Firewall's control panel. 38 | * 39 | * For example: https://yoursite.com/firewall/panel/ 40 | * Just use the path component of a URI. 41 | * 42 | * @var string 43 | */ 44 | protected $panelUri; 45 | 46 | /** 47 | * Constructor. 48 | * 49 | * @param string $storage See property `storage` explanation. 50 | * @param string $panelUri See property `panelUri` explanation. 51 | * 52 | * @return void 53 | */ 54 | public function __construct(string $storage = '', string $panelUri = '') 55 | { 56 | $dir = dirname($_SERVER['SCRIPT_FILENAME']); 57 | 58 | $this->storage = $dir . '/../shieldon_firewall'; 59 | $this->panelUri = '/firewall/panel/'; 60 | 61 | if ('' !== $storage) { 62 | $this->storage = $storage; 63 | } 64 | 65 | if ('' !== $panelUri) { 66 | $this->panelUri = $panelUri; 67 | } 68 | } 69 | 70 | /** 71 | * Shieldon middleware invokable class. 72 | * 73 | * @param Request $request PSR-7 request 74 | * @param RequestHandler $handler PSR-15 request handler 75 | * 76 | * @return Response 77 | */ 78 | public function process(Request $request, RequestHandler $handler): Response 79 | { 80 | $firewall = new Firewall($request); 81 | $firewall->configure($this->storage); 82 | $firewall->controlPanel($this->panelUri); 83 | 84 | // Pass Slim CSRF Token to Captcha form. 85 | $firewall->getKernel()->setCaptcha( 86 | new Csrf([ 87 | 'name' => 'csrf_name', 88 | 'value' => $request->getAttribute('csrf_name'), 89 | ]) 90 | ); 91 | 92 | $firewall->getKernel()->setCaptcha( 93 | new Csrf([ 94 | 'name' => 'csrf_value', 95 | 'value' => $request->getAttribute('csrf_value'), 96 | ]) 97 | ); 98 | 99 | $response = $firewall->run(); 100 | 101 | if ($response->getStatusCode() !== 200) { 102 | $httpResolver = new HttpResolver(); 103 | $httpResolver($response); 104 | } 105 | 106 | return $handler->handle($request); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Firewall/Integration/ZendPsr15.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\Firewall\Integration; 14 | 15 | use Psr\Http\Message\ResponseInterface as Response; 16 | use Psr\Http\Message\ServerRequestInterface as Request; 17 | use Psr\Http\Server\MiddlewareInterface as Middleware; 18 | use Psr\Http\Server\RequestHandlerInterface as RequestHandler; 19 | use Shieldon\Firewall\Firewall; 20 | use Shieldon\Firewall\HttpResolver; 21 | use Shieldon\Firewall\Captcha\Csrf; 22 | use function dirname; 23 | 24 | /** 25 | * PSR-15 Middleware for Zend Framework. 26 | */ 27 | class ZendPsr15 implements Middleware 28 | { 29 | /** 30 | * The absolute path of the storage where stores Shieldon generated data. 31 | * 32 | * @var string 33 | */ 34 | protected $storage; 35 | 36 | /** 37 | * The entry point of Shieldon Firewall's control panel. 38 | * 39 | * For example: https://yoursite.com/firewall/panel/ 40 | * Just use the path component of a URI. 41 | * 42 | * @var string 43 | */ 44 | protected $panelUri; 45 | 46 | /** 47 | * Constructor. 48 | * 49 | * @param string $storage See property `storage` explanation. 50 | * @param string $panelUri See property `panelUri` explanation. 51 | * 52 | * @return void 53 | */ 54 | public function __construct(string $storage = '', string $panelUri = '') 55 | { 56 | $dir = dirname($_SERVER['SCRIPT_FILENAME']); 57 | 58 | $this->storage = $dir . '/../data/shieldon_firewall'; 59 | $this->panelUri = '/firewall/panel/'; 60 | 61 | if ('' !== $storage) { 62 | $this->storage = $storage; 63 | } 64 | 65 | if ('' !== $panelUri) { 66 | $this->panelUri = $panelUri; 67 | } 68 | } 69 | 70 | /** 71 | * Shieldon middleware invokable class. 72 | * 73 | * @param Request $request PSR-7 request 74 | * @param RequestHandler $delegat PSR-15 request handler 75 | * 76 | * @return Response 77 | */ 78 | public function process(Request $request, RequestHandler $handler): Response 79 | { 80 | $firewall = new Firewall($request); 81 | $firewall->configure($this->storage); 82 | $firewall->controlPanel($this->panelUri); 83 | 84 | // Pass \Zend\Validator\Csrf CSRF Token to Captcha form. 85 | $firewall->getKernel()->setCaptcha( 86 | new Csrf([ 87 | 'name' => '_shieldon_csrf', 88 | 'value' => $request->getAttribute('_shieldon_csrf'), 89 | ]) 90 | ); 91 | 92 | $response = $firewall->run(); 93 | 94 | if ($response->getStatusCode() !== 200) { 95 | $httpResolver = new HttpResolver(); 96 | $httpResolver($response); 97 | } 98 | 99 | return $handler->handle($request); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Firewall/Integration/ZendPsr7.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\Firewall\Integration; 14 | 15 | use Psr\Http\Message\ResponseInterface as Response; 16 | use Psr\Http\Message\ServerRequestInterface as Request; 17 | use Shieldon\Firewall\Firewall; 18 | use Shieldon\Firewall\HttpResolver; 19 | use Shieldon\Firewall\Captcha\Csrf; 20 | use function dirname; 21 | 22 | /** 23 | * PSR-7 Middleware for Zend Framework 24 | */ 25 | class ZendPsr7 26 | { 27 | /** 28 | * The absolute path of the storage where stores Shieldon generated data. 29 | * 30 | * @var string 31 | */ 32 | protected $storage; 33 | 34 | /** 35 | * The entry point of Shieldon Firewall's control panel. 36 | * 37 | * For example: https://yoursite.com/firewall/panel/ 38 | * Just use the path component of a URI. 39 | * 40 | * @var string 41 | */ 42 | protected $panelUri; 43 | 44 | /** 45 | * Constructor. 46 | * 47 | * @param string $storage See property `storage` explanation. 48 | * @param string $panelUri See property `panelUri` explanation. 49 | * 50 | * @return void 51 | */ 52 | public function __construct(string $storage = '', string $panelUri = '') 53 | { 54 | $dir = dirname($_SERVER['SCRIPT_FILENAME']); 55 | 56 | $this->storage = $dir . '/../data/shieldon_firewall'; 57 | $this->panelUri = '/firewall/panel/'; 58 | 59 | if ('' !== $storage) { 60 | $this->storage = $storage; 61 | } 62 | 63 | if ('' !== $panelUri) { 64 | $this->panelUri = $panelUri; 65 | } 66 | } 67 | 68 | /** 69 | * Shieldon middleware invokable class 70 | * 71 | * @param Request $request PSR7 request 72 | * @param Response $response PSR7 response 73 | * @param callable $next Next middleware 74 | * 75 | * @return Response 76 | */ 77 | public function __invoke(Request $request, Response $response, $next): Response 78 | { 79 | $firewall = new Firewall($request); 80 | $firewall->configure($this->storage); 81 | $firewall->controlPanel($this->panelUri); 82 | 83 | // Pass \Zend\Validator\Csrf CSRF Token to Captcha form. 84 | $firewall->getKernel()->setCaptcha( 85 | new Csrf([ 86 | 'name' => '_shieldon_csrf', 87 | 'value' => $request->getAttribute('_shieldon_csrf'), 88 | ]) 89 | ); 90 | 91 | $response = $firewall->run(); 92 | 93 | if ($response->getStatusCode() !== 200) { 94 | $httpResolver = new HttpResolver(); 95 | $httpResolver($response); 96 | } 97 | 98 | return $next($request, $response); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Firewall/Kernel/MessengerTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Kernel; 24 | 25 | use Shieldon\Messenger\Messenger\MessengerInterface; 26 | use RuntimeException; 27 | 28 | /* 29 | * Messenger Trait is loaded in Kernel instance only. 30 | */ 31 | trait MessengerTrait 32 | { 33 | /** 34 | * Public methods | Desctiotion 35 | * ----------------------|--------------------------------------------- 36 | * setMessenger | Set a messenger 37 | * ----------------------|--------------------------------------------- 38 | */ 39 | 40 | /** 41 | * The ways Shieldon send a message to when someone has been blocked. 42 | * The collection of \Shieldon\Messenger\Messenger\MessengerInterface 43 | * 44 | * @var array 45 | */ 46 | protected $messenger = []; 47 | 48 | /** 49 | * The message that will be sent to the third-party API. 50 | * 51 | * @var string 52 | */ 53 | protected $msgBody = ''; 54 | 55 | /** 56 | * Get a class name without namespace string. 57 | * 58 | * @param object $instance Class 59 | * 60 | * @return string 61 | */ 62 | abstract protected function getClassName($instance): string; 63 | 64 | /** 65 | * Set a messenger 66 | * 67 | * @param MessengerInterface $instance The messenger instance. 68 | * 69 | * @return void 70 | */ 71 | public function setMessenger(MessengerInterface $instance): void 72 | { 73 | $class = $this->getClassName($instance); 74 | $this->messenger[$class] = $instance; 75 | } 76 | 77 | /** 78 | * Set the message body. 79 | * 80 | * @param string $message The message text. 81 | * 82 | * @return void 83 | */ 84 | protected function setMessageBody(string $message = ''): void 85 | { 86 | $this->msgBody = $message; 87 | } 88 | 89 | // @codeCoverageIgnoreStart 90 | 91 | /** 92 | * Undocumented function 93 | * 94 | * @return void 95 | */ 96 | protected function triggerMessengers(): void 97 | { 98 | if (empty($this->msgBody)) { 99 | return; 100 | } 101 | 102 | try { 103 | foreach ($this->messenger as $messenger) { 104 | $messenger->setTimeout(2); 105 | $messenger->send($this->msgBody); 106 | } 107 | // phpcs:ignore 108 | } catch (RuntimeException $e) { 109 | // Do not throw error, becasue the third-party services might be unavailable. 110 | } 111 | } 112 | 113 | // @codeCoverageIgnoreEnd 114 | } 115 | -------------------------------------------------------------------------------- /src/Firewall/Log/SessionLogger.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Log; 24 | 25 | use function date; 26 | use function file_put_contents; 27 | use function is_dir; 28 | use function mkdir; 29 | use function umask; 30 | use function debug_backtrace; 31 | use const PHP_EOL; 32 | use const FILE_APPEND; 33 | 34 | /** 35 | * Only use this class for debugging after running the unit tests. 36 | */ 37 | final class SessionLogger 38 | { 39 | /** 40 | * Log the message for debugging. 41 | * 42 | * @param string $text The message. 43 | * 44 | * @return void 45 | */ 46 | public static function log(string $text = ''): void 47 | { 48 | $dir = BOOTSTRAP_DIR . '/../tmp/shieldon/session_logs'; 49 | $file = $dir . '/' . date('Y-m-d') . '.json'; 50 | 51 | $originalUmask = umask(0); 52 | 53 | if (!is_dir($dir)) { 54 | mkdir($dir, 0777, true); 55 | } 56 | 57 | umask($originalUmask); 58 | 59 | $method = json_encode(debug_backtrace()[3], JSON_PRETTY_PRINT); 60 | 61 | $content = date('Y-m-d H:i:s') . ' [text]' . $text . "\n"; 62 | $content .= $method; 63 | 64 | file_put_contents($file, $content . PHP_EOL, FILE_APPEND); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Firewall/Middleware/Header.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Middleware; 24 | 25 | use Psr\Http\Message\ResponseInterface; 26 | use Psr\Http\Message\ServerRequestInterface; 27 | use Psr\Http\Server\MiddlewareInterface; 28 | use Psr\Http\Server\RequestHandlerInterface; 29 | use Shieldon\Psr7\Response; 30 | 31 | /** 32 | * A PSR-15 middleware that denys requests without specific header inforamtion. 33 | */ 34 | class Header implements MiddlewareInterface 35 | { 36 | /** 37 | * 406 - Not Acceptable. 38 | * 39 | * @var int 40 | */ 41 | const HTTP_STATUS_CODE = 406; 42 | 43 | /** 44 | * Very common requests from normal users. 45 | * 46 | * @var array 47 | */ 48 | protected $fieldList = [ 49 | 'Accept', 50 | 'Accept-Language', 51 | 'Accept-Encoding', 52 | ]; 53 | 54 | /** 55 | * Constructor. 56 | * 57 | * @param array $fieldList The list that want to be denied. 58 | * 59 | * @return void 60 | */ 61 | public function __construct(array $fieldList = []) 62 | { 63 | if (!empty($fieldList)) { 64 | $this->fieldList = $fieldList; 65 | } 66 | } 67 | 68 | /** 69 | * Invoker. 70 | * 71 | * @param ServerRequestInterface $request The PSR-7 server request. 72 | * @param RequestHandlerInterface $handler The PSR-15 request handler. 73 | * 74 | * @return ResponseInterface 75 | */ 76 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface 77 | { 78 | foreach ($this->fieldList as $fieldName) { 79 | if (!$request->hasHeader($fieldName)) { 80 | return (new Response)->withStatus(self::HTTP_STATUS_CODE); 81 | } 82 | } 83 | return $handler->handle($request); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Firewall/Middleware/UserAgent.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Middleware; 24 | 25 | use Psr\Http\Message\ResponseInterface; 26 | use Psr\Http\Message\ServerRequestInterface; 27 | use Psr\Http\Server\MiddlewareInterface; 28 | use Psr\Http\Server\RequestHandlerInterface; 29 | use Shieldon\Psr7\Response; 30 | use function implode; 31 | use function preg_match; 32 | 33 | /** 34 | * A PSR-15 middleware that denys all malicious user-agent requests. 35 | */ 36 | class UserAgent implements MiddlewareInterface 37 | { 38 | /** 39 | * 400 - Bad Request. 40 | * 41 | * @var int 42 | */ 43 | const HTTP_STATUS_CODE = 400; 44 | 45 | /** 46 | * The URL list that you want to protect. 47 | * 48 | * @var array 49 | */ 50 | protected $deniedList = [ 51 | 52 | // Backlink crawlers 53 | 'Ahrefs', // http://ahrefs.com/robot/ 54 | 'roger', // rogerbot (SEOMOZ) 55 | 'moz.com', // SEOMOZ crawlers 56 | 'MJ12bot', // Majestic crawlers 57 | 'findlinks', // http://wortschatz.uni-leipzig.de/findlinks 58 | 'Semrush', // http://www.semrush.com/bot.html 59 | 60 | // Web information crawlers 61 | 'domain', // Domain name information crawlers. 62 | 'copyright', // Copyright information crawlers. 63 | 64 | // Others 65 | 'archive', // Wayback machine 66 | ]; 67 | 68 | /** 69 | * Constructor. 70 | * 71 | * @param array $deniedList The list that want to be denied. 72 | * 73 | * @return void 74 | */ 75 | public function __construct(array $deniedList = []) 76 | { 77 | if (!empty($deniedList)) { 78 | $this->deniedList = $deniedList; 79 | } 80 | } 81 | 82 | /** 83 | * Invoker. 84 | * 85 | * @param ServerRequestInterface $request The PSR-7 server request. 86 | * @param RequestHandlerInterface $handler The PSR-15 request handler. 87 | * 88 | * @return ResponseInterface 89 | */ 90 | public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface 91 | { 92 | $userAgent = $request->getHeaderLine('user-agent'); 93 | 94 | if (empty($userAgent)) { 95 | return (new Response)->withStatus(self::HTTP_STATUS_CODE); 96 | } 97 | 98 | if (!empty($this->deniedList)) { 99 | if (preg_match('/(' . implode('|', $this->deniedList). ')/i', $userAgent)) { 100 | return (new Response)->withStatus(self::HTTP_STATUS_CODE); 101 | } 102 | } 103 | 104 | return $handler->handle($request); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Firewall/Panel/CsrfTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel; 24 | 25 | /* 26 | * Tradit for handling CSRF function. 27 | */ 28 | trait CsrfTrait 29 | { 30 | /** 31 | * Public methods | Desctiotion 32 | * ----------------------|--------------------------------------------- 33 | * csrf | Receive the CSRF name and token from the App. 34 | * setCsrfField | Set CSRF input fields. 35 | * fieldCsrf | Output HTML input element with CSRF token. 36 | * ----------------------|--------------------------------------------- 37 | */ 38 | 39 | /** 40 | * See $this->csrf() 41 | * 42 | * @var array 43 | */ 44 | protected $csrfField = []; 45 | 46 | /** 47 | * Most popular PHP framework has a built-in CSRF protection such as Laravel. 48 | * We need to pass the CSRF token for our form actions. 49 | * 50 | * @param array ...$csrfparams The arguments. 51 | * 52 | * @return void 53 | */ 54 | public function csrf(...$csrfparams): void 55 | { 56 | foreach ($csrfparams as $value) { 57 | foreach ($value as $k => $v) { 58 | $this->csrfField[] = [ 59 | 'name' => $k, 60 | 'value' => $v, 61 | ]; 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * Set CSRF input fields. 68 | * 69 | * @param array $csrfParams The arguments. 70 | * 71 | * @return void 72 | */ 73 | public function setCsrfField(array $csrfParams): void 74 | { 75 | $this->csrfField = $csrfParams; 76 | } 77 | 78 | /** 79 | * Output HTML input element with CSRF token. 80 | * 81 | * @return string 82 | */ 83 | public function fieldCsrf(): string 84 | { 85 | $string = ''; 86 | if (!empty($this->csrfField)) { 87 | foreach ($this->csrfField as $value) { 88 | // phpcs:ignore 89 | $string .= ''; 90 | } 91 | } 92 | return $string; 93 | } 94 | 95 | /** 96 | * Get CSRF input fields. 97 | * 98 | * @return array 99 | */ 100 | protected function getCsrfField(): array 101 | { 102 | return $this->csrfField; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Firewall/Panel/DemoModeTrait.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel; 24 | 25 | use Shieldon\Firewall\Container; 26 | 27 | /* 28 | * Tradit for demonstration. 29 | */ 30 | trait DemoModeTrait 31 | { 32 | /** 33 | * Public methods | Desctiotion 34 | * ----------------------|--------------------------------------------- 35 | * demo | Start a demo mode. Setting fields are hidden. 36 | * ----------------------|--------------------------------------------- 37 | */ 38 | 39 | /** 40 | * The mode of the firewall control panel. 41 | * self: Shieldon | managed: Firewall | demo: Demo 42 | * 43 | * @var string 44 | */ 45 | protected $mode = 'self'; 46 | 47 | /** 48 | * Login as a demo user. 49 | * 50 | * @var array 51 | */ 52 | protected $demoUser = [ 53 | 'user' => 'demo', 54 | 'pass' => 'demo', 55 | ]; 56 | 57 | /** 58 | * Mark as demo. 59 | * 60 | * @var string 61 | */ 62 | protected $markAsDemo = ''; 63 | 64 | /** 65 | * In demo mode, user's submit will not take effect. 66 | * 67 | * @param string $user The user name. 68 | * @param string $pass The user password. 69 | * 70 | * @return void 71 | */ 72 | public function demo(string $user = '', string $pass = ''): void 73 | { 74 | $this->demoUser['user'] = $user ?: 'demo'; 75 | $this->demoUser['pass'] = $pass ?: 'demo'; 76 | 77 | $this->mode = 'demo'; 78 | $this->markAsDemo = ' (DEMO)'; 79 | 80 | Container::get('shieldon')->managedBy('demo'); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/LineNotify.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\LineNotify as LineNotifyTest; 26 | 27 | /** 28 | * The sandbox for Line Notify. 29 | */ 30 | class LineNotify 31 | { 32 | /** 33 | * Invoker. 34 | * 35 | * @param array $args The arguments. 36 | * 37 | * @return bool 38 | */ 39 | public function __invoke(array $args): bool 40 | { 41 | return $this->sandbox($args[0], $args[1]); 42 | } 43 | 44 | /** 45 | * Test Line Notify. 46 | * 47 | * @param array $getParams The GET params passed from tryMessenger method. 48 | * @param array $message The message title and body. 49 | * 50 | * @return bool 51 | */ 52 | private function sandbox($getParams, $message) 53 | { 54 | $accessToken = $getParams['accessToken'] ?? ''; 55 | 56 | if (!empty($accessToken)) { 57 | $messenger = new LineNotifyTest($accessToken); 58 | 59 | if ($messenger->send($message['body'])) { 60 | // @codeCoverageIgnoreStart 61 | return true; 62 | // @codeCoverageIgnoreEnd 63 | } 64 | } 65 | return false; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/Mailgun.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\Mailgun as MailgunTest; 26 | use function explode; 27 | use function filter_var; 28 | use function str_replace; 29 | 30 | /** 31 | * The sandbox for Sendgrid. 32 | */ 33 | class Mailgun 34 | { 35 | /** 36 | * Invoker. 37 | * 38 | * @param array $args The arguments. 39 | * 40 | * @return bool 41 | */ 42 | public function __invoke(array $args): bool 43 | { 44 | return $this->sandbox($args[0], $args[1]); 45 | } 46 | 47 | /** 48 | * Test Mailgun. 49 | * 50 | * @param array $getParams The GET params passed from tryMessenger method. 51 | * @param array $message The message title and body. 52 | * 53 | * @return bool 54 | */ 55 | private function sandbox($getParams, $message) 56 | { 57 | $apiKey = $getParams['apiKey'] ?? ''; 58 | $domain = $getParams['domain'] ?? ''; 59 | $sender = $getParams['sender'] ?? ''; 60 | $recipients = $getParams['recipients'] ?? ''; 61 | 62 | if (!empty($sender) && !empty($recipients) && !empty($apiKey) && !empty($domain)) { 63 | $recipients = str_replace("\r", '|', $recipients); 64 | $recipients = str_replace("\n", '|', $recipients); 65 | $recipients = explode('|', $recipients); 66 | 67 | $messenger = new MailgunTest($apiKey, $domain); 68 | 69 | foreach ($recipients as $recipient) { 70 | if (filter_var($recipient, FILTER_VALIDATE_EMAIL)) { 71 | $messenger->addRecipient($recipient); 72 | } 73 | } 74 | 75 | if (filter_var($sender, FILTER_VALIDATE_EMAIL)) { 76 | $messenger->addSender($sender); 77 | } 78 | 79 | $messenger->setSubject($message['title']); 80 | 81 | if ($messenger->send($message['body'])) { 82 | // @codeCoverageIgnoreStart 83 | return true; 84 | // @codeCoverageIgnoreEnd 85 | } 86 | } 87 | return false; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/NativePhpMail.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\Mail as MailTest; 26 | use function explode; 27 | use function filter_var; 28 | use function function_exists; 29 | use function str_replace; 30 | 31 | /** 32 | * The sandbox for PHP native mail. 33 | */ 34 | class NativePhpMail 35 | { 36 | /** 37 | * Invoker. 38 | * 39 | * @param array $args The arguments. 40 | * 41 | * @return bool 42 | */ 43 | public function __invoke(array $args): bool 44 | { 45 | return $this->sandbox($args[0], $args[1]); 46 | } 47 | 48 | /** 49 | * Test PHP native mail. 50 | * 51 | * @param array $getParams The GET params passed from tryMessenger method. 52 | * @param array $message The message title and body. 53 | * 54 | * @return bool 55 | */ 56 | private function sandbox($getParams, $message) 57 | { 58 | $sender = $getParams['sender'] ?? ''; 59 | $recipients = $getParams['recipients'] ?? ''; 60 | 61 | if (!empty($sender) && !empty($recipients)) { 62 | $recipients = str_replace("\r", '|', $recipients); 63 | $recipients = str_replace("\n", '|', $recipients); 64 | $recipients = explode('|', $recipients); 65 | 66 | $messenger = new MailTest(); 67 | 68 | foreach ($recipients as $recipient) { 69 | if (filter_var($recipient, FILTER_VALIDATE_EMAIL)) { 70 | $messenger->addRecipient($recipient); 71 | } 72 | } 73 | 74 | if (filter_var($sender, FILTER_VALIDATE_EMAIL)) { 75 | $messenger->addSender($sender); 76 | } 77 | 78 | $messenger->setSubject($message['title']); 79 | 80 | if (!defined('PHP_UNIT_TEST') && $messenger->send($message['body'])) { 81 | // @codeCoverageIgnoreStart 82 | return true; 83 | // @codeCoverageIgnoreEnd 84 | } 85 | } 86 | 87 | // @codeCoverageIgnoreStart 88 | return false; 89 | // @codeCoverageIgnoreEnd 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/RocketChat.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\RocketChat as RocketChatTest; 26 | 27 | /** 28 | * The sandbox for RocketChat. 29 | */ 30 | class RocketChat 31 | { 32 | /** 33 | * Invoker. 34 | * 35 | * @param array $args The arguments. 36 | * 37 | * @return bool 38 | */ 39 | public function __invoke(array $args): bool 40 | { 41 | return $this->sandbox($args[0], $args[1]); 42 | } 43 | 44 | /** 45 | * Test RocketChat. 46 | * 47 | * @param array $getParams The GET params passed from tryMessenger method. 48 | * @param array $message The message title and body. 49 | * 50 | * @return bool 51 | */ 52 | private function sandbox($getParams, $message): bool 53 | { 54 | $serverUrl = $getParams['serverUrl'] ?? ''; 55 | $userId = $getParams['userId'] ?? ''; 56 | $accessToken = $getParams['accessToken'] ?? ''; 57 | $channel = $getParams['channel'] ?? ''; 58 | 59 | if (!empty($serverUrl) && 60 | !empty($userId) && 61 | !empty($accessToken) && 62 | !empty($channel) 63 | ) { 64 | $messenger = new RocketChatTest( 65 | $accessToken, 66 | $userId, 67 | $serverUrl, 68 | $channel 69 | ); 70 | 71 | if ($messenger->send($message['body'])) { 72 | // @codeCoverageIgnoreStart 73 | return true; 74 | // @codeCoverageIgnoreEnd 75 | } 76 | } 77 | return false; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/Sendgrid.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\Sendgrid as SendgridTest; 26 | use function explode; 27 | use function filter_var; 28 | use function str_replace; 29 | 30 | /** 31 | * The sandbox for Sendgrid. 32 | */ 33 | class Sendgrid 34 | { 35 | /** 36 | * Invoker. 37 | * 38 | * @param array $args The arguments. 39 | * 40 | * @return bool 41 | */ 42 | public function __invoke(array $args): bool 43 | { 44 | return $this->sandbox($args[0], $args[1]); 45 | } 46 | 47 | /** 48 | * Test Sendgrid. 49 | * 50 | * @param array $getParams The GET params passed from tryMessenger method. 51 | * @param array $message The message title and body. 52 | * 53 | * @return bool 54 | */ 55 | private function sandbox($getParams, $message) 56 | { 57 | $apiKey = $getParams['apiKey'] ?? ''; 58 | $sender = $getParams['sender'] ?? ''; 59 | $recipients = $getParams['recipients'] ?? ''; 60 | 61 | if (!empty($sender) && !empty($recipients) && !empty($apiKey)) { 62 | $recipients = str_replace("\r", '|', $recipients); 63 | $recipients = str_replace("\n", '|', $recipients); 64 | $recipients = explode('|', $recipients); 65 | 66 | $messenger = new SendgridTest($apiKey); 67 | 68 | foreach ($recipients as $recipient) { 69 | if (filter_var($recipient, FILTER_VALIDATE_EMAIL)) { 70 | $messenger->addRecipient($recipient); 71 | } 72 | } 73 | 74 | if (filter_var($sender, FILTER_VALIDATE_EMAIL)) { 75 | $messenger->addSender($sender); 76 | } 77 | 78 | $messenger->setSubject($message['title']); 79 | 80 | if ($messenger->send($message['body'])) { 81 | // @codeCoverageIgnoreStart 82 | return true; 83 | // @codeCoverageIgnoreEnd 84 | } 85 | } 86 | return false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/Slack.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\Slack as SlackTest; 26 | 27 | /** 28 | * The sandbox for Slack. 29 | */ 30 | class Slack 31 | { 32 | /** 33 | * Invoker. 34 | * 35 | * @param array $args The arguments. 36 | * 37 | * @return bool 38 | */ 39 | public function __invoke(array $args): bool 40 | { 41 | return $this->sandbox($args[0], $args[1]); 42 | } 43 | 44 | /** 45 | * Test Slack. 46 | * 47 | * @param array $getParams The GET params passed from tryMessenger method. 48 | * @param array $message The message title and body. 49 | * 50 | * @return bool 51 | */ 52 | private function sandbox($getParams, $message) 53 | { 54 | $botToken = $getParams['botToken'] ?? ''; 55 | $channel = $getParams['channel'] ?? ''; 56 | 57 | if (!empty($botToken) && !empty($channel)) { 58 | $messenger = new SlackTest($botToken, $channel); 59 | 60 | if ($messenger->send($message['body'])) { 61 | // @codeCoverageIgnoreStart 62 | return true; 63 | // @codeCoverageIgnoreEnd 64 | } 65 | } 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/SlackWebhook.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\SlackWebhook as SlackWebhookTest; 26 | 27 | /** 28 | * The sandbox for Slack Webhook. 29 | */ 30 | class SlackWebhook 31 | { 32 | /** 33 | * Invoker. 34 | * 35 | * @param array $args The arguments. 36 | * 37 | * @return bool 38 | */ 39 | public function __invoke(array $args): bool 40 | { 41 | return $this->sandbox($args[0], $args[1]); 42 | } 43 | 44 | /** 45 | * Test Slack Webhook. 46 | * 47 | * @param array $getParams The GET params passed from tryMessenger method. 48 | * @param array $message The message title and body. 49 | * 50 | * @return bool 51 | */ 52 | private function sandbox($getParams, $message) 53 | { 54 | $webhookUrl = $getParams['webhookUrl'] ?? ''; 55 | 56 | if (!empty($webhookUrl)) { 57 | $messenger = new SlackWebhookTest($webhookUrl); 58 | 59 | if ($messenger->send($message['body'])) { 60 | // @codeCoverageIgnoreStart 61 | return true; 62 | // @codeCoverageIgnoreEnd 63 | } 64 | } 65 | return false; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Firewall/Panel/Sandbox/Telegram.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Panel\Sandbox; 24 | 25 | use Shieldon\Messenger\Telegram as TelegramTest; 26 | 27 | /** 28 | * The sandbox for Telegram. 29 | */ 30 | class Telegram 31 | { 32 | /** 33 | * Invoker. 34 | * 35 | * @param array $args The arguments. 36 | * 37 | * @return bool 38 | */ 39 | public function __invoke(array $args): bool 40 | { 41 | return $this->sandbox($args[0], $args[1]); 42 | } 43 | 44 | /** 45 | * Test Telegram. 46 | * 47 | * @param array $getParams The GET params passed from tryMessenger method. 48 | * @param array $message The message title and body. 49 | * 50 | * @return bool 51 | */ 52 | private function sandbox($getParams, $message) 53 | { 54 | $apiKey = $getParams['apiKey'] ?? ''; 55 | $channel = $getParams['channel'] ?? ''; 56 | 57 | if (!empty($apiKey) && !empty($channel)) { 58 | $messenger = new TelegramTest($apiKey, $channel); 59 | 60 | if ($messenger->send($message['body'])) { 61 | // @codeCoverageIgnoreStart 62 | return true; 63 | // @codeCoverageIgnoreEnd 64 | } 65 | } 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /templates/panel/iptables_status.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | use function Shieldon\Firewall\_e; 26 | 27 | ?> 28 | 29 |
30 |
31 |
32 | 33 |
34 | 35 |
36 | iptables -L.' 41 | ); 42 | ?> 43 |
44 | 45 | 46 |
47 | ip6tables -L.' 52 | ); 53 | ?> 54 |
55 | 56 |
57 |
58 |
59 | 60 | : 61 | 62 | 63 | 64 |      65 | 66 | 67 |
68 | 69 |
70 |
-------------------------------------------------------------------------------- /templates/panel/js/common.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | ?> 26 | -------------------------------------------------------------------------------- /templates/panel/messenger.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | use function Shieldon\Firewall\_e; 26 | 27 | $timezone = ''; 28 | 29 | ?> 30 |
31 | 32 |
33 |
34 | loadViewPart('panel/messenger/tab'); ?> 35 | 36 |
37 | loadViewPart('panel/messenger/events'); ?> 38 |
39 | 40 |
41 | loadViewPart('panel/messenger/modules'); ?> 42 |
43 |
44 |
45 | 48 |
49 |
50 | fieldCsrf(); ?> 51 | 52 | 53 | 54 |
55 | 56 | loadViewPart('panel/js/common'); 59 | 60 | -------------------------------------------------------------------------------- /templates/panel/messenger/tab.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | use function Shieldon\Firewall\_e; 26 | 27 | $tab = $_POST['tab'] ?? 'events'; 28 | 29 | ?> 30 | 31 | checked($tab, 'events', false); ?> /> 32 | 35 | 36 | checked($tab, 'modules', false); ?> 38 | /> 39 | 42 | 43 | -------------------------------------------------------------------------------- /templates/panel/setting.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | use function Shieldon\Firewall\_e; 26 | 27 | $timezone = ''; 28 | 29 | ?> 30 |
31 | 32 |
33 |
34 | loadViewPart('panel/setting/tab'); ?> 35 | 36 |
37 | loadViewPart('panel/setting/daemon'); ?> 38 |
39 | 40 |
41 | loadViewPart('panel/setting/components'); ?> 42 |
43 | 44 |
45 | loadViewPart('panel/setting/filters'); ?> 46 |
47 | 48 |
49 | loadViewPart('panel/setting/captchas'); ?> 50 |
51 | 52 |
53 | loadViewPart('panel/setting/dialog_ui'); ?> 54 |
55 | 56 |
57 | loadViewPart('panel/setting/admin_login'); ?> 58 |
59 |
60 |
61 | 64 |
65 |
66 | fieldCsrf(); ?> 67 | 68 | 69 |
70 | 71 | loadViewPart('panel/setting/import_export'); ?> 72 | 73 | loadViewPart('panel/js/common'); 76 | 77 | -------------------------------------------------------------------------------- /templates/panel/setting/admin_login.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | use function Shieldon\Firewall\_e; 26 | 27 | ?> 28 |
29 |

30 |
31 |
32 | 33 | 34 | 35 | 42 | 43 |
36 | 40 |
41 |
44 |
45 |
46 | 47 | 48 | 49 | 56 | 57 |
50 | 54 |
55 |
58 |
59 |
60 | 61 | 62 | 63 | 67 | 68 |
64 | _('admin.last_modified'); ?> 65 | 66 |
69 |
-------------------------------------------------------------------------------- /templates/panel/setting/tab.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | defined('SHIELDON_VIEW') || die('Illegal access'); 24 | 25 | use function Shieldon\Firewall\_e; 26 | 27 | $tab = $_POST['tab'] ?? 'daemon'; 28 | 29 | ?> 30 | 31 | checked($tab, 'daemon', false); ?> /> 32 | 35 | 36 | checked($tab, 'components', false); ?> 38 | /> 39 | 42 | 43 | checked($tab, 'filters', false); ?> 45 | /> 46 | 49 | 50 | checked($tab, 'captchas', false); ?> 52 | /> 53 | 56 | 57 | checked($tab, 'dialog_ui', false); ?> 59 | /> 60 | 63 | 64 | checked($tab, 'admin_login', false); ?> 66 | /> 67 | 70 | -------------------------------------------------------------------------------- /tests/Firewall/BashScriptTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | class BashScriptTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | protected $iptablesWatchingFolder = ''; 28 | 29 | public function prepareFiles() 30 | { 31 | $this->iptablesWatchingFolder = BOOTSTRAP_DIR . '/../tmp/iptables'; 32 | 33 | if (!is_dir($this->iptablesWatchingFolder)) { 34 | $originalUmask = umask(0); 35 | mkdir($this->iptablesWatchingFolder, 0777, true); 36 | umask($originalUmask); 37 | 38 | // Create default log files. 39 | if (is_writable($this->iptablesWatchingFolder)) { 40 | fopen($this->iptablesWatchingFolder . '/iptables_queue.log', 'w+'); 41 | fopen($this->iptablesWatchingFolder . '/ipv4_status.log', 'w+'); 42 | fopen($this->iptablesWatchingFolder . '/ipv6_status.log', 'w+'); 43 | fopen($this->iptablesWatchingFolder . '/ipv4_command.log', 'w+'); 44 | fopen($this->iptablesWatchingFolder . '/ipv6_command.log', 'w+'); 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * This testing method does not work in Windows system. 51 | * 52 | * @return void 53 | */ 54 | public function testCommandBridge() 55 | { 56 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 57 | $this->markTestSkipped('[Warning] BashScriptTest is not available in Windows system!'); 58 | } 59 | 60 | $this->prepareFiles(); 61 | 62 | $bashScriptPath = BOOTSTRAP_DIR . '/../bin/iptables_bridge.sh'; 63 | 64 | // Add a command. 65 | $queueFilePath = $this->iptablesWatchingFolder . '/iptables_queue.log'; 66 | $commandFilePath = $this->iptablesWatchingFolder . '/ipv4_command.log'; 67 | 68 | // Clear the conent from this file. 69 | file_put_contents($queueFilePath, ''); 70 | file_put_contents($commandFilePath, ''); 71 | 72 | // command, ipv4/6, ip, subnet, port, protocol, action 73 | // add,4,127.0.0.1,all,80,tcp,drop (example) 74 | $command = 'add,4,33.33.33.34,all,all,all,deny'; 75 | 76 | // Add this IP address to itables_queue.log 77 | // Use `bin/iptables.sh` for adding it into IPTABLES. See document for more information. 78 | file_put_contents($queueFilePath, $command . "\n", FILE_APPEND | LOCK_EX); 79 | 80 | @exec('sudo bash ' . $bashScriptPath . ' --watch=' . $this->iptablesWatchingFolder); 81 | 82 | $resultString = file_get_contents($commandFilePath); 83 | 84 | $this->assertSame(trim($resultString), $command); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/Firewall/Captcha/CsrfTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Captcha; 24 | 25 | class CsrfTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function test__construct() 28 | { 29 | $captchaInstance = new \Shieldon\Firewall\Captcha\Csrf([ 30 | 'name' => 'pool', 31 | 'value' => '209b131bfec1c01c0f84d858bbf0ff47', 32 | ]); 33 | 34 | $reflection = new \ReflectionObject($captchaInstance); 35 | $p1 = $reflection->getProperty('name'); 36 | $p1->setAccessible(true); 37 | $p2 = $reflection->getProperty('value'); 38 | $p2->setAccessible(true); 39 | 40 | $name = $p1->getValue($captchaInstance); 41 | $value = $p2->getValue($captchaInstance); 42 | 43 | $this->assertSame($name, 'pool'); 44 | $this->assertSame($value, '209b131bfec1c01c0f84d858bbf0ff47'); 45 | } 46 | 47 | public function testResponse() 48 | { 49 | $captchaInstance = new \Shieldon\Firewall\Captcha\Csrf([ 50 | 'name' => 'pool', 51 | 'value' => '209b131bfec1c01c0f84d858bbf0ff47', 52 | ]); 53 | 54 | $_POST['pool'] = '209b131bfec1c01c0f84d858bbf0ff47'; 55 | 56 | $result = $captchaInstance->response(); 57 | 58 | $this->assertTrue($result); 59 | } 60 | 61 | public function testForm() 62 | { 63 | $captchaInstance = new \Shieldon\Firewall\Captcha\Csrf([ 64 | 'name' => 'pool', 65 | 'value' => '209b131bfec1c01c0f84d858bbf0ff47', 66 | ]); 67 | 68 | $result = $captchaInstance->form(); 69 | $this->assertSame($result, ''); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/Firewall/Captcha/FoundationTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Captcha; 24 | 25 | class FoundationTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testResponse() 28 | { 29 | $captchaInstance = new \Shieldon\Firewall\Captcha\Foundation(); 30 | 31 | $result = $captchaInstance->response(); 32 | $this->assertFalse($result); 33 | 34 | $_POST['shieldon_captcha'] = 'ok'; 35 | $this->refreshRequest(); 36 | 37 | $result = $captchaInstance->response(); 38 | $this->assertTrue($result); 39 | } 40 | 41 | public function testForm() 42 | { 43 | $html = ''; 44 | $html .= ''; 45 | 46 | $captchaInstance = new \Shieldon\Firewall\Captcha\Foundation(); 47 | 48 | $result = $captchaInstance->form(); 49 | $this->assertSame($result, $html); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Firewall/Component/DenyTraitTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Component; 24 | 25 | class DenyTraitTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testGetDeniedItems() 28 | { 29 | $rdns = new \Shieldon\Firewall\Component\Rdns(); 30 | 31 | $deniedList = $rdns->getDeniedItems(); 32 | $rdnsList = [ 33 | 'unknown_1' => '.webcrawler.link', 34 | ]; 35 | 36 | $this->assertEquals($deniedList, $rdnsList); 37 | } 38 | 39 | public function testGetDeniedItem() 40 | { 41 | $rdns = new \Shieldon\Firewall\Component\Rdns(); 42 | 43 | $deniedList = $rdns->getDeniedItem('unknown_1'); 44 | 45 | $rdnsList = '.webcrawler.link'; 46 | 47 | $this->assertEquals($deniedList, $rdnsList); 48 | } 49 | 50 | public function testRemoveDeniedItem() 51 | { 52 | $rdns = new \Shieldon\Firewall\Component\Rdns(); 53 | 54 | $this->assertTrue($rdns->hasDeniedItem('unknown_1')); 55 | 56 | $rdns->removeDeniedItem('unknown_1'); 57 | 58 | 59 | $deniedList = $rdns->getDeniedItems(); 60 | 61 | $this->assertEquals($deniedList, []); 62 | } 63 | 64 | public function testRemoveDeniedItems() 65 | { 66 | $rdns = new \Shieldon\Firewall\Component\Rdns(); 67 | 68 | $rdns->removeDeniedItems(); 69 | 70 | $deniedList = $rdns->getDeniedItems(); 71 | 72 | $this->assertEquals($deniedList, []); 73 | } 74 | 75 | public function testgetDenyWithPrefix() 76 | { 77 | $rdns = new \Shieldon\Firewall\Component\Rdns(); 78 | 79 | $deniedList = $rdns->getDenyWithPrefix('unknown'); 80 | 81 | $rdnsList = [ 82 | 'unknown_1' => '.webcrawler.link', 83 | ]; 84 | 85 | $this->assertEquals($deniedList, $rdnsList); 86 | } 87 | 88 | // removeDenyWithPrefix 89 | 90 | public function testremoveDenyWithPrefix() 91 | { 92 | $rdns = new \Shieldon\Firewall\Component\Rdns(); 93 | 94 | $rdns->removeDenyWithPrefix('unknown'); 95 | 96 | $rdnsList = []; 97 | 98 | $deniedList = $rdns->getDeniedItems(); 99 | 100 | $this->assertEquals($deniedList, $rdnsList); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /tests/Firewall/ContainerTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | class ContainerTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testAll() 28 | { 29 | $firewall = new \Shieldon\Firewall\Firewall(); 30 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 31 | 32 | $firewall = \Shieldon\Firewall\Container::get('firewall'); 33 | 34 | if ($firewall instanceof \Shieldon\Firewall\Firewall) { 35 | $this->assertTrue(true); 36 | } else { 37 | $this->assertTrue(false); 38 | } 39 | 40 | $typo = \Shieldon\Firewall\Container::get('firewall_typo'); 41 | $this->assertEquals($typo, null); 42 | 43 | $result = \Shieldon\Firewall\Container::has('firewall'); 44 | $this->assertTrue($result); 45 | 46 | \Shieldon\Firewall\Container::remove('firewall'); 47 | $result = \Shieldon\Firewall\Container::has('firewall'); 48 | $this->assertFalse($result); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/Firewall/Driver/AbstractDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Driver; 24 | 25 | class AbstractDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testHas() 28 | { 29 | $mock = $this->getMockForAbstractClass('Shieldon\Firewall\Driver\AbstractDriver'); 30 | $this->assertFalse($mock->has('22.22.22.22')); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Firewall/Driver/DriverProviderTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Driver; 24 | 25 | class DriverProviderTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testSetChannel() 28 | { 29 | $driverProvider = new \Shieldon\Firewall\Driver\DriverProvider(); 30 | $driverProvider->setChannel('unittest'); 31 | $this->assertSame($driverProvider->getChannel(), 'unittest'); 32 | } 33 | 34 | public function testGetChannel() 35 | { 36 | $driverProvider = new \Shieldon\Firewall\Driver\DriverProvider(); 37 | $this->assertSame($driverProvider->getChannel(), ''); 38 | } 39 | 40 | public function testParseData() 41 | { 42 | $driverProvider = new \Shieldon\Firewall\Driver\DriverProvider(); 43 | $result = $driverProvider->parseData([], 'filter'); 44 | 45 | $fields = [ 46 | 'ip' => '', 47 | 'session' => '', 48 | 'hostname' => '', 49 | 'first_time_s' => 0, 50 | 'first_time_m' => 0, 51 | 'first_time_h' => 0, 52 | 'first_time_d' => 0, 53 | 'first_time_flag' => 0, 54 | 'last_time' => 0, 55 | 'flag_js_cookie' => 0, 56 | 'flag_multi_session' => 0, 57 | 'flag_empty_referer' => 0, 58 | 'pageviews_cookie' => 0, 59 | 'pageviews_s' => 0, 60 | 'pageviews_m' => 0, 61 | 'pageviews_h' => 0, 62 | 'pageviews_d' => 0, 63 | ]; 64 | 65 | $this->assertSame($result, $fields); 66 | 67 | $this->assertSame([], $driverProvider->parseData([], 'rule')); 68 | $this->assertSame([], $driverProvider->parseData([], 'session')); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/Firewall/Driver/MysqlDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Driver; 24 | 25 | class MysqlDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function test__construct() 28 | { 29 | $db = [ 30 | 'host' => '127.0.0.1', 31 | 'dbname' => 'shieldon_unittest', 32 | 'user' => 'shieldon', 33 | 'pass' => 'taiwan', 34 | 'charset' => 'utf8', 35 | ]; 36 | 37 | $pdoInstance = new \PDO( 38 | 'mysql:host=' . $db['host'] . ';dbname=' . $db['dbname'] . ';charset=' . $db['charset'], 39 | $db['user'], 40 | $db['pass'] 41 | ); 42 | 43 | try { 44 | $db = new \Shieldon\Firewall\Driver\MysqlDriver($pdoInstance); 45 | } catch (\PDOException $e) { 46 | $this->assertTrue(false); 47 | } 48 | 49 | if ($db instanceof MysqlDriver) { 50 | $this->assertTrue(true); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/Firewall/Driver/SqliteDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Driver; 24 | 25 | class SqliteDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function test__construct() 28 | { 29 | try { 30 | $pdoInstance = new \PDO('sqlite::memory:'); 31 | $db = new \Shieldon\Firewall\Driver\SqliteDriver($pdoInstance); 32 | } catch (\PDOException $e) { 33 | $this->assertTrue(false); 34 | } 35 | 36 | if ($db instanceof MysqlDriver) { 37 | $this->assertTrue(true); 38 | } 39 | } 40 | 41 | 42 | public function testInstallSql() 43 | { 44 | $dbLocation = $this->getWritableTestFilePath('shieldon_unittest.sqlite3'); 45 | $pdoInstance = new \PDO('sqlite:' . $dbLocation); 46 | $db = new \Shieldon\Firewall\Driver\SqliteDriver($pdoInstance); 47 | 48 | try { 49 | $class = new \ReflectionObject($db); 50 | $method = $class->getMethod('installSql'); 51 | $method->setAccessible(true); 52 | $method->invoke($db); 53 | $this->assertTrue(true); 54 | } catch (\Exception $e) { 55 | $this->assertTrue(false); 56 | } 57 | } 58 | 59 | public function testCheckTableExists() 60 | { 61 | $dbLocation = $this->getWritableTestFilePath('shieldon_unittest.sqlite3'); 62 | $pdoInstance = new \PDO('sqlite:' . $dbLocation); 63 | $db = new \Shieldon\Firewall\Driver\SqliteDriver($pdoInstance); 64 | 65 | try { 66 | $class = new \ReflectionObject($db); 67 | $method = $class->getMethod('checkTableExists'); 68 | $method->setAccessible(true); 69 | $result = $method->invoke($db); 70 | $this->assertTrue($result); 71 | } catch (\Exception $e) { 72 | $this->assertTrue(false); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Firewall/Firewall/Driver/DriverFactoryTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Tests\Firewall\Driver; 24 | 25 | class DriverFactoryTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testGetInstance() 28 | { 29 | $instance = new \Shieldon\Firewall\Firewall\Driver\DriverFactory(); 30 | $fileDriver = $instance::getInstance('file', ['directory_path' => '/']); 31 | 32 | if ($fileDriver instanceof \Shieldon\Firewall\Driver\FileDriver) { 33 | $this->assertTrue(true); 34 | } else { 35 | $this->assertTrue(false); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Firewall/Firewall/Driver/ItemFileDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Tests\Firewall\Driver; 24 | 25 | class ItemFileDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testGet() 28 | { 29 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemFileDriver(); 30 | $fileDriver = $instance::get( 31 | [ 32 | 'directory_path' => BOOTSTRAP_DIR . '/../tmp', 33 | ] 34 | ); 35 | 36 | if ($fileDriver instanceof \Shieldon\Firewall\Driver\FileDriver) { 37 | $this->assertTrue(true); 38 | } else { 39 | $this->assertTrue(false); 40 | } 41 | } 42 | 43 | public function testGetWithInvalidSetting() 44 | { 45 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemFileDriver(); 46 | $fileDriver = $instance::get(['directory_path' => '']); 47 | 48 | $this->assertEquals($fileDriver, null); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/Firewall/Firewall/Driver/ItemMysqlDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Tests\Firewall\Driver; 24 | 25 | class ItemMysqlDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testGet() 28 | { 29 | $setting['host'] = 'localhost'; 30 | $setting['dbname'] = 'shieldon_unittest'; 31 | $setting['charset'] = 'utf8'; 32 | $setting['user'] = 'shieldon'; 33 | $setting['pass'] = 'taiwan'; 34 | 35 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemMysqlDriver(); 36 | $mysqlDriver = $instance::get($setting); 37 | 38 | if ($mysqlDriver instanceof \Shieldon\Firewall\Driver\MysqlDriver) { 39 | $this->assertTrue(true); 40 | } else { 41 | $this->assertTrue(false); 42 | } 43 | } 44 | 45 | public function testGetWithInvalidSetting() 46 | { 47 | $setting['host'] = 'localhost'; 48 | $setting['dbname'] = 'shieldon_unittest'; 49 | $setting['charset'] = 'utf8'; 50 | $setting['user'] = 'user_not_exist'; 51 | $setting['pass'] = 'taiwan'; 52 | 53 | $this->console('Test invalid MySQL database settings.', 'info'); 54 | 55 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemMysqlDriver(); 56 | $mysqlDriver = $instance::get($setting); 57 | 58 | $this->assertEquals($mysqlDriver, null); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/Firewall/Firewall/Driver/ItemRedisDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Tests\Firewall\Driver; 24 | 25 | class ItemRedisDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testGet() 28 | { 29 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemRedisDriver(); 30 | $redisDriver = $instance::get([]); 31 | 32 | if ($redisDriver instanceof \Shieldon\Firewall\Driver\RedisDriver) { 33 | $this->assertTrue(true); 34 | } else { 35 | $this->assertTrue(false); 36 | } 37 | } 38 | 39 | public function testGetWithInvalidSetting() 40 | { 41 | $setting['host'] = '127.0.0.1'; 42 | $setting['port'] = 8888; 43 | 44 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemRedisDriver(); 45 | $redisDriver = $instance::get($setting); 46 | 47 | $this->assertEquals($redisDriver, null); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Firewall/Firewall/Driver/ItemSqliteDriverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\Firewall\Tests\Firewall\Driver; 24 | 25 | class ItemSqliteDriverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testGet() 28 | { 29 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemSqliteDriver(); 30 | $sqliteDriver = $instance::get( 31 | [ 32 | 'directory_path' => BOOTSTRAP_DIR . '/../tmp', 33 | ] 34 | ); 35 | 36 | if ($sqliteDriver instanceof \Shieldon\Firewall\Driver\SqliteDriver) { 37 | $this->assertTrue(true); 38 | } else { 39 | $this->assertTrue(false); 40 | } 41 | } 42 | 43 | public function testGetWithInvalidSetting() 44 | { 45 | $instance = new \Shieldon\Firewall\Firewall\Driver\ItemSqliteDriver(); 46 | $sqliteDriver = $instance::get(['directory_path' => '']); 47 | 48 | $this->assertEquals($sqliteDriver, null); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/Firewall/FirewallTraitTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | class FirewallTraitTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testConfig() 28 | { 29 | $mock = $this->getMockForTrait('Shieldon\Firewall\FirewallTrait'); 30 | $mock->setConfig('a', 'one'); 31 | $mock->setConfig('b.c', 'two'); 32 | $mock->setConfig('d.e.f', 'three'); 33 | $mock->setConfig('g.h.i.j', 'four'); 34 | $mock->setConfig('k.l.m.o.p', 'five'); 35 | $mock->setConfig('q.r.s.t.u.v', 'six'); 36 | 37 | $a = $mock->getConfig('a'); 38 | $b = $mock->getConfig('b.c'); 39 | $c = $mock->getConfig('d.e.f'); 40 | $d = $mock->getConfig('g.h.i.j'); 41 | $e = $mock->getConfig('k.l.m.o.p'); 42 | $f = $mock->getConfig('q.r.s.t.u.v'); 43 | 44 | $this->assertSame($a, 'one'); 45 | $this->assertSame($b, 'two'); 46 | $this->assertSame($c, 'three'); 47 | $this->assertSame($d, 'four'); 48 | $this->assertSame($e, 'five'); 49 | $this->assertSame($f, ''); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Firewall/HttpResolverTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | class HttpResolverTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testHttpResolver() 28 | { 29 | $httpFactory = new \Shieldon\Firewall\HttpFactory(); 30 | $response = $httpFactory->createResponse(); 31 | $response = $response->withHeader('Set-Cookie', 'name=; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0'); 32 | 33 | $stream = $response->getBody(); 34 | $stream->write('test'); 35 | $stream->rewind(); 36 | $response = $response->withBody($stream); 37 | 38 | $httpResolver = new \Shieldon\Firewall\HttpResolver(); 39 | 40 | ob_start(); 41 | $httpResolver($response); 42 | $output = ob_get_contents(); 43 | ob_end_clean(); 44 | 45 | if (function_exists('xdebug_get_headers')) { 46 | $this->assertContains( 47 | 'Set-Cookie: name=; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0', 48 | xdebug_get_headers() 49 | ); 50 | } else { 51 | $this->console('function "xdebug_get_headers()" is needed to test the header output.', 'notice'); 52 | } 53 | 54 | $this->assertStringContainsString('test', $output); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Firewall/IpTraitTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | class IpTraitTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testSetIp() 28 | { 29 | $mock = $this->getMockForTrait('Shieldon\Firewall\IpTrait'); 30 | $mock->setIp('192.168.1.1'); 31 | 32 | $this->assertSame('192.168.1.1', $mock->getIp()); 33 | 34 | $mock->setIp('192.168.22.22', true); 35 | 36 | $this->assertNotSame('192.168.1.1', $mock->getIp()); 37 | } 38 | 39 | public function testGetIp() 40 | { 41 | $mock = $this->getMockForTrait('Shieldon\Firewall\IpTrait'); 42 | $mock->setIp('192.168.3.3'); 43 | 44 | $this->assertSame('192.168.3.3', $mock->getIp()); 45 | } 46 | 47 | public function testSetRdns() 48 | { 49 | $mock = $this->getMockForTrait('Shieldon\Firewall\IpTrait'); 50 | $mock->setRdns('unitest.local'); 51 | 52 | $this->assertSame('unitest.local', $mock->getRdns()); 53 | } 54 | 55 | public function testGetRdns() 56 | { 57 | $mock = $this->getMockForTrait('Shieldon\Firewall\IpTrait'); 58 | $mock->setRdns('unitest.local2'); 59 | 60 | $this->assertSame('unitest.local2', $mock->getRdns()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/Firewall/Log/ActionLogParsedCacheTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Log; 24 | 25 | class ActionLogParsedCacheTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function test__construct() 28 | { 29 | try { 30 | $logger = new \Shieldon\Firewall\Log\ActionLogParsedCache(BOOTSTRAP_DIR . '/../tmp/shieldon'); 31 | } catch (\Exception $e) { 32 | $this->assertTrue(false); 33 | } 34 | } 35 | 36 | public function testSaveAndGet() 37 | { 38 | $logger = new \Shieldon\Firewall\Log\ActionLogParsedCache(BOOTSTRAP_DIR . '/../tmp/shieldon'); 39 | 40 | foreach (['yesterday', 'last_month', 'this_month', 'past_seven_hours', 'today'] as $period) { 41 | $data['foo'] = 'bar'; 42 | $logger->save($period, $data); 43 | $s = $logger->get($period); 44 | $this->assertSame($s['foo'], $data['foo']); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Firewall/Log/ActionLoggerTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Log; 24 | 25 | use Shieldon\Firewall\Kernel\Enum; 26 | 27 | class ActionLoggerTest extends \Shieldon\FirewallTest\ShieldonTestCase 28 | { 29 | public function test__construct() 30 | { 31 | try { 32 | $logger = new \Shieldon\Firewall\Log\ActionLogger(BOOTSTRAP_DIR . '/../tmp/shieldon'); 33 | 34 | $info = $logger->getCurrentLoggerInfo(); 35 | 36 | $this->assertIsArray($info); 37 | } catch (\Exception $e) { 38 | $this->assertTrue(false); 39 | } 40 | 41 | if ($logger instanceof \Shieldon\Firewall\Log\ActionLogger) { 42 | $this->assertTrue(true); 43 | } 44 | } 45 | 46 | public function testAdd() 47 | { 48 | $kernel = new \Shieldon\Firewall\Kernel(); 49 | $logger = new \Shieldon\Firewall\Log\ActionLogger(BOOTSTRAP_DIR . '/../tmp/shieldon/test_logs', '19890604'); 50 | 51 | $data['ip'] = '127.0.0.1'; 52 | $data['session_id'] = md5((string) time()); 53 | $data['action_code'] = Enum::ACTION_TEMPORARILY_DENY; 54 | $data['timestamp'] = time(); 55 | 56 | $logger->add($data); 57 | 58 | $data['ip'] = '127.0.0.1'; 59 | $data['session_id'] = md5((string) time()); 60 | $data['action_code'] = Enum::ACTION_UNBAN; 61 | $data['timestamp'] = time() + 4; 62 | 63 | $logger->add($data); 64 | 65 | $results = $logger->get('19890604'); 66 | 67 | $this->assertEquals($data['ip'], $results[1]['ip']); 68 | $this->assertEquals($data['action_code'], $results[1]['action_code']); 69 | $this->assertEquals($data['timestamp'], $results[1]['timestamp']); 70 | 71 | $results = $logger->get('19890604', date('Ymd')); 72 | 73 | $logger->purgeLogs(); 74 | } 75 | 76 | public function testGet() 77 | { 78 | // This method has been tested in testAdd. 79 | } 80 | 81 | public function testCheckDirectory() 82 | { 83 | $logger = new \Shieldon\Firewall\Log\ActionLogger(BOOTSTRAP_DIR . '/../tmp/shieldon'); 84 | 85 | $reflection = new \ReflectionObject($logger); 86 | $methodCreateDirectory = $reflection->getMethod('checkDirectory'); 87 | $methodCreateDirectory->setAccessible(true); 88 | 89 | $result = $methodCreateDirectory->invokeArgs($logger, []); 90 | 91 | $this->assertTrue($result); 92 | } 93 | 94 | public function testPurgeLogs() 95 | { 96 | // This method has been tested in testAdd. 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /tests/Firewall/Middleware/HeaderTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Middleware; 24 | 25 | class HeaderTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testHeaderDeny() 28 | { 29 | $firewall = new \Shieldon\Firewall\Firewall(); 30 | $firewall->add(new \Shieldon\Firewall\Middleware\Header([ 31 | 'Accept', 32 | 'Accept-Language', 33 | 'Accept-Encoding', 34 | ])); 35 | $response = $firewall->run(); 36 | $this->assertSame($response->getStatusCode(), 406); 37 | } 38 | 39 | public function testHeaderAllow() 40 | { 41 | $_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;q=0.9'; 42 | $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7'; 43 | $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip'; 44 | $this->refreshRequest(); 45 | 46 | $firewall = new \Shieldon\Firewall\Firewall(); 47 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 48 | $firewall->getKernel()->driver->rebuild(); 49 | $firewall->getKernel()->setIp('131.132.87.12'); 50 | $firewall->getKernel()->disableFilters(); 51 | $firewall->getKernel()->disableComponents(); 52 | $firewall->add(new \Shieldon\Firewall\Middleware\Header()); 53 | $response = $firewall->run(); 54 | $this->assertSame($response->getStatusCode(), 200); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Firewall/Middleware/UserAgentTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Middleware; 24 | 25 | class UserAgentTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testUserAgent() 28 | { 29 | $_SERVER['HTTP_USER_AGENT'] = 'moz.com'; 30 | $this->refreshRequest(); 31 | 32 | $deniedList = [ 33 | 'Ahrefs', 34 | 'roger', 35 | 'moz.com', 36 | 'MJ12bot', 37 | 'findlinks', 38 | 'Semrush', 39 | 'domain', 40 | 'copyright', 41 | 'archive', 42 | ]; 43 | 44 | $firewall = new \Shieldon\Firewall\Firewall(); 45 | $firewall->add(new \Shieldon\Firewall\Middleware\UserAgent($deniedList)); 46 | $response = $firewall->run(); 47 | $this->assertSame($response->getStatusCode(), 400); 48 | } 49 | 50 | public function testUserAgentEmptyValue() 51 | { 52 | $_SERVER['HTTP_USER_AGENT'] = ''; 53 | $this->refreshRequest(); 54 | 55 | $firewall = new \Shieldon\Firewall\Firewall(); 56 | $firewall->add(new \Shieldon\Firewall\Middleware\UserAgent()); 57 | $response = $firewall->run(); 58 | $this->assertSame($response->getStatusCode(), 400); 59 | } 60 | 61 | public function testUserAgentPass() 62 | { 63 | $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'; 64 | $this->refreshRequest(); 65 | 66 | $firewall = new \Shieldon\Firewall\Firewall(); 67 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 68 | $firewall->getKernel()->driver->rebuild(); 69 | $firewall->getKernel()->setIp('131.132.87.12'); 70 | $firewall->getKernel()->disableFilters(); 71 | $firewall->getKernel()->disableComponents(); 72 | $firewall->add(new \Shieldon\Firewall\Middleware\UserAgent()); 73 | $response = $firewall->run(); 74 | $this->assertSame($response->getStatusCode(), 200); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/Firewall/Mock/MockMessenger.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\FirewallTest\Mock; 14 | 15 | use Shieldon\Messenger\Messenger\MessengerInterface; 16 | 17 | /** 18 | * For unit-testing purpose. 19 | * 20 | * @author Terry L. 21 | * @since 1.0.0 22 | */ 23 | class MockMessenger implements MessengerInterface 24 | { 25 | /** 26 | * Constructor. 27 | */ 28 | public function __construct() 29 | { 30 | // Nothing to do. 31 | } 32 | 33 | /** 34 | * Send the message. 35 | * 36 | * @inheritDoc 37 | */ 38 | public function send(string $message): bool 39 | { 40 | if (!empty($message)) { 41 | echo "\n" . $this->provider() . "\n"; 42 | echo "\n--- BEGIN - Mock of sending message ---\n\n"; 43 | echo $message; 44 | echo "\n--- END - Mock of sending message ---\n"; 45 | 46 | return true; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Get the provider name. 54 | * 55 | * @inheritDoc 56 | */ 57 | public function provider(): string 58 | { 59 | return ''; 60 | } 61 | 62 | /** 63 | * Set the timeout. 64 | * 65 | * @inheritDoc 66 | */ 67 | public function setTimeout(int $timeout = 0): void 68 | { 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/Firewall/Mock/MockSaveConfig.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | declare(strict_types=1); 12 | 13 | namespace Shieldon\FirewallTest\Mock; 14 | 15 | class MockSaveConfig 16 | { 17 | public static function get() 18 | { 19 | $json = file_get_contents(__DIR__ . '/save_config_form_test.json'); 20 | 21 | return json_decode($json, true); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/Firewall/Panel/AssetTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Panel; 24 | 25 | class AssetTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | use RouteTestTrait; 28 | 29 | public function testCss() 30 | { 31 | $_SERVER['REQUEST_URI'] = 'firewall/panel/asset/css'; 32 | 33 | $response = $this->route(false); 34 | 35 | $this->assertTrue(($response instanceof \Psr\Http\Message\ResponseInterface)); 36 | $this->assertSame('text/css; charset=UTF-8', $response->getHeaderLine('Content-Type')); 37 | } 38 | 39 | public function testJs() 40 | { 41 | $_SERVER['REQUEST_URI'] = '/firewall/panel/asset/js'; 42 | 43 | $response = $this->route(false); 44 | 45 | $this->assertTrue(($response instanceof \Psr\Http\Message\ResponseInterface)); 46 | $this->assertSame('text/javascript; charset=UTF-8', $response->getHeaderLine('Content-Type')); 47 | } 48 | 49 | public function testFavicon() 50 | { 51 | $_SERVER['REQUEST_URI'] = '/firewall/panel/asset/favicon'; 52 | 53 | $response = $this->route(false); 54 | 55 | $this->assertTrue(($response instanceof \Psr\Http\Message\ResponseInterface)); 56 | $this->assertSame('image/x-icon', $response->getHeaderLine('Content-Type')); 57 | } 58 | 59 | public function testLogo() 60 | { 61 | $_SERVER['REQUEST_URI'] = '/firewall/panel/asset/logo'; 62 | 63 | $response = $this->route(false); 64 | 65 | $this->assertTrue(($response instanceof \Psr\Http\Message\ResponseInterface)); 66 | $this->assertSame('image/png', $response->getHeaderLine('Content-Type')); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /tests/Firewall/Panel/CircleTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Panel; 24 | 25 | class CircleTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | use RouteTestTrait; 28 | 29 | public function testFilterTable() 30 | { 31 | $this->assertOutputContainsString( 32 | 'firewall/panel/circle/filter', 33 | 'Data Circle - Filter Table' 34 | ); 35 | } 36 | 37 | public function testRuleTableFormSubmit() 38 | { 39 | $_POST['ip'] = '127.0.1.127'; 40 | $_POST['action'] = 'permanently_ban'; 41 | $this->refreshRequest(); 42 | 43 | $this->assertOutputContainsString( 44 | 'firewall/panel/circle/rule', 45 | '127.0.1.127' 46 | ); 47 | 48 | $_POST['ip'] = '127.0.1.127'; 49 | $_POST['action'] = 'remove'; 50 | $this->refreshRequest(); 51 | 52 | $this->assertOutputNotContainsString( 53 | 'firewall/panel/circle/rule', 54 | '127.0.1.127' 55 | ); 56 | } 57 | 58 | public function testSessionTable() 59 | { 60 | $this->assertOutputContainsString( 61 | 'firewall/panel/circle/session', 62 | 'Data Circle - Session Table' 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/Firewall/Panel/DemoModeTraitTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Panel; 24 | 25 | class DemoModeTraitTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testAll() 28 | { 29 | $firewall = new \Shieldon\Firewall\Firewall(); 30 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 31 | 32 | $panel = new \Shieldon\Firewall\Panel(); 33 | $panel->demo('hello', 'world'); 34 | $panel->csrf(['test' => '1234']); 35 | 36 | $reflection = new \ReflectionObject($panel); 37 | $t = $reflection->getProperty('demoUser'); 38 | $t->setAccessible(true); 39 | $demoUser = $t->getValue($panel); 40 | 41 | $t = $reflection->getProperty('mode'); 42 | $t->setAccessible(true); 43 | $mode = $t->getValue($panel); 44 | 45 | $this->assertSame($demoUser['user'], 'hello'); 46 | $this->assertSame($demoUser['pass'], 'world'); 47 | $this->assertSame($mode, 'demo'); 48 | 49 | $kernel = $firewall->getKernel(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Firewall/Panel/HomeTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Panel; 24 | 25 | class HomeTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | use RouteTestTrait; 28 | 29 | public function testOverview() 30 | { 31 | $this->assertOutputContainsString( 32 | 'firewall/panel/home/overview', 33 | 'Overview' 34 | ); 35 | } 36 | 37 | public function testOverviewFormPostResetDataCircle() 38 | { 39 | $_POST['action_type'] = 'reset_data_circle'; 40 | $this->refreshRequest(); 41 | 42 | $this->assertOutputContainsString( 43 | 'firewall/panel/home/overview', 44 | 'Data circle tables have been reset.' 45 | ); 46 | } 47 | 48 | public function testOverviewFormPostResetActionLogs() 49 | { 50 | $_POST['action_type'] = 'reset_action_logs'; 51 | $this->refreshRequest(); 52 | 53 | $this->assertOutputContainsString( 54 | 'firewall/panel/home/overview', 55 | 'Action logs have been removed.' 56 | ); 57 | } 58 | 59 | public function testOverviewTemplateVarsOfActionLogger() 60 | { 61 | if (!defined('SHIELDON_PANEL_BASE')) { 62 | define('SHIELDON_PANEL_BASE', 'firewall/panel'); 63 | } 64 | 65 | $firewall = new \Shieldon\Firewall\Firewall(); 66 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 67 | $firewall->getKernel()->disableFilters(); 68 | $firewall->getKernel()->disableComponents(); 69 | $firewall->getKernel()->setLogger( 70 | new \Shieldon\Firewall\Log\ActionLogger( 71 | BOOTSTRAP_DIR . '/samples/action_logs' 72 | ) 73 | ); 74 | 75 | $resolver = new \Shieldon\Firewall\HttpResolver(); 76 | 77 | $controllerClass = new \Shieldon\Firewall\Panel\Home(); 78 | 79 | ob_start(); 80 | $resolver(call_user_func([$controllerClass, 'overview'])); 81 | $output = ob_get_contents(); 82 | ob_end_clean(); 83 | 84 | $this->assertStringContainsString('2020-02-03', $output); 85 | $this->assertStringContainsString('16', $output); 86 | $this->assertStringContainsString('0.41663 MB', $output); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/Firewall/Panel/ReportTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest\Panel; 24 | 25 | class ReportTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | use RouteTestTrait; 28 | 29 | private function prepareSampleLogs() 30 | { 31 | $dir = BOOTSTRAP_DIR . '/../tmp/shieldon/action_logs'; 32 | 33 | $it = new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS); 34 | $files = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST); 35 | 36 | foreach ($files as $file) { 37 | if ($file->isDir()) { 38 | rmdir($file->getRealPath()); 39 | } else { 40 | unlink($file->getRealPath()); 41 | } 42 | } 43 | 44 | // Copy sample files. 45 | $dir2 = BOOTSTRAP_DIR . '/../tests/samples/action_logs'; 46 | 47 | $it = new \RecursiveDirectoryIterator($dir2, \RecursiveDirectoryIterator::SKIP_DOTS); 48 | $files = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::CHILD_FIRST); 49 | 50 | foreach ($files as $file) { 51 | if (!$file->isDir()) { 52 | copy($file->getRealPath(), $dir . '/' . $file->getFilename()); 53 | } 54 | } 55 | } 56 | 57 | public function testActionLog() 58 | { 59 | $this->prepareSampleLogs(); 60 | 61 | $this->assertOutputContainsString( 62 | 'firewall/panel/report/actionLog', 63 | 'Action Logs' 64 | ); 65 | } 66 | 67 | public function testActionLogWithCachedData() 68 | { 69 | $this->assertOutputContainsString( 70 | 'firewall/panel/report/actionLog', 71 | 'Action Logs' 72 | ); 73 | } 74 | 75 | public function testOperationStatus() 76 | { 77 | $this->assertOutputContainsString( 78 | 'firewall/panel/report/operation', 79 | 'Operation Status' 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tests/Firewall/PanelTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | class PanelTest extends \Shieldon\FirewallTest\ShieldonTestCase 26 | { 27 | public function testPanelLoginPage() 28 | { 29 | $firewall = new \Shieldon\Firewall\Firewall(); 30 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 31 | 32 | $panel = new \Shieldon\Firewall\Panel(); 33 | 34 | ob_start(); 35 | $panel->entry('firewall/panel'); 36 | $output = ob_get_contents(); 37 | ob_end_clean(); 38 | 39 | $this->assertStringContainsString('Login to Shieldon Firewall Panel', $output); 40 | } 41 | 42 | public function testPanelLoginPageDemoMode() 43 | { 44 | $firewall = new \Shieldon\Firewall\Firewall(); 45 | $firewall->configure(BOOTSTRAP_DIR . '/../tmp/shieldon'); 46 | 47 | $panel = new \Shieldon\Firewall\Panel(); 48 | $panel->demo(); 49 | 50 | ob_start(); 51 | $panel->entry('firewall/panel'); 52 | $output = ob_get_contents(); 53 | ob_end_clean(); 54 | 55 | $this->assertStringContainsString('(DEMO)', $output); 56 | } 57 | 58 | public function testGetFirewallInstance() 59 | { 60 | $panel = new \Shieldon\Firewall\Panel(); 61 | 62 | $reflection = new \ReflectionObject($panel); 63 | $methodSetSessionId = $reflection->getMethod('getFirewallInstance'); 64 | $methodSetSessionId->setAccessible(true); 65 | 66 | // Test exception. 67 | $this->expectException(\RuntimeException::class); 68 | 69 | $methodSetSessionId->invokeArgs($panel, []); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/Firewall/SessionTest.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | namespace Shieldon\FirewallTest; 24 | 25 | use function Shieldon\Firewall\get_session_instance; 26 | use function Shieldon\Firewall\get_response; 27 | 28 | class SessionTest extends \Shieldon\FirewallTest\ShieldonTestCase 29 | { 30 | public function testGetChannel() 31 | { 32 | $kernel = $this->getKernelInstance('file'); 33 | $kernel->setChannel('test_session_get_channel'); 34 | 35 | $session = get_session_instance(); 36 | $channelName = $session->getChannel(); 37 | 38 | $this->assertSame('test_session_get_channel', $channelName); 39 | } 40 | 41 | public function testAll() 42 | { 43 | $kernel = $this->getKernelInstance('file'); 44 | $kernel->setChannel('test_session_get_channel'); 45 | 46 | $session = get_session_instance(); 47 | 48 | $this->assertFalse($session->has('no_such_key')); 49 | 50 | $session->set('foo', 'bar'); 51 | $session->set('foo2', 'bar2'); 52 | 53 | $this->assertTrue($session->has('foo')); 54 | 55 | $this->assertSame($session->get('foo'), 'bar'); 56 | 57 | $session->remove('foo'); 58 | 59 | $this->assertFalse($session->has('foo')); 60 | 61 | $session->setId('e04'); 62 | 63 | $this->assertSame('e04', $session->getId()); 64 | 65 | $session->clear(); 66 | 67 | $this->assertFalse($session->has('foo2')); 68 | } 69 | 70 | public function testResetCookie() 71 | { 72 | $session = get_session_instance(); 73 | 74 | $expiredTime = time() + 3600; 75 | $expires = date('D, d M Y H:i:s', $expiredTime) . ' GMT'; 76 | $cookieName = '_shieldon'; 77 | 78 | $session->resetCookie(); 79 | 80 | $sessionId = $session->getId(); 81 | $string = $cookieName . '=' . $sessionId . '; Path=/; Expires=' . $expires; 82 | 83 | $response = get_response(); 84 | 85 | $this->assertSame($response->getHeaderLine('Set-Cookie'), $string); 86 | } 87 | 88 | public function testAssertInit() 89 | { 90 | $this->expectException(\RuntimeException::class); 91 | 92 | $session = get_session_instance(); 93 | $session->set('foo', 'bar'); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /tests/Fixture/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | wget \ 7 | gnupg \ 8 | gnupg \ 9 | libonig-dev \ 10 | libicu-dev \ 11 | zlib1g-dev \ 12 | libssl-dev \ 13 | software-properties-common \ 14 | curl \ 15 | sudo \ 16 | iptables 17 | 18 | RUN add-apt-repository --yes ppa:ondrej/php 19 | 20 | RUN apt-get update && apt-get install -y \ 21 | mariadb-server \ 22 | redis-server \ 23 | memcached \ 24 | libmemcached-dev 25 | 26 | RUN apt-get install -y \ 27 | php8.2-fpm \ 28 | php-pear \ 29 | php8.2-cli \ 30 | php8.2-common \ 31 | php8.2-curl \ 32 | php8.2-intl \ 33 | php8.2-mbstring \ 34 | php8.2-memcached \ 35 | php8.2-mongodb \ 36 | php8.2-mysql \ 37 | php8.2-redis \ 38 | php8.2-sqlite3 \ 39 | php8.2- zip \ 40 | php8.2-xdebug \ 41 | php8.2-gd 42 | 43 | RUN echo "xdebug.mode=coverage" >> /etc/php/8.2/cli/php.ini 44 | RUN sed -i 's/bind 127.0.0.1/#bind 127.0.0.1/' /etc/redis/redis.conf 45 | 46 | WORKDIR /app 47 | COPY . /app 48 | 49 | RUN rm -rf /var/lib/apt/lists/ 50 | 51 | RUN wget https://raw.githubusercontent.com/composer/getcomposer.org/76a7060ccb93902cd7576b67264ad91c8a2700e2/web/installer -O - -q | php -- --quiet 52 | RUN mv composer.phar /usr/local/bin/composer 53 | ENV COMPOSER_ALLOW_SUPERUSER=1 54 | RUN composer update --no-interaction 55 | RUN chmod +x ./tests/Fixture/docker/entry-point.sh 56 | 57 | ENTRYPOINT ["./tests/Fixture/docker/entry-point.sh"] 58 | 59 | -------------------------------------------------------------------------------- /tests/Fixture/docker/entry-point.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | service mariadb start 4 | service redis-server restart 5 | service memcached start 6 | 7 | mysql -uroot -e 'CREATE DATABASE shieldon_unittest;' 8 | mysql -uroot -e "CREATE USER 'shieldon'@'localhost' IDENTIFIED BY 'taiwan';" 9 | mysql -uroot -e "GRANT ALL ON shieldon_unittest.* TO 'shieldon'@'localhost';" 10 | 11 | service --status-all 12 | cd /test-app 13 | ls -al 14 | composer test 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | * 10 | * php version 7.1.0 11 | * 12 | * @category Web-security 13 | * @package Shieldon 14 | * @author Terry Lin 15 | * @copyright 2019 terrylinooo 16 | * @license https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT 17 | * @link https://github.com/terrylinooo/shieldon 18 | * @see https://shieldon.io 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | date_default_timezone_set('UTC'); 24 | 25 | define('BOOTSTRAP_DIR', __DIR__); 26 | define('NO_MOCK_ENV', true); 27 | 28 | use Shieldon\Firewall\Helpers; 29 | 30 | include __DIR__ . '/../autoload.php'; 31 | include __DIR__ . '/../vendor/autoload.php'; 32 | include __DIR__ . '/../vendor/shieldon/messenger/autoload.php'; 33 | 34 | // Mock for PHPUnit. 35 | if (!isset($_SERVER['REMOTE_ADDR'])) { 36 | $_SERVER['REMOTE_ADDR'] = '127.0.0.127'; 37 | } 38 | 39 | if (!isset($_SERVER['HTTP_CF_CONNECTING_IP'])) { 40 | $_SERVER['HTTP_CF_CONNECTING_IP'] = '127.0.0.128'; 41 | } 42 | 43 | if (!isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { 44 | $_SERVER['HTTP_X_FORWARDED_HOST'] = '127.0.0.129'; 45 | } 46 | 47 | if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 48 | $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.130'; 49 | } 50 | 51 | if (!isset($_SERVER['HTTPS'])) { 52 | $_SERVER['HTTPS'] = 'on'; 53 | } 54 | 55 | if (!isset($_SERVER['REQUEST_URI'])) { 56 | $_SERVER['REQUEST_URI'] = '/'; 57 | } 58 | 59 | if (!isset($_SERVER['HTTP_HOST'])) { 60 | $_SERVER['HTTP_HOST'] = 'shieldon.io'; 61 | } 62 | 63 | new Helpers(); 64 | 65 | function test_event_disptcher() 66 | { 67 | echo 'This is a function call.'; 68 | } 69 | -------------------------------------------------------------------------------- /tests/samples/xss_bypass_list/test_sample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/tests/samples/xss_bypass_list/test_sample.jpg -------------------------------------------------------------------------------- /tests/samples/xss_bypass_list/test_sample_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/tests/samples/xss_bypass_list/test_sample_2.jpg -------------------------------------------------------------------------------- /tests/samples/xss_bypass_list/test_sample_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terrylinooo/shieldon/72cf49cf58d9828816e8e445fb1708ceb18676ec/tests/samples/xss_bypass_list/test_sample_3.jpg --------------------------------------------------------------------------------