- Timestamp:
- Jul 7, 2009, 10:27:37 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/charlies_content/getid3/getid3/module.archive.gzip.php
r3318 r3544 1 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$ 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); 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; 79 $idx = 0; 80 for ($i = 0; $i < $num_members; $i++) { 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']); 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; 214 $inflated = ''; 215 $chkcrc32 = ''; 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 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 22 class 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 } 294 269 } 295 270
Note: See TracChangeset
for help on using the changeset viewer.