All pastes #744648 Raw Edit

Stuff

public text v1 · immutable
·published 2007-10-21 17:55 UTC
rendered paste body
<?php

class Tar
{	
	public function unpack($tar_file, $destination_dir, $verbose = false)
	{
		$tar_file = str_replace('\\', '/', $tar_file);
		$destination_dir = str_replace('\\', '/', $destination_dir);

		if((!is_dir($destination_dir)) && (!mkdir($destination_dir))) {
			throw new Exception("{$destination_dir} is not a directory and can not be made!");
		}
		
		if($verbose) echo "<h2>Unpacking <em>{$tar_file}</em> to <em>{$destination_dir}</em></h2>\n";
		
		$files = $this->read($tar_file);
		
		foreach($files as $file) {
			$destination_file = $destination_dir . $file['name'];
			
			$file_directory = dirname($destination_file);
			if(!is_dir($file_directory)) {
				if($verbose) echo "<p><strong>creating directory:</strong> <em>{$file_directory}</em></p>\n";
				mkdir($file_directory, 0777, true);
			}
			
			if($verbose) echo "<p><strong>unpacking:</strong> <em>{$file['name']}</em> to <em>{$destination_file}</em></p>\n";
			
			flush();
				
			$fh = fopen($destination_file, 'w');
			fwrite($fh, $file['raw'], $file['size']);
			fclose($fh);
		}
		
		if($verbose) echo "<h3>done!</h3>";
	}
	
	public function read($tar_file)
	{
		if(!file_exists($tar_file)) {
			throw new Exception("{$tar_file} does not exist!");
		}
		
		if(!$file = fopen($tar_file, 'rb')) {
			throw new Exception("{$tar_file} can not be read!");
		}
		
		$header = 'a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8chksum/a1typeflag/a100linkname/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix';
		$files = array();
		        
        while(!feof($file)) {
        	$buffer = fread($file, 512);
        	$checksum = 0;
        	
			for($i = 0; $i < 148; $i++) {
				$checksum += ord(substr($buffer, $i, 1));
			}
			for($i = 148; $i < 156; $i++) {
				$checksum += 32;
			}
			for ($i = 156; $i < 512; $i++) {
				$checksum += ord(substr($buffer, $i, 1));
			}
						
			$file_info = unpack($header, $buffer);			
			$octal_values = array('mode', 'uid', 'gid', 'size', 'mtime', 'chksum', 'devmajor', 'devminor');
			
			$file_info = array_map('trim', $file_info);
			
			foreach($file_info as $key => $value) {
				if(in_array($key, $octal_values)) {
					$file_info[$key] = octdec($file_info[$key]);
				}
			}
			
			$file_info['name'] = ($file_info['prefix']) ? "{$file_info['prefix']}/{$file_info['name']}" : substr($file_info['name'], 2);
			$file_info['typeflag'] = (substr($file_info['name'], -1, 1) == '/') ? 5 : $file_info['typeflag'] ;
          
            if(($buffer == str_repeat('\0', 512)) || ($file_info['name'] == null) || (($file_info['chksum'] == 0) && ($checksum == 256))) {
            	break;
            }
            
            if($file_info['size'] > 0) {
	            $file_info['raw'] = fread($file, $file_info['size']);
	            
	            if(strlen($file_info['raw']) != $file_info['size']) {
	            	throw new Exception("Oh noes, {$file_info['name']} raw data does not match the reported file size of {$file_info['size']}!");
	            }
            }
            
            $diffrence = $file_info['size'] % 512;
            
            if($diffrence != 0) {
            	fread($file, 512 - $diffrence);
            }
                     
            array_push($files, $file_info);
        }
        
        fclose($file);
        
		return $files;
	}
}

$install_dir = dirname(__FILE__) . '/test/';
$tar_file = $install_dir . 'install.tar';

$tar = new Tar();

try {
	$tar->unpack($tar_file, $install_dir, true);
} catch(Exception $e) {
	echo 'error: ' . $e->getMessage();
}

?>