GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#33)
by Oliver
03:18
created

Reader::determineFileTypeByHeader()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 0
dl 0
loc 12
rs 9.9666
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
namespace TYPO3\PharStreamWrapper\Phar;
4
5
/*
6
 * This file is part of the TYPO3 project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under the terms
9
 * of the MIT License (MIT). For the full copyright and license information,
10
 * please read the LICENSE file that was distributed with this source code.
11
 *
12
 * The TYPO3 project - inspiring people to share!
13
 */
14
15
class Reader
16
{
17
    /**
18
     * @var string
19
     */
20
    private $fileName;
21
22
    /**
23
     * @var string
24
     */
25
    private $fileType;
26
27
    /**
28
     * @param string $fileName
29
     */
30
    public function __construct(string $fileName)
31
    {
32
        if (strpos($fileName, '://') !== false) {
33
            throw new ReaderException(
34
                'File name must not contain stream prefix',
35
                1539623708
36
            );
37
        }
38
39
        $this->fileName = $fileName;
40
        $this->fileType = $this->determineFileType();
41
    }
42
43
    /**
44
     * @return Container
45
     */
46
    public function resolveContainer(): Container
47
    {
48
        $data = $this->extractData($this->resolveStream() . $this->fileName);
49
50
        if ($data['stubContent'] === null) {
51
            throw new ReaderException(
52
                'Cannot resolve stub',
53
                1547807881
54
            );
55
        }
56
        if ($data['manifestContent'] === null || $data['manifestLength'] === null) {
57
            throw new ReaderException(
58
                'Cannot resolve manifest',
59
                1547807882
60
            );
61
        }
62
        if (strlen($data['manifestContent']) < $data['manifestLength']) {
63
            throw new ReaderException(
64
                sprintf(
65
                    'Exected manifest length %d, got %d',
66
                    strlen($data['manifestContent']),
67
                    $data['manifestLength']
68
                ),
69
                1547807883
70
            );
71
        }
72
73
        return new Container(
74
            Stub::fromContent($data['stubContent']),
75
            Manifest::fromContent($data['manifestContent'])
76
        );
77
    }
78
79
    /**
80
     * @param string $fileName e.g. '/path/file.phar' or 'compress.zlib:///path/file.phar'
81
     * @return array
82
     */
83
    private function extractData(string $fileName): array
84
    {
85
        $stubContent = null;
86
        $manifestContent = null;
87
        $manifestLength = null;
88
89
        $resource = fopen($fileName, 'r');
90
        if (!is_resource($resource)) {
91
            throw new ReaderException(
92
                sprintf('Resource %s could not be opened', $fileName),
93
                1547902055
94
            );
95
        }
96
97
        while (!feof($resource)) {
98
            $line = fgets($resource);
99
            // stop reading file when manifest can be extracted
100
            if ($manifestLength !== null && $manifestContent !== null && strlen($manifestContent) >= $manifestLength) {
101
                break;
102
            }
103
104
            $manifestPosition = strpos($line, '__HALT_COMPILER();');
105
106
            // first line contains start of manifest
107
            if ($stubContent === null && $manifestContent === null && $manifestPosition !== false) {
108
                $stubContent = substr($line, 0, $manifestPosition - 1);
109
                $manifestContent = preg_replace('#^.*__HALT_COMPILER\(\);(?>[ \n]\?>(?>\r\n|\n)?)?#', '', $line);
110
                $manifestLength = $this->resolveManifestLength($manifestContent);
111
            // line contains start of stub
112
            } elseif ($stubContent === null) {
113
                $stubContent = $line;
114
            // line contains start of manifest
115
            } elseif ($manifestContent === null && $manifestPosition !== false) {
116
                $manifestContent = preg_replace('#^.*__HALT_COMPILER\(\);(?>[ \n]\?>(?>\r\n|\n)?)?#', '', $line);
117
                $manifestLength = $this->resolveManifestLength($manifestContent);
118
            // manifest has been started (thus is cannot be stub anymore), add content
119
            } elseif ($manifestContent !== null) {
120
                $manifestContent .= $line;
121
                $manifestLength = $this->resolveManifestLength($manifestContent);
122
            // stub has been started (thus cannot be manifest here, yet), add content
123
            } elseif ($stubContent !== null) {
124
                $stubContent .= $line;
125
            }
126
        }
127
        fclose($resource);
128
129
        return [
130
            'stubContent' => $stubContent,
131
            'manifestContent' => $manifestContent,
132
            'manifestLength' => $manifestLength,
133
        ];
134
    }
135
136
    /**
137
     * Resolves stream in order to handle compressed Phar archives.
138
     *
139
     * @return string
140
     */
141
    private function resolveStream(): string
142
    {
143
        if ($this->fileType === 'application/x-gzip') {
144
            return 'compress.zlib://';
145
        } elseif ($this->fileType === 'application/x-bzip2') {
146
            return 'compress.bzip2://';
147
        }
148
        return '';
149
    }
150
151
    /**
152
     * @return string
153
     */
154
    private function determineFileType()
155
    {
156
        if (class_exists('\\finfo')) {
157
            $fileInfo = new \finfo();
158
            return $fileInfo->file($this->fileName, FILEINFO_MIME_TYPE);
159
        }
160
        return $this->determineFileTypeByHeader();
161
    }
162
163
    /**
164
     * @return string
165
     */
166
    private function determineFileTypeByHeader(): string
167
    {
168
        $resource = fopen($this->fileName, 'r');
169
        $header = fgets($resource, 4);
0 ignored issues
show
Bug introduced by
It seems like $resource can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

169
        $header = fgets(/** @scrutinizer ignore-type */ $resource, 4);
Loading history...
170
        fclose($resource);
0 ignored issues
show
Bug introduced by
It seems like $resource can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

170
        fclose(/** @scrutinizer ignore-type */ $resource);
Loading history...
171
        $mimeType = '';
172
        if (strpos($header, "\x42\x5a\x68") === 0) {
173
            $mimeType = 'application/x-bzip2';
174
        } elseif (strpos($header, "\x1f\x8b") === 0) {
175
            $mimeType = 'application/x-gzip';
176
        }
177
        return $mimeType;
178
    }
179
180
    /**
181
     * @param string $content
182
     * @return int|null
183
     */
184
    private function resolveManifestLength(string $content)
185
    {
186
        if (strlen($content) < 4) {
187
            return null;
188
        }
189
        return static::resolveFourByteLittleEndian($content, 0);
190
    }
191
192
    /**
193
     * @param string $content
194
     * @param int $start
195
     * @return int
196
     */
197
    public static function resolveFourByteLittleEndian(string $content, int $start): int
198
    {
199
        $payload = substr($content, $start, 4);
200
        if (!is_string($payload)) {
0 ignored issues
show
introduced by
The condition is_string($payload) is always true.
Loading history...
201
            throw new ReaderException(
202
                sprintf('Cannot resolve value at offset %d', $start),
203
                1539614260
204
            );
205
        }
206
207
        $value = unpack('V', $payload);
208
        if (!isset($value[1])) {
209
            throw new ReaderException(
210
                sprintf('Cannot resolve value at offset %d', $start),
211
                1539614261
212
            );
213
        }
214
        return $value[1];
215
    }
216
217
    /**
218
     * @param string $content
219
     * @param int $start
220
     * @return int
221
     */
222
    public static function resolveTwoByteBigEndian(string $content, int $start): int
223
    {
224
        $payload = substr($content, $start, 2);
225
        if (!is_string($payload)) {
0 ignored issues
show
introduced by
The condition is_string($payload) is always true.
Loading history...
226
            throw new ReaderException(
227
                sprintf('Cannot resolve value at offset %d', $start),
228
                1539614263
229
            );
230
        }
231
232
        $value = unpack('n', $payload);
233
        if (!isset($value[1])) {
234
            throw new ReaderException(
235
                sprintf('Cannot resolve value at offset %d', $start),
236
                1539614264
237
            );
238
        }
239
        return $value[1];
240
    }
241
}
242