// --------------------------------------------------------------------------------
function privFileDescrExpand(&$p_filedescr_list, &$p_options)
// ----- Create a result list
$v_result_list = array();
for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
$v_descr = $p_filedescr_list[$i];
// ----- Reduce the filename
$v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
$v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
// ----- Look for real file or folder
if (file_exists($v_descr['filename'])) {
if (@is_file($v_descr['filename'])) {
$v_descr['type'] = 'file';
else if (@is_dir($v_descr['filename'])) {
$v_descr['type'] = 'folder';
else if (@is_link($v_descr['filename'])) {
// ----- Look for string added as file
else if (isset($v_descr['content'])) {
$v_descr['type'] = 'virtual_file';
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
return PclZip::errorCode();
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
// ----- Add the descriptor in result list
$v_result_list[sizeof($v_result_list)] = $v_descr;
if ($v_descr['type'] == 'folder') {
// ----- List of items in folder
$v_dirlist_descr = array();
if ($v_folder_handler = @opendir($v_descr['filename'])) {
while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
// ----- Skip '.' and '..'
if (($v_item_handler == '.') || ($v_item_handler == '..')) {
// ----- Compose the full filename
$v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
// ----- Look for different stored filename
// Because the name of the folder was changed, the name of the
// files/sub-folders also change
if (($v_descr['stored_filename'] != $v_descr['filename'])
&& (!isset($p_options[PCLZIP_OPT_RECopy_ALL_PATH]))) {
if ($v_descr['stored_filename'] != '') {
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
@closedir($v_folder_handler);
// TBC : unable to open folder in read mode
// ----- Expand each element of the list
if ($v_dirlist_nb != 0) {
if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
// ----- Concat the resulting list
$v_result_list = array_merge($v_result_list, $v_dirlist_descr);
// ----- Free local array
// ----- Get the result list
$p_filedescr_list = $v_result_list;
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCreate()
// --------------------------------------------------------------------------------
function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
$v_list_detail = array();
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the file in write mode
if (($v_result = $this->privOpenFd('wb')) != 1)
// ----- Add the list of files
$v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
$v_list_detail = array();
// ----- Look if the archive exists or is empty
if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
$v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the zip file
if (($v_result=$this->privOpenFd('rb')) != 1)
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
$this->privSwapBackMagicQuotes();
// ----- Go to beginning of File
// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Open the temporary file in write mode
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
return PclZip::errorCode();
// ----- Copy the files from the archive to the temporary file
// TBC : Here I should better append the file and go back to erase the central dir
$v_size = $v_central_dir['offset'];
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
// ----- Swap the file descriptor
// Here is a trick : I swap the temporary fd with the zip fd, in order to use
// the following methods on the temporary fil and not the real archive
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;
$v_header_list = array();
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
@unlink($v_zip_temp_name);
$this->privSwapBackMagicQuotes();
// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);
// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
$v_buffer = @fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
// ----- Create the Central Dir files header
for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
// ----- Create the file header
if ($v_header_list[$i]['status'] == 'ok') {
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
@unlink($v_zip_temp_name);
$this->privSwapBackMagicQuotes();
// ----- Transform the header to a 'usable' info
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
// ----- Zip file comment
$v_comment = $v_central_dir['comment'];
if (isset($p_options[PCLZIP_OPT_COMMENT])) {
$v_comment = $p_options[PCLZIP_OPT_COMMENT];
if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
$v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
$v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
// ----- Calculate the size of the central header
$v_size = @ftell($this->zip_fd)-$v_offset;
// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
// ----- Reset the file list
$this->privSwapBackMagicQuotes();
// ----- Swap back the file descriptor
$this->zip_fd = $v_zip_temp_fd;
$v_zip_temp_fd = $v_swap;
// ----- Close the temporary file
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Delete the zip file
// TBC : I should test the result ...
// ----- Rename the temporary file
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
PclZipUtilRename($v_zip_temp_name, $this->zipname);
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privOpenFd()
// --------------------------------------------------------------------------------
function privOpenFd($p_mode)
// ----- Look if already open
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
return PclZip::errorCode();
// ----- Open the zip file
if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
return PclZip::errorCode();
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privCloseFd()
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAddList()
// $p_add_dir and $p_reCopy_dir will give the ability to memorize a path which is
// different from the real path of the file. This is usefull if you want to have PclTar
// running in any directory, and memorize relative path from an other directory.
// $p_list : An array containing the file or directory names to add in the tar
// $p_result_list : list of added files with their properties (specially the status field)
// $p_add_dir : Path to add in the filename path archived
// $p_reCopy_dir : Path to reCopy in the filename path archived
// --------------------------------------------------------------------------------
// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_reCopy_dir, $p_reCopy_all_dir, &$p_options)
function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
$v_header_list = array();
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);
// ----- Create the Central Dir files header
for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
// ----- Create the file header
if ($v_header_list[$i]['status'] == 'ok') {
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
// ----- Transform the header to a 'usable' info
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
// ----- Zip file comment
if (isset($p_options[PCLZIP_OPT_COMMENT])) {
$v_comment = $p_options[PCLZIP_OPT_COMMENT];
// ----- Calculate the size of the central header
$v_size = @ftell($this->zip_fd)-$v_offset;
// ----- Create the central dir footer
if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
// ----- Reset the file list
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privAddFileList()
// $p_filedescr_list : An array containing the file description
// or directory names to add in the zip
// $p_result_list : list of added files with their properties (specially the status field)
// --------------------------------------------------------------------------------
function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
// ----- Recuperate the current number of elt in list
$v_nb = sizeof($p_result_list);
// ----- Loop on the files
for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
// ----- Format the filename
$p_filedescr_list[$j]['filename']
= PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
// ----- Skip empty file names
// TBC : Can this be possible ? not checked in DescrParseAtt ?
if ($p_filedescr_list[$j]['filename'] == "") {
// ----- Check the filename
if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
&& (!file_exists($p_filedescr_list[$j]['filename']))) {
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
return PclZip::errorCode();
// ----- Look if it is a file or a dir with no all path reCopy option
// or a dir with all its path reCopyd
// if ( (is_file($p_filedescr_list[$j]['filename']))
// || ( is_dir($p_filedescr_list[$j]['filename'])
if ( ($p_filedescr_list[$j]['type'] == 'file')
|| ($p_filedescr_list[$j]['type'] == 'virtual_file')
|| ( ($p_filedescr_list[$j]['type'] == 'folder')