Passed
Push — 2.x ( f0bfd9...ba8268 )
by Terry
01:56
created

include_i18n_file()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 6
nop 2
dl 0
loc 20
rs 9.9
c 0
b 0
f 0
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;
14
15
use Psr\Http\Message\ServerRequestInterface;
16
use Psr\Http\Message\ResponseInterface;
17
use Shieldon\Firewall\HttpFactory;
18
use Shieldon\Firewall\Utils\Collection;
19
use Shieldon\Firewall\Utils\Container;
20
use function explode;
21
use function file_exists;
22
use function func_get_arg;
23
use function func_num_args;
24
use function implode;
25
use function is_array;
26
use function is_null;
27
use function preg_split;
28
use function round;
29
use function shell_exec;
30
use function str_repeat;
31
use function str_replace;
32
use function stripos;
33
use function strtoupper;
34
use function substr;
35
use function sys_getloadavg;
36
use function trim;
37
use const PHP_OS;
38
39
/**
40
 * This value will be only displayed on Firewall Panel.
41
 */
42
define('SHIELDON_FIREWALL_VERSION', '2.0');
43
44
/**
45
 * Just use PSR-4 autoloader to load those helper functions.
46
 */
47
class Helpers
48
{
49
50
}
51
52
/**
53
 * Get user lang.
54
 * 
55
 * This method is a part of  __()
56
 *
57
 * @return string
58
 */
59
function get_user_lang(): string
60
{
61
    static $lang;
62
63
    if (!$lang) {
64
        $lang = 'en';
65
66
        // Fetch session variables.
67
        $session = get_session();
68
        $panelLang = $session->get('shieldon_panel_lang');
69
        $uiLang = $session->get('shieldon_ui_lang');
70
    
71
        if (!empty($panelLang)) {
72
            $lang = $panelLang;
73
        } elseif (!empty($uiLang)) {
74
            $lang = $uiLang;
75
        }
76
    }
77
78
    return $lang;
79
}
80
81
/**
82
 * Include i18n file.
83
 * 
84
 * This method is a part of  __()
85
 *
86
 * @param string $lang
87
 * @param string $filename
88
 *
89
 * @return void
90
 */
91
function include_i18n_file(string $lang, string $filename): array
92
{
93
    $content = [];
94
    $lang = str_replace('-', '_', $lang);
95
96
    if (stripos($lang, 'zh_') !== false) {
97
        if (stripos($lang, 'zh_CN') !== false) {
98
            $lang = 'zh_CN';
99
        } else {
100
            $lang = 'zh';
101
        }
102
    }
103
104
    $file = __DIR__ . '/../../localization/' . $lang . '/' . $filename . '.php';
105
    
106
    if (file_exists($file)) {
107
        $content = include $file;
108
    }
109
110
    return $content;
111
}
112
113
/**
114
 * Get locale message.
115
 *
116
 * @return string
117
 */
118
function __(): string
119
{
120
    /**
121
     * Load locale string from i18n files and store them into this array 
122
     * for further use.
123
     * 
124
     * @var array 
125
     */
126
    static $i18n;
127
128
    /**
129
     * Check the file exists for not.
130
     *
131
     * @var array 
132
     */
133
    static $fileChecked;
134
135
    $num = func_num_args();
136
137
    $filename    = func_get_arg(0); // required.
138
    $langcode    = func_get_arg(1); // required.
139
    $placeholder = ($num > 2) ? func_get_arg(2) : '';
140
    $replacement = ($num > 3) ? func_get_arg(3) : [];
141
    $lang        = get_user_lang();
142
143
    if (empty($i18n[$filename]) && empty($fileChecked[$filename])) {
144
        $fileChecked[$filename] = true;
145
        $i18n[$filename] = include_i18n_file($lang, $filename);
146
    }
147
148
    // If we don't get the string from the localization file, use placeholder instead.
149
    $resultString = $placeholder;
150
151
    if (!empty($i18n[$filename][$langcode])) {
152
        $resultString = $i18n[$filename][$langcode];
153
    }
154
155
    if (is_array($replacement)) { 
156
        /**
157
         * Example:
158
         *     __('test', 'example_string', 'Search results: {0} items. Total items: {1}.', [5, 150]);
159
         * 
160
         * Result:
161
         *     Search results: 5 items. Total items: 150.
162
         */
163
        foreach ($replacement as $i => $r) {
164
            $resultString = str_replace('{' . $i . '}', $replacement[$i], $resultString);
165
        }
166
    }
167
    
168
    return str_replace("'", '’', $resultString);
169
}
170
171
/**
172
 * Echo string from __()
173
 *
174
 * @return void
175
 */
