Issues (378)

app/Extensions/util/PhpYenc.php (1 issue)

Severity
1
<?php
2
3
/**
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 * GNU General Public License for more details.
12
 * You should have received a copy of the GNU General Public License
13
 * along with this program (see LICENSE.txt in the base directory.  If
14
 * not, see:.
15
 *
16
 * @link      <http://www.gnu.org/licenses/>.
17
 *
18
 * @author    niel
19
 * @copyright 2016 nZEDb
20
 */
21
22
namespace App\Extensions\util;
23
24
/**
25
 * Class Php.
26
 */
27
class PhpYenc
28
{
29
    public static function decode(&$text, bool $ignore = false): bool|string
0 ignored issues
show
The parameter $ignore is not used and could be removed. ( Ignorable by Annotation )

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

29
    public static function decode(&$text, /** @scrutinizer ignore-unused */ bool $ignore = false): bool|string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
30
    {
31
        $crc = '';
32
        // Extract the yEnc string itself.
33
        if (preg_match(
34
            '/=ybegin.*size=([^ $]+).*\\r\\n(.*)\\r\\n=yend.*size=([^ $\\r\\n]+)(.*)/ims',
35
            $text,
36
            $encoded
37
        )) {
38
            if (preg_match('/crc32=([^ $\\r\\n]+)/ims', $encoded[4], $trailer)) {
39
                $crc = trim($trailer[1]);
40
            }
41
42
            [$headerSize, $encoded, $trailerSize] = $encoded;
43
        } else {
44
            return false;
45
        }
46
47
        // Remove line breaks from the string.
48
        $encoded = trim(str_replace("\r\n", '', $encoded));
49
50
        // Make sure the header and trailer file sizes match up.
51
        if ($headerSize !== $trailerSize) {
52
            $message = 'Header and trailer file sizes do not match. This is a violation of the yEnc specification.';
53
            throw new \RuntimeException($message);
54
        }
55
56
        // Decode.
57
        $decoded = '';
58
        $encodedLength = \strlen($encoded);
59
        for ($chr = 0; $chr < $encodedLength; $chr++) {
60
            $decoded .= (
61
                $encoded[$chr] === '=' ?
62
                    \chr((\ord($encoded[$chr]) - 42) % 256) :
63
                    \chr((((\ord($encoded[++$chr]) - 64) % 256) - 42) % 256)
64
            );
65
        }
66
67
        // Make sure the decoded file size is the same as the size specified in the header.
68
        if (\strlen($decoded) !== $headerSize) {
69
            $message = 'Header file size ('.$headerSize.') and actual file size ('.\strlen($decoded).') do not match. The file is probably corrupt.';
70
71
            throw new \RuntimeException($message);
72
        }
73
74
        // Check the CRC value
75
        if ($crc !== '' && (strtolower($crc) !== strtolower(sprintf('%04X', crc32($decoded))))) {
76
            $message = 'CRC32 checksums do not match. The file is probably corrupt.';
77
78
            throw new \RuntimeException($message);
79
        }
80
81
        return $decoded;
82
    }
83
84
    /**
85
     * Decode a string of text encoded with yEnc. Ignores all errors.
86
     *
87
     * @param  string  $text  The encoded text to decode.
88
     * @return string The decoded yEnc string, or the input string, if it's not yEnc.
89
     */
90
    public static function decodeIgnore(string &$text): string
91
    {
92
        if (preg_match('/^(=yBegin.*=yEnd[^$]*)$/ims', $text, $input)) {
93
            $text = '';
94
            $input =
95
                trim(
96
                    preg_replace(
97
                        '/\r\n/im',
98
                        '',
99
                        preg_replace(
100
                            '/(^=yEnd.*)/im',
101
                            '',
102
                            preg_replace(
103
                                '/(^=yPart.*\\r\\n)/im',
104
                                '',
105
                                preg_replace('/(^=yBegin.*\\r\\n)/im', '', $input[1], 1),
106
                                1
107
                            ),
108
                            1
109
                        )
110
                    )
111
                );
112
113
            $length = \strlen($input);
114
            for ($chr = 0; $chr < $length; $chr++) {
115
                $text .= (
116
                    $input[$chr] === '=' ?
117
                        \chr((((\ord($input[++$chr]) - 64) % 256) - 42) % 256) :
118
                        \chr((\ord($input[$chr]) - 42) % 256)
119
                );
120
            }
121
        }
122
123
        return $text;
124
    }
125
126
    public static function enabled(): bool
127
    {
128
        return true;
129
    }
130
131
    public static function encode($data, $filename, int $lineLength = 128, bool $crc32 = true): string
132
    {
133
        // yEnc 1.3 draft doesn't allow line lengths of more than 254 bytes.
134
        if ($lineLength > 254) {
135
            $lineLength = 254;
136
        }
137
138
        if ($lineLength < 1) {
139
            $message = $lineLength.' is not a valid line length.';
140
141
            throw new \RuntimeException($message);
142
        }
143
144
        $encoded = '';
145
        $stringLength = \strlen($data);
146
        // Encode each character of the string one at a time.
147
        foreach ($data as $i => $iValue) {
148
            $value = ((\ord($iValue) + 42) % 256);
149
150
            // Escape NULL, TAB, LF, CR, space, . and = characters.
151
            $encoded .= match ($value) {
152
                0, 10, 13, 61 => ('='.\chr(($value + 64) % 256)),
153
                default => \chr($value),
154
            };
155
        }
156
157
        $encoded =
158
            '=ybegin line='.
159
            $lineLength.
160
            ' size='.
161
            $stringLength.
162
            ' name='.
163
            trim($filename).
164
            "\r\n".
165
            trim(chunk_split($encoded, $lineLength)).
166
            "\r\n=yend size=".
167
            $stringLength;
168
169
        // Add a CRC32 checksum if desired.
170
        if ($crc32 === true) {
171
            $encoded .= ' crc32='.strtolower(sprintf('%X', crc32($data)));
172
        }
173
174
        return $encoded;
175
    }
176
}
177