Passed
Branch master (f2d2e3)
by Michael
18:45
created

getid3_gzip::Analyze()   F

Complexity

Conditions 26
Paths 4563

Size

Total Lines 223

Duplication

Lines 25
Ratio 11.21 %

Importance

Changes 0
Metric Value
cc 26
nc 4563
nop 0
dl 25
loc 223
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// +----------------------------------------------------------------------+
3
// | PHP version 5                                                        |
4
// +----------------------------------------------------------------------+
5
// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
6
// +----------------------------------------------------------------------+
7
// | This source file is subject to version 2 of the GPL license,         |
8
// | that is bundled with this package in the file license.txt and is     |
9
// | available through the world-wide-web at the following url:           |
10
// | http://www.gnu.org/copyleft/gpl.html                                 |
11
// +----------------------------------------------------------------------+
12
// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
13
// +----------------------------------------------------------------------+
14
// | Authors: James Heinrich <info�getid3*org>                            |
15
// |          Allan Hansen <ah�artemis*dk>                                |
16
// +----------------------------------------------------------------------+
17
// | module.archive.gzip.php                                              |
18
// | module for analyzing GZIP files                                      |
19
// | dependencies: PHP compiled with zlib support (optional)              |
20
// +----------------------------------------------------------------------+
21
// | Module originally written by Mike Mozolin <teddybear�mail*ru>        |
22
// +----------------------------------------------------------------------+
23
//
24
// $Id: module.archive.gzip.php,v 1.4 2006/12/04 16:00:35 ah Exp $
25
26
        
27
        
