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 = '') { 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; 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) { $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 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 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; } ?>