Source for file TAR.class.php
Documentation is available at TAR.class.php
echo "<h3>You have to define the constant CLASSPATH!</h3>\r\n";
echo "Example: define( 'CLASSPATH', '../path/to/classes/' );\r\n";
require_once( CLASSPATH. "communication/FTPHost.class.php" );
include_once( CLASSPATH. "core/Arrays.class.php" );
* This class reads and writes Tape-Archive (TAR) Files and Gzip
* compressed TAR files, which are mainly used on UNIX systems.
* This class works on both windows AND unix systems, and does
* NOT rely on external applications!! Woohoo!
* 1.0 04/10/2002 - InitialRelease
* 2.0 04/11/2002 - Merged both tarReader and tarWriter classes into one
* - Added support for gzipped tar files
* Remember to name for .tar.gz or .tgz
* if you use gzip compression!
* :: THIS REQUIRES ZLIB EXTENSION ::
* - Added additional comments to functions to help users
* directories from archive
* 2.1 04/12/2002 - Fixed serious bug in generating tar
* - Created another example file
* - Added check to make sure ZLIB is installed before running
* GZIP compression on TAR
* 2.2 05/07/2002 - Added automatic detection of Gzipped tar files
* (Thanks go to Jürgen Falch for the idea)
* - Changed "private" functions to have special function names
* beginning with two underscores
* If you use this script in your application/website, please send me an e-mail
* letting me know about it :)
* Please report any bugs you might find to my e-mail address at joshb@npt.com.
* If you have already created a fix/patch for the bug, please do send it to me
* so I can incorporate it into my release.
* @author Josh Barger <joshb@npt.com>
* @license http://www.gnu.org/copyleft/lesser.html
* GNU Lesser General Public License
* @copyright Copyright (c) 2002 Josh Barger <joshb@npt.com>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License.
* This library 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 Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
// Unprocessed Archive Information
* The data content of the archive will be stored in ths variable.
* This reference of a FTP object is for the use of the filesystem on the
* server via FTP, cause of SAFE MODE restriction.
// Processed Archive Information
* Class Constructor -- Does nothing...
* Perhaps it sets a reference to an FTPHost-Object.
* @author Josh Barger <joshb@npt.com>
function TAR( $ftp_host = null )
{ $this->ftp = & $ftp_host; }
* Adds ftp data to this object. This can be useful for writing dumps if the
* sever has SAFE MODE restrictions.
* @author Daniel Plücken <daniel@debakel.net>
* @param string $password
{ $this->ftp = new FTPHost( $host, $user, $password, $port ); }
* Computes the unsigned Checksum of a file's header to try to ensure valid
* @author Josh Barger <joshb@npt.com>
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;
* Converts a NULL padded string to a non-NULL padded string.
* @author Josh Barger <joshb@npt.com>
return substr( $string, 0, $position );
* This function parses the current TAR file.
* @author Josh Barger <joshb@npt.com>
// Read Files from archive
while( $main_offset < $tar_length )
// If we read a block of 512 nulls, we are at the end of the archive
// Parse the file user ID
// Parse the file group ID
// Parse the file update time - unix timestamp format
// Make sure our file is valid
/* ### 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);
// Increment number of files
// Create us a new file in our array
$activeFile = &$this->files[];
$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;
// Increment number of directories
// Create a new directory in our array
$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 );
* Read a non gzipped tar file in for processing.
* @author Josh Barger <joshb@npt.com>
// Set the filename to load
$fp = fopen( $filename, "rb" );
* Generates a TAR file from the processed data.
* @author Josh Barger <joshb@npt.com>
// Clear any data currently in $this->tar_file
// Generate Records for each directory, if we have directories
// Generate tar header for this directory
// Filename, Permissions, UID, GID, size, Time, checksum, typeflag,
// linkname, magic, version, user name, group name, devmajor,
$header = str_pad( $information["name"], 100, chr(0) );
decoct( $information["mode"] ),
decoct( $information["user_id"] ),
decoct( $information["group_id"] ),
decoct( $information["time"] ),
// Compute header checksum
for ( $i = 0; $i < 6; $i++ )
$header[(148+ $i)] = substr( $checksum, $i, 1 );
// Add new tar formatted data to tar file contents
// Generate Records for each file, if we have files (We should...)
foreach ( $this->files as $key => $information )
// Generate the TAR header for this file
// Filename, Permissions, UID, GID, size, Time, checksum, typeflag,
// linkname, magic, version, user name, group name, devmajor,
$header .= str_pad( $information["name"], 100, chr(0) );
decoct( $information["mode"] ),
decoct( $information["user_id"] ),
decoct( $information["group_id"] ),
decoct( $information["size"] ),
decoct( $information["time"] ),
// How do I get a file's user name from PHP?
$header .= str_pad( $information["user_name"], 32, chr(0) );
// How do I get a file's group name from PHP?
$header .= str_pad( $information["group_name"], 32, chr(0) );
// Compute header checksum
for ( $i = 0; $i < 6; $i++ )
$header[(148+ $i)] = substr( $checksum, $i, 1 );
// Pad file contents to byte count divisible by 512
(ceil($information["size"]/ 512) * 512),
// Add new tar formatted data to tar file contents
$this->tar_file .= $header. $file_contents;
// Add 512 bytes of NULLs to designate EOF
* Computes the unsigned Checksum of a file's header to try to ensure valid
* @author Josh Barger <joshb@npt.com>
* @param string $filename
// Clear any values from previous tar archives
// If the tar file doesn't exist...
* Appends a tar file to the end of the currently opened tar file.
* @author Josh Barger <joshb@npt.com>
* @param string $filename
// If the tar file doesn't exist...
* Retrieves information about a file in the current tar archive.
* @author Josh Barger <joshb@npt.com>
* @param string $filename
foreach ( $this->files as $key => $information )
if ( $information["name"] == $filename )
* Retrieves information about a directory in the current tar archive.
* @author Josh Barger <joshb@npt.com>
if ( $information["name"] == $dirname )
* Check if this tar archive contains a specific file.
* @author Josh Barger <joshb@npt.com>
* @param string $filename
foreach ( $this->files as $key => $information )
if ( $information["name"] == $filename )
* Check if this tar archive contains a specific directory.
* @author Josh Barger <joshb@npt.com>
if ( $information["name"] == $dirname )
* Check if this tar archive contains a specific directory.
* @author Josh Barger <joshb@npt.com>
* @author Daniel Plücken <daniel@debakel.net> (only FTP-Functionality)
* @param boolean $recursive
if ( strpos( $dirname, "/" ) === 0 )
$dirname = substr( $dirname, 1 );
if ( !$this->ftp->is_dir( $dirname, false ) )
$this->ftp->disconnect();
// Add directory to processed data
$file_information["mode"] = "16895";
$res_arr = $this->ftp->loadFolderContent(
$d_mem, "", "", false, "name", false
foreach ( $res_arr as $tmp )
// echo $d_mem."/".$tmp["name"]."<br />";
if ( $this->ftp->is_dir( $d_mem. "/". $tmp["name"], false ) )
if ( $this->ftp->is_file( $d_mem. "/". $tmp["name"], false ) )
$this->addFile( $d_mem. "/". $tmp["name"], false );
// Add directory to processed data
// Get directory information
$file_information = stat( $dirname );
$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;
* Add a file to the tar archive.
* @author Josh Barger <joshb@npt.com>
* @param boolean $ftp_disconnect
function addFile( $filename, $ftp_disconnect = true )
// Make sure there are no other files in the archive that have this same
if ( strpos( $filename, "/" ) === 0 )
$filename = substr( $filename, 1 );
// Make sure the file we are adding exists!
if ( !$this->ftp->is_file( $filename, false ) )
$this->ftp->disconnect();
// Read in the file's contents
$file_contents = $this->ftp->loadFileContent(
$file_information["mode"] = "33279";
$file_information["size"] = strlen( $file_contents );
// Make sure the file we are adding exists!
$file_information = stat( $filename );
// Read in the file's contents
$fp = fopen( $filename, "rb" );
// Add file to processed data
$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;
* Remove a file from the tar archive.
* @author Josh Barger <joshb@npt.com>
foreach ( $this->files as $key => $information )
if ( $information["name"] == $filename )
unset ( $this->files[$key] );
* Remove a directory from the tar archive.
* @author Josh Barger <joshb@npt.com>
if ( $information["name"] == $dirname )
* Write the currently loaded tar archive to disk or to a ftp ressource
* if the attribute ftp is a FTPHost-Object.
* @author Josh Barger <joshb@npt.com>
* @author Daniel Plücken <daniel@debakel.net> (only FTP-Functionality)
// Write tar to current file using specified gzip compression
* Saves tar archive to a different file than the current file.
* @author Josh Barger <joshb@npt.com>
* @author Daniel Plücken <daniel@debakel.net> (only FTP-Functionality)
* @param string $filename
* @param boolean $useGzip
function toTar( $filename, $useGzip )
// Encode processed files into TAR file format
// GZ Compress the data if we need to
// Make sure we have gzip support
$this->ftp->saveFile( $filename, $file );
$fp = fopen( $filename, "wb" );
|