28
class getid3_gzip extends getid3_handler
29
{
30
31
    // public: Optional file list - disable for speed.
32
    public $option_gzip_parse_contents = true; // decode gzipped files, if possible, and parse recursively (.tar.gz for example)
33
34
    
35
    // Reads the gzip-file
36
    function Analyze() {
37
38
        $info = &$this->getid3->info;
39
40
        $info['fileformat'] = 'gzip';
41
42
        $start_length = 10;
43
        $unpack_header = 'a1id1/a1id2/a1cmethod/a1flags/a4mtime/a1xflags/a1os';
44
        
45
        //+---+---+---+---+---+---+---+---+---+---+
46
        //|ID1|ID2|CM |FLG|     MTIME     |XFL|OS |
47
        //+---+---+---+---+---+---+---+---+---+---+
48
        
49
        @fseek($this->getid3->fp, 0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fseek(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

49
        /** @scrutinizer ignore-unhandled */ @fseek($this->getid3->fp, 0);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
50
        $buffer = @fread($this->getid3->fp, $info['filesize']);
51
52
        $arr_members = explode("\x1F\x8B\x08", $buffer);
53
        
54
        while (true) {
55
            $is_wrong_members = false;
56
            $num_members = intval(count($arr_members));
57
            for ($i = 0; $i < $num_members; $i++) {
58
                if (strlen($arr_members[$i]) == 0) {
59
                    continue;
60
                }
61
                $buf = "\x1F\x8B\x08".$arr_members[$i];
62
63
                $attr = unpack($unpack_header, substr($buf, 0, $start_length));
64
                if (!$this->get_os_type(ord($attr['os']))) {
65
        
66
                    // Merge member with previous if wrong OS type
67
                    $arr_members[$i - 1] .= $buf;
68
                    $arr_members[$i] = '';
69
                    $is_wrong_members = true;
70
                    continue;
71
                }
72
            }
73
            if (!$is_wrong_members) {
74
                break;
75
            }
76
        }
77
78
        $fpointer = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $fpointer is dead and can be removed.
Loading history...
79
        $idx = 0;
80
        for ($i = 0; $i < $num_members; $i++) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $num_members does not seem to be defined for all execution paths leading up to this point.
Loading history...
81
            if (strlen($arr_members[$i]) == 0) {
82
                continue;
83
            }
84
            $info_gzip_member_header_idx = &$info['gzip']['member_header'][++$idx];
85
86
            $buff = "\x1F\x8B\x08".$arr_members[$i];
87
88
            $attr = unpack($unpack_header, substr($buff, 0, $start_length));
89
            $info_gzip_member_header_idx['filemtime']      = getid3_lib::LittleEndian2Int($attr['mtime']);
90
            $info_gzip_member_header_idx['raw']['id1']     = ord($attr['cmethod']);
91
            $info_gzip_member_header_idx['raw']['id2']     = ord($attr['cmethod']);
92
            $info_gzip_member_header_idx['raw']['cmethod'] = ord($attr['cmethod']);
93
            $info_gzip_member_header_idx['raw']['os']      = ord($attr['os']);
94
            $info_gzip_member_header_idx['raw']['xflags']  = ord($attr['xflags']);
95
            $info_gzip_member_header_idx['raw']['flags']   = ord($attr['flags']);
96
97
            $info_gzip_member_header_idx['flags']['crc16']    = (bool) ($info_gzip_member_header_idx['raw']['flags'] & 0x02);
98
            $info_gzip_member_header_idx['flags']['extra']    = (bool) ($info_gzip_member_header_idx['raw']['flags'] & 0x04);
99
            $info_gzip_member_header_idx['flags']['filename'] = (bool) ($info_gzip_member_header_idx['raw']['flags'] & 0x08);
100
            $info_gzip_member_header_idx['flags']['comment']  = (bool) ($info_gzip_member_header_idx['raw']['flags'] & 0x10);
101
102
            $info_gzip_member_header_idx['compression'] = $this->get_xflag_type($info_gzip_member_header_idx['raw']['xflags']);
103
104
            $info_gzip_member_header_idx['os'] = $this->get_os_type($info_gzip_member_header_idx['raw']['os']);
105
            if (!$info_gzip_member_header_idx['os']) {
106
                $info['error'][] = 'Read error on gzip file';
107
                return false;
108
            }
109
110
            $fpointer = 10;
111
            $arr_xsubfield = array ();
112
            
113
            // bit 2 - FLG.FEXTRA
114
            //+---+---+=================================+
115
            //| XLEN  |...XLEN bytes of "extra field"...|
116
            //+---+---+=================================+
117
            
118
            if ($info_gzip_member_header_idx['flags']['extra']) {
119
                $w_xlen = substr($buff, $fpointer, 2);
120
                $xlen = getid3_lib::LittleEndian2Int($w_xlen);
121
                $fpointer += 2;
122
123
                $info_gzip_member_header_idx['raw']['xfield'] = substr($buff, $fpointer, $xlen);
124
            
125
                // Extra SubFields
126
                //+---+---+---+---+==================================+
127
                //|SI1|SI2|  LEN  |... LEN bytes of subfield data ...|
128
                //+---+---+---+---+==================================+
129
            
130
                $idx = 0;
131
                while (true) {
132
                    if ($idx >= $xlen) {
133
                        break;
134
                    }
135
                    $si1 = ord(substr($buff, $fpointer + $idx++, 1));
136
                    $si2 = ord(substr($buff, $fpointer + $idx++, 1));
137
                    if (($si1 == 0x41) && ($si2 == 0x70)) {
138
                        $w_xsublen = substr($buff, $fpointer+$idx, 2);
139
                        $xsublen = getid3_lib::LittleEndian2Int($w_xsublen);
140
                        $idx += 2;
141
                        $arr_xsubfield[] = substr($buff, $fpointer+$idx, $xsublen);
142
                        $idx += $xsublen;
143
                    } else {
144
                        break;
145
                    }
146
                }
147
                $fpointer += $xlen;
148
            }
149
            
150
            // bit 3 - FLG.FNAME
151
            //+=========================================+
152
            //|...original file name, zero-terminated...|
153
            //+=========================================+
154
            // GZIP files may have only one file, with no filename, so assume original filename is current filename without .gz
155
            
156
            $info_gzip_member_header_idx['filename'] = eregi_replace('.gz$', '', @$info['filename']);
0 ignored issues
show
Deprecated Code introduced by
The function eregi_replace() has been deprecated: 5.3.0 Use preg_replace() instead ( Ignorable by Annotation )

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

156
            $info_gzip_member_header_idx['filename'] = /** @scrutinizer ignore-deprecated */ eregi_replace('.gz$', '', @$info['filename']);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
157
            if ($info_gzip_member_header_idx['flags']['filename']) {
158
                while (true) {
159
                    if (ord($buff[$fpointer]) == 0) {
160
                        $fpointer++;
161
                        break;
162
                    }
163
                    $info_gzip_member_header_idx['filename'] .= $buff[$fpointer];
164
                    $fpointer++;
165
                }
166
            }
167
            
168
            // bit 4 - FLG.FCOMMENT
169
            //+===================================+
170
            //|...file comment, zero-terminated...|
171
            //+===================================+
172
            
173
            if ($info_gzip_member_header_idx['flags']['comment']) {
174
                while (true) {
175
                    if (ord($buff[$fpointer]) == 0) {
176
                        $fpointer++;
177
                        break;
178
                    }
179
                    $info_gzip_member_header_idx['comment'] .= $buff[$fpointer];
180
                    $fpointer++;
181
                }
182
            }
183
            
184
            // bit 1 - FLG.FHCRC
185
            //+---+---+
186
            //| CRC16 |
187
            //+---+---+
188
            
189
            if ($info_gzip_member_header_idx['flags']['crc16']) {
190
                $w_crc = substr($buff, $fpointer, 2);
191
                $info_gzip_member_header_idx['crc16'] = getid3_lib::LittleEndian2Int($w_crc);
192
                $fpointer += 2;
193
            }
194
            
195
            // bit 0 - FLG.FTEXT
196
            //if ($info_gzip_member_header_idx['raw']['flags'] & 0x01) {
197
            //  Ignored...
198
            //}
199
            // bits 5, 6, 7 - reserved
200
201
            $info_gzip_member_header_idx['crc32']    = getid3_lib::LittleEndian2Int(substr($buff, strlen($buff) - 8, 4));
202
            $info_gzip_member_header_idx['filesize'] = getid3_lib::LittleEndian2Int(substr($buff, strlen($buff) - 4));
203
204
            if ($this->option_gzip_parse_contents) {
205
206
                // Try to inflate GZip
207
                
208
                if (!function_exists('gzinflate')) {
209
                    $this->getid3->warning('PHP does not have zlib support - contents not parsed.');
210
                    return true;
211
                }
212
213
                $csize = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $csize is dead and can be removed.
Loading history...
214
                $inflated = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $inflated is dead and can be removed.
Loading history...
215
                $chkcrc32 = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $chkcrc32 is dead and can be removed.
Loading history...
216
217
                $cdata = substr($buff, $fpointer);
218
                $cdata = substr($cdata, 0, strlen($cdata) - 8);
219
                $csize = strlen($cdata);
220
                $inflated = gzinflate($cdata);
221
222
                // Calculate CRC32 for inflated content
223
                $info_gzip_member_header_idx['crc32_valid'] = (bool) (sprintf('%u', crc32($inflated)) == $info_gzip_member_header_idx['crc32']);
224
225
                
226
                //// Analyse contents
227
                
228
                // write content to temp file
229
                if (($temp_file_name = tempnam('*', 'getID3'))  === false) {
230
                    throw new getid3_exception('Unable to create temporary file.');
231
                }
232
233
                if ($tmp = fopen($temp_file_name, 'wb')) {
234
                    fwrite($tmp, $inflated);
235
                    fclose($tmp);
236
                    
237
                    // clone getid3 - we want same settings
238
                    $clone = clone $this->getid3;
239
                    unset($clone->info);
240
                    try {
241
                        $clone->Analyze($temp_file_name);
242
                        $info_gzip_member_header_idx['parsed_content'] = $clone->info;
243
                    }
244
                    catch (getid3_exception $e) {
245
                        // unable to parse contents
246
                    }
247
                    
248
                    unlink($temp_file_name);
249
                }
250
            
251
                // Unknown/unhandled format 
252
                else {
253
                                        
254
                }
255
            }
256
        }
257
        return true;
258
    }
259
260
261
    // Converts the OS type
262
    public static function get_os_type($key) {
263
        static $os_type = array (
264
            '0'   => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)',
265
            '1'   => 'Amiga',
266
            '2'   => 'VMS (or OpenVMS)',
267
            '3'   => 'Unix',
268
            '4'   => 'VM/CMS',
269
            '5'   => 'Atari TOS',
270
            '6'   => 'HPFS filesystem (OS/2, NT)',
271
            '7'   => 'Macintosh',
272
            '8'   => 'Z-System',
273
            '9'   => 'CP/M',
274
            '10'  => 'TOPS-20',
275
            '11'  => 'NTFS filesystem (NT)',
276
            '12'  => 'QDOS',
277
            '13'  => 'Acorn RISCOS',
278
            '255' => 'unknown'
279
        );
280
        return @$os_type[$key];
281
    }
282
283
284
    // Converts the eXtra FLags
285
    public static function get_xflag_type($key) {
286
        static $xflag_type = array (
287
            '0' => 'unknown',
288
            '2' => 'maximum compression',
289
            '4' => 'fastest algorithm'
290
        );
291
        return @$xflag_type[$key];
292
    }
293
    
294
}
295
296
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...