rlm@3: | rlm@3: // | Allan Hansen | rlm@3: // +----------------------------------------------------------------------+ rlm@3: // | module.archive.tar.php | rlm@3: // | module for analyzing TAR files | rlm@3: // | dependencies: NONE | rlm@3: // +----------------------------------------------------------------------+ rlm@3: // | Module originally written by Mike Mozolin | rlm@3: // +----------------------------------------------------------------------+ rlm@3: // rlm@3: // $Id: module.archive.tar.php,v 1.2 2006/11/02 10:48:00 ah Exp $ rlm@3: rlm@3: rlm@3: rlm@3: class getid3_tar extends getid3_handler rlm@3: { rlm@3: rlm@3: function Analyze() { rlm@3: rlm@3: $info = &$this->getid3->info; rlm@3: rlm@3: $info['fileformat'] = 'tar'; rlm@3: rlm@3: $fp = $this->getid3->fp; rlm@3: rlm@3: fseek($fp, 0); rlm@3: rlm@3: $unpack_header = 'a100fname/a8mode/a8uid/a8gid/a12size/a12mtime/a8chksum/a1typflag/a100lnkname/a6magic/a2ver/a32uname/a32gname/a8devmaj/a8devmin/a155/prefix'; rlm@3: rlm@3: $null_512k = str_repeat("\0", 512); // end-of-file marker rlm@3: rlm@3: $already_warned = false; rlm@3: rlm@3: while (!feof($fp)) { rlm@3: rlm@3: $buffer = fread($fp, 512); rlm@3: rlm@3: // check the block rlm@3: $checksum = 0; rlm@3: for ($i = 0; $i < 148; $i++) { rlm@3: $checksum += ord(substr($buffer, $i, 1)); rlm@3: } rlm@3: for ($i = 148; $i < 156; $i++) { rlm@3: $checksum += ord(' '); rlm@3: } rlm@3: for ($i = 156; $i < 512; $i++) { rlm@3: $checksum += ord(substr($buffer, $i, 1)); rlm@3: } rlm@3: $attr = unpack($unpack_header, $buffer); rlm@3: $name = trim(@$attr['fname']); rlm@3: $mode = octdec(trim(@$attr['mode'])); rlm@3: $uid = octdec(trim(@$attr['uid'])); rlm@3: $gid = octdec(trim(@$attr['gid'])); rlm@3: $size = octdec(trim(@$attr['size'])); rlm@3: $mtime = octdec(trim(@$attr['mtime'])); rlm@3: $chksum = octdec(trim(@$attr['chksum'])); rlm@3: $typflag = trim(@$attr['typflag']); rlm@3: $lnkname = trim(@$attr['lnkname']); rlm@3: $magic = trim(@$attr['magic']); rlm@3: $ver = trim(@$attr['ver']); rlm@3: $uname = trim(@$attr['uname']); rlm@3: $gname = trim(@$attr['gname']); rlm@3: $devmaj = octdec(trim(@$attr['devmaj'])); rlm@3: $devmin = octdec(trim(@$attr['devmin'])); rlm@3: $prefix = trim(@$attr['prefix']); rlm@3: rlm@3: // EOF Found rlm@3: if (($checksum == 256) && ($chksum == 0)) { rlm@3: break; rlm@3: } rlm@3: rlm@3: // Check if filename if 7bit as spec requires rlm@3: if (!$already_warned) { rlm@3: for ($i = 0; $i < strlen($name); $i++) { rlm@3: if ($name{$i} < chr(32) || $name{$i} > chr(127)) { rlm@3: $this->getid3->warning('Some filenames contains extended characters, which breaks the tar specifation. This is not uncommon, but you will have to handle the character encoding for filenames yourself.'); rlm@3: $already_warned = true; rlm@3: break; rlm@3: } rlm@3: } rlm@3: } rlm@3: rlm@3: if ($prefix) { rlm@3: $name = $prefix.'/'.$name; rlm@3: } rlm@3: if ((preg_match('#/$#', $name)) && !$name) { rlm@3: $typeflag = 5; rlm@3: } rlm@3: rlm@3: // If it's the end of the tar-file... rlm@3: if ($buffer == $null_512k) { rlm@3: break; rlm@3: } rlm@3: rlm@3: // Protect against tar-files with garbage at the end rlm@3: if ($name == '') { rlm@3: break; rlm@3: } rlm@3: rlm@3: $info['tar']['file_details'][$name] = array ( rlm@3: 'name' => $name, rlm@3: 'mode_raw' => $mode, rlm@3: 'mode' => getid3_tar::display_perms($mode), rlm@3: 'uid' => $uid, rlm@3: 'gid' => $gid, rlm@3: 'size' => $size, rlm@3: 'mtime' => $mtime, rlm@3: 'chksum' => $chksum, rlm@3: 'typeflag' => getid3_tar::get_flag_type($typflag), rlm@3: 'linkname' => $lnkname, rlm@3: 'magic' => $magic, rlm@3: 'version' => $ver, rlm@3: 'uname' => $uname, rlm@3: 'gname' => $gname, rlm@3: 'devmajor' => $devmaj, rlm@3: 'devminor' => $devmin rlm@3: ); rlm@3: rlm@3: // Skip the next chunk rlm@3: fseek($fp, $size, SEEK_CUR); rlm@3: rlm@3: // Throw away padding rlm@3: if ($size % 512) { rlm@3: fseek($fp, 512 - $diff, SEEK_CUR); rlm@3: } rlm@3: rlm@3: } rlm@3: return true; rlm@3: } rlm@3: rlm@3: rlm@3: // Parses the file mode to file permissions rlm@3: public static function display_perms($mode) { rlm@3: rlm@3: // Determine Type rlm@3: if ($mode & 0x1000) { rlm@3: $type='p'; // FIFO pipe rlm@3: } rlm@3: elseif ($mode & 0x2000) { rlm@3: $type='c'; // Character special rlm@3: } rlm@3: elseif ($mode & 0x4000) { rlm@3: $type='d'; // Directory rlm@3: } rlm@3: elseif ($mode & 0x6000) { rlm@3: $type='b'; // Block special rlm@3: } rlm@3: elseif ($mode & 0x8000) { rlm@3: $type='-'; // Regular rlm@3: } rlm@3: elseif ($mode & 0xA000) { rlm@3: $type='l'; // Symbolic Link rlm@3: } rlm@3: elseif ($mode & 0xC000) { rlm@3: $type='s'; // Socket rlm@3: } rlm@3: else { rlm@3: $type='u'; // UNKNOWN rlm@3: } rlm@3: rlm@3: // Determine permissions rlm@3: $owner['read'] = (($mode & 00400) ? 'r' : '-'); rlm@3: $owner['write'] = (($mode & 00200) ? 'w' : '-'); rlm@3: $owner['execute'] = (($mode & 00100) ? 'x' : '-'); rlm@3: $group['read'] = (($mode & 00040) ? 'r' : '-'); rlm@3: $group['write'] = (($mode & 00020) ? 'w' : '-'); rlm@3: $group['execute'] = (($mode & 00010) ? 'x' : '-'); rlm@3: $world['read'] = (($mode & 00004) ? 'r' : '-'); rlm@3: $world['write'] = (($mode & 00002) ? 'w' : '-'); rlm@3: $world['execute'] = (($mode & 00001) ? 'x' : '-'); rlm@3: rlm@3: // Adjust for SUID, SGID and sticky bit rlm@3: if ($mode & 0x800) { rlm@3: $owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S'; rlm@3: } rlm@3: if ($mode & 0x400) { rlm@3: $group['execute'] = ($group['execute'] == 'x') ? 's' : 'S'; rlm@3: } rlm@3: if ($mode & 0x200) { rlm@3: $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T'; rlm@3: } rlm@3: rlm@3: $s = sprintf('%1s', $type); rlm@3: $s .= sprintf('%1s%1s%1s', $owner['read'], $owner['write'], $owner['execute']); rlm@3: $s .= sprintf('%1s%1s%1s', $group['read'], $group['write'], $group['execute']); rlm@3: $s .= sprintf('%1s%1s%1s'."\n", $world['read'], $world['write'], $world['execute']); rlm@3: rlm@3: return $s; rlm@3: } rlm@3: rlm@3: rlm@3: // Converts the file type rlm@3: public static function get_flag_type($typflag) { rlm@3: rlm@3: static $flag_types = array ( rlm@3: '0' => 'LF_NORMAL', rlm@3: '1' => 'LF_LINK', rlm@3: '2' => 'LF_SYNLINK', rlm@3: '3' => 'LF_CHR', rlm@3: '4' => 'LF_BLK', rlm@3: '5' => 'LF_DIR', rlm@3: '6' => 'LF_FIFO', rlm@3: '7' => 'LF_CONFIG', rlm@3: 'D' => 'LF_DUMPDIR', rlm@3: 'K' => 'LF_LONGLINK', rlm@3: 'L' => 'LF_LONGNAME', rlm@3: 'M' => 'LF_MULTIVOL', rlm@3: 'N' => 'LF_NAMES', rlm@3: 'S' => 'LF_SPARSE', rlm@3: 'V' => 'LF_VOLHDR' rlm@3: ); rlm@3: rlm@3: return @$flag_types[$typflag]; rlm@3: } rlm@3: rlm@3: } rlm@3: rlm@3: ?>