Passed
Push — 2.x ( 364dd8...03335a )
by Terry
01:58
created

ConfigMethodsTrait::saveConfigCheckActionLogger()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 38
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 21
c 1
b 0
f 0
nc 10
nop 1
dl 0
loc 38
rs 8.9617
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
11
declare(strict_types=1);
12
13
namespace Shieldon\Firewall\Panel;
14
15
use function Shieldon\Firewall\__;
16
17
use PDO;
18
use PDOException;
19
use Redis;
20
use RedisException;
21
use function class_exists;
22
use function file_exists;
23
use function is_numeric;
24
use function is_string;
25
use function is_writable;
26
use function mkdir;
27
use function password_hash;
28
use function preg_split;
29
use function rtrim;
30
use function str_replace;
31
use function umask;
32
33
/*
34
 * @since 2.0.0
35
 */
36
trait ConfigMethodsTrait
37
{
38
     /**
39
     * Parse the POST fields and set them into configuration data structure.
40
     * Used for saveConfig method only.
41
     *
42
     * @param array $postParams
43
     *
44
     * @return void
45
     */
46
    protected function saveConfigPrepareSettings(array $postParams): void
47
    {
48
        foreach ($postParams as $postKey => $postData) {
49
            if (is_string($postData)) {
50
                if ($postData === 'on') {
51
                    $this->setConfig(str_replace('__', '.', $postKey), true);
0 ignored issues
show
Bug introduced by
It seems like setConfig() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

51
                    $this->/** @scrutinizer ignore-call */ 
52
                           setConfig(str_replace('__', '.', $postKey), true);
Loading history...
52
53
                } elseif ($postData === 'off') {
54
                    $this->setConfig(str_replace('__', '.', $postKey), false);
55
56
                } else {
57
                    if ($postKey === 'ip_variable_source') {
58
                        $this->setConfig('ip_variable_source.REMOTE_ADDR', false);
59
                        $this->setConfig('ip_variable_source.HTTP_CF_CONNECTING_IP', false);
60
                        $this->setConfig('ip_variable_source.HTTP_X_FORWARDED_FOR', false);
61
                        $this->setConfig('ip_variable_source.HTTP_X_FORWARDED_HOST', false);
62
                        $this->setConfig('ip_variable_source.' . $postData, true);
63
64
                    } elseif ($postKey === 'dialog_ui__shadow_opacity') {
65
                        $this->setConfig('dialog_ui.shadow_opacity', (string) $postData);
66
67
                    } elseif ($postKey === 'admin__pass') {
68
                        if (strlen($postParams['admin__pass']) < 58) {
69
                            $this->setConfig('admin.pass', password_hash($postData, PASSWORD_BCRYPT));
70
                        }
71
                    } else if ($postKey === 'messengers__sendgrid__config__recipients') {
72
                        $this->setConfig(
73
                            'messengers.sendgrid.config.recipients',
74
                            preg_split('/\r\n|[\r\n]/',
75
                            $postData)
76
                        );
77
                    } else {
78
                        if (is_numeric($postData)) {
79
                            $this->setConfig(str_replace('__', '.', $postKey), (int) $postData);
80
                        } else  {
81
                            $this->setConfig(str_replace('__', '.', $postKey), $postData);
82
                        }
83
                    }
84
                }
85
            }
86
        }
87
    }
88
89
    /**
90
     * Check the settings of Action Logger.
91
     *
92
     * @return bool
93
     */
94
    protected function saveConfigCheckActionLogger(bool $result): bool
95
    {
96
        if (!$result) {
97
            return false;
98
        }
99
100
        // Check Action Logger settings.
101
        $enableActionLogger = $this->getConfig('loggers.action.enable');
0 ignored issues
show
Bug introduced by
It seems like getConfig() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

101
        /** @scrutinizer ignore-call */ 
102
        $enableActionLogger = $this->getConfig('loggers.action.enable');
Loading history...
102
        $actionLogDir = rtrim($this->getConfig('loggers.action.config.directory_path'), '\\/ ');
103
104
        $result = true;
105
106
        if ($enableActionLogger) {
107
            if (empty($actionLogDir)) {
108
                $actionLogDir = $this->directory . '/action_logs';
109
            }
110
111
            $this->setConfig('loggers.action.config.directory_path', $actionLogDir);
112
113
            if (!is_dir($actionLogDir)) {
114
                $originalUmask = umask(0);
115
                mkdir($actionLogDir, 0777, true);
116
                umask($originalUmask);
117
            }
118
119
            if (!is_writable($actionLogDir)) {
120
                $result = false;
121
                $this->pushMessage('error',
0 ignored issues
show
Bug introduced by
It seems like pushMessage() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

121
                $this->/** @scrutinizer ignore-call */ 
122
                       pushMessage('error',
Loading history...
122
                    __(
123
                        'panel',
124
                        'error_logger_directory_not_writable',
125
                        'Action Logger requires the storage directory writable.'
126
                    )
127
                );
128
            }
129
        }
130
131
        return $result;
132
    }
133
134
    /**
135
     * Check the settings of Iptables.
136
     * 
137
     * @param bool $result The result passed from previous check.
138
     *
139
     * @return bool
140
     */
141
    protected function saveConfigCheckIptables(bool $result): bool
142
    {
143
        if (!$result) {
144
            return false;
145
        }
146
147
        // System firewall.
148
        $enableIptables = $this->getConfig('iptables.enable');
149
        $iptablesWatchingFolder = rtrim($this->getConfig('iptables.config.watching_folder'), '\\/ ');
150
151
        $result = true;
152
153
        if ($enableIptables) {
154
            if (empty($iptablesWatchingFolder)) {
155
                $iptablesWatchingFolder = $this->directory . '/iptables';
156
            }
157
158
            $this->setConfig('iptables.config.watching_folder', $iptablesWatchingFolder);
159
160
            if (!is_dir($iptablesWatchingFolder)) {
161
                $originalUmask = umask(0);
162
                mkdir($iptablesWatchingFolder, 0777, true);
163
                umask($originalUmask);
164
165
                // Create default log files.
166
                if (is_writable($iptablesWatchingFolder)) {
167
                    fopen($iptablesWatchingFolder . '/iptables_queue.log', 'w+');
168
                    fopen($iptablesWatchingFolder . '/ipv4_status.log',    'w+');
169
                    fopen($iptablesWatchingFolder . '/ipv6_status.log',    'w+');
170
                    fopen($iptablesWatchingFolder . '/ipv4_command.log',   'w+');
171
                    fopen($iptablesWatchingFolder . '/ipv6_command.log',   'w+');
172
                }
173
            }
174
    
175
            if (!is_writable($iptablesWatchingFolder)) {
176
                $result = false;
177
                $this->pushMessage('error',
178
                    __(
179
                        'panel',
180
                        'error_ip6tables_directory_not_writable',
181
                        'iptables watching folder requires the storage directory writable.'
182
                    )
183
                );
184
            }
185
        }
186
187
        return $result;
188
    }
189
190
    /**
191
     * Check the settings of Data drivers.
192
     *
193
     * @param bool $result The result passed from previous check.
194
     *
195
     * @return bool
196
     */
197
    protected function saveConfigCheckDataDriver(bool $result): bool
198
    {
199
        if (!$result) {
200
            return false;
201
        }
202
203
        switch ($this->configuration['driver_type']) {
204
            case 'mysql':
205
                $result = $this->saveCofigCheckDataDriverMySql($result);
206
                break;
207
208
            case 'sqlite':
209
                $result = $this->saveCofigCheckDataDriverSqlLite($result);
210
                break;
211
212
            case 'redis':
213
                $result = $this->saveCofigCheckDataDriverRedis($result);
214
                break;
215
216
            case 'file':
217
            default:
218
                $result = $this->saveCofigCheckDataDriverFile($result);
219
            // endswitch
220
        }
221
222
        return $result;
223
    }
224
225
    /**
226
     * Check the settings of Data drivers.
227
     *
228
     * @param bool $result The result passed from previous check.
229
     *
230
     * @return bool
231
     */
232
    protected function saveCofigCheckDataDriverMySql(bool $result): bool
233
    {
234
        if (class_exists('PDO')) {
235
            $db = [
236
                'host'    => $this->getConfig('drivers.mysql.host'),
237
                'dbname'  => $this->getConfig('drivers.mysql.dbname'),
238
                'user'    => $this->getConfig('drivers.mysql.user'),
239
                'pass'    => $this->getConfig('drivers.mysql.pass'),
240
                'charset' => $this->getConfig('drivers.mysql.charset'),
241
            ];
242
243
            try {
244
                new PDO(
245
                    'mysql:host=' . $db['host'] . ';dbname=' . $db['dbname'] . ';charset=' . $db['charset'],
246
                    (string) $db['user'],
247
                    (string) $db['pass']
248
                );
249
            } catch(PDOException $e) {
250
                $result = false;
251
                $this->pushMessage('error', 
252
                    __(
253
                        'panel',
254
                        'error_mysql_connection',
255
                        'Cannot access to your MySQL database, please check your settings.'
256
                    )
257
                );
258
            }
259
        } else {
260
            $result = false;
261
            $this->pushMessage('error',
262
                __(
263
                    'panel',
264
                    'error_mysql_driver_not_supported',
265
                    'Your system doesn’t support MySQL driver.'
266
                )
267
            );
268
        }
269
270
        return $result;
271
    }
272
273
    /**
274
     * Check the settings of Data drivers.
275
     *
276
     * @param bool $result The result passed from previous check.
277
     *
278
     * @return bool
279
     */
280
    protected function saveCofigCheckDataDriverSqlLite(bool $result): bool
281
    {
282
        $sqliteDir = rtrim($this->getConfig('drivers.sqlite.directory_path'), '\\/ ');
283
284
        if (empty($sqliteDir)) {
285
            $sqliteDir = $this->directory . '/data_driver_sqlite';
286
        }
287
288
        $sqliteFilePath = $sqliteDir . '/shieldon.sqlite3';
289
        $this->setConfig('drivers.sqlite.directory_path', $sqliteDir);
290
        
291
        if (!file_exists($sqliteFilePath)) {
292
            if (!is_dir($sqliteDir)) {
293
                $originalUmask = umask(0);
294
                mkdir($sqliteDir, 0777, true);
295
                umask($originalUmask);
296
            }
297
        }
298
299
        if (class_exists('PDO')) {
300
            try {
301
                new PDO('sqlite:' . $sqliteFilePath);
302
            } catch(PDOException $e) { 
303
                $this->pushMessage('error', $e->getMessage());
304
                $result = false;
305
            }
306
        } else {
307
            $this->pushMessage('error',
308
                __(
309
                    'panel',
310
                    'error_sqlite_driver_not_supported',
311
                    'Your system doesn’t support SQLite driver.'
312
                )
313
            );
314
            $result = false;
315
        }
316
317
        if (!is_writable($sqliteFilePath)) {
318
            $this->pushMessage('error',
319
                __(
320
                    'panel',
321
                    'error_sqlite_directory_not_writable',
322
                    'SQLite data driver requires the storage directory writable.'
323
                )
324
            );
325
            $result = false;
326
        }
327
        return $result;
328
    }
329
330
    /**
331
     * Check the settings of Data drivers.
332
     *
333
     * @param bool $result The result passed from previous check.
334
     *
335
     * @return bool
336
     */
337
    protected function saveCofigCheckDataDriverRedis(bool $result): bool
338
    {
339
        if (class_exists('Redis')) {
340
            try {
341
                $redis = new Redis();
342
                $redis->connect(
343
                    (string) $this->getConfig('drivers.redis.host'), 
344
                    (int)    $this->getConfig('drivers.redis.port')
345
                );
346
                unset($redis);
347
            } catch(RedisException $e) {
348
                $this->pushMessage('error', $e->getMessage());
349
                $result = false;
350
            }
351
352
        } else {     
353
            $this->pushMessage('error',
354
                __(
355
                    'panel',
356
                    'error_redis_driver_not_supported',
357
                    'Your system doesn’t support Redis driver.'
358
                )
359
            );
360
            $result = false;
361
        }
362
        return $result;
363
    }
364
365
    /**
366
     * Check the settings of Data drivers.
367
     *
368
     * @param bool $result The result passed from previous check.
369
     *
370
     * @return bool
371
     */
372
    protected function saveCofigCheckDataDriverFile(bool $result): bool
373
    {
374
        $fileDir = rtrim($this->getConfig('drivers.file.directory_path'), '\\/ ');
375
376
        if (empty($fileDir)) {
377
            $fileDir = $this->directory . '/data_driver_file';
378
            $this->setConfig('drivers.file.directory_path', $fileDir);
379
        }
380
381
        $this->setConfig('drivers.file.directory_path', $fileDir);
382
383
        if (!is_dir($fileDir)) {
384
            $originalUmask = umask(0);
385
            mkdir($fileDir, 0777, true);
386
            umask($originalUmask);
387
        }
388
389
        if (!is_writable($fileDir)) {
390
            $result = false;
391
            $this->pushMessage('error',
392
                __(
393
                    'panel',
394
                    'error_file_directory_not_writable',
395
                    'File data driver requires the storage directory writable.'
396
                )
397
            );
398
        }
399
400
        return $result;
401
    }
402
}
403