/** * @return bool */ public function analyze() { $info =& $this->getid3->info; $info['fileformat'] = 'rar'; if ($this->option_use_rar_extension === true) { if (function_exists('rar_open')) { if ($rp = rar_open($info['filenamepath'])) { $info['rar']['files'] = array(); $entries = rar_list($rp); foreach ($entries as $entry) { $info['rar']['files'] = Helper::array_merge_clobber($info['rar']['files'], Helper::CreateDeepArray($entry->getName(), '/', $entry->getUnpackedSize())); } rar_close($rp); return true; } else { $info['error'][] = 'failed to rar_open(' . $info['filename'] . ')'; } } else { $info['error'][] = 'RAR support does not appear to be available in this PHP installation'; } } else { $info['error'][] = 'PHP-RAR processing has been disabled (set $getid3_rar->option_use_rar_extension=true to enable)'; } return false; }
/** * @return bool */ public function analyze() { $info =& $this->getid3->info; $info['fileformat'] = 'gzip'; $start_length = 10; $unpack_header = 'a1id1/a1id2/a1cmethod/a1flags/a4mtime/a1xflags/a1os'; //+---+---+---+---+---+---+---+---+---+---+ //|ID1|ID2|CM |FLG| MTIME |XFL|OS | //+---+---+---+---+---+---+---+---+---+---+ if ($info['filesize'] > $info['php_memory_limit']) { $info['error'][] = 'File is too large (' . number_format($info['filesize']) . ' bytes) to read into memory (limit: ' . number_format($info['php_memory_limit'] / 1048576) . 'MB)'; return false; } fseek($this->getid3->fp, 0); $buffer = fread($this->getid3->fp, $info['filesize']); $arr_members = explode("‹", $buffer); while (true) { $is_wrong_members = false; $num_members = intval(count($arr_members)); for ($i = 0; $i < $num_members; ++$i) { if (strlen($arr_members[$i]) == 0) { continue; } $buf = "‹" . $arr_members[$i]; $attr = unpack($unpack_header, substr($buf, 0, $start_length)); if (!$this->get_os_type(ord($attr['os']))) { // Merge member with previous if wrong OS type $arr_members[$i - 1] .= $buf; $arr_members[$i] = ''; $is_wrong_members = true; continue; } } if (!$is_wrong_members) { break; } } $info['gzip']['files'] = array(); $fpointer = 0; $idx = 0; for ($i = 0; $i < $num_members; ++$i) { if (strlen($arr_members[$i]) == 0) { continue; } $thisInfo =& $info['gzip']['member_header'][++$idx]; $buff = "‹" . $arr_members[$i]; $attr = unpack($unpack_header, substr($buff, 0, $start_length)); $thisInfo['filemtime'] = Helper::LittleEndian2Int($attr['mtime']); $thisInfo['raw']['id1'] = ord($attr['cmethod']); $thisInfo['raw']['id2'] = ord($attr['cmethod']); $thisInfo['raw']['cmethod'] = ord($attr['cmethod']); $thisInfo['raw']['os'] = ord($attr['os']); $thisInfo['raw']['xflags'] = ord($attr['xflags']); $thisInfo['raw']['flags'] = ord($attr['flags']); $thisInfo['flags']['crc16'] = (bool) ($thisInfo['raw']['flags'] & 0x2); $thisInfo['flags']['extra'] = (bool) ($thisInfo['raw']['flags'] & 0x4); $thisInfo['flags']['filename'] = (bool) ($thisInfo['raw']['flags'] & 0x8); $thisInfo['flags']['comment'] = (bool) ($thisInfo['raw']['flags'] & 0x10); $thisInfo['compression'] = $this->get_xflag_type($thisInfo['raw']['xflags']); $thisInfo['os'] = $this->get_os_type($thisInfo['raw']['os']); if (!$thisInfo['os']) { $info['error'][] = 'Read error on gzip file'; return false; } $fpointer = 10; $arr_xsubfield = array(); // bit 2 - FLG.FEXTRA //+---+---+=================================+ //| XLEN |...XLEN bytes of "extra field"...| //+---+---+=================================+ if ($thisInfo['flags']['extra']) { $w_xlen = substr($buff, $fpointer, 2); $xlen = Helper::LittleEndian2Int($w_xlen); $fpointer += 2; $thisInfo['raw']['xfield'] = substr($buff, $fpointer, $xlen); // Extra SubFields //+---+---+---+---+==================================+ //|SI1|SI2| LEN |... LEN bytes of subfield data ...| //+---+---+---+---+==================================+ $idx = 0; while (true) { if ($idx >= $xlen) { break; } $si1 = ord(substr($buff, $fpointer + $idx++, 1)); $si2 = ord(substr($buff, $fpointer + $idx++, 1)); if ($si1 == 0x41 && $si2 == 0x70) { $w_xsublen = substr($buff, $fpointer + $idx, 2); $xsublen = Helper::LittleEndian2Int($w_xsublen); $idx += 2; $arr_xsubfield[] = substr($buff, $fpointer + $idx, $xsublen); $idx += $xsublen; } else { break; } } $fpointer += $xlen; } // bit 3 - FLG.FNAME //+=========================================+ //|...original file name, zero-terminated...| //+=========================================+ // GZIP files may have only one file, with no filename, so assume original filename is current filename without .gz $thisInfo['filename'] = preg_replace('#\\.gz$#i', '', $info['filename']); if ($thisInfo['flags']['filename']) { while (true) { if (ord($buff[$fpointer]) == 0) { ++$fpointer; break; } $thisInfo['filename'] .= $buff[$fpointer]; ++$fpointer; } } // bit 4 - FLG.FCOMMENT //+===================================+ //|...file comment, zero-terminated...| //+===================================+ if ($thisInfo['flags']['comment']) { while (true) { if (ord($buff[$fpointer]) == 0) { ++$fpointer; break; } $thisInfo['comment'] .= $buff[$fpointer]; ++$fpointer; } } // bit 1 - FLG.FHCRC //+---+---+ //| CRC16 | //+---+---+ if ($thisInfo['flags']['crc16']) { $w_crc = substr($buff, $fpointer, 2); $thisInfo['crc16'] = Helper::LittleEndian2Int($w_crc); $fpointer += 2; } // bit 0 - FLG.FTEXT //if ($thisInfo['raw']['flags'] & 0x01) { // Ignored... //} // bits 5, 6, 7 - reserved $thisInfo['crc32'] = Helper::LittleEndian2Int(substr($buff, strlen($buff) - 8, 4)); $thisInfo['filesize'] = Helper::LittleEndian2Int(substr($buff, strlen($buff) - 4)); $info['gzip']['files'] = Helper::array_merge_clobber($info['gzip']['files'], Helper::CreateDeepArray($thisInfo['filename'], '/', $thisInfo['filesize'])); if ($this->option_gzip_parse_contents) { // Try to inflate GZip $csize = 0; $inflated = ''; $chkcrc32 = ''; if (function_exists('gzinflate')) { $cdata = substr($buff, $fpointer); $cdata = substr($cdata, 0, strlen($cdata) - 8); $csize = strlen($cdata); $inflated = gzinflate($cdata); // Calculate CRC32 for inflated content $thisInfo['crc32_valid'] = (bool) (sprintf('%u', crc32($inflated)) == $thisInfo['crc32']); // determine format $formattest = substr($inflated, 0, 32774); $getid3_temp = new GetId3Core(); $determined_format = $getid3_temp->GetFileFormat($formattest); unset($getid3_temp); // file format is determined $determined_format['module'] = isset($determined_format['module']) ? $determined_format['module'] : ''; switch ($determined_format['module']) { case 'tar': // view TAR-file info if (class_exists($determined_format['class'])) { if (($temp_tar_filename = tempnam(GetId3Core::getTempDir(), 'getID3')) === false) { // can't find anywhere to create a temp file, abort $info['error'][] = 'Unable to create temp file to parse TAR inside GZIP file'; break; } if ($fp_temp_tar = fopen($temp_tar_filename, 'w+b')) { fwrite($fp_temp_tar, $inflated); fclose($fp_temp_tar); $getid3_temp = new GetId3Core(); $getid3_temp->openfile($temp_tar_filename); $getid3_tar = new Tar($getid3_temp); $getid3_tar->analyze(); $info['gzip']['member_header'][$idx]['tar'] = $getid3_temp->info['tar']; unset($getid3_temp, $getid3_tar); unlink($temp_tar_filename); } else { $info['error'][] = 'Unable to fopen() temp file to parse TAR inside GZIP file'; break; } } break; case '': default: // unknown or unhandled format break; } } } } return true; }
/** * @return bool */ public function analyze() { $info =& $this->getid3->info; $info['fileformat'] = 'zip'; $info['zip']['encoding'] = 'ISO-8859-1'; $info['zip']['files'] = array(); $info['zip']['compressed_size'] = 0; $info['zip']['uncompressed_size'] = 0; $info['zip']['entries_count'] = 0; if (!Helper::intValueSupported($info['filesize'])) { $info['error'][] = 'File is larger than ' . round(PHP_INT_MAX / 1073741824) . 'GB, not supported by PHP'; return false; } else { $EOCDsearchData = ''; $EOCDsearchCounter = 0; while ($EOCDsearchCounter++ < 512) { fseek($this->getid3->fp, -128 * $EOCDsearchCounter, SEEK_END); $EOCDsearchData = fread($this->getid3->fp, 128) . $EOCDsearchData; if (strstr($EOCDsearchData, 'PK' . "")) { $EOCDposition = strpos($EOCDsearchData, 'PK' . ""); fseek($this->getid3->fp, -128 * $EOCDsearchCounter + $EOCDposition, SEEK_END); $info['zip']['end_central_directory'] = $this->ZIPparseEndOfCentralDirectory(); fseek($this->getid3->fp, $info['zip']['end_central_directory']['directory_offset'], SEEK_SET); $info['zip']['entries_count'] = 0; while ($centraldirectoryentry = $this->ZIPparseCentralDirectory($this->getid3->fp)) { $info['zip']['central_directory'][] = $centraldirectoryentry; ++$info['zip']['entries_count']; $info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size']; $info['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size']; if ($centraldirectoryentry['uncompressed_size'] > 0) { $info['zip']['files'] = Helper::array_merge_clobber($info['zip']['files'], Helper::CreateDeepArray($centraldirectoryentry['filename'], '/', $centraldirectoryentry['uncompressed_size'])); } } if ($info['zip']['entries_count'] == 0) { $info['error'][] = 'No Central Directory entries found (truncated file?)'; return false; } if (!empty($info['zip']['end_central_directory']['comment'])) { $info['zip']['comments']['comment'][] = $info['zip']['end_central_directory']['comment']; } if (isset($info['zip']['central_directory'][0]['compression_method'])) { $info['zip']['compression_method'] = $info['zip']['central_directory'][0]['compression_method']; } if (isset($info['zip']['central_directory'][0]['flags']['compression_speed'])) { $info['zip']['compression_speed'] = $info['zip']['central_directory'][0]['flags']['compression_speed']; } if (isset($info['zip']['compression_method']) && $info['zip']['compression_method'] == 'store' && !isset($info['zip']['compression_speed'])) { $info['zip']['compression_speed'] = 'store'; } return true; } } } if ($this->getZIPentriesFilepointer()) { // central directory couldn't be found and/or parsed // scan through actual file data entries, recover as much as possible from probable trucated file if ($info['zip']['compressed_size'] > $info['filesize'] - 46 - 22) { $info['error'][] = 'Warning: Truncated file! - Total compressed file sizes (' . $info['zip']['compressed_size'] . ' bytes) is greater than filesize minus Central Directory and End Of Central Directory structures (' . ($info['filesize'] - 46 - 22) . ' bytes)'; } $info['error'][] = 'Cannot find End Of Central Directory - returned list of files in [zip][entries] array may not be complete'; foreach ($info['zip']['entries'] as $key => $valuearray) { $info['zip']['files'][$valuearray['filename']] = $valuearray['uncompressed_size']; } return true; } else { unset($info['zip']); $info['fileformat'] = ''; $info['error'][] = 'Cannot find End Of Central Directory (truncated file?)'; return false; } }
/** * @param type $directorydata * * @return string */ public function ParseDirectoryRecord($directorydata) { $info =& $this->getid3->info; if (isset($info['iso']['supplementary_volume_descriptor'])) { $TextEncoding = 'UTF-16BE'; // Big-Endian Unicode } else { $TextEncoding = 'ISO-8859-1'; // Latin-1 } fseek($this->getid3->fp, $directorydata['location_bytes'], SEEK_SET); $DirectoryRecordData = fread($this->getid3->fp, 1); while (ord($DirectoryRecordData[0]) > 33) { $DirectoryRecordData .= fread($this->getid3->fp, ord($DirectoryRecordData[0]) - 1); $ThisDirectoryRecord['raw']['length'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 0, 1)); $ThisDirectoryRecord['raw']['extended_attribute_length'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 1, 1)); $ThisDirectoryRecord['raw']['offset_logical'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 2, 4)); $ThisDirectoryRecord['raw']['filesize'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 10, 4)); $ThisDirectoryRecord['raw']['recording_date_time'] = substr($DirectoryRecordData, 18, 7); $ThisDirectoryRecord['raw']['file_flags'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 25, 1)); $ThisDirectoryRecord['raw']['file_unit_size'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 26, 1)); $ThisDirectoryRecord['raw']['interleave_gap_size'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 27, 1)); $ThisDirectoryRecord['raw']['volume_sequence_number'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 28, 2)); $ThisDirectoryRecord['raw']['file_identifier_length'] = Helper::LittleEndian2Int(substr($DirectoryRecordData, 32, 1)); $ThisDirectoryRecord['raw']['file_identifier'] = substr($DirectoryRecordData, 33, $ThisDirectoryRecord['raw']['file_identifier_length']); $ThisDirectoryRecord['file_identifier_ascii'] = Helper::iconv_fallback($TextEncoding, $info['encoding'], $ThisDirectoryRecord['raw']['file_identifier']); $ThisDirectoryRecord['filesize'] = $ThisDirectoryRecord['raw']['filesize']; $ThisDirectoryRecord['offset_bytes'] = $ThisDirectoryRecord['raw']['offset_logical'] * 2048; $ThisDirectoryRecord['file_flags']['hidden'] = (bool) ($ThisDirectoryRecord['raw']['file_flags'] & 0x1); $ThisDirectoryRecord['file_flags']['directory'] = (bool) ($ThisDirectoryRecord['raw']['file_flags'] & 0x2); $ThisDirectoryRecord['file_flags']['associated'] = (bool) ($ThisDirectoryRecord['raw']['file_flags'] & 0x4); $ThisDirectoryRecord['file_flags']['extended'] = (bool) ($ThisDirectoryRecord['raw']['file_flags'] & 0x8); $ThisDirectoryRecord['file_flags']['permissions'] = (bool) ($ThisDirectoryRecord['raw']['file_flags'] & 0x10); $ThisDirectoryRecord['file_flags']['multiple'] = (bool) ($ThisDirectoryRecord['raw']['file_flags'] & 0x80); $ThisDirectoryRecord['recording_timestamp'] = $this->ISOtime2UNIXtime($ThisDirectoryRecord['raw']['recording_date_time']); if ($ThisDirectoryRecord['file_flags']['directory']) { $ThisDirectoryRecord['filename'] = $directorydata['full_path']; } else { $ThisDirectoryRecord['filename'] = $directorydata['full_path'] . $this->ISOstripFilenameVersion($ThisDirectoryRecord['file_identifier_ascii']); $info['iso']['files'] = Helper::array_merge_clobber($info['iso']['files'], Helper::CreateDeepArray($ThisDirectoryRecord['filename'], '/', $ThisDirectoryRecord['filesize'])); } $DirectoryRecord[] = $ThisDirectoryRecord; $DirectoryRecordData = fread($this->getid3->fp, 1); } return $DirectoryRecord; }
/** * @return bool */ public function analyze() { $info =& $this->getid3->info; $info['fileformat'] = 'tar'; $info['tar']['files'] = array(); $unpack_header = 'a100fname/a8mode/a8uid/a8gid/a12size/a12mtime/a8chksum/a1typflag/a100lnkname/a6magic/a2ver/a32uname/a32gname/a8devmaj/a8devmin/a155prefix'; $null_512k = str_repeat("", 512); // end-of-file marker fseek($this->getid3->fp, 0); while (!feof($this->getid3->fp)) { $buffer = fread($this->getid3->fp, 512); if (strlen($buffer) < 512) { break; } // check the block $checksum = 0; for ($i = 0; $i < 148; ++$i) { $checksum += ord($buffer[$i]); } for ($i = 148; $i < 156; ++$i) { $checksum += ord(' '); } for ($i = 156; $i < 512; ++$i) { $checksum += ord($buffer[$i]); } $attr = unpack($unpack_header, $buffer); $name = isset($attr['fname']) ? trim($attr['fname']) : ''; $mode = octdec(isset($attr['mode']) ? trim($attr['mode']) : ''); $uid = octdec(isset($attr['uid']) ? trim($attr['uid']) : ''); $gid = octdec(isset($attr['gid']) ? trim($attr['gid']) : ''); $size = octdec(isset($attr['size']) ? trim($attr['size']) : ''); $mtime = octdec(isset($attr['mtime']) ? trim($attr['mtime']) : ''); $chksum = octdec(isset($attr['chksum']) ? trim($attr['chksum']) : ''); $typflag = isset($attr['typflag']) ? trim($attr['typflag']) : ''; $lnkname = isset($attr['lnkname']) ? trim($attr['lnkname']) : ''; $magic = isset($attr['magic']) ? trim($attr['magic']) : ''; $ver = isset($attr['ver']) ? trim($attr['ver']) : ''; $uname = isset($attr['uname']) ? trim($attr['uname']) : ''; $gname = isset($attr['gname']) ? trim($attr['gname']) : ''; $devmaj = octdec(isset($attr['devmaj']) ? trim($attr['devmaj']) : ''); $devmin = octdec(isset($attr['devmin']) ? trim($attr['devmin']) : ''); $prefix = isset($attr['prefix']) ? trim($attr['prefix']) : ''; if ($checksum == 256 && $chksum == 0) { // EOF Found break; } if ($prefix) { $name = $prefix . '/' . $name; } if (preg_match('#/$#', $name) && !$name) { $typeflag = 5; } if ($buffer == $null_512k) { // it's the end of the tar-file... break; } // Read to the next chunk fseek($this->getid3->fp, $size, SEEK_CUR); $diff = $size % 512; if ($diff != 0) { // Padding, throw away fseek($this->getid3->fp, 512 - $diff, SEEK_CUR); } // Protect against tar-files with garbage at the end if ($name == '') { break; } $info['tar']['file_details'][$name] = array('name' => $name, 'mode_raw' => $mode, 'mode' => self::display_perms($mode), 'uid' => $uid, 'gid' => $gid, 'size' => $size, 'mtime' => $mtime, 'chksum' => $chksum, 'typeflag' => self::get_flag_type($typflag), 'linkname' => $lnkname, 'magic' => $magic, 'version' => $ver, 'uname' => $uname, 'gname' => $gname, 'devmajor' => $devmaj, 'devminor' => $devmin); $info['tar']['files'] = Helper::array_merge_clobber($info['tar']['files'], Helper::CreateDeepArray($info['tar']['file_details'][$name]['name'], '/', $size)); } return true; }