1<?php 2 3///////////////////////////////////////////////////////////////// 4/// getID3() by James Heinrich <info@getid3.org> // 5// available at https://github.com/JamesHeinrich/getID3 // 6// or https://www.getid3.org // 7// or http://getid3.sourceforge.net // 8// see readme.txt for more details // 9///////////////////////////////////////////////////////////////// 10// // 11// module.archive.tar.php // 12// module for analyzing TAR files // 13// dependencies: NONE // 14// /// 15///////////////////////////////////////////////////////////////// 16// // 17// Module originally written by // 18// Mike Mozolin <teddybearØmail*ru> // 19// // 20///////////////////////////////////////////////////////////////// 21 22if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers 23 exit; 24} 25 26class getid3_tar extends getid3_handler 27{ 28 /** 29 * @return bool 30 */ 31 public function Analyze() { 32 $info = &$this->getid3->info; 33 34 $info['fileformat'] = 'tar'; 35 $info['tar']['files'] = array(); 36 37 $unpack_header = 'a100fname/a8mode/a8uid/a8gid/a12size/a12mtime/a8chksum/a1typflag/a100lnkname/a6magic/a2ver/a32uname/a32gname/a8devmaj/a8devmin/a155prefix'; 38 $null_512k = str_repeat("\x00", 512); // end-of-file marker 39 40 $this->fseek(0); 41 while (!feof($this->getid3->fp)) { 42 $buffer = $this->fread(512); 43 if (strlen($buffer) < 512) { 44 break; 45 } 46 47 // check the block 48 $checksum = 0; 49 for ($i = 0; $i < 148; $i++) { 50 $checksum += ord($buffer[$i]); 51 } 52 for ($i = 148; $i < 156; $i++) { 53 $checksum += ord(' '); 54 } 55 for ($i = 156; $i < 512; $i++) { 56 $checksum += ord($buffer[$i]); 57 } 58 $attr = unpack($unpack_header, $buffer); 59 $name = (isset($attr['fname'] ) ? trim($attr['fname'] ) : ''); 60 $mode = octdec(isset($attr['mode'] ) ? trim($attr['mode'] ) : ''); 61 $uid = octdec(isset($attr['uid'] ) ? trim($attr['uid'] ) : ''); 62 $gid = octdec(isset($attr['gid'] ) ? trim($attr['gid'] ) : ''); 63 $size = octdec(isset($attr['size'] ) ? trim($attr['size'] ) : ''); 64 $mtime = octdec(isset($attr['mtime'] ) ? trim($attr['mtime'] ) : ''); 65 $chksum = octdec(isset($attr['chksum'] ) ? trim($attr['chksum'] ) : ''); 66 $typflag = (isset($attr['typflag']) ? trim($attr['typflag']) : ''); 67 $lnkname = (isset($attr['lnkname']) ? trim($attr['lnkname']) : ''); 68 $magic = (isset($attr['magic'] ) ? trim($attr['magic'] ) : ''); 69 $ver = (isset($attr['ver'] ) ? trim($attr['ver'] ) : ''); 70 $uname = (isset($attr['uname'] ) ? trim($attr['uname'] ) : ''); 71 $gname = (isset($attr['gname'] ) ? trim($attr['gname'] ) : ''); 72 $devmaj = octdec(isset($attr['devmaj'] ) ? trim($attr['devmaj'] ) : ''); 73 $devmin = octdec(isset($attr['devmin'] ) ? trim($attr['devmin'] ) : ''); 74 $prefix = (isset($attr['prefix'] ) ? trim($attr['prefix'] ) : ''); 75 if (($checksum == 256) && ($chksum == 0)) { 76 // EOF Found 77 break; 78 } 79 if ($prefix) { 80 $name = $prefix.'/'.$name; 81 } 82 if ((preg_match('#/$#', $name)) && !$name) { 83 $typeflag = 5; 84 } 85 if ($buffer == $null_512k) { 86 // it's the end of the tar-file... 87 break; 88 } 89 90 // Read to the next chunk 91 $this->fseek($size, SEEK_CUR); 92 93 $diff = $size % 512; 94 if ($diff != 0) { 95 // Padding, throw away 96 $this->fseek((512 - $diff), SEEK_CUR); 97 } 98 // Protect against tar-files with garbage at the end 99 if ($name == '') { 100 break; 101 } 102 $info['tar']['file_details'][$name] = array ( 103 'name' => $name, 104 'mode_raw' => $mode, 105 'mode' => self::display_perms($mode), 106 'uid' => $uid, 107 'gid' => $gid, 108 'size' => $size, 109 'mtime' => $mtime, 110 'chksum' => $chksum, 111 'typeflag' => self::get_flag_type($typflag), 112 'linkname' => $lnkname, 113 'magic' => $magic, 114 'version' => $ver, 115 'uname' => $uname, 116 'gname' => $gname, 117 'devmajor' => $devmaj, 118 'devminor' => $devmin 119 ); 120 $info['tar']['files'] = getid3_lib::array_merge_clobber($info['tar']['files'], getid3_lib::CreateDeepArray($info['tar']['file_details'][$name]['name'], '/', $size)); 121 } 122 return true; 123 } 124 125 /** 126 * Parses the file mode to file permissions. 127 * 128 * @param int $mode 129 * 130 * @return string 131 */ 132 public function display_perms($mode) { 133 // Determine Type 134 if ($mode & 0x1000) $type='p'; // FIFO pipe 135 elseif ($mode & 0x2000) $type='c'; // Character special 136 elseif ($mode & 0x4000) $type='d'; // Directory 137 elseif ($mode & 0x6000) $type='b'; // Block special 138 elseif ($mode & 0x8000) $type='-'; // Regular 139 elseif ($mode & 0xA000) $type='l'; // Symbolic Link 140 elseif ($mode & 0xC000) $type='s'; // Socket 141 else $type='u'; // UNKNOWN 142 143 // Determine permissions 144 $owner['read'] = (($mode & 00400) ? 'r' : '-'); 145 $owner['write'] = (($mode & 00200) ? 'w' : '-'); 146 $owner['execute'] = (($mode & 00100) ? 'x' : '-'); 147 $group['read'] = (($mode & 00040) ? 'r' : '-'); 148 $group['write'] = (($mode & 00020) ? 'w' : '-'); 149 $group['execute'] = (($mode & 00010) ? 'x' : '-'); 150 $world['read'] = (($mode & 00004) ? 'r' : '-'); 151 $world['write'] = (($mode & 00002) ? 'w' : '-'); 152 $world['execute'] = (($mode & 00001) ? 'x' : '-'); 153 154 // Adjust for SUID, SGID and sticky bit 155 if ($mode & 0x800) $owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S'; 156 if ($mode & 0x400) $group['execute'] = ($group['execute'] == 'x') ? 's' : 'S'; 157 if ($mode & 0x200) $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T'; 158 159 $s = sprintf('%1s', $type); 160 $s .= sprintf('%1s%1s%1s', $owner['read'], $owner['write'], $owner['execute']); 161 $s .= sprintf('%1s%1s%1s', $group['read'], $group['write'], $group['execute']); 162 $s .= sprintf('%1s%1s%1s'."\n", $world['read'], $world['write'], $world['execute']); 163 return $s; 164 } 165 166 /** 167 * Converts the file type. 168 * 169 * @param string $typflag 170 * 171 * @return mixed|string 172 */ 173 public function get_flag_type($typflag) { 174 static $flag_types = array( 175 '0' => 'LF_NORMAL', 176 '1' => 'LF_LINK', 177 '2' => 'LF_SYNLINK', 178 '3' => 'LF_CHR', 179 '4' => 'LF_BLK', 180 '5' => 'LF_DIR', 181 '6' => 'LF_FIFO', 182 '7' => 'LF_CONFIG', 183 'D' => 'LF_DUMPDIR', 184 'K' => 'LF_LONGLINK', 185 'L' => 'LF_LONGNAME', 186 'M' => 'LF_MULTIVOL', 187 'N' => 'LF_NAMES', 188 'S' => 'LF_SPARSE', 189 'V' => 'LF_VOLHDR' 190 ); 191 return (isset($flag_types[$typflag]) ? $flag_types[$typflag] : ''); 192 } 193 194} 195