From 852f552b4af0fefcecf651c87bf0fc698ef498e4 Mon Sep 17 00:00:00 2001 From: "Paul S. Owen" Date: Mon, 21 Jul 2003 15:44:39 +0000 Subject: add .tar, .tar.gz and .tar.bz2 support, rejiggle source, seperate compress objects extending the base class git-svn-id: file:///svn/phpbb/trunk@4305 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/functions_compress.php | 2085 ++------------------------------- 1 file changed, 92 insertions(+), 1993 deletions(-) (limited to 'phpBB/includes/functions_compress.php') diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index 4f964a8fad..71efca7ece 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -10,51 +10,20 @@ // TODO // Extract files -class archive_zip +class compress { - 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)) { + $src_prefix = ($src_prefix) ? preg_replace('#^(' . preg_quote($src_prefix) . ')#', '', $src) : $src; + if (!($fp = @fopen($phpbb_root_path . $src, 'rb'))) { return false; @@ -63,10 +32,17 @@ class archive_zip $data = fread($fp, filesize($phpbb_root_path . $src)); fclose($fp); - $this->data($src_prefix, $data); + $this->data($src_prefix, $data, filemtime($phpbb_root_path . $src), false); } else if (is_dir($phpbb_root_path . $src)) { + // 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; + $filelist = filelist($phpbb_root_path . $src, '', '*'); ksort($filelist); @@ -106,6 +82,36 @@ class archive_zip $this->data($name, $src); return true; } +} + +class compress_zip extends compress +{ + + 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; + + function compress_zip($mode, $file) + { + return $this->fp = @fopen($phpbb_root_path . $file, $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 extract($dst) { @@ -197,1990 +203,83 @@ class archive_zip } } -// -------------------------------------------------------------------------------- -// 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) +// Tar/tar.gz compression routine +// Header/checksum creation derived from tarfile.pl, © Tom Horsley, 1994 +class compress_tar extends compress { - - $v_result = 1; - $v_header = array(); - - // Recuperate the current number of elt in list - $v_nb = sizeof($p_list_detail); + var $fzopen = ''; + var $fzclose = ''; + var $fzread = ''; + var $fzwrite = ''; + var $fzseek = ''; + var $isgz = false; - // Check the parameters - if ($p_tar == 0) + function compress_tar($mode, $file) { - // 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; ($jisgz = (strpos($file, '.tar.gz') !== false || strpos($file, '.tgz') !== false) ? true : false; + $this->isbz = (strpos($file, '.tar.bz2') !== false) ? true : false; - // 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; + $this->fzopen = ($this->isbz && function_exists('bzopen')) ? 'bzopen' : (($this->isgz && extension_loaded('zlib')) ? 'gzopen' : 'fopen'); + $this->fzclose = ($this->isbz && function_exists('bzclose')) ? 'bzclose' : (($this->isgz && extension_loaded('zlib')) ? 'gzclose' : 'fclose'); + $this->fzread = ($this->isbz && function_exists('bzread')) ? 'bzread' : (($this->isgz && extension_loaded('zlib')) ? 'gzread' : 'fread'); + $this->fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && extension_loaded('zlib')) ? 'gzwrite' : 'fwrite'); - // Check the parameters - if ($p_tar == 0) - { - // Return - trigger_error(PclErrorString(), E_USER_ERROR); - + $fzopen = $this->fzopen; + return $this->fp = @$fzopen($phpbb_root_path . $file, $mode . 'b'); } - // Skip empty file names - if ($p_filename == '') + function extract($dst) { - // 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 != "") + function close() { - 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; - + $fzclose = $this->fzclose; + $fzclose($this->fp); } - // Check the path length - if (strlen($v_stored_filename) > 99) + function data($name, $data, $mtime = false, $is_dir = false) { - // Error log - + $fzwrite = $this->fzwrite; + $fzread = $this->fzread; - // Return - trigger_error(PclErrorString(), E_USER_ERROR); - - } + $mode = ($is_dir) ? '493' : '436'; + $mtime = (!$mtime) ? time() : $mtime; + $filesize = ($is_dir) ? 0 : strlen($data); + $typeflag = ($is_dir) ? '5' : ''; - // Look for a file - if (is_file($p_filename)) - { - // Open the source file - if (($v_file = fopen($p_filename, "rb")) == 0) - { - // Error log - + $header = pack("x512", 0); + $header = substr_replace($header, pack("a100", $name), 0, 100); + $header = substr_replace($header, pack("a8", sprintf("%07o", $mode)), 100, 8); +// $header = substr_replace($header, pack("a8", sprintf("%07o", 0)), 108, 8); +// $header = substr_replace($header, pack("a8", sprintf("%07o", 0)), 116, 8); + $header = substr_replace($header, pack("a12", sprintf("%011o", $filesize)), 124, 12); + $header = substr_replace($header, pack("a12", sprintf("%011o", $mtime)), 136, 12); + $header = substr_replace($header, pack("a", $typeflag), 156, 1); - // Return - trigger_error(PclErrorString(), E_USER_ERROR); - - } + $header = substr_replace($header, 'ustar', 257, 5); + $header = substr_replace($header, '00', 263, 2); - // 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; - } + // Space padded for checksum + $header = substr_replace($header, ' ', 148, 8); - // Read the file by 512 octets blocks - $i=0; - while (($v_buffer = fread($v_file, 512)) != "") + for ($i = 0; $i < 512; $i++) { - $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++; + $b = unpack("c1char", substr($header, $i, 1)); + $checksum += $b['char']; } - + $header = substr_replace($header, pack("a8",sprintf("%07o", $checksum)), 148, 8); - // Close the file - fclose($v_file); - } + $fzwrite($this->fp, $header); - // 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) + $i = 0; + // Read the data 512 bytes at a time and write it out + while ($buffer = substr($data, $i, 512)) { - // Return status - - return $v_result; + $fzwrite($this->fp, pack("a512", $buffer)); + $i += 512; } } - - // 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 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 $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 $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= 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; } ?> \ No newline at end of file -- cgit v1.2.1