source: extensions/charlies_content/getid3/getid3/module.archive.gzip.php @ 3544

Last change on this file since 3544 was 3544, checked in by vdigital, 15 years ago

Change: getid3 upgraded to -> 1.7.9

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1<?php
2/////////////////////////////////////////////////////////////////
3/// getID3() by James Heinrich <info@getid3.org>               //
4//  available at http://getid3.sourceforge.net                 //
5//            or http://www.getid3.org                         //
6/////////////////////////////////////////////////////////////////
7// See readme.txt for more details                             //
8/////////////////////////////////////////////////////////////////
9//                                                             //
10// module.archive.gzip.php                                     //
11// module for analyzing GZIP files                             //
12// dependencies: NONE                                          //
13//                                                            ///
14/////////////////////////////////////////////////////////////////
15//                                                             //
16// Module originally written by                                //
17//      Mike Mozolin <teddybearØmail*ru>                       //
18//                                                             //
19/////////////////////////////////////////////////////////////////
20
21
22class getid3_gzip {
23
24        // public: Optional file list - disable for speed.
25        var $option_gzip_parse_contents = false; // decode gzipped files, if possible, and parse recursively (.tar.gz for example)
26
27        function getid3_gzip(&$fd, &$ThisFileInfo) {
28                $ThisFileInfo['fileformat'] = 'gzip';
29
30                $start_length = 10;
31                $unpack_header = 'a1id1/a1id2/a1cmethod/a1flags/a4mtime/a1xflags/a1os';
32                //+---+---+---+---+---+---+---+---+---+---+
33                //|ID1|ID2|CM |FLG|     MTIME     |XFL|OS |
34                //+---+---+---+---+---+---+---+---+---+---+
35                @fseek($fd, 0);
36                $buffer = @fread($fd, $ThisFileInfo['filesize']);
37
38                $arr_members = explode("\x1F\x8B\x08", $buffer);
39                while (true) {
40                        $is_wrong_members = false;
41                        $num_members = intval(count($arr_members));
42                        for ($i = 0; $i < $num_members; $i++) {
43                                if (strlen($arr_members[$i]) == 0) {
44                                        continue;
45                                }
46                                $buf = "\x1F\x8B\x08".$arr_members[$i];
47
48                                $attr = unpack($unpack_header, substr($buf, 0, $start_length));
49                                if (!$this->get_os_type(ord($attr['os']))) {
50                                        // Merge member with previous if wrong OS type
51                                        $arr_members[$i - 1] .= $buf;
52                                        $arr_members[$i] = '';
53                                        $is_wrong_members = true;
54                                        continue;
55                                }
56                        }
57                        if (!$is_wrong_members) {
58                                break;
59                        }
60                }
61
62                $ThisFileInfo['gzip']['files'] = array();
63
64                $fpointer = 0;
65                $idx = 0;
66                for ($i = 0; $i < $num_members; $i++) {
67                        if (strlen($arr_members[$i]) == 0) {
68                                continue;
69                        }
70                        $thisThisFileInfo = &$ThisFileInfo['gzip']['member_header'][++$idx];
71
72                        $buff = "\x1F\x8B\x08".$arr_members[$i];
73
74                        $attr = unpack($unpack_header, substr($buff, 0, $start_length));
75                        $thisThisFileInfo['filemtime']      = getid3_lib::LittleEndian2Int($attr['mtime']);
76                        $thisThisFileInfo['raw']['id1']     = ord($attr['cmethod']);
77                        $thisThisFileInfo['raw']['id2']     = ord($attr['cmethod']);
78                        $thisThisFileInfo['raw']['cmethod'] = ord($attr['cmethod']);
79                        $thisThisFileInfo['raw']['os']      = ord($attr['os']);
80                        $thisThisFileInfo['raw']['xflags']  = ord($attr['xflags']);
81                        $thisThisFileInfo['raw']['flags']   = ord($attr['flags']);
82
83                        $thisThisFileInfo['flags']['crc16']    = (bool) ($thisThisFileInfo['raw']['flags'] & 0x02);
84                        $thisThisFileInfo['flags']['extra']    = (bool) ($thisThisFileInfo['raw']['flags'] & 0x04);
85                        $thisThisFileInfo['flags']['filename'] = (bool) ($thisThisFileInfo['raw']['flags'] & 0x08);
86                        $thisThisFileInfo['flags']['comment']  = (bool) ($thisThisFileInfo['raw']['flags'] & 0x10);
87
88                        $thisThisFileInfo['compression'] = $this->get_xflag_type($thisThisFileInfo['raw']['xflags']);
89
90                        $thisThisFileInfo['os'] = $this->get_os_type($thisThisFileInfo['raw']['os']);
91                        if (!$thisThisFileInfo['os']) {
92                                $ThisFileInfo['error'][] = 'Read error on gzip file';
93                                return false;
94                        }
95
96                        $fpointer = 10;
97                        $arr_xsubfield = array();
98                        // bit 2 - FLG.FEXTRA
99                        //+---+---+=================================+
100                        //| XLEN  |...XLEN bytes of "extra field"...|
101                        //+---+---+=================================+
102                        if ($thisThisFileInfo['flags']['extra']) {
103                                $w_xlen = substr($buff, $fpointer, 2);
104                                $xlen = getid3_lib::LittleEndian2Int($w_xlen);
105                                $fpointer += 2;
106
107                                $thisThisFileInfo['raw']['xfield'] = substr($buff, $fpointer, $xlen);
108                                // Extra SubFields
109                                //+---+---+---+---+==================================+
110                                //|SI1|SI2|  LEN  |... LEN bytes of subfield data ...|
111                                //+---+---+---+---+==================================+
112                                $idx = 0;
113                                while (true) {
114                                        if ($idx >= $xlen) {
115                                                break;
116                                        }
117                                        $si1 = ord(substr($buff, $fpointer + $idx++, 1));
118                                        $si2 = ord(substr($buff, $fpointer + $idx++, 1));
119                                        if (($si1 == 0x41) && ($si2 == 0x70)) {
120                                                $w_xsublen = substr($buff, $fpointer + $idx, 2);
121                                                $xsublen = getid3_lib::LittleEndian2Int($w_xsublen);
122                                                $idx += 2;
123                                                $arr_xsubfield[] = substr($buff, $fpointer + $idx, $xsublen);
124                                                $idx += $xsublen;
125                                        } else {
126                                                break;
127                                        }
128                                }
129                                $fpointer += $xlen;
130                        }
131                        // bit 3 - FLG.FNAME
132                        //+=========================================+
133                        //|...original file name, zero-terminated...|
134                        //+=========================================+
135                        // GZIP files may have only one file, with no filename, so assume original filename is current filename without .gz
136                        $thisThisFileInfo['filename'] = eregi_replace('.gz$', '', $ThisFileInfo['filename']);
137                        if ($thisThisFileInfo['flags']['filename']) {
138                                while (true) {
139                                        if (ord($buff[$fpointer]) == 0) {
140                                                $fpointer++;
141                                                break;
142                                        }
143                                        $thisThisFileInfo['filename'] .= $buff[$fpointer];
144                                        $fpointer++;
145                                }
146                        }
147                        // bit 4 - FLG.FCOMMENT
148                        //+===================================+
149                        //|...file comment, zero-terminated...|
150                        //+===================================+
151                        if ($thisThisFileInfo['flags']['comment']) {
152                                while (true) {
153                                        if (ord($buff[$fpointer]) == 0) {
154                                                $fpointer++;
155                                                break;
156                                        }
157                                        $thisThisFileInfo['comment'] .= $buff[$fpointer];
158                                        $fpointer++;
159                                }
160                        }
161                        // bit 1 - FLG.FHCRC
162                        //+---+---+
163                        //| CRC16 |
164                        //+---+---+
165                        if ($thisThisFileInfo['flags']['crc16']) {
166                                $w_crc = substr($buff, $fpointer, 2);
167                                $thisThisFileInfo['crc16'] = getid3_lib::LittleEndian2Int($w_crc);
168                                $fpointer += 2;
169                        }
170                        // bit 0 - FLG.FTEXT
171                        //if ($thisThisFileInfo['raw']['flags'] & 0x01) {
172                        //      Ignored...
173                        //}
174                        // bits 5, 6, 7 - reserved
175
176                        $thisThisFileInfo['crc32']    = getid3_lib::LittleEndian2Int(substr($buff, strlen($buff) - 8, 4));
177                        $thisThisFileInfo['filesize'] = getid3_lib::LittleEndian2Int(substr($buff, strlen($buff) - 4));
178
179                        $ThisFileInfo['gzip']['files'] = getid3_lib::array_merge_clobber($ThisFileInfo['gzip']['files'], getid3_lib::CreateDeepArray($thisThisFileInfo['filename'], '/', $thisThisFileInfo['filesize']));
180
181                        if ($this->option_gzip_parse_contents) {
182                                // Try to inflate GZip
183                                $csize = 0;
184                                $inflated = '';
185                                $chkcrc32 = '';
186                                if (function_exists('gzinflate')) {
187                                        $cdata = substr($buff, $fpointer);
188                                        $cdata = substr($cdata, 0, strlen($cdata) - 8);
189                                        $csize = strlen($cdata);
190                                        $inflated = gzinflate($cdata);
191
192                                        // Calculate CRC32 for inflated content
193                                        $thisThisFileInfo['crc32_valid'] = (bool) (sprintf('%u', crc32($inflated)) == $thisThisFileInfo['crc32']);
194
195                                        // determine format
196                                        $formattest = substr($inflated, 0, 32774);
197                                        $newgetID3 = new getID3();
198                                        $determined_format = $newgetID3->GetFileFormat($formattest);
199                                        unset($newgetID3);
200
201                                // file format is determined
202                                switch (@$determined_format['module']) {
203                                        case 'tar':
204                                                        // view TAR-file info
205                                                        if (file_exists(GETID3_INCLUDEPATH.$determined_format['include']) && @include_once(GETID3_INCLUDEPATH.$determined_format['include'])) {
206                                                                if (($temp_tar_filename = tempnam('*', 'getID3')) === false) {
207                                                                        // can't find anywhere to create a temp file, abort
208                                                                        $ThisFileInfo['error'][] = 'Unable to create temp file to parse TAR inside GZIP file';
209                                                                        break;
210                                                                }
211                                                                if ($fp_temp_tar = fopen($temp_tar_filename, 'w+b')) {
212                                                                        fwrite($fp_temp_tar, $inflated);
213                                                                        rewind($fp_temp_tar);
214                                                                        $getid3_tar = new getid3_tar($fp_temp_tar, $dummy);
215                                                                        $ThisFileInfo['gzip']['member_header'][$idx]['tar'] = $dummy['tar'];
216                                                                        unset($dummy);
217                                                                        unset($getid3_tar);
218                                                                        fclose($fp_temp_tar);
219                                                                        unlink($temp_tar_filename);
220                                                                } else {
221                                                                        $ThisFileInfo['error'][] = 'Unable to fopen() temp file to parse TAR inside GZIP file';
222                                                                        break;
223                                                                }
224                                                        }
225                                                        break;
226
227                                        case '':
228                                        default:
229                                                // unknown or unhandled format
230                                                break;
231                                        }
232                                }
233                        }
234                }
235                return true;
236        }
237
238        // Converts the OS type
239        function get_os_type($key) {
240                static $os_type = array(
241                        '0'   => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)',
242                        '1'   => 'Amiga',
243                        '2'   => 'VMS (or OpenVMS)',
244                        '3'   => 'Unix',
245                        '4'   => 'VM/CMS',
246                        '5'   => 'Atari TOS',
247                        '6'   => 'HPFS filesystem (OS/2, NT)',
248                        '7'   => 'Macintosh',
249                        '8'   => 'Z-System',
250                        '9'   => 'CP/M',
251                        '10'  => 'TOPS-20',
252                        '11'  => 'NTFS filesystem (NT)',
253                        '12'  => 'QDOS',
254                        '13'  => 'Acorn RISCOS',
255                        '255' => 'unknown'
256                );
257                return @$os_type[$key];
258        }
259
260        // Converts the eXtra FLags
261        function get_xflag_type($key) {
262                static $xflag_type = array(
263                        '0' => 'unknown',
264                        '2' => 'maximum compression',
265                        '4' => 'fastest algorithm'
266                );
267                return @$xflag_type[$key];
268        }
269}
270
271?>
Note: See TracBrowser for help on using the repository browser.