Passed
Push — master ( 7d85ee...9e45b8 )
by Lars
02:39
created

Bootup   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Test Coverage

Coverage 91.3%

Importance

Changes 0
Metric Value
eloc 74
dl 0
loc 229
ccs 63
cts 69
cp 0.913
rs 10
c 0
b 0
f 0
wmc 21

6 Methods

Rating   Name   Duplication   Size   Complexity  
A filterRequestInputs() 0 41 5
A get_random_bytes() 0 13 3
A initAll() 0 7 1
A is_php() 0 16 2
A filterString() 0 9 1
B filterRequestUri() 0 74 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace voku\helper;
6
7
/**
8
 * @psalm-immutable
9
 */
10
class Bootup
11
{
12
    /**
13
     * filter request inputs
14
     *
15
     * Ensures inputs are well formed UTF-8
16
     * When not, assumes Windows-1252 and converts to UTF-8
17
     * Tests only values, not keys
18
     *
19
     * @param int    $normalization_form
20
     * @param string $leading_combining
21
     *
22
     * @return bool
23
     *
24
     * @deprecated <p>This method will be removed in future releases, so please don't use it anymore.</p>
25
     */
26 1
    public static function filterRequestInputs(
27
        int $normalization_form = \Normalizer::NFC,
28
        string $leading_combining = '◌'
29
    ): bool {
30
        $a = [
31 1
            &$_FILES,
32 1
            &$_ENV,
33 1
            &$_GET,
34 1
            &$_POST,
35 1
            &$_COOKIE,
36 1
            &$_SERVER,
37 1
            &$_REQUEST,
38
        ];
39
40
        /** @noinspection ReferenceMismatchInspection */
41
        /** @noinspection ForeachSourceInspection */
42 1
        foreach ($a[0] as &$r) {
43 1
            $a[] = [
44 1
                &$r['name'],
45 1
                &$r['type'],
46
            ];
47
        }
48 1
        unset($r, $a[0]);
49
50 1
        $len = \count($a) + 1;
51 1
        for ($i = 1; $i < $len; ++$i) {
52
            /** @noinspection ReferenceMismatchInspection */
53
            /** @noinspection ForeachSourceInspection */
54 1
            foreach ($a[$i] as &$r) {
55
                /** @noinspection ReferenceMismatchInspection */
56 1
                $s = $r; // $r is a reference, $s a copy
57 1
                if (\is_array($s)) {
58 1
                    $a[$len++] = &$r;
59
                } else {
60 1
                    $r = self::filterString($s, $normalization_form, $leading_combining);
61
                }
62
            }
63 1
            unset($r, $a[$i]);
64
        }
65
66 1
        return $len > 1;
67
    }
68
69
    /**
70
     * Filter current REQUEST_URI .
71
     *
72
     * @param string|null $uri  <p>If null is set, then the server REQUEST_URI will be used.</p>
73
     * @param bool        $exit
74
     *
75
     * @return mixed
76
     *
77
     * @deprecated <p>This method will be removed in future releases, so please don't use it anymore.</p>
78
     */
79 1
    public static function filterRequestUri($uri = null, bool $exit = true)
80
    {
81 1
        if ($uri === null) {
82 1
            if (!isset($_SERVER['REQUEST_URI'])) {
83 1
                return false;
84
            }
85
86 1
            $uri = (string) $_SERVER['REQUEST_URI'];
87
        }
88
89 1
        $uriOrig = $uri;
90
91
        //
92
        // Ensures the URL is well formed UTF-8
93
        //
94
95 1
        if (UTF8::is_utf8(\rawurldecode($uri)) === true) {
96 1
            return $uri;
97
        }
98
99
        //
100
        // When not, assumes Windows-1252 and redirects to the corresponding UTF-8 encoded URL
101
        //
102
103 1
        $uri = (string) \preg_replace_callback(
104
            '/[\x80-\xFF]+/',
105
            /**
106
             * @param array $m
107
             *
108
             * @return string
109
             */
110 1
            static function (array $m): string {
111 1
                return \rawurlencode($m[0]);
112
            },
113 1
            $uri
114
        );
115
116 1
        $uri = (string) \preg_replace_callback(
117
            '/(?:%[89A-F][0-9A-F])+/i',
118
            /**
119
             * @param array $m
120
             *
121
             * @return string
122
             */
123 1
            static function (array $m): string {
124 1
                return \rawurlencode(UTF8::rawurldecode($m[0]));
125
            },
126 1
            $uri
127
        );
128
129
        if (
130 1
            $uri !== $uriOrig
131
            &&
132 1
            $exit === true
133
            &&
134 1
            \headers_sent() === false
135
        ) {
136
            $severProtocol = ($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1');
137
            \header($severProtocol . ' 301 Moved Permanently');
138
139
            if (\strncmp($uri, '/', 1) === 0) {
140
                \header('Location: /' . \ltrim($uri, '/'));
141
            } else {
142
                \header('Location: ' . $uri);
143
            }
144
145
            exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
146
        }
147
148 1
        if (\strncmp($uri, '/', 1) === 0) {
149 1
            $uri = '/' . \ltrim($uri, '/');
150
        }
151
152 1
        return $uri;
153
    }
154
155
    /**
156
     * Normalizes to UTF-8 NFC, converting from WINDOWS-1252 when needed.
157
     *
158
     * @param mixed  $input
159
     * @param int    $normalization_form
160
     * @param string $leading_combining
161
     *
162
     * @return mixed
163
     */
164 1
    public static function filterString(
165
        $input,
166
        int $normalization_form = \Normalizer::NFC,
167
        string $leading_combining = '◌'
168
    ) {
169 1
        return UTF8::filter(
170 1
            $input,
171
            $normalization_form,
172
            $leading_combining
173
        );
174
    }
175
176
    /**
177
     * Get random bytes via "random_bytes()"
178
     *
179
     * @param int $length <p>output length</p>
180
     *
181
     * @throws \Exception if it was not possible to gather sufficient entropy
182
     *
183
     * @return false|string
184
     *                      <strong>false</strong> on error
185
     */
186 1
    public static function get_random_bytes($length)
187
    {
188 1
        if (!$length) {
189 1
            return false;
190
        }
191
192 1
        $length = (int) $length;
193
194 1
        if ($length <= 0) {
195 1
            return false;
196
        }
197
198 1
        return \random_bytes($length);
199
    }
200
201
    /**
202
     * @return bool
203
     */
204 1
    public static function initAll(): bool
205
    {
206 1
        $result = \ini_set('default_charset', 'UTF-8');
207
208
        // everything else is init via composer, so we are done here ...
209
210 1
        return $result !== false;
211
    }
212
213
    /**
214
     * Determines if the current version of PHP is equal to or greater than the supplied value.
215
     *
216
     * @param string $version <p>e.g. "7.1"<p>
217
     *
218
     * @return bool
219
     *              <p>Return <strong>true</strong> if the current version is $version or greater.</p>
220
     *
221
     * @psalm-pure
222
     */
223 29
    public static function is_php($version): bool
224
    {
225
        /**
226
         * @psalm-suppress ImpureStaticVariable
227
         *
228
         * @var bool[]
229
         */
230 29
        static $_IS_PHP;
231
232 29
        $version = (string) $version;
233
234 29
        if (!isset($_IS_PHP[$version])) {
235 4
            $_IS_PHP[$version] = \version_compare(\PHP_VERSION, $version, '>=');
236
        }
237
238 29
        return $_IS_PHP[$version];
239
    }
240
}
241