<? 
/**------------------------------------------------- 
 | EasyTar.class V0.8 -  by Alban LOPEZ 
 | Copyright (c) 2007 Alban LOPEZ 
 | Email bugs/suggestions to [email protected] 
 +-------------------------------------------------- 
 | This file is part of EasyArchive.class V0.9. 
 | EasyArchive is free software: you can redistribute it and/or modify 
 | it under the terms of the GNU General Public License as published by 
 | the Free Software Foundation, either version 3 of the License, or 
 | (at your option) any later version. 
 | EasyArchive is distributed in the hope that it will be useful, 
 | but WITHOUT ANY WARRANTY; without even the implied warranty of 
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 | See the GNU General Public License for more details on http://www.gnu.org/licenses/ 
 +-------------------------------------------------- 
 http://www.phpclasses.org/browse/package/4239.html **/ 
class tar 
{ /* http://www.mkssoftware.com/docs/man4/tar.4.asp */ 
/** 
// You can use this class like that. 
$test = new tar; 
$test->makeTar('./','./toto.Tar'); 
var_export($test->infosTar('./toto.Tar')); 
$test->extractTar('./toto.Tar', './new/'); 
**/ 
    function infosTar ($src, $data=true) 
    { 
        if ($this->is_tar($src)) 
        { 
            file_put_contents ($tmp='~tmp('.microtime().').tar', $src); 
            $src = $tmp; 
        } 
        $ptr = fopen($src, 'r'); 
        while (!feof($ptr)) 
        { 
            $infos = $this->readTarHeader ($ptr); 
            if ($infos['name']) 
            { 
                if (!$data) unset($infos['data']); 
                $result[$infos['name']]=$infos; 
            } 
        } 
        if (is_file($tmp)) unlink($tmp); 
        return $result; 
    } 
    function makeTar($src, $dest=false) 
    { 
        $src = is_array($src) ? $src : array($src); 
        $src = array_map('realpath', $src); 
        foreach ($src as $item) 
            $Tar .= $this->addTarItem($item.((is_dir($item) && substr($item, -1)!='/')?'/':''), dirname($item).'/'); 
         
        $Tar = str_pad($Tar, floor((strlen($Tar) + 10240 - 1) / 10240) * 10240, "\0"); 
        if (empty($dest)) return $Tar; 
        elseif (file_put_contents($dest, $Tar)) return $dest; 
        else false; 
    } 
    function extractTar ($src, $dest) 
    { 
        if ($this->is_tar($src)) 
        { 
            file_put_contents ($tmp='~tmp('.microtime().').tar', $src); 
            $src = $tmp; 
        } 
        $ptr = fopen($src, 'r'); 
        while (!feof($ptr)) 
        { 
            $infos = $this->readTarHeader ($ptr); 
            if ($infos['type']=='5' && @mkdir($dest.$infos['name'], 0775, true)) 
                $result[]=$dest.$infos['name']; 
            elseif (($infos['type']=='0' || $infos['type']==chr(0)) && file_put_contents($dest.$infos['name'], $infos['data'])) 
                $result[]=$dest.$infos['name']; 
            if ($infos) 
                chmod($dest.$infos['name'], 0775); 
//                 chmod(, $infos['mode']); 
//                 chgrp(, $infos['uname']); 
//                 chown(, $infos['gname']); 
        } 
        if (is_file($tmp)) unlink($tmp); 
        return $result; 
    } 
    function is_tar($str) 
    { 
        $block = substr($str,0, 512); 
        if (strlen($block)!=512) return false; 
        $realchecksum = octdec(substr($str,148,8)); 
        $checksum = 0; 
        $block = substr_replace($block, '        ', 148, 8); 
        for ($i = 0; $i < 512; $i++) 
            $checksum += ord(substr($block, $i, 1)); 
        if ($realchecksum==$checksum) return true; 
        return false; 
    } 
    function tarHeader512($infos) 
    { /* http://www.mkssoftware.com/docs/man4/tar.4.asp */ 
        $bigheader = $header = ''; 
        if (strlen($infos['name100'])>100) 
        { 
            $bigheader = pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155a12", 
                '././@LongLink','0000000','0000000','0000000', 
                sprintf("%011o", strlen($infos['name100'])),'00000000000', 
                '        ', 'L', '', 'ustar ', '0', 
                $infos['userName32'], 
                $infos['groupName32'],'','','',''); 
 
            $bigheader .= str_pad($infos['name100'], floor((strlen($infos['name100']) + 512 - 1) / 512) * 512, "\0"); 
 
            $checksum = 0; 
            for ($i = 0; $i < 512; $i++) 
                $checksum += ord(substr($bigheader, $i, 1)); 
            $bigheader = substr_replace($bigheader, sprintf("%06o", $checksum)."\0 ", 148, 8); 
        } 
        $header = pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155a12", // book the memorie area 
            substr($infos['name100'],0,100),        //  0     100     File name 
            str_pad(substr(sprintf("%07o",$infos['mode8']),-4), 7, '0', STR_PAD_LEFT),        // 100     8         File mode 
            sprintf("%07o", $infos['uid8']),        // 108     8         Owner user ID 
            sprintf("%07o", $infos['gid8']),        // 116     8         Group user ID 
            sprintf("%011o", $infos['size12']),        // 124     12         File size in bytes 
            sprintf("%011o", $infos['mtime12']),    // 136     12         Last modification time 
            '        ',                                // 148     8         Check sum for header block 
            $infos['link1'],                        // 156     1         Link indicator / ustar Type flag 
            $infos['link100'],                        // 157     100     Name of linked file 
            'ustar ',                                // 257     6         USTAR indicator "ustar" 
            ' ',                                    // 263     2         USTAR version "00" 
            $infos['userName32'],                // 265     32         Owner user name 
            $infos['groupName32'],                // 297     32         Owner group name 
            '',                                    // 329     8         Device major number 
            '',                                    // 337     8         Device minor number 
            $infos['prefix155'],                    // 345     155     Filename prefix 
            '');                                    // 500     12         ?? 
 
        $checksum = 0; 
        for ($i = 0; $i < 512; $i++) 
            $checksum += ord(substr($header, $i, 1)); 
        $header = substr_replace($header, sprintf("%06o", $checksum)."\0 ", 148, 8); 
 
        return $bigheader.$header; 
    } 
    function addTarItem ($item, $racine) 
    { 
        $infos['name100'] = str_replace($racine, '', $item); 
        list (, , $infos['mode8'], , $infos['uid8'], $infos['gid8'], , , , $infos['mtime12'] ) = stat($item); 
        $infos['size12'] = is_dir($item) ? 0 : filesize($item); 
        $infos['link1'] = is_link($item) ? 2 : is_dir ($item) ? 5 : 0; 
        $infos['link100'] == 2 ? readlink($item) : ""; 
 
            $a=function_exists('posix_getpwuid')?posix_getpwuid (fileowner($item)):array('name'=>'Unknown'); 
        $infos['userName32'] = $a['name']; 
 
            $a=function_exists('posix_getgrgid')?posix_getgrgid (filegroup($item)):array('name'=>'Unknown'); 
        $infos['groupName32'] = $a['name']; 
        $infos['prefix155'] = ''; 
 
        $header = $this->tarHeader512($infos); 
        $data = str_pad(file_get_contents($item), floor(($infos['size12'] + 512 - 1) / 512) * 512, "\0"); 
        if (is_dir($item)) 
        { 
            $lst = scandir($item); 
            array_shift($lst); // remove  ./  of $lst 
            array_shift($lst); // remove ../  of $lst 
            foreach ($lst as $subitem) 
                $sub .= $this->addTarItem($item.$subitem.(is_dir($item.$subitem)?'/':''), $racine); 
        } 
        return $header.$data.$sub; 
    } 
    function readTarHeader ($ptr) 
    { 
        $block = fread($ptr, 512); 
        if (strlen($block)!=512) return false; 
        $hdr = unpack ("a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12temp", $block); 
            $hdr['mode']=$hdr['mode']+0; 
            $hdr['uid']=octdec($hdr['uid']); 
            $hdr['gid']=octdec($hdr['gid']); 
            $hdr['size']=octdec($hdr['size']); 
            $hdr['mtime']=octdec($hdr['mtime']); 
            $hdr['checksum']=octdec($hdr['checksum']); 
        $checksum = 0; 
        $block = substr_replace($block, '        ', 148, 8); 
        for ($i = 0; $i < 512; $i++) 
            $checksum += ord(substr($block, $i, 1)); 
        if (isset($hdr['name']) && $hdr['checksum']==$checksum) 
        { 
            if ($hdr['name']=='././@LongLink' && $hdr['type']=='L') 
            { 
                $realName = substr(fread($ptr, floor(($hdr['size'] + 512 - 1) / 512) * 512), 0, $hdr['size']-1); 
                $hdr2 = $this->readTarHeader ($ptr); 
                $hdr2['name'] = $realName; 
                return $hdr2; 
            } 
            elseif (strtolower(substr($hdr['magic'], 0, 5) == 'ustar')) 
            { 
                if ($hdr['size']>0) 
                    $hdr['data'] = substr(fread($ptr, floor(($hdr['size'] + 512 - 1) / 512) * 512), 0, $hdr['size']); 
                else $hdr['data'] = ''; 
                return $hdr; 
            } 
            else return false; 
        } 
        else return false; 
    } 
} 
?>
 
 |