Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
524 lines (431 sloc) 17.3 KB
<?Php
die('FUCK THE SHIT OFF YEAH');
$counter = 0;
$x = 0;
$tar = new tar();
foreach (glob('img/*') as $image) {
$tar->addFile($image);
if ($counter > 200) {
++$x;
$tar->toTar('tars/img_'.$x.'.tar', false);
unset($tar);
$tar = new tar();
$counter = 0;
}
++$counter;
}
echo 'DONE!';
class tar
{
// Unprocessed Archive Information
public $filename;
public $isGzipped;
public $tar_file;
// Processed Archive Information
public $files;
public $directories;
public $numFiles;
public $numDirectories;
// Class Constructor -- Does nothing...
public function tar()
{
return true;
}
// Computes the unsigned Checksum of a file's header
// to try to ensure valid file
// PRIVATE ACCESS FUNCTION
public function __computeUnsignedChecksum($bytestring)
{
for ($i = 0; $i < 512; ++$i) {
$unsigned_chksum += ord($bytestring[$i]);
}
for ($i = 0; $i < 8; ++$i) {
$unsigned_chksum -= ord($bytestring[148 + $i]);
}
$unsigned_chksum += ord(' ') * 8;
return $unsigned_chksum;
}
// Converts a NULL padded string to a non-NULL padded string
// PRIVATE ACCESS FUNCTION
public function __parseNullPaddedString($string)
{
$position = strpos($string, chr(0));
return substr($string, 0, $position);
}
// This function parses the current TAR file
// PRIVATE ACCESS FUNCTION
public function __parseTar()
{
// Read Files from archive
$tar_length = strlen($this->tar_file);
$main_offset = 0;
while ($main_offset < $tar_length) {
// If we read a block of 512 nulls, we are at the end of the archive
if (substr($this->tar_file, $main_offset, 512) == str_repeat(chr(0), 512)) {
break;
}
// Parse file name
$file_name = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset, 100));
// Parse the file mode
$file_mode = substr($this->tar_file, $main_offset + 100, 8);
// Parse the file user ID
$file_uid = octdec(substr($this->tar_file, $main_offset + 108, 8));
// Parse the file group ID
$file_gid = octdec(substr($this->tar_file, $main_offset + 116, 8));
// Parse the file size
$file_size = octdec(substr($this->tar_file, $main_offset + 124, 12));
// Parse the file update time - unix timestamp format
$file_time = octdec(substr($this->tar_file, $main_offset + 136, 12));
// Parse Checksum
$file_chksum = octdec(substr($this->tar_file, $main_offset + 148, 6));
// Parse user name
$file_uname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 265, 32));
// Parse Group name
$file_gname = $this->__parseNullPaddedString(substr($this->tar_file, $main_offset + 297, 32));
// Make sure our file is valid
if ($this->__computeUnsignedChecksum(substr($this->tar_file, $main_offset, 512)) != $file_chksum) {
return false;
}
// Parse File Contents
$file_contents = substr($this->tar_file, $main_offset + 512, $file_size);
/* ### Unused Header Information ###
$activeFile["typeflag"] = substr($this->tar_file,$main_offset + 156,1);
$activeFile["linkname"] = substr($this->tar_file,$main_offset + 157,100);
$activeFile["magic"] = substr($this->tar_file,$main_offset + 257,6);
$activeFile["version"] = substr($this->tar_file,$main_offset + 263,2);
$activeFile["devmajor"] = substr($this->tar_file,$main_offset + 329,8);
$activeFile["devminor"] = substr($this->tar_file,$main_offset + 337,8);
$activeFile["prefix"] = substr($this->tar_file,$main_offset + 345,155);
$activeFile["endheader"] = substr($this->tar_file,$main_offset + 500,12);
*/
if ($file_size > 0) {
// Increment number of files
++$this->numFiles;
// Create us a new file in our array
$activeFile = &$this->files[];
// Asign Values
$activeFile['name'] = $file_name;
$activeFile['mode'] = $file_mode;
$activeFile['size'] = $file_size;
$activeFile['time'] = $file_time;
$activeFile['user_id'] = $file_uid;
$activeFile['group_id'] = $file_gid;
$activeFile['user_name'] = $file_uname;
$activeFile['group_name'] = $file_gname;
$activeFile['checksum'] = $file_chksum;
$activeFile['file'] = $file_contents;
} else {
// Increment number of directories
++$this->numDirectories;
// Create a new directory in our array
$activeDir = &$this->directories[];
// Assign values
$activeDir['name'] = $file_name;
$activeDir['mode'] = $file_mode;
$activeDir['time'] = $file_time;
$activeDir['user_id'] = $file_uid;
$activeDir['group_id'] = $file_gid;
$activeDir['user_name'] = $file_uname;
$activeDir['group_name'] = $file_gname;
$activeDir['checksum'] = $file_chksum;
}
// Move our offset the number of blocks we have processed
$main_offset += 512 + (ceil($file_size / 512) * 512);
}
return true;
}
// Read a non gzipped tar file in for processing
// PRIVATE ACCESS FUNCTION
public function __readTar($filename = '')
{
// Set the filename to load
if (!$filename) {
$filename = $this->filename;
}
// Read in the TAR file
$fp = fopen($filename, 'rb');
$this->tar_file = fread($fp, filesize($filename));
fclose($fp);
if ($this->tar_file[0] == chr(31) && $this->tar_file[1] == chr(139) && $this->tar_file[2] == chr(8)) {
if (!function_exists('gzinflate')) {
return false;
}
$this->isGzipped = true;
$this->tar_file = gzinflate(substr($this->tar_file, 10, -4));
}
// Parse the TAR file
$this->__parseTar();
return true;
}
// Generates a TAR file from the processed data
// PRIVATE ACCESS FUNCTION
public function __generateTAR()
{
// Clear any data currently in $this->tar_file
unset($this->tar_file);
// Generate Records for each directory, if we have directories
if ($this->numDirectories > 0) {
foreach ($this->directories as $key => $information) {
unset($header);
// Generate tar header for this directory
// Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
$header .= str_pad($information['name'], 100, chr(0));
$header .= str_pad(decoct($information['mode']), 7, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['user_id']), 7, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['group_id']), 7, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct(0), 11, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['time']), 11, '0', STR_PAD_LEFT).chr(0);
$header .= str_repeat(' ', 8);
$header .= '5';
$header .= str_repeat(chr(0), 100);
$header .= str_pad('ustar', 6, chr(32));
$header .= chr(32).chr(0);
$header .= str_pad('', 32, chr(0));
$header .= str_pad('', 32, chr(0));
$header .= str_repeat(chr(0), 8);
$header .= str_repeat(chr(0), 8);
$header .= str_repeat(chr(0), 155);
$header .= str_repeat(chr(0), 12);
// Compute header checksum
$checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, '0', STR_PAD_LEFT);
for ($i = 0; $i < 6; ++$i) {
$header[(148 + $i)] = substr($checksum, $i, 1);
}
$header[154] = chr(0);
$header[155] = chr(32);
// Add new tar formatted data to tar file contents
$this->tar_file .= $header;
}
}
// Generate Records for each file, if we have files (We should...)
if ($this->numFiles > 0) {
foreach ($this->files as $key => $information) {
unset($header);
// Generate the TAR header for this file
// Filename, Permissions, UID, GID, size, Time, checksum, typeflag, linkname, magic, version, user name, group name, devmajor, devminor, prefix, end
$header .= str_pad($information['name'], 100, chr(0));
$header .= str_pad(decoct($information['mode']), 7, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['user_id']), 7, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['group_id']), 7, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['size']), 11, '0', STR_PAD_LEFT).chr(0);
$header .= str_pad(decoct($information['time']), 11, '0', STR_PAD_LEFT).chr(0);
$header .= str_repeat(' ', 8);
$header .= '0';
$header .= str_repeat(chr(0), 100);
$header .= str_pad('ustar', 6, chr(32));
$header .= chr(32).chr(0);
$header .= str_pad($information['user_name'], 32, chr(0)); // How do I get a file's user name from PHP?
$header .= str_pad($information['group_name'], 32, chr(0)); // How do I get a file's group name from PHP?
$header .= str_repeat(chr(0), 8);
$header .= str_repeat(chr(0), 8);
$header .= str_repeat(chr(0), 155);
$header .= str_repeat(chr(0), 12);
// Compute header checksum
$checksum = str_pad(decoct($this->__computeUnsignedChecksum($header)), 6, '0', STR_PAD_LEFT);
for ($i = 0; $i < 6; ++$i) {
$header[(148 + $i)] = substr($checksum, $i, 1);
}
$header[154] = chr(0);
$header[155] = chr(32);
// Pad file contents to byte count divisible by 512
$file_contents = str_pad($information['file'], (ceil($information['size'] / 512) * 512), chr(0));
// Add new tar formatted data to tar file contents
$this->tar_file .= $header.$file_contents;
}
}
// Add 512 bytes of NULLs to designate EOF
$this->tar_file .= str_repeat(chr(0), 512);
return true;
}
// Open a TAR file
public function openTAR($filename)
{
// Clear any values from previous tar archives
unset($this->filename);
unset($this->isGzipped);
unset($this->tar_file);
unset($this->files);
unset($this->directories);
unset($this->numFiles);
unset($this->numDirectories);
// If the tar file doesn't exist...
if (!file_exists($filename)) {
return false;
}
$this->filename = $filename;
// Parse this file
$this->__readTar();
return true;
}
// Appends a tar file to the end of the currently opened tar file
public function appendTar($filename)
{
// If the tar file doesn't exist...
if (!file_exists($filename)) {
return false;
}
$this->__readTar($filename);
return true;
}
// Retrieves information about a file in the current tar archive
public function getFile($filename)
{
if ($this->numFiles > 0) {
foreach ($this->files as $key => $information) {
if ($information['name'] == $filename) {
return $information;
}
}
}
return false;
}
// Retrieves information about a directory in the current tar archive
public function getDirectory($dirname)
{
if ($this->numDirectories > 0) {
foreach ($this->directories as $key => $information) {
if ($information['name'] == $dirname) {
return $information;
}
}
}
return false;
}
// Check if this tar archive contains a specific file
public function containsFile($filename)
{
if ($this->numFiles > 0) {
foreach ($this->files as $key => $information) {
if ($information['name'] == $filename) {
return true;
}
}
}
return false;
}
// Check if this tar archive contains a specific directory
public function containsDirectory($dirname)
{
if ($this->numDirectories > 0) {
foreach ($this->directories as $key => $information) {
if ($information['name'] == $dirname) {
return true;
}
}
}
return false;
}
// Add a directory to this tar archive
public function addDirectory($dirname)
{
if (!file_exists($dirname)) {
return false;
}
// Get directory information
$file_information = stat($dirname);
// Add directory to processed data
++$this->numDirectories;
$activeDir = &$this->directories[];
$activeDir['name'] = $dirname;
$activeDir['mode'] = $file_information['mode'];
$activeDir['time'] = $file_information['time'];
$activeDir['user_id'] = $file_information['uid'];
$activeDir['group_id'] = $file_information['gid'];
$activeDir['checksum'] = $checksum;
return true;
}
// Add a file to the tar archive
public function addFile($filename)
{
// Make sure the file we are adding exists!
if (!file_exists($filename)) {
return false;
}
// Make sure there are no other files in the archive that have this same filename
if ($this->containsFile($filename)) {
return false;
}
// Get file information
$file_information = stat($filename);
// Read in the file's contents
$fp = fopen($filename, 'rb');
$file_contents = fread($fp, filesize($filename));
fclose($fp);
// Add file to processed data
++$this->numFiles;
$activeFile = &$this->files[];
$activeFile['name'] = $filename;
$activeFile['mode'] = $file_information['mode'];
$activeFile['user_id'] = $file_information['uid'];
$activeFile['group_id'] = $file_information['gid'];
$activeFile['size'] = $file_information['size'];
$activeFile['time'] = $file_information['mtime'];
$activeFile['checksum'] = $checksum;
$activeFile['user_name'] = '';
$activeFile['group_name'] = '';
$activeFile['file'] = $file_contents;
return true;
}
// Remove a file from the tar archive
public function removeFile($filename)
{
if ($this->numFiles > 0) {
foreach ($this->files as $key => $information) {
if ($information['name'] == $filename) {
--$this->numFiles;
unset($this->files[$key]);
return true;
}
}
}
return false;
}
// Remove a directory from the tar archive
public function removeDirectory($dirname)
{
if ($this->numDirectories > 0) {
foreach ($this->directories as $key => $information) {
if ($information['name'] == $dirname) {
--$this->numDirectories;
unset($this->directories[$key]);
return true;
}
}
}
return false;
}
// Write the currently loaded tar archive to disk
public function saveTar()
{
if (!$this->filename) {
return false;
}
// Write tar to current file using specified gzip compression
$this->toTar($this->filename, $this->isGzipped);
return true;
}
// Saves tar archive to a different file than the current file
public function toTar($filename, $useGzip)
{
if (!$filename) {
return false;
}
// Encode processed files into TAR file format
$this->__generateTar();
// GZ Compress the data if we need to
if ($useGzip) {
// Make sure we have gzip support
if (!function_exists('gzencode')) {
return false;
}
$file = gzencode($this->tar_file);
} else {
$file = $this->tar_file;
}
// Write the TAR file
$fp = fopen($filename, 'wb');
fwrite($fp, $file);
fclose($fp);
return true;
}
}