Passed
Push — 2.x ( 23da62...4d98bd )
by Terry
02:49
created

unset_superglobal()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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