Passed
Push — 2.x ( 9c7c64...09a803 )
by Terry
02:14
created

Panel::setRouteBase()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
rs 10
1
<?php
2
/**
3
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <[email protected]>
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 <[email protected]>
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 Shieldon\Firewall\HttpResolver;
27
use Shieldon\Firewall\Panel\CsrfTrait;
28
use Shieldon\Firewall\Panel\DemoModeTrait;
29
use Shieldon\Firewall\Panel\User;
30
use function Shieldon\Firewall\get_request;
31
use function Shieldon\Firewall\get_response;
32
33
use function call_user_func;
34
use function explode;
35
use function in_array;
36
use function property_exists;
37
use function str_replace;
38
use function trim;
39
use function ucfirst;
40
41
/**
42
 * Firewall's Control Panel
43
 *
44
 * Display a Control Panel UI for developers or administrators.
45
 */
46
class Panel
47
{
48
    use DemoModeTrait;
49
    use CsrfTrait;
50
51
    /**
52
     * Route map.
53
     *
54
     * @var array
55
     */
56
    protected $registerRoutes;
57
58
    /**
59
     * The HTTP resolver.
60
     * 
61
     * We need to resolve the HTTP result by ourselves to prevent conficts
62
     * with other frameworks.
63
     *
64
     * @var \Shieldon\Firewall\HttpResolver
65
     */
66
    protected $resolver = null;
67
68
    /**
69
     * Firewall panel constructor.                         
70
     */
71
    public function __construct() 
72
    {
73
        $this->registerRoutes = [
74
            'ajax/changeLocale',
75
            'ajax/tryMessenger',
76
            'circle/filter',
77
            'circle/rule',
78
            'circle/session',
79
            'home/index',
80
            'home/overview',
81
            'iptables/ip4',
82
            'iptables/ip4status',
83
            'iptables/ip6',
84
            'iptables/ip6status',
85
            'report/actionLog',
86
            'report/operation',
87
            'security/authentication',
88
            'security/xssProtection',
89
            'setting/basic',
90
            'setting/exclusion',
91
            'setting/export',
92
            'setting/import',
93
            'setting/ipManager',
94
            'setting/messenger',
95
            'user/login',
96
            'user/logout',
97
        ];
98
99
        $this->resolver = new HttpResolver();
100
    }
101
102
    /**
103
     * Display pages.
104
     * 
105
     * @param string $basePath The base URL of the firewall panel.
106
     * 
107
     * @return void
108
     */
109
    public function entry($basePath): void
110
    {
111
        $request = get_request();
112
        $response = get_response();
113
114
        $path = trim($request->getUri()->getPath(), '/');
115
        $base = trim($basePath, '/');
116
        $urlSegment = trim(str_replace($base, '', $path), '/');
117
118
        if ($urlSegment === $basePath || $urlSegment === '') {
119
            $urlSegment = 'home/index';
120
        }
121
122
        $urlParts = explode('/', $urlSegment);
123
124
        $controller = $urlParts[0] ?? 'home';
125
        $method = $urlParts[1] ?? 'index';
126
127
        if (in_array("$controller/$method", $this->registerRoutes)) {
128
            $this->setRouteBase($base);
129
            $this->checkAuth();
130
131
            $controller = __CLASS__ . '\\' . ucfirst($controller);
132
133
            $controllerClass = new $controller();
134
            $controllerClass->csrf($this->csrfField);
135
136
            if ('demo' === $this->mode) {
137
138
                // For security reasons, the POST method is not allowed 
139
                // in the Demo mode.
140
                set_request(get_request()->withParsedBody([])->withMethod('GET'));
141
                unset_superglobal(null, 'post');
142
143
                $controllerClass->demo(
144
                    $this->demoUser['user'],
145
                    $this->demoUser['pass']
146
                );
147
            }
148
149
            $this->resolver(call_user_func([$controllerClass, $method]));
1 ignored issue
show
Bug introduced by
The method resolver() does not exist on Shieldon\Firewall\Panel. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

149
            $this->/** @scrutinizer ignore-call */ 
150
                   resolver(call_user_func([$controllerClass, $method]));
Loading history...
150
        }
151
       
152
        $this->resolver($response->withStatus(404));
153
    }
154
155
    /**
156
     * Set the base route for the panel.
157
     *
158
     * @param string $base The base path.
159
     *
160
     * @return void
161
     */
162
    protected function setRouteBase(string $base)
163
    {
164
        if (!defined('SHIELDON_PANEL_BASE')) {
165
            define('SHIELDON_PANEL_BASE', $base);
166
        }
167
    }
168
169
    /**
170
     * Prompt an authorization login.
171
     *
172
     * @return void
173
     */
174
    protected function checkAuth(): void
175
    {
176
        $check = get_session()->get('shieldon_user_login');
177
178
        if (empty($check)) {
179
            $this->resolver((new User)->login($this->mode));
180
        }
181
    }
182
183
    /**
184
     * Magic method.
185
     * 
186
     * Helps the property `$resolver` to work like a function.
187
     * 
188
     * @param string $method The method name.
189
     * @param array  $args   The arguments.
190
     *
191
     * @return mixed
192
     */
193
    public function __call($method, $args)
194
    {
195
        if (property_exists($this, $method)) {
196
            $callable = $this->{$method};
197
198
            if (isset($args[0]) && $args[0] instanceof ResponseInterface) {
199
                return $callable($args[0]);
200
            }
201
        }
202
        // @codeCoverageIgnoreStart
203
    }
204
    // @codeCoverageIgnoreEnd
205
}
206