176
function _e(): void
177
{
178
    $num = func_num_args();
179
180
    $filename    = func_get_arg(0); // required.
181
    $langcode    = func_get_arg(1); // required.
182
    $placeholder = ($num > 2) ? func_get_arg(2) : '';
183
    $replacement = ($num > 3) ? func_get_arg(3) : [];
184
185
    echo __($filename, $langcode, $placeholder, $replacement);
186
}
187
188
/**
189
 * Mask strings with asterisks.
190
 *
191
 * @param string $str
192
 *
193
 * @return string
194
 */
195
function mask_string($str): string
196
{
197
    if (filter_var($str, FILTER_VALIDATE_IP) !== false) {
198
        $tmp = explode('.', $str);
199
        $tmp[0] = '*';
200
        $tmp[1] = '*';
201
        $masked = implode('.', $tmp);
202
203
    } else {
204
        $masked =  str_repeat('*', strlen($str) - 6) . substr(str, -6);
0 ignored issues
show
Bug introduced by
The constant Shieldon\Firewall\str was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
205
    }
206
207
    return $masked;
208
}
209
210
/**
211
 * Get current CPU usage information.
212
 *
213
 * This function is only used in sending notifications and it is unavailable on Win system.
214
 * If you are using shared hosting and your hosting provider has disabled `sys_getloadavg`
215
 * and `shell_exec`, it won't work either.
216
 *
217
 * @return string
218
 */
219
function get_cpu_usage(): string
220
{
221
    $return = '';
222
223
    // This feature is not available on Windows platform.
224
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
225
        return $return;
226
    }
227
228
    $cpuLoads = @sys_getloadavg();
229
    $cpuCores = trim(@shell_exec("grep -P '^processor' /proc/cpuinfo|wc -l"));
230
231
    if (!empty($cpuCores) && !empty($cpuLoads)) {
232
        $return = round($cpuLoads[1] / ($cpuCores + 1) * 100, 0) . '%';
233
    }
234
    return $return;
235
}
236
237
/**
238
 * Get current RAM usage information. 
239
 *
240
 * If you are using shared hosting and your hosting provider has disabled `shell_exec`, 
241
 * This function may not work.
242
 *
243
 * @return string
244
 */
245
function get_memory_usage(): string
246
{
247
    $return = '';
248
249
    // This feature is not available on Windows platform.
250
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
251
        return $return;
252
    }
253
254
    $freeResult = explode("\n", trim(@shell_exec('free')));
255
256
    if (!empty($freeResult)) {
257
        $parsed = preg_split("/[\s]+/", $freeResult[1]);
258
        $return = round($parsed[2] / $parsed[1] * 100, 0) . '%';
259
    }
260
    return $return;
261
}
262
263
/**
264
 * The default settings of Shieldon core.
265
 *
266
 * @return array
267
 */
268
function get_default_properties(): array
269
{
270
    return [
271
272
        'time_unit_quota' => [
273
            's' => 2,
274
            'm' => 10,
275
            'h' => 30,
276
            'd' => 60
277
        ],
278
279
        'time_reset_limit' => 3600,
280
        'interval_check_referer' => 5,
281
        'interval_check_session' => 30,
282
        'limit_unusual_behavior' => [
283
            'cookie'  => 5,
284
            'session' => 5,
285
            'referer' => 10
286
        ],
287
288
        'cookie_name' => 'ssjd',
289
        'cookie_domain' => '',
290
        'cookie_value' => '1',
291
        'display_online_info' => true,
292
        'display_user_info' => false,
293
294
        /**
295
         * If you set this option enabled, Shieldon will record every CAPTCHA fails in a row, 
296
         * Once that user have reached the limitation number, Shieldon will put it as a blocked IP in rule table,
297
         * until the new data cycle begins.
298
         * 
299
         * Once that user have been blocked, they are still access the warning page, it means that they are not
300
         * humain for sure, so let's throw them into the system firewall and say goodbye to them forever.
301
         */
302
        'deny_attempt_enable' => [
303
            'data_circle'     => false,
304
            'system_firewall' => false,
305
        ],
306
        'deny_attempt_notify' => [
307
            'data_circle'     => false,
308
            'system_firewall' => false,
309
        ],
310
        'deny_attempt_buffer' => [
311
            'data_circle'     => 10,
312
            'system_firewall' => 10,
313
        ],
314
315
        /**
316
         * To prevent dropping social platform robots into iptables firewall, such as Facebook, Line, 
317
         * and others who scrape snapshots from your web pages, you should adjust the values below 
318
         * to fit your needs. (unit: second)
319
         */
320
        'record_attempt_detection_period' => 5, // 5 seconds.
321
322
        // Reset the counter after n second.
323
        'reset_attempt_counter' => 1800, // 30 minutes.
324
325
        // System-layer firewall, ip6table service watches this folder to 
326
        // receive command created by Shieldon Firewall.
327
        'iptables_watching_folder' => '/tmp/',
328
    ];
329
}
330
331
/**
332
 * PSR-7 HTTP server request
333
 *
334
 * @return \Psr\Http\Message\ServerRequestInterface
335
 */
