if ($p_local_header['flag'] != $p_central_header['flag']) {
if ($p_local_header['compression'] != $p_central_header['compression']) {
if ($p_local_header['mtime'] != $p_central_header['mtime']) {
if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
// ----- Look for flag bit 3
if (($p_local_header['flag'] & 8) == 8) {
$p_local_header['size'] = $p_central_header['size'];
$p_local_header['compressed_size'] = $p_central_header['compressed_size'];
$p_local_header['crc'] = $p_central_header['crc'];
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privReadEndCentralDir()
// --------------------------------------------------------------------------------
function privReadEndCentralDir(&$p_central_dir)
// ----- Go to the end of the zip file
$v_size = filesize($this->zipname);
@fseek($this->zip_fd, $v_size);
if (@ftell($this->zip_fd) != $v_size)
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
return PclZip::errorCode();
// ----- First try : look if this is an archive with no commentaries (most of the time)
// in this case the end of central dir is at 22 bytes of the file end
@fseek($this->zip_fd, $v_size-22);
if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
return PclZip::errorCode();
$v_binary_data = @fread($this->zip_fd, 4);
$v_data = @unpack('Vid', $v_binary_data);
if ($v_data['id'] == 0x06054b50) {
$v_pos = ftell($this->zip_fd);
// ----- Go back to the maximum possible size of the Central Dir End Record
$v_maximum_size = 65557; // 0xFFFF + 22;
if ($v_maximum_size > $v_size)
$v_maximum_size = $v_size;
@fseek($this->zip_fd, $v_size-$v_maximum_size);
if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
return PclZip::errorCode();
// ----- Read byte per byte in order to find the signature
$v_pos = ftell($this->zip_fd);
$v_byte = @fread($this->zip_fd, 1);
//$v_bytes = ($v_bytes << 8) | Ord($v_byte);
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
// ----- Compare the bytes
if ($v_bytes == 0x504b0506)
// ----- Look if not found end of central dir
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
return PclZip::errorCode();
// ----- Read the first 18 bytes of the header
$v_binary_data = fread($this->zip_fd, 18);
// ----- Look for invalid block size
if (strlen($v_binary_data) != 18)
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
return PclZip::errorCode();
// ----- Extract the values
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
// ----- Check the global size
if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
// ----- ReCopyd in release 2.2 see readme file
// The check of the file size is a little too strict.
// Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
// While decrypted, zip has training 0 bytes
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
'The central dir is not at the end of the archive.'
.' Some trailing bytes exists after the archive.');
return PclZip::errorCode();
if ($v_data['comment_size'] != 0) {
$p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
$p_central_dir['comment'] = '';
$p_central_dir['entries'] = $v_data['entries'];
$p_central_dir['disk_entries'] = $v_data['disk_entries'];
$p_central_dir['offset'] = $v_data['offset'];
$p_central_dir['size'] = $v_data['size'];
$p_central_dir['disk'] = $v_data['disk'];
$p_central_dir['disk_start'] = $v_data['disk_start'];
//for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privDeleteByRule()
// --------------------------------------------------------------------------------
function privDeleteByRule(&$p_result_list, &$p_options)
$v_list_detail = array();
// ----- Open the zip file
if (($v_result=$this->privOpenFd('rb')) != 1)
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
// ----- Go to beginning of File
// ----- Scan all the files
// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];
if (@fseek($this->zip_fd, $v_pos_entry))
// ----- Close the zip file
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
return PclZip::errorCode();
$v_header_list = array();
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
// ----- Read the file header
$v_header_list[$v_nb_extracted] = array();
if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
// ----- Close the zip file
$v_header_list[$v_nb_extracted]['index'] = $i;
// ----- Look for the specific extract rules
// ----- Look for extract by name rule
if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
// ----- Look if the filename is in the list
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
// ----- Look for a directory
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
// ----- Look if the directory is in the filename path
if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
&& (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
&& ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
// ----- Look for a filename
elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
// ----- Look for extract by ereg rule
// ereg() is deprecated with PHP 5.3
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
// ----- Look for extract by preg rule
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
// ----- Look for extract by index rule
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
// ----- Look if the index is in the list
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
// ----- Look for deletion
unset($v_header_list[$v_nb_extracted]);
// ----- Look if something need to be deleted
if ($v_nb_extracted > 0) {
// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Creates a temporary zip archive
$v_temp_zip = new PclZip($v_zip_temp_name);
// ----- Open the temporary zip file in write mode
if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
// ----- Look which file need to be kept
for ($i=0; $i<sizeof($v_header_list); $i++) {
// ----- Calculate the position of the header
if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
// ----- Close the zip file
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
return PclZip::errorCode();
// ----- Read the file header
$v_local_header = array();
if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
// ----- Close the zip file
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Check that local file header is same as central file header
if ($this->privCheckFileHeaders($v_local_header,
$v_header_list[$i]) != 1) {
// ----- Write the file header
if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
// ----- Close the zip file
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Read/write the data block
if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
// ----- Close the zip file
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Store the offset of the central dir
$v_offset = @ftell($v_temp_zip->zip_fd);
// ----- Re-Create the Central Dir files header
for ($i=0; $i<sizeof($v_header_list); $i++) {
// ----- Create the file header
if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Transform the header to a 'usable' info
$v_temp_zip->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($v_temp_zip->zip_fd)-$v_offset;
// ----- Create the central dir footer
if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
// ----- Reset the file list
$v_temp_zip->privCloseFd();
@unlink($v_zip_temp_name);
$v_temp_zip->privCloseFd();
// ----- 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);
// ----- Destroy the temporary archive
// ----- ReCopy every files : reset the file
else if ($v_central_dir['entries'] != 0) {
if (($v_result = $this->privOpenFd('wb')) != 1) {
if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privDirCheck()
// Check if a directory exists, if not it creates it and all the parents directory
// $p_dir : Directory path to check.
// -1 : Unable to create directory
// --------------------------------------------------------------------------------
function privDirCheck($p_dir, $p_is_dir=false)
// ----- ReCopy the final '/'