File indexing completed on 2024-12-22 05:33:10

0001 <?php
0002 /////////////////////////////////////////////////////////////////
0003 /// getID3() by James Heinrich <info@getid3.org>               //
0004 //  available at http://getid3.sourceforge.net                 //
0005 //            or http://www.getid3.org                         //
0006 //          also https://github.com/JamesHeinrich/getID3       //
0007 /////////////////////////////////////////////////////////////////
0008 // See readme.txt for more details                             //
0009 /////////////////////////////////////////////////////////////////
0010 //                                                             //
0011 // module.archive.tar.php                                      //
0012 // module for analyzing TAR files                              //
0013 // dependencies: NONE                                          //
0014 //                                                            ///
0015 /////////////////////////////////////////////////////////////////
0016 //                                                             //
0017 // Module originally written by                                //
0018 //      Mike Mozolin <teddybearØmail*ru>                       //
0019 //                                                             //
0020 /////////////////////////////////////////////////////////////////
0021 
0022 
0023 class getid3_tar extends getid3_handler
0024 {
0025 
0026   public function Analyze() {
0027     $info = &$this->getid3->info;
0028 
0029     $info['fileformat'] = 'tar';
0030     $info['tar']['files'] = array();
0031 
0032     $unpack_header = 'a100fname/a8mode/a8uid/a8gid/a12size/a12mtime/a8chksum/a1typflag/a100lnkname/a6magic/a2ver/a32uname/a32gname/a8devmaj/a8devmin/a155prefix';
0033     $null_512k = str_repeat("\x00", 512); // end-of-file marker
0034 
0035     $this->fseek(0);
0036     while (!feof($this->getid3->fp)) {
0037       $buffer = $this->fread(512);
0038       if (strlen($buffer) < 512) {
0039         break;
0040       }
0041 
0042       // check the block
0043       $checksum = 0;
0044       for ($i = 0; $i < 148; $i++) {
0045         $checksum += ord($buffer{$i});
0046       }
0047       for ($i = 148; $i < 156; $i++) {
0048         $checksum += ord(' ');
0049       }
0050       for ($i = 156; $i < 512; $i++) {
0051         $checksum += ord($buffer{$i});
0052       }
0053       $attr    = unpack($unpack_header, $buffer);
0054       $name    =       (isset($attr['fname']  ) ? trim($attr['fname']  ) : '');
0055       $mode    = octdec(isset($attr['mode']   ) ? trim($attr['mode']   ) : '');
0056       $uid     = octdec(isset($attr['uid']    ) ? trim($attr['uid']    ) : '');
0057       $gid     = octdec(isset($attr['gid']    ) ? trim($attr['gid']    ) : '');
0058       $size    = octdec(isset($attr['size']   ) ? trim($attr['size']   ) : '');
0059       $mtime   = octdec(isset($attr['mtime']  ) ? trim($attr['mtime']  ) : '');
0060       $chksum  = octdec(isset($attr['chksum'] ) ? trim($attr['chksum'] ) : '');
0061       $typflag =       (isset($attr['typflag']) ? trim($attr['typflag']) : '');
0062       $lnkname =       (isset($attr['lnkname']) ? trim($attr['lnkname']) : '');
0063       $magic   =       (isset($attr['magic']  ) ? trim($attr['magic']  ) : '');
0064       $ver     =       (isset($attr['ver']    ) ? trim($attr['ver']    ) : '');
0065       $uname   =       (isset($attr['uname']  ) ? trim($attr['uname']  ) : '');
0066       $gname   =       (isset($attr['gname']  ) ? trim($attr['gname']  ) : '');
0067       $devmaj  = octdec(isset($attr['devmaj'] ) ? trim($attr['devmaj'] ) : '');
0068       $devmin  = octdec(isset($attr['devmin'] ) ? trim($attr['devmin'] ) : '');
0069       $prefix  =       (isset($attr['prefix'] ) ? trim($attr['prefix'] ) : '');
0070       if (($checksum == 256) && ($chksum == 0)) {
0071         // EOF Found
0072         break;
0073       }
0074       if ($prefix) {
0075         $name = $prefix.'/'.$name;
0076       }
0077       if ((preg_match('#/$#', $name)) && !$name) {
0078         $typeflag = 5;
0079       }
0080       if ($buffer == $null_512k) {
0081         // it's the end of the tar-file...
0082         break;
0083       }
0084 
0085       // Read to the next chunk
0086       $this->fseek($size, SEEK_CUR);
0087 
0088       $diff = $size % 512;
0089       if ($diff != 0) {
0090         // Padding, throw away
0091         $this->fseek((512 - $diff), SEEK_CUR);
0092       }
0093       // Protect against tar-files with garbage at the end
0094       if ($name == '') {
0095         break;
0096       }
0097       $info['tar']['file_details'][$name] = array (
0098         'name'     => $name,
0099         'mode_raw' => $mode,
0100         'mode'     => self::display_perms($mode),
0101         'uid'      => $uid,
0102         'gid'      => $gid,
0103         'size'     => $size,
0104         'mtime'    => $mtime,
0105         'chksum'   => $chksum,
0106         'typeflag' => self::get_flag_type($typflag),
0107         'linkname' => $lnkname,
0108         'magic'    => $magic,
0109         'version'  => $ver,
0110         'uname'    => $uname,
0111         'gname'    => $gname,
0112         'devmajor' => $devmaj,
0113         'devminor' => $devmin
0114       );
0115       $info['tar']['files'] = getid3_lib::array_merge_clobber($info['tar']['files'], getid3_lib::CreateDeepArray($info['tar']['file_details'][$name]['name'], '/', $size));
0116     }
0117     return true;
0118   }
0119 
0120   // Parses the file mode to file permissions
0121   public function display_perms($mode) {
0122     // Determine Type
0123     if     ($mode & 0x1000) $type='p'; // FIFO pipe
0124     elseif ($mode & 0x2000) $type='c'; // Character special
0125     elseif ($mode & 0x4000) $type='d'; // Directory
0126     elseif ($mode & 0x6000) $type='b'; // Block special
0127     elseif ($mode & 0x8000) $type='-'; // Regular
0128     elseif ($mode & 0xA000) $type='l'; // Symbolic Link
0129     elseif ($mode & 0xC000) $type='s'; // Socket
0130     else                    $type='u'; // UNKNOWN
0131 
0132     // Determine permissions
0133     $owner['read']    = (($mode & 00400) ? 'r' : '-');
0134     $owner['write']   = (($mode & 00200) ? 'w' : '-');
0135     $owner['execute'] = (($mode & 00100) ? 'x' : '-');
0136     $group['read']    = (($mode & 00040) ? 'r' : '-');
0137     $group['write']   = (($mode & 00020) ? 'w' : '-');
0138     $group['execute'] = (($mode & 00010) ? 'x' : '-');
0139     $world['read']    = (($mode & 00004) ? 'r' : '-');
0140     $world['write']   = (($mode & 00002) ? 'w' : '-');
0141     $world['execute'] = (($mode & 00001) ? 'x' : '-');
0142 
0143     // Adjust for SUID, SGID and sticky bit
0144     if ($mode & 0x800) $owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S';
0145     if ($mode & 0x400) $group['execute'] = ($group['execute'] == 'x') ? 's' : 'S';
0146     if ($mode & 0x200) $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T';
0147 
0148     $s  = sprintf('%1s', $type);
0149     $s .= sprintf('%1s%1s%1s',      $owner['read'], $owner['write'], $owner['execute']);
0150     $s .= sprintf('%1s%1s%1s',      $group['read'], $group['write'], $group['execute']);
0151     $s .= sprintf('%1s%1s%1s'."\n", $world['read'], $world['write'], $world['execute']);
0152     return $s;
0153   }
0154 
0155   // Converts the file type
0156   public function get_flag_type($typflag) {
0157     static $flag_types = array(
0158       '0' => 'LF_NORMAL',
0159       '1' => 'LF_LINK',
0160       '2' => 'LF_SYNLINK',
0161       '3' => 'LF_CHR',
0162       '4' => 'LF_BLK',
0163       '5' => 'LF_DIR',
0164       '6' => 'LF_FIFO',
0165       '7' => 'LF_CONFIG',
0166       'D' => 'LF_DUMPDIR',
0167       'K' => 'LF_LONGLINK',
0168       'L' => 'LF_LONGNAME',
0169       'M' => 'LF_MULTIVOL',
0170       'N' => 'LF_NAMES',
0171       'S' => 'LF_SPARSE',
0172       'V' => 'LF_VOLHDR'
0173     );
0174     return (isset($flag_types[$typflag]) ? $flag_types[$typflag] : '');
0175   }
0176 
0177 }