// ----- Look for path to add
if (substr($p_add_dir, -1) == "/")
$v_stored_filename = $p_add_dir.$v_stored_filename;
$v_stored_filename = $p_add_dir."/".$v_stored_filename;
// ----- Filename (reduce the path of stored name)
$v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
$p_filedescr['stored_filename'] = $v_stored_filename;
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privWriteFileHeader()
// --------------------------------------------------------------------------------
function privWriteFileHeader(&$p_header)
// ----- Store the offset position of the file
$p_header['offset'] = ftell($this->zip_fd);
// ----- Transform UNIX mtime to DOS format mdate/mtime
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
$v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
$p_header['version_extracted'], $p_header['flag'],
$p_header['compression'], $v_mtime, $v_mdate,
$p_header['crc'], $p_header['compressed_size'],
strlen($p_header['stored_filename']),
// ----- Write the first 148 bytes of the header in the archive
fputs($this->zip_fd, $v_binary_data, 30);
// ----- Write the variable fields
if (strlen($p_header['stored_filename']) != 0)
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
if ($p_header['extra_len'] != 0)
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privWriteCentralFileHeader()
// --------------------------------------------------------------------------------
function privWriteCentralFileHeader(&$p_header)
//for(reset($p_header); $key = key($p_header); next($p_header)) {
// ----- Transform UNIX mtime to DOS format mdate/mtime
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
$v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
$p_header['version'], $p_header['version_extracted'],
$p_header['flag'], $p_header['compression'],
$v_mtime, $v_mdate, $p_header['crc'],
$p_header['compressed_size'], $p_header['size'],
strlen($p_header['stored_filename']),
$p_header['extra_len'], $p_header['comment_len'],
$p_header['disk'], $p_header['internal'],
$p_header['external'], $p_header['offset']);
// ----- Write the 42 bytes of the header in the zip file
fputs($this->zip_fd, $v_binary_data, 46);
// ----- Write the variable fields
if (strlen($p_header['stored_filename']) != 0)
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
if ($p_header['extra_len'] != 0)
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
if ($p_header['comment_len'] != 0)
fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privWriteCentralHeader()
// --------------------------------------------------------------------------------
function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
$v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
$p_offset, strlen($p_comment));
// ----- Write the 22 bytes of the header in the zip file
fputs($this->zip_fd, $v_binary_data, 22);
// ----- Write the variable fields
if (strlen($p_comment) != 0)
fputs($this->zip_fd, $p_comment, strlen($p_comment));
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
function privList(&$p_list)
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the zip file
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
return PclZip::errorCode();
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
$this->privSwapBackMagicQuotes();
// ----- Go to beginning of Central Dir
if (@fseek($this->zip_fd, $v_central_dir['offset']))
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
return PclZip::errorCode();
for ($i=0; $i<$v_central_dir['entries']; $i++)
// ----- Read the file header
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
$this->privSwapBackMagicQuotes();
// ----- Get the only interesting attributes
$this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
// ----- Close the zip file
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privConvertHeader2FileInfo()
// This function takes the file informations from the central directory
// entries and extract the interesting parameters that will be given back.
// The resulting file infos are set in the array $p_info
// $p_info['filename'] : Filename with full path. Given by user (add),
// extracted in the filesystem (extract).
// $p_info['stored_filename'] : Stored filename in the archive.
// $p_info['size'] = Size of the file.
// $p_info['compressed_size'] = Compressed size of the file.
// $p_info['mtime'] = Last modification date of the file.
// $p_info['comment'] = Comment associated with the file.
// $p_info['folder'] = true/false : indicates if the entry is a folder or not.
// $p_info['status'] = status of the action on the file.
// $p_info['crc'] = CRC of the file content.
// --------------------------------------------------------------------------------
function privConvertHeader2FileInfo($p_header, &$p_info)
// ----- Get the interesting attributes
$v_temp_path = PclZipUtilPathReduction($p_header['filename']);
$p_info['filename'] = $v_temp_path;
$v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']);
$p_info['stored_filename'] = $v_temp_path;
$p_info['size'] = $p_header['size'];
$p_info['compressed_size'] = $p_header['compressed_size'];
$p_info['mtime'] = $p_header['mtime'];
$p_info['comment'] = $p_header['comment'];
$p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
$p_info['index'] = $p_header['index'];
$p_info['status'] = $p_header['status'];
$p_info['crc'] = $p_header['crc'];
// --------------------------------------------------------------------------------
// --------------------------------------------------------------------------------
// Function : privExtractByRule()
// Extract a file or directory depending of rules (by index, by name, ...)
// $p_file_list : An array where will be placed the properties of each
// $p_path : Path to add while writing the extracted files
// $p_reCopy_path : Path to reCopy (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_reCopy_path does not apply to 'list' mode.
// $p_path and $p_reCopy_path are commulative.
// 1 on success,0 or less on error (see error code list)
// --------------------------------------------------------------------------------
function privExtractByRule(&$p_file_list, $p_path, $p_reCopy_path, $p_reCopy_all_path, &$p_options)
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
|| ( (substr($p_path, 0, 1) != "/")
&& (substr($p_path, 0, 3) != "../")
&& (substr($p_path,1,2)!=":/")))
// ----- Reduce the path last (and duplicated) '/'
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);
// ----- Look for path to reCopy format (should end by /)
if (($p_reCopy_path != "") && (substr($p_reCopy_path, -1) != '/'))
$p_reCopy_path_size = strlen($p_reCopy_path);
// ----- Open the zip file
if (($v_result = $this->privOpenFd('rb')) != 1)
$this->privSwapBackMagicQuotes();
// ----- Read the central directory informations
$v_central_dir = array();
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
// ----- Close the zip file
$this->privSwapBackMagicQuotes();
// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
// ----- Read next Central dir entry
if (@fseek($this->zip_fd, $v_pos_entry))
// ----- Close the zip file
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
return PclZip::errorCode();
// ----- Read the file header
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
// ----- Close the zip file
$this->privSwapBackMagicQuotes();
// ----- Store the file position
$v_pos_entry = ftell($this->zip_fd);
// ----- 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_extract); $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['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
&& (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
// ----- Look for a filename
elseif ($v_header['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['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['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_extract); $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 no rule, which means extract all the archive
// ----- Check compression method
&& ( ($v_header['compression'] != 8)
&& ($v_header['compression'] != 0))) {
$v_header['status'] = 'unsupported_compression';
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
"Filename '".$v_header['stored_filename']."' is "
."compressed by an unsupported compression "
."method (".$v_header['compression'].") ");
return PclZip::errorCode();
// ----- Check encrypted files
if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
$v_header['status'] = 'unsupported_encryption';
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
$this->privSwapBackMagicQuotes();
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
"Unsupported encryption for "
." filename '".$v_header['stored_filename']
return PclZip::errorCode();
// ----- Look for real extraction
if (($v_extract) && ($v_header['status'] != 'ok')) {
$v_result = $this->privConvertHeader2FileInfo($v_header,
$p_file_list[$v_nb_extracted++]);
$this->privSwapBackMagicQuotes();
// ----- Look for real extraction
// ----- Go to the file position
if (@fseek($this->zip_fd, $v_header['offset']))
// ----- Close the zip file