phpbb/phpBB/includes/functions_compress.php
Paul S. Owen e0c4360705 Ignore given list of files
git-svn-id: file:///svn/phpbb/trunk@4291 89ea8834-ac86-4346-8a33-228a782c2dd0
2003-07-20 14:37:14 +00:00

2186 lines
No EOL
51 KiB
PHP

<?
// Zip creation class from phpMyAdmin 2.3.0 © Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, Marc Delisle
// http://www.phpmyadmin.net/
//
// Modified extensively by psoTFX, © phpBB Group, 2003
//
// Based on work by Eric Mueller and Denis125
// Official ZIP file format: http://www.pkware.com/appnote.txt
// TODO
// Extract files
class archive_zip
{
var $datasec = array();
var $ctrl_dir = array();
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
var $old_offset = 0;
var $datasec_len = 0;
var $fp = 0;
function archive_zip($mode, $dst)
{
return $this->fp = @fopen($phpbb_root_path . $dst, $mode . 'b');
}
function unix_to_dos_time($time)
{
$timearray = (!$time) ? getdate() : getdate($time);
if ($timearray['year'] < 1980)
{
$timearray['year'] = 1980;
$timearray['mon'] = $timearray['mday'] = 1;
$timearray['hours'] = $timearray['minutes'] = $timearray['seconds'] = 0;
}
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
}
function add_file($src, $src_prefix = '', $skip_files = '')
{
global $phpbb_root_path;
// Remove prefix from src path
$src_prefix = ($src_prefix) ? preg_replace('#^(' . preg_quote($src_prefix) . ')#', '', $src) : $src;
// Clean up path, remove initial / if present, add ending / if not present
$src_prefix = (strpos($src_prefix, '/') === 0) ? substr($src_prefix, 1) : $src_prefix;
$src_prefix = (strrpos($src_prefix, '/') != strlen($src_prefix) - 1) ? (($src_prefix != '') ? $src_prefix . '/' : '') : $src_prefix;
$skip_files = explode(',', $skip_files);
if (is_file($phpbb_root_path . $src))
{
if (!($fp = @fopen($phpbb_root_path . $src, 'rb')))
{
return false;
}
$data = fread($fp, filesize($phpbb_root_path . $src));
fclose($fp);
$this->data($src_prefix, $data);
}
else if (is_dir($phpbb_root_path . $src))
{
$filelist = filelist($phpbb_root_path . $src, '', '*');
ksort($filelist);
if ($src_prefix)
{
$this->data($src_prefix, '', filemtime($src_prefix), true);
}
foreach ($filelist as $path => $file_ary)
{
if ($path)
{
// Same as for src_prefix
$path = (strpos($path, '/') === 0) ? substr($path, 1) : $path;
$path = (strrpos($path, '/') != strlen($path) - 1) ? $path . '/' : $path;
$this->data($src_prefix . $path, '', filemtime($src_prefix . $path), true);
}
foreach ($file_ary as $file)
{
if (in_array($path . $file, $skip_files))
{
continue;
}
$this->data($src_prefix . $path . $file, implode('', file($phpbb_root_path . $src . $path . $file)), filemtime($phpbb_root_path . $src . $path . $file), false);
}
}
}
return true;
}
function add_data($src, $name)
{
$this->data($name, $src);
return true;
}
function extract($dst)
{
}
function close()
{
// Write out central file directory and footer
fwrite($this->fp, $this->file());
fclose($this->fp);
}
function data($name, $data, $mtime = false, $is_dir = false)
{
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->unix_to_dos_time($mtime));
$hexdtime = '\x' . $dtime[6] . $dtime[7] . '\x' . $dtime[4] . $dtime[5] . '\x' . $dtime[2] . $dtime[3] . '\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
$unc_len = strlen($data);
$crc = crc32($data);
$zdata = gzcompress($data);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
$c_len = strlen($zdata);
unset($data);
$fr = "\x50\x4b\x03\x04";
$fr .= "\x14\x00"; // ver needed to extract
$fr .= "\x00\x00"; // gen purpose bit flag
$fr .= "\x08\x00"; // compression method
$fr .= $hexdtime; // last mod time and date
$fr .= pack('V', $crc); // crc32
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
$fr .= pack('v', strlen($name));// length of filename
$fr .= pack('v', 0); // extra field length
$fr .= $name;
$fr .= $zdata;
unset($zdata);
$fr .= pack('V', $crc);
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
$this->datasec_len += strlen($fr);
// Add data to file ... by writing data out incrementally we
// save some memory
fwrite($this->fp, $fr);
unset($fr);
// Are we a file or a directory? Set archive for file
$attrib = ($is_dir) ? 0x41FF0010 : 32;
$cdrec = "\x50\x4b\x01\x02";
$cdrec .= "\x00\x00"; // version made by
$cdrec .= "\x14\x00"; // version needed to extract
$cdrec .= "\x00\x00"; // gen purpose bit flag
$cdrec .= "\x08\x00"; // compression method
$cdrec .= $hexdtime; // last mod time & date
$cdrec .= pack('V', $crc); // crc32
$cdrec .= pack('V', $c_len); // compressed filesize
$cdrec .= pack('V', $unc_len); // uncompressed filesize
$cdrec .= pack('v', strlen($name)); // length of filename
$cdrec .= pack('v', 0); // extra field length
$cdrec .= pack('v', 0); // file comment length
$cdrec .= pack('v', 0); // disk number start
$cdrec .= pack('v', 0); // internal file attributes
$cdrec .= pack('V', $attrib); // external file attributes
$cdrec .= pack('V', $this->old_offset); // relative offset of local header
$cdrec .= $name;
// Save to central directory
$this->ctrl_dir[] = $cdrec;
$this->old_offset = $this->datasec_len;
}
function file()
{
$ctrldir = implode('', $this->ctrl_dir);
return $ctrldir . $this->eof_ctrl_dir .
pack('v', sizeof($this->ctrl_dir)) . // total # of entries "on this disk"
pack('v', sizeof($this->ctrl_dir)) . // total # of entries overall
pack('V', strlen($ctrldir)) . // size of central dir
pack('V', $this->datasec_len) . // offset to start of central dir
"\x00\x00"; // .zip file comment length
}
}
// --------------------------------------------------------------------------------
// PhpConcept Library - Tar Module 1.3
// --------------------------------------------------------------------------------
// License GNU/GPL - Vincent Blavet - August 2001
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
//
// Modified extensively by psoTFX, © phpBB Group, 2003
class archive_tar
{
var $fopen = '';
var $fclose = '';
var $fread = '';
var $fwrite = '';
var $feof = '';
var $fseek = '';
function archive_tar($dst, $mode = 'gz')
{
$this->fopen = ($mode == 'gz' && extension_loaded('zlib')) ? 'gzopen' : 'fopen';
$this->fclose = ($mode == 'gz' && extension_loaded('zlib')) ? 'gzclose' : 'fclose';
$this->fread = ($mode == 'gz' && extension_loaded('zlib')) ? 'gzread' : 'fread';
$this->fwrite = ($mode == 'gz' && extension_loaded('zlib')) ? 'gzwrite' : 'fwrite';
$this->feof = ($mode == 'gz' && extension_loaded('zlib')) ? 'gzeof' : 'feof';
$this->fseek = ($mode == 'gz' && extension_loaded('zlib')) ? 'gzseek' : 'fseek';
}
}
function PclTarCreate($p_tarname, $p_filelist = '', $p_mode = '', $p_add_dir = '', $p_remove_dir = '')
{
$v_result = 1;
// Look for default mode
if ($p_mode == '' || ($p_mode != 'tar' && $p_mode != 'tgz'))
{
// Extract the tar format from the extension
if (($p_mode = PclTarHandleExtension($p_tarname)) == '')
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
}
if (is_array($p_filelist))
{
// Look if the $p_filelist is really an array
$v_result = PclTarHandleCreate($p_tarname, $p_filelist, $p_mode, $p_add_dir, $p_remove_dir);
}
else if (is_string($p_filelist))
{
// Look if the $p_filelist is a string. Create a list with the elements from the string
$v_list = explode(' ', $p_filelist);
// Call the create fct
$v_result = PclTarHandleCreate($p_tarname, $v_list, $p_mode, $p_add_dir, $p_remove_dir);
}
else
{
// Invalid variable
$v_result = -3;
}
return $v_result;
}
function PclTarAdd($p_tarname, $p_filelist)
{
$v_result = 1;
$v_list_detail = array();
// Extract the tar format from the extension
if (($p_mode = PclTarHandleExtension($p_tarname)) == '')
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Look if the $p_filelist is really an array
if (is_array($p_filelist))
{
$v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $v_list_detail, "", "");
}
else if (is_string($p_filelist))
{
// Look if the $p_filelist is a string. Create a list with the elements from the string
$v_list = explode(" ", $p_filelist);
$v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $v_list_detail, "", "");
}
else
{
$v_result = -3;
}
unset($v_list_detail);
return $v_result;
}
function PclTarAddList($p_tarname, $p_filelist, $p_add_dir = '', $p_remove_dir = '', $p_mode = '')
{
$v_result = 1;
$p_list_detail = array();
// Extract the tar format from the extension
if ($p_mode == '' || ($p_mode != 'tar' && $p_mode != 'tgz'))
{
if (($p_mode = PclTarHandleExtension($p_tarname)) == '')
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
}
// Look if the $p_filelist is really an array
if (is_array($p_filelist))
{
$v_result = PclTarHandleAppend($p_tarname, $p_filelist, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
}
else if (is_string($p_filelist))
{
// Look if the $p_filelist is a string
$v_list = explode(' ', $p_filelist);
$v_result = PclTarHandleAppend($p_tarname, $v_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
}
else
{
// Invalid variable
$v_result = -3;
}
return ($v_result != 1) ? 0 : $p_list_detail;
}
function PclTarList($p_tarname, $p_mode = '')
{
$v_result = 1;
// Extract the tar format from the extension
if ($p_mode == '' || ($p_mode != 'tar' && $p_mode != 'tgz'))
{
if (($p_mode = PclTarHandleExtension($p_tarname)) == '')
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
}
// Call the extracting fct
$p_list = array();
if (($v_result = PclTarHandleExtract($p_tarname, 0, $p_list, 'list', '', $p_mode, '')) != 1)
{
unset($p_list);
return 0;
}
return $p_list;
}
function PclTarExtract($p_tarname, $p_path="./", $p_remove_path = '', $p_mode = '')
{
$v_result = 1;
// Extract the tar format from the extension
if ($p_mode == '' || ($p_mode != 'tar' && $p_mode != 'tgz'))
{
if (($p_mode = PclTarHandleExtension($p_tarname)) == '')
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
}
// Call the extracting fct
if (($v_result = PclTarHandleExtract($p_tarname, 0, &$p_list, 'complete', $p_path, $v_tar_mode, $p_remove_path)) != 1)
{
return 0;
}
return $p_list;
}
function PclTarHandleCreate($p_tarname, $p_list, $p_mode, $p_add_dir = '', $p_remove_dir = '')
{
$v_result = 1;
$v_list_detail = array();
// Extract the tar format from the extension
if ($p_mode == '' || ($p_mode != 'tar' && $p_mode != 'tgz'))
{
if (($p_mode = PclTarHandleExtension($p_tarname)) == '')
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
}
$fopen = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzopen' : 'fopen';
$fclose = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzclose' : 'fclose';
$fread = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzread' : 'fread';
$fwrite = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzwrite' : 'fwrite';
$feof = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzeof' : 'feof';
$fseek = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzseek' : 'fseek';
// Open the tar file
if (!($p_tar = $fopen($p_tarname, "wb")))
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Call the adding fct inside the tar
if (($v_result = PclTarHandleAddList($p_tar, $p_list, $p_mode, $v_list_detail, $p_add_dir, $p_remove_dir)) == 1)
{
// Call the footer of the tar archive
$v_result = PclTarHandleFooter($p_tar, $p_mode);
}
// Close the tarfile
$fclose($p_tar);
return $v_result;
}
function PclTarHandleAppend($p_tarname, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir)
{
$v_result = 1;
clearstatcache();
// Check the file size
if (!is_file($p_tarname) || ((($v_size = filesize($p_tarname)) % 512) && $p_mode == 'tar'))
{
trigger_error('Archive missing or corrupt', E_USER_ERROR);
}
$fopen = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzopen' : 'fopen';
$fclose = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzclose' : 'fclose';
$fread = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzread' : 'fread';
$fwrite = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzwrite' : 'fwrite';
$feof = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzeof' : 'feof';
$fseek = ($p_tar == 'tar.gz' && extension_loaded('zlib')) ? 'gzseek' : 'fseek';
if (($p_tar = @$fopen($p_tarname, 'rb')) == 0)
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Open a temporary file in write mode
$v_temp_tarname = uniqid('pcltar-') . '.tmp';
if (($v_temp_tar = @$fopen($v_temp_tarname, 'wb')) == 0)
{
$fclose($p_tar);
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Read new 512 block and write the already read
while ($v_buffer = $fread($p_tar, 512))
{
// Write the already read block
$v_binary_data = pack("a512", "$v_buffer");
$fwrite($v_temp_tar, $v_binary_data);
}
// Call the adding fct inside the tar
if (($v_result = PclTarHandleAddList($v_temp_tar, $p_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir)) == 1)
{
// Call the footer of the tar archive
$v_result = PclTarHandleFooter($v_temp_tar, $p_mode);
}
// Close the files
$fclose($p_tar);
$fclose($v_temp_tar);
// Unlink tar file
if (!@unlink($p_tarname))
{
trigger_error('Could not unlink file :: ' . $p_tarname, E_USER_ERROR);
}
// Rename tar file
if (!@rename($v_temp_tarname, $p_tarname))
{
trigger_error('Could not unlink file :: ' . $v_temp_tarname . ' / ' . $p_tarname, E_USER_ERROR);
}
return $v_result;
}
function PclTarHandleAddList($p_tar, $p_list, $p_mode, &$p_list_detail, $p_add_dir, $p_remove_dir)
{
$v_result = 1;
$v_header = array();
// Recuperate the current number of elt in list
$v_nb = sizeof($p_list_detail);
// Check the parameters
if ($p_tar == 0)
{
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Check the arguments
if (sizeof($p_list) == 0)
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Loop on the files
for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++)
{
// Recuperate the filename
$p_filename = $p_list[$j];
// Skip empty file names
if ($p_filename == '')
{
continue;
}
// Check the filename
if (!file_exists($p_filename))
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Check the path length
if (strlen($p_filename) > 99)
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Add the file
if (($v_result = PclTarHandleAddFile($p_tar, $p_filename, $p_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1)
{
// Return status
return $v_result;
}
// Store the file infos
$p_list_detail[$v_nb++] = $v_header;
// Look for directory
if (is_dir($p_filename))
{
// Look for path
if ($p_filename != ".")
$v_path = $p_filename."/";
else
$v_path = "";
// Read the directory for files and sub-directories
$p_hdir = opendir($p_filename);
$p_hitem = readdir($p_hdir); // '.' directory
$p_hitem = readdir($p_hdir); // '..' directory
while ($p_hitem = readdir($p_hdir))
{
// Look for a file
if (is_file($v_path.$p_hitem))
{
// Add the file
if (($v_result = PclTarHandleAddFile($p_tar, $v_path.$p_hitem, $p_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1)
{
// Return status
return $v_result;
}
// Store the file infos
$p_list_detail[$v_nb++] = $v_header;
}
// Recursive call to PclTarHandleAddFile()
else
{
// Need an array as parameter
$p_temp_list[0] = $v_path.$p_hitem;
$v_result = PclTarHandleAddList($p_tar, $p_temp_list, $p_mode, $p_list_detail, $p_add_dir, $p_remove_dir);
}
}
// Free memory for the recursive loop
unset($p_temp_list);
unset($p_hdir);
unset($p_hitem);
}
}
// Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : PclTarHandleAddFile()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function PclTarHandleAddFile($p_tar, $p_filename, $p_mode, &$p_header, $p_add_dir, $p_remove_dir)
{
$v_result = 1;
// Check the parameters
if ($p_tar == 0)
{
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Skip empty file names
if ($p_filename == '')
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Calculate the stored filename
$v_stored_filename = $p_filename;
if ($p_remove_dir != "")
{
if (substr($p_remove_dir, -1) != '/')
$p_remove_dir .= "/";
if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
{
if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
$p_remove_dir = "./".$p_remove_dir;
if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
$p_remove_dir = substr($p_remove_dir, 2);
}
if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
{
$v_stored_filename = substr($p_filename, strlen($p_remove_dir));
}
}
if ($p_add_dir != "")
{
if (substr($p_add_dir, -1) == "/")
$v_stored_filename = $p_add_dir.$v_stored_filename;
else
$v_stored_filename = $p_add_dir."/".$v_stored_filename;
}
// Check the path length
if (strlen($v_stored_filename) > 99)
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Look for a file
if (is_file($p_filename))
{
// Open the source file
if (($v_file = fopen($p_filename, "rb")) == 0)
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Call the header generation
if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1)
{
// Return status
return $v_result;
}
// Read the file by 512 octets blocks
$i=0;
while (($v_buffer = fread($v_file, 512)) != "")
{
$v_binary_data = pack("a512", "$v_buffer");
if ($p_mode == "tar")
fputs($p_tar, $v_binary_data);
else
gzputs($p_tar, $v_binary_data);
$i++;
}
// Close the file
fclose($v_file);
}
// Look for a directory
else
{
// Call the header generation
if (($v_result = PclTarHandleHeader($p_tar, $p_filename, $p_mode, $p_header, $v_stored_filename)) != 1)
{
// Return status
return $v_result;
}
}
// Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : PclTarHandleHeader()
// Description :
// This function creates in the TAR $p_tar, the TAR header for the file
// $p_filename.
//
// 1. The informations needed to compose the header are recuperated and formatted
// 2. Two binary strings are composed for the first part of the header, before
// and after checksum field.
// 3. The checksum is calculated from the two binary strings
// 4. The header is write in the tar file (first binary string, binary string
// for checksum and last binary string).
// Parameters :
// $p_tar : a valid file descriptor, opened in write mode,
// $p_filename : The name of the file the header is for,
// $p_mode : The mode of the archive ("tar" or "tgz").
// $p_header : A pointer to a array where will be set the file properties
// Return Values :
// --------------------------------------------------------------------------------
function PclTarHandleHeader($p_tar, $p_filename, $p_mode, &$p_header, $p_stored_filename)
{
$v_result = 1;
// Check the parameters
if (($p_tar == 0) || ($p_filename == ''))
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Filename (reduce the path of stored name)
if ($p_stored_filename == '')
$p_stored_filename = $p_filename;
$v_reduce_filename = PclTarHandlePathReduction($p_stored_filename);
// Get file info
$v_info = stat($p_filename);
$v_uid = sprintf("%6s ", DecOct($v_info[4]));
$v_gid = sprintf("%6s ", DecOct($v_info[5]));
$v_perms = sprintf("%6s ", DecOct(fileperms($p_filename)));
// File mtime
$v_mtime_data = filemtime($p_filename);
$v_mtime = sprintf("%11s", DecOct($v_mtime_data));
// File typeflag
// '0' or '\0' is the code for regular file
// '5' is directory
if (is_dir($p_filename))
{
$v_typeflag = "5";
$v_size = 0;
}
else
{
$v_typeflag = "";
// Get the file size
clearstatcache();
$v_size = filesize($p_filename);
}
$v_size = sprintf("%11s ", DecOct($v_size));
// Linkname
$v_linkname = "";
// Magic
$v_magic = "";
// Version
$v_version = "";
// uname
$v_uname = "";
// gname
$v_gname = "";
// devmajor
$v_devmajor = "";
// devminor
$v_devminor = "";
// prefix
$v_prefix = "";
// Compose the binary string of the header in two parts arround the checksum position
$v_binary_data_first = pack("a100a8a8a8a12A12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime);
$v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, "");
// Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
for ($i=0; $i<148; $i++)
{
$v_checksum += ord(substr($v_binary_data_first,$i,1));
}
// ..... Ignore the checksum value and replace it by ' ' (space)
for ($i=148; $i<156; $i++)
{
$v_checksum += ord(' ');
}
// ..... Last part of the header
for ($i=156, $j=0; $i<512; $i++, $j++)
{
$v_checksum += ord(substr($v_binary_data_last,$j,1));
}
// Write the first 148 bytes of the header in the archive
if ($p_mode == "tar")
fputs($p_tar, $v_binary_data_first, 148);
else
gzputs($p_tar, $v_binary_data_first, 148);
// Write the calculated checksum
$v_checksum = sprintf("%6s ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
if ($p_mode == "tar")
fputs($p_tar, $v_binary_data, 8);
else
gzputs($p_tar, $v_binary_data, 8);
// Write the last 356 bytes of the header in the archive
if ($p_mode == "tar")
fputs($p_tar, $v_binary_data_last, 356);
else
gzputs($p_tar, $v_binary_data_last, 356);
// Set the properties in the header "structure"
$p_header['filename'] = $v_reduce_filename;
$p_header['mode'] = $v_perms;
$p_header['uid'] = $v_uid;
$p_header['gid'] = $v_gid;
$p_header['size'] = $v_size;
$p_header['mtime'] = $v_mtime;
$p_header['typeflag'] = $v_typeflag;
$p_header['status'] = "added";
// Return
return $v_result;
}
// --------------------------------------------------------------------------------
function PclTarHandleFooter($p_tar, $p_mode)
{
$v_result = 1;
// Write the last 0 filled block for end of archive
$v_binary_data = pack("a512", "");
if ($p_mode == "tar")
fputs($p_tar, $v_binary_data);
else
gzputs($p_tar, $v_binary_data);
// Return
return $v_result;
}
// --------------------------------------------------------------------------------
// Function : PclTarHandleExtract()
// Description :
// Parameters :
// $p_tarname : Filename of the tar (or tgz) archive
// $p_file_list : An array which contains the list of files to extract, this
// array may be empty when $p_mode is 'complete'
// $p_list_detail : An array where will be placed the properties of each extracted/listed file
// $p_mode : 'complete' will extract all files from the archive,
// 'partial' will look for files in $p_file_list
// 'list' will only list the files from the archive without any extract
// $p_path : Path to add while writing the extracted files
// $p_tar_mode : 'tar' for GNU TAR archive, 'tgz' for compressed archive
// $p_remove_path : Path to remove (from the file memorized path) while writing the
// extracted files. If the path does not match the file path,
// the file is extracted with its memorized path.
// $p_remove_path does not apply to 'list' mode.
// $p_path and $p_remove_path are commulative.
// Return Values :
// --------------------------------------------------------------------------------
function PclTarHandleExtract($p_tarname, $p_file_list, &$p_list_detail, $p_mode, $p_path, $p_tar_mode, $p_remove_path)
{
$v_result = 1;
$v_nb = 0;
$v_extract_all = TRUE;
$v_listing = FALSE;
// Check the path
if (($p_path == '') || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../")))
$p_path = "./".$p_path;
// Look for path to remove format (should end by /)
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
{
$p_remove_path .= '/';
}
$p_remove_path_size = strlen($p_remove_path);
// Study the mode
switch ($p_mode) {
case "complete" :
// Flag extract of all files
$v_extract_all = TRUE;
$v_listing = FALSE;
break;
case "partial" :
// Flag extract of specific files
$v_extract_all = FALSE;
$v_listing = FALSE;
break;
case "list" :
// Flag list of all files
$v_extract_all = FALSE;
$v_listing = TRUE;
break;
default :
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Open the tar file
if ($p_tar_mode == "tar")
{
$v_tar = fopen($p_tarname, "rb");
}
else
{
$v_tar = @gzopen($p_tarname, "rb");
}
// Check that the archive is open
if ($v_tar == 0)
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Read the blocks
While (!($v_end_of_file = ($p_tar_mode == "tar"?feof($v_tar):gzeof($v_tar))))
{
// Clear cache of file infos
clearstatcache();
// Reset extract tag
$v_extract_file = FALSE;
$v_extraction_stopped = 0;
// Read the 512 bytes header
if ($p_tar_mode == "tar")
$v_binary_data = fread($v_tar, 512);
else
$v_binary_data = gzread($v_tar, 512);
// Read the header properties
if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1)
{
// Close the archive file
if ($p_tar_mode == "tar")
fclose($v_tar);
else
gzclose($v_tar);
// Return
return $v_result;
}
// Look for empty blocks to skip
if ($v_header['filename'] == '')
{
continue;
}
// Look for partial extract
if ((!$v_extract_all) && (is_array($p_file_list)))
{
// By default no unzip if the file is not found
$v_extract_file = FALSE;
// Look into the file list
for ($i=0; $i<sizeof($p_file_list); $i++)
{
// Look if it is a directory
if (substr($p_file_list[$i], -1) == "/")
{
// Look if the directory is in the filename path
if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i]))
{
// The file is in the directory, so extract it
$v_extract_file = TRUE;
// End of loop
break;
}
}
// It is a file, so compare the file names
else if ($p_file_list[$i] == $v_header['filename'])
{
// File found
$v_extract_file = TRUE;
// End of loop
break;
}
}
// Trace
if (!$v_extract_file)
{
}
}
else
{
// All files need to be extracted
$v_extract_file = TRUE;
}
// Look if this file need to be extracted
if (($v_extract_file) && (!$v_listing))
{
// Look for path to remove
if (($p_remove_path != "")
&& (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path))
{
// Remove the path
$v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
}
// Add the path to the file
if (($p_path != "./") && ($p_path != "/"))
{
// Look for the path end '/'
while (substr($p_path, -1) == "/")
{
$p_path = substr($p_path, 0, strlen($p_path)-1);
}
// Add the path
if (substr($v_header['filename'], 0, 1) == "/")
$v_header['filename'] = $p_path.$v_header['filename'];
else
$v_header['filename'] = $p_path."/".$v_header['filename'];
}
// Trace
// Check that the file does not exists
if (file_exists($v_header['filename']))
{
// Look if file is a directory
if (is_dir($v_header['filename']))
{
// Change the file status
$v_header['status'] = "already_a_directory";
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
// Look if file is write protected
else if (!is_writeable($v_header['filename']))
{
// Change the file status
$v_header['status'] = "write_protected";
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
// Look if the extracted file is older
else if (filemtime($v_header['filename']) > $v_header['mtime'])
{
// Change the file status
$v_header['status'] = "newer_exist";
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
}
// Check the directory availability and create it if necessary
else
{
if ($v_header['typeflag']=="5")
$v_dir_to_check = $v_header['filename'];
else if (!strstr($v_header['filename'], "/"))
$v_dir_to_check = "";
else
$v_dir_to_check = dirname($v_header['filename']);
if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1)
{
// Change the file status
$v_header['status'] = "path_creation_fail";
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
}
// Do the extraction
if (($v_extract_file) && ($v_header['typeflag']!="5"))
{
// Open the destination file in write mode
if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0)
{
// Change the file status
$v_header['status'] = "write_error";
// Jump to next file
if ($p_tar_mode == "tar")
fseek($v_tar, ftell($v_tar)+(ceil(($v_header['size']/512))*512));
else
gzseek($v_tar, gztell($v_tar)+(ceil(($v_header['size']/512))*512));
}
else
{
// Read data
$n = floor($v_header['size']/512);
for ($i=0; $i<$n; $i++)
{
if ($p_tar_mode == "tar")
$v_content = fread($v_tar, 512);
else
$v_content = gzread($v_tar, 512);
fwrite($v_dest_file, $v_content, 512);
}
if (($v_header['size'] % 512) != 0)
{
if ($p_tar_mode == "tar")
$v_content = fread($v_tar, 512);
else
$v_content = gzread($v_tar, 512);
fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
}
// Close the destination file
fclose($v_dest_file);
// Change the file mode, mtime
touch($v_header['filename'], $v_header['mtime']);
//chmod($v_header['filename'], DecOct($v_header['mode']));
}
// Check the file size
clearstatcache();
if (filesize($v_header['filename']) != $v_header['size'])
{
// Close the archive file
if ($p_tar_mode == "tar")
fclose($v_tar);
else
gzclose($v_tar);
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Trace
}
else
{
// Jump to next file
if ($p_tar_mode == "tar")
fseek($v_tar, ftell($v_tar)+(ceil(($v_header['size']/512))*512));
else
gzseek($v_tar, gztell($v_tar)+(ceil(($v_header['size']/512))*512));
}
}
// Look for file that is not to be unzipped
else
{
// Trace
// Jump to next file
if ($p_tar_mode == "tar")
fseek($v_tar, ($p_tar_mode=="tar"?ftell($v_tar):gztell($v_tar))+(ceil(($v_header['size']/512))*512));
else
gzseek($v_tar, gztell($v_tar)+(ceil(($v_header['size']/512))*512));
}
if ($p_tar_mode == "tar")
$v_end_of_file = feof($v_tar);
else
$v_end_of_file = gzeof($v_tar);
// File name and properties are logged if listing mode or file is extracted
if ($v_listing || $v_extract_file || $v_extraction_stopped)
{
// Log extracted files
if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename'])
$v_file_dir = "";
if ((substr($v_header['filename'], 0, 1) == "/") && ($v_file_dir == ''))
$v_file_dir = "/";
// Add the array describing the file into the list
$p_list_detail[$v_nb] = $v_header;
// Increment
$v_nb++;
}
}
// Close the tarfile
if ($p_tar_mode == "tar")
fclose($v_tar);
else
gzclose($v_tar);
// Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : PclTarHandleExtractByIndexList()
// Description :
// Extract the files which are at the indexes specified. If the 'file' at the
// index is a directory, the directory only is created, not all the files stored
// for that directory.
// Parameters :
// $p_index_string : String of indexes of files to extract. The form of the
// string is "0,4-6,8-12" with only numbers and '-' for
// for range, and ',' to separate ranges. No spaces or ';'
// are allowed.
// Return Values :
// --------------------------------------------------------------------------------
function PclTarHandleExtractByIndexList($p_tarname, $p_index_string, &$p_list_detail, $p_path, $p_remove_path, $p_tar_mode)
{
$v_result = 1;
$v_nb = 0;
// TBC : I should check the string by a regexp
// Check the path
if (($p_path == '') || ((substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path, 0, 2) != "./")))
$p_path = "./".$p_path;
// Look for path to remove format (should end by /)
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
{
$p_remove_path .= '/';
}
$p_remove_path_size = strlen($p_remove_path);
// Open the tar file
if ($p_tar_mode == "tar")
{
$v_tar = @fopen($p_tarname, "rb");
}
else
{
$v_tar = @gzopen($p_tarname, "rb");
}
// Check that the archive is open
if ($v_tar == 0)
{
// Error log
// Return
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Manipulate the index list
$v_list = explode(",", $p_index_string);
sort($v_list);
// Loop on the index list
$v_index=0;
for ($i=0; ($i<sizeof($v_list)) && ($v_result); $i++)
{
// Extract range
$v_index_list = explode("-", $v_list[$i]);
$v_size_index_list = sizeof($v_index_list);
if ($v_size_index_list == 1)
{
// Do the extraction
$v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[0], $p_list_detail, $p_path, $p_remove_path, $p_tar_mode);
}
else if ($v_size_index_list == 2)
{
// Do the extraction
$v_result = PclTarHandleExtractByIndex($v_tar, $v_index, $v_index_list[0], $v_index_list[1], $p_list_detail, $p_path, $p_remove_path, $p_tar_mode);
}
}
// Close the tarfile
if ($p_tar_mode == "tar")
fclose($v_tar);
else
gzclose($v_tar);
// Return
return $v_result;
}
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : PclTarHandleExtractByIndex()
// Description :
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
function PclTarHandleExtractByIndex($p_tar, &$p_index_current, $p_index_start, $p_index_stop, &$p_list_detail, $p_path, $p_remove_path, $p_tar_mode)
{
$v_result = 1;
$v_nb = 0;
// TBC : I should replace all $v_tar by $p_tar in this function ....
$v_tar = $p_tar;
// Look the number of elements already in $p_list_detail
$v_nb = sizeof($p_list_detail);
// Read the blocks
While (!($v_end_of_file = ($p_tar_mode == "tar"?feof($v_tar):gzeof($v_tar))))
{
if ($p_index_current > $p_index_stop)
{
break;
}
// Clear cache of file infos
clearstatcache();
// Reset extract tag
$v_extract_file = FALSE;
$v_extraction_stopped = 0;
// Read the 512 bytes header
if ($p_tar_mode == "tar")
$v_binary_data = fread($v_tar, 512);
else
$v_binary_data = gzread($v_tar, 512);
// Read the header properties
if (($v_result = PclTarHandleReadHeader($v_binary_data, $v_header)) != 1)
{
// Return
return $v_result;
}
// Look for empty blocks to skip
if ($v_header['filename'] == '')
{
continue;
}
// Look if file is in the range to be extracted
if (($p_index_current >= $p_index_start) && ($p_index_current <= $p_index_stop))
{
$v_extract_file = TRUE;
}
else
{
$v_extract_file = FALSE;
}
// Look if this file need to be extracted
if ($v_extract_file)
{
if (($v_result = PclTarHandleExtractFile($v_tar, $v_header, $p_path, $p_remove_path, $p_tar_mode)) != 1)
{
// Return
return $v_result;
}
}
// Look for file that is not to be extracted
else
{
// Trace
// Jump to next file
if ($p_tar_mode == "tar")
fseek($v_tar, ($p_tar_mode=="tar"?ftell($v_tar):gztell($v_tar))+(ceil(($v_header['size']/512))*512));
else
gzseek($v_tar, gztell($v_tar)+(ceil(($v_header['size']/512))*512));
}
if ($p_tar_mode == "tar")
$v_end_of_file = feof($v_tar);
else
$v_end_of_file = gzeof($v_tar);
// File name and properties are logged if listing mode or file is extracted
if ($v_extract_file)
{
// Log extracted files
if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename'])
$v_file_dir = "";
if ((substr($v_header['filename'], 0, 1) == "/") && ($v_file_dir == ''))
$v_file_dir = "/";
// Add the array describing the file into the list
$p_list_detail[$v_nb] = $v_header;
// Increment
$v_nb++;
}
// Increment the current file index
$p_index_current++;
}
// Return
return $v_result;
}
function PclTarHandleExtractFile($p_tar, &$v_header, $p_path, $p_remove_path, $p_tar_mode)
{
$v_result = 1;
$v_extract_file = 1;
$p_remove_path_size = strlen($p_remove_path);
// Look for path to remove
if ($p_remove_path && substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)
{
// Remove the path
$v_header['filename'] = substr($v_header['filename'], $p_remove_path_size);
}
// Add the path to the file
if ($p_path != './' && $p_path != '/')
{
// Look for the path end '/'
while (substr($p_path, -1) == '/')
{
$p_path = substr($p_path, 0, strlen($p_path)-1);
}
// Add the path
$v_header['filename'] = (substr($v_header['filename'], 0, 1) == '/') ? $p_path . $v_header['filename'] : $p_path . '/' . $v_header['filename'];
}
// Check that the file does not exists
if (file_exists($v_header['filename']))
{
// Look if file is a directory
if (is_dir($v_header['filename']))
{
// Change the file status
$v_header['status'] = 'already_a_directory';
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
else if (!is_writeable($v_header['filename']))
{
// Look if file is write protected
// Change the file status
$v_header['status'] = 'write_protected';
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
else if (filemtime($v_header['filename']) > $v_header['mtime'])
{
// Look if the extracted file is older
// Change the file status
$v_header['status'] = 'newer_exist';
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
}
else
{
// Check the directory availability and create it if necessary
$v_dir_to_check = ($v_header['typeflag'] == '5') ? $v_header['filename'] : ((!strstr($v_header['filename'], '/')) ? '' : dirname($v_header['filename']));
if (($v_result = PclTarHandlerDirCheck($v_dir_to_check)) != 1)
{
// Change the file status
$v_header['status'] = "path_creation_fail";
// Skip the extract
$v_extraction_stopped = 1;
$v_extract_file = 0;
}
}
// Do the real bytes extraction (if not a directory)
if ($v_extract_file && $v_header['typeflag'] != '5')
{
// Open the destination file in write mode
if (!($v_dest_file = @fopen($v_header['filename'], "wb")))
{
// Change the file status
$v_header['status'] = 'write_error';
// Jump to next file
$fseek($p_tar, $ftell($p_tar) + (ceil(($v_header['size'] / 512)) * 512));
}
else
{
// Read data
$n = floor($v_header['size'] / 512);
for ($i = 0; $i < $n; $i++)
{
$v_content = $fread($p_tar, 512);
fwrite($v_dest_file, $v_content, 512);
}
if (($v_header['size'] % 512) != 0)
{
$v_content = $fread($p_tar, 512);
fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
}
// Close the destination file
fclose($v_dest_file);
// Change the file mode, mtime
touch($v_header['filename'], $v_header['mtime']);
}
// Check the file size
clearstatcache();
if (filesize($v_header['filename']) != $v_header['size'])
{
trigger_error('Invalid header', E_USER_ERROR);
}
}
else
{
// Jump to next file
$fseek($p_tar, $ftell($p_tar) + (ceil(($v_header['size'] / 512)) *512));
}
return $v_result;
}
function PclTarHandleDelete($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode)
{
$v_result = 1;
$v_nb = 0;
// Look for regular tar file
if (($v_tar = @$fopen($p_tarname, 'rb')) == 0)
{
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Open a temporary file in write mode
$v_temp_tarname = uniqid('pcltar-') . '.tmp';
if (($v_temp_tar = @$fopen($v_temp_tarname, 'wb')) == 0)
{
// Close tar file
$fclose($v_tar);
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Read the blocks
while ($v_binary_data = $fread($v_tar, 512))
{
// Clear cache of file infos
clearstatcache();
// Reset delete tag
$v_delete_file = FALSE;
// Read the header properties
if (($v_result = PclTarHandleReadHeader($v_binary_data, &$v_header)) != 1)
{
// Close the archive file
$fclose($v_tar);
$fclose($v_temp_tar);
@unlink($v_temp_tarname);
return $v_result;
}
// Look for empty blocks to skip
if ($v_header['filename'] == '')
{
continue;
}
// Look for filenames to delete
for ($i = 0, $v_delete_file = FALSE; $i <sizeof($p_file_list) && !$v_delete_file; $i++)
{
// Compare the file names
if (($v_len = strcmp($p_file_list[$i], $v_header['filename'])) <= 0)
{
if ($v_len==0)
{
$v_delete_file = TRUE;
}
else
{
if (substr($v_header['filename'], strlen($p_file_list[$i]), 1) == "/")
{
$v_delete_file = TRUE;
}
}
}
}
// Copy files that do not need to be deleted
if (!$v_delete_file)
{
$fwrite($v_temp_tar, $v_binary_data, 512);
// Write the file data
$n = ceil($v_header['size'] / 512);
for ($i = 0; $i < $n; $i++)
{
$v_content = $fread($v_tar, 512);
$fwrite($v_temp_tar, $v_content, 512);
}
// File name and properties are logged if listing mode or file is extracted
// Add the array describing the file into the list
$p_list_detail[$v_nb] = $v_header;
$p_list_detail[$v_nb]['status'] = 'ok';
// Increment
$v_nb++;
}
else
{
// Look for file that is to be deleted
// Jump to next file
$fseek($v_tar, $ftell($v_tar) + (ceil(($v_header['size'] / 512)) *512));
}
}
// Write the last empty buffer
PclTarHandleFooter($v_temp_tar, $p_tar_mode);
// Close the tarfile
$fclose($v_tar);
$fclose($v_temp_tar);
// Unlink tar file
if (!@unlink($p_tarname))
{
trigger_error('', E_USER_ERROR);
}
// Rename tar file
if (!@rename($v_temp_tarname, $p_tarname))
{
trigger_error('', E_USER_ERROR);
}
return $v_result;
}
function PclTarHandleUpdate($p_tarname, $p_file_list, &$p_list_detail, $p_tar_mode, $p_add_dir, $p_remove_dir)
{
$v_result = 1;
$v_nb = 0;
$v_found_list = array();
// Look for regular tar file
if (!($v_tar = @$fopen($p_tarname, 'rb')))
{
trigger_error('Could not open archive :: ' . $p_tarname, E_USER_ERROR);
}
// Open a temporary file in write mode
$v_temp_tarname = uniqid('pcltar-') . '.tmp';
if (!($v_temp_tar = @$fopen($v_temp_tarname, 'wb')))
{
// Close tar file
@$fclose($v_tar);
trigger_error(PclErrorString(), E_USER_ERROR);
}
// Prepare the list of files
for ($i = 0; $i < sizeof($p_file_list); $i++)
{
// Reset the found list
$v_found_list[$i] = 0;
// Calculate the stored filename
$v_stored_list[$i] = $p_file_list[$i];
if ($p_remove_dir != '')
{
if (substr($p_file_list[$i], -1) != '/')
{
$p_remove_dir .= '/';
}
if (substr($p_file_list[$i], 0, strlen($p_remove_dir)) == $p_remove_dir)
{
$v_stored_list[$i] = substr($p_file_list[$i], strlen($p_remove_dir));
}
}
if ($p_add_dir != '')
{
$v_stored_list[$i] = (substr($p_add_dir, -1) == '/') ? $p_add_dir . $v_stored_list[$i] : $p_add_dir . '/' . $v_stored_list[$i];
}
$v_stored_list[$i] = PclTarHandlePathReduction($v_stored_list[$i]);
}
// Update file cache
clearstatcache();
// Read the blocks
while ($v_binary_data = $fread($v_tar, 512))
{
// Clear cache of file infos
clearstatcache();
// Reset current found filename
$v_current_filename = '';
// Reset delete tag
$v_delete_file = FALSE;
// Read the header properties
if (($v_result = PclTarHandleReadHeader($v_binary_data, &$v_header)) != 1)
{
// Close the archive file
$fclose($v_tar);
$fclose($v_temp_tar);
@unlink($v_temp_tarname);
return $v_result;
}
// Look for empty blocks to skip
if ($v_header['filename'] == '')
{
continue;
}
// Look for filenames to update
for ($i = 0, $v_update_file = FALSE, $v_found_file = FALSE; $i < sizeof($v_stored_list) && !$v_update_file; $i++)
{
// Compare the file names
if ($v_stored_list[$i] == $v_header['filename'])
{
// Store found informations
$v_found_file = TRUE;
$v_current_filename = $p_file_list[$i];
// Look if the file need to be updated
$v_update_file = (filemtime($p_file_list[$i]) > $v_header['mtime']) ? TRUE : FALSE;
// Flag the name in order not to add the file at the end
$v_found_list[$i] = 1;
}
}
// Copy files that do not need to be updated
if (!$v_update_file)
{
// Write the file header
$fwrite($v_temp_tar, $v_binary_data, 512);
// Write the file data
$n = ceil($v_header['size'] / 512);
for ($j = 0; $j < $n; $j++)
{
$v_content = $fread($v_tar, 512);
$fwrite($v_temp_tar, $v_content, 512);
}
// Add the array describing the file into the list
$p_list_detail[$v_nb] = $v_header;
$p_list_detail[$v_nb]['status'] = ($v_found_file?"not_updated":"ok");
// Increment
$v_nb++;
}
else
{
// Look for file that need to be updated
// Store the old file size
$v_old_size = $v_header['size'];
// Add the file
if (($v_result = PclTarHandleAddFile($v_temp_tar, $v_current_filename, $p_tar_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1)
{
// Close the tarfile
$fclose($v_tar);
$fclose($v_temp_tar);
@unlink($p_temp_tarname);
return $v_result;
}
// Jump to next file
$fseek($v_tar, $ftell($v_tar) + (ceil(($v_header['size'] / 512)) *512));
// Add the array describing the file into the list
$p_list_detail[$v_nb] = $v_header;
$p_list_detail[$v_nb]['status'] = 'updated';
// Increment
$v_nb++;
}
}
// Look for files that does not exists in the archive and need to be added
for ($i=0; $i<sizeof($p_file_list); $i++)
{
// Look if file not found in the archive
if (!$v_found_list[$i])
{
// Add the file
if (($v_result = PclTarHandleAddFile($v_temp_tar, $p_file_list[$i], $p_tar_mode, $v_header, $p_add_dir, $p_remove_dir)) != 1)
{
$fclose($v_tar);
$fclose($v_temp_tar);
@unlink($p_temp_tarname);
return $v_result;
}
// Add the array describing the file into the list
$p_list_detail[$v_nb] = $v_header;
$p_list_detail[$v_nb][status] = 'added';
// Increment
$v_nb++;
}
}
// Write the last empty buffer
PclTarHandleFooter($v_temp_tar, $p_tar_mode);
// Close the tarfile
$fclose($v_tar);
$fclose($v_temp_tar);
// Unlink tar file
if (!@unlink($p_tarname))
{
trigger_error('', E_USER_ERROR);
}
// Rename tar file
if (!@rename($v_temp_tarname, $p_tarname))
{
trigger_error('', E_USER_ERROR);
}
return $v_result;
}
function PclTarHandleReadHeader($v_binary_data, &$v_header)
{
$v_result = 1;
// Look for no more block
if (strlen($v_binary_data)==0)
{
$v_header['filename'] = '';
$v_header['status'] = 'empty';
return $v_result;
}
// Look for invalid block size
if (strlen($v_binary_data) != 512)
{
$v_header['filename'] = '';
$v_header['status'] = 'invalid_header';
trigger_error('Invalid header in archive', E_USER_ERROR);
}
// Calculate the checksum
$v_checksum = 0;
for ($i = 0; $i < 148; $i++)
{
$v_checksum += ord(substr($v_binary_data,$i,1));
}
// ..... Ignore the checksum value and replace it by ' ' (space)
for ($i = 148; $i < 156; $i++)
{
$v_checksum += ord(' ');
}
// ..... Last part of the header
for ($i = 156; $i < 512; $i++)
{
$v_checksum += ord(substr($v_binary_data,$i,1));
}
$v_data = unpack('a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor', $v_binary_data);
// Extract the checksum for check
$v_header['checksum'] = octdec(trim($v_data['checksum']));
if ($v_header['checksum'] != $v_checksum)
{
$v_header['filename'] = '';
$v_header['status'] = 'invalid_header';
// Look for last block (empty block)
if ($v_checksum == 256 && $v_header['checksum'] == 0)
{
$v_header['status'] = 'empty';
return $v_result;
}
trigger_error('Invalid header in archive', E_USER_ERROR);
}
// Extract the properties
$v_header['filename'] = trim($v_data['filename']);
$v_header['mode'] = octdec(trim($v_data['mode']));
$v_header['uid'] = octdec(trim($v_data['uid']));
$v_header['gid'] = octdec(trim($v_data['gid']));
$v_header['size'] = octdec(trim($v_data['size']));
$v_header['mtime'] = octdec(trim($v_data['mtime']));
if (($v_header['typeflag'] = $v_data['typeflag']) == '5')
{
$v_header['size'] = 0;
}
$v_header['status'] = 'ok';
return $v_result;
}
// Check if a directory exists, if not it creates it and all the parents directory
// which may be useful.
function PclTarHandlerDirCheck($p_dir)
{
$v_result = 1;
// Check the directory availability
if (is_dir($p_dir) || $p_dir == '')
{
return 1;
}
// Extract parent directory
$p_parent_dir = dirname($p_dir);
// Look for parent directory
if ($p_parent_dir != $p_dir && $p_parent_dir != '')
{
if (($v_result = PclTarHandlerDirCheck($p_parent_dir)) != 1)
{
return $v_result;
}
}
umask(0);
// Create the directory
if (!@mkdir($p_dir, 0777))
{
trigger_error('Failed to create archive directory in :: ' . $p_dir, E_USER_ERROR);
}
return 1;
}
// Look for file extension
function PclTarHandleExtension($p_tarname)
{
return (substr($p_tarname, -7) == '.tar.gz' || substr($p_tarname, -4) == '.tgz') ? 'tgz' : '';
}
function PclTarHandlePathReduction($p_dir)
{
$v_result = '';
// Look for not empty path
if ($p_dir)
{
// Explode path by directory names
$v_list = explode('/', $p_dir);
// Study directories from last to first
for ($i = sizeof($v_list) - 1; $i >= 0; $i--)
{
// Look for current path
if ($v_list[$i] == '.')
{
}
else if ($v_list[$i] == '..')
{
// Ignore it and ignore the $i-1
$i--;
}
else if ($v_list[$i] == '' && $i != (sizeof($v_list) - 1 && $i))
{
}
else
{
$v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? "/$v_result" : '');
}
}
}
return $v_result;
}
?>