336
function get_request(): ServerRequestInterface
337
{
338
    $request = Container::get('request');
339
340
    if (is_null($request)) {
341
        $request = HttpFactory::createRequest();
342
        Container::set('request', $request);
343
    }
344
345
    return $request;
346
}
347
348
/**
349
 * PSR-7 HTTP response.
350
 *
351
 * @return ResponseInterface
352
 */
353
function get_response(): ResponseInterface
354
{
355
    $response = Container::get('response');
356
357
    if (is_null($response)) {
358
        $response = HttpFactory::createResponse();
359
        Container::set('response', $response);
360
    }
361
362
    return $response;
363
}
364
365
/**
366
 * Session
367
 *
368
 * @return \Shieldon\Firewall\Utils\Collection
369
 */
370
function get_session(): Collection
371
{
372
    $session = Container::get('session');
373
374
    if (is_null($session)) {
375
        $session = HttpFactory::createSession();
376
        Container::set('session', $session);
377
    }
378
379
    return $session;
380
}
381
382
/**
383
 * Set a PSR-7 HTTP server request into container.
384
 *
385
 * @param \Psr\Http\Message\ServerRequestInterface $request
386
 *
387
 * @return void
388
 */
389
function set_request(ServerRequestInterface $request): void
390
{
391
    Container::set('request', $request, true);
392
}
393
394
/**
395
 * Set a PSR-7 HTTP response into container.
396
 *
397
 * @param \Psr\Http\Message\ResponseInterface $response
398
 *
399
 * @return void
400
 */
401
function set_response(ResponseInterface $response): void
402
{
403
    Container::set('response', $response, true);
404
}
405
406
/**
407
 * Unset a variable of superglobal.
408
 *
409
 * @param string|null $name The name (key) in the array of the superglobal.
410
 *                          If $name is null that means clear all.
411
 * @return void
412
 */
413
function unset_superglobal($name, string $type): void
414
{
415
    if (is_string($name)) {
416
417
        switch ($type) {
418
            case 'cookie':
419
                $cookieParams = get_request()->getCookieParams();
420
                unset($cookieParams[$name]);
421
                set_request(get_request()->withCookieParams($cookieParams));
422
                set_response(get_response()->withHeader(
423
                    'Set-Cookie',
424
                    "$name=; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0"
425
                ));
426
                // Prevent direct access to superglobal.
427
                unset($_COOKIE[$name]);
428
                break;
429
    
430
            case 'post':
431
                $postParams = get_request()->getParsedBody();
432
                unset($postParams[$name]);
433
                set_request(get_request()->withParsedBody($postParams));
434
                unset($_POST[$name]);
435
                break;
436
    
437
            case 'get':
438
                $getParams = get_request()->getQueryParams();
439
                unset($getParams[$name]);
440
                set_request(get_request()->withQueryParams($getParams));
441
                unset($_GET[$name]);
442
                break;
443
    
444
            case 'session':
445
                get_session()->remove($name);
446
                unset($_SESSION[$name]);
447
                break;
448
    
449
            default:
450
                break;
451
        }
452
453
    } elseif (is_null($name)) {
0 ignored issues
show
introduced by
The condition is_null($name) is always true.
Loading history...
454
455
        switch ($type) {
456
            case 'cookie':
457
                $cookieParams = get_request()->getCookieParams();
458
                set_request(get_request()->withCookieParams([]));
459
                foreach (array_keys($cookieParams) as $name) {
0 ignored issues
show
introduced by
$name is overwriting one of the parameters of this function.
Loading history...
460
                    set_response(get_response()->withHeader(
461
                        'Set-Cookie',
462
                        "$name=; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0"
463
                    ));
464
                }
465
                $_COOKIE = [];
466
                break;
467
    
468
            case 'post':
469
                set_request(get_request()->withParsedBody([]));
470
                $_POST = [];
471
                break;
472
    
473
            case 'get':
474
                set_request(get_request()->withQueryParams([]));
475
                $_GET = [];
476
                break;
477
 
478
            case 'session':
479
                get_session()->clear();
480
                $_SESSION = [];
481
                break;
482
483
            default:
484
                break;
485
        }
486
    }
487
}