protected function readCentralDirectory()
{
$strMbCharset = null;
// Set the mbstring encoding to ASCII (see #5842)
if (ini_get('mbstring.func_overload') > 0) {
$strMbCharset = mb_internal_encoding();
if (mb_internal_encoding('ASCII') === false) {
$strMbCharset = null;
}
}
$intOffset = 0;
$pos = 0;
$intInterval = min(filesize(TL_ROOT . '/' . $this->strFile), 1024);
$strBuffer = '';
// Read to delimiter
do {
$intOffset -= $intInterval;
$fseek = @fseek($this->resFile, $intOffset, SEEK_END);
$strBuffer = @fread($this->resFile, abs($intOffset)) . $strBuffer;
} while ($fseek != -1 && ($pos = strpos($strBuffer, self::CENTRAL_DIR_END)) === false);
// Reposition pointer
fseek($this->resFile, $intOffset + $pos, SEEK_END);
$strSignature = @fread($this->resFile, 4);
// Read archive header
if ($strSignature != self::CENTRAL_DIR_END) {
throw new \Exception('Error reading central directory');
}
$arrHeader = array();
$arrHeader['number_of_this_disk'] = unpack('v', @fread($this->resFile, 2));
$arrHeader['number_of_disk_with_cd'] = unpack('v', @fread($this->resFile, 2));
$arrHeader['total_cd_entries_disk'] = unpack('v', @fread($this->resFile, 2));
$arrHeader['total_cd_entries'] = unpack('v', @fread($this->resFile, 2));
$arrHeader['size_of_cd'] = unpack('V', @fread($this->resFile, 4));
$arrHeader['offset_start_cd'] = unpack('V', @fread($this->resFile, 4));
$arrHeader['zipfile_comment_length'] = unpack('v', @fread($this->resFile, 2));
$arrHeader['zipfile_comment'] = $arrHeader['zipfile_comment_length'][1] ? @fread($this->resFile, $arrHeader['zipfile_comment_length'][1]) : '';
// Eliminate nested arrays
foreach ($arrHeader as $k => $v) {
$arrHeader[$k] = is_array($v) ? $v[1] : $v;
}
$this->arrHeader = $arrHeader;
// Reposition pointer to begin of the central directory
fseek($this->resFile, $this->arrHeader['offset_start_cd'], SEEK_SET);
$strSignature = @fread($this->resFile, 4);
// Build file list
while ($strSignature == self::CENTRAL_DIR_START) {
$arrFile = array();
$arrFile['version_made_by'] = unpack('v', @fread($this->resFile, 2));
$arrFile['version_needed_to_extract'] = unpack('v', @fread($this->resFile, 2));
$arrFile['general_purpose_bit_flag'] = unpack('v', @fread($this->resFile, 2));
$arrFile['compression_method'] = unpack('v', @fread($this->resFile, 2));
$arrFile['last_mod_file_time'] = unpack('v', @fread($this->resFile, 2));
$arrFile['last_mod_file_date'] = unpack('v', @fread($this->resFile, 2));
$arrFile['crc-32'] = unpack('V', @fread($this->resFile, 4));
$arrFile['compressed_size'] = unpack('V', @fread($this->resFile, 4));
$arrFile['uncompressed_size'] = unpack('V', @fread($this->resFile, 4));
$arrFile['file_name_length'] = unpack('v', @fread($this->resFile, 2));
$arrFile['extra_field_length'] = unpack('v', @fread($this->resFile, 2));
$arrFile['file_comment_length'] = unpack('v', @fread($this->resFile, 2));
$arrFile['disk_number_start'] = unpack('v', @fread($this->resFile, 2));
$arrFile['internal_file_attributes'] = unpack('v', @fread($this->resFile, 2));
$arrFile['external_file_attributes'] = unpack('V', @fread($this->resFile, 4));
$arrFile['offset_of_local_header'] = unpack('V', @fread($this->resFile, 4));
$arrFile['file_name'] = @fread($this->resFile, $arrFile['file_name_length'][1]);
$arrFile['extra_field'] = $arrFile['extra_field_length'][1] ? @fread($this->resFile, $arrFile['extra_field_length'][1]) : '';
$arrFile['file_comment'] = $arrFile['file_comment_length'][1] ? @fread($this->resFile, $arrFile['file_comment_length'][1]) : '';
// Skip directories
if (substr($arrFile['file_name'], -1) == '/') {
$strSignature = @fread($this->resFile, 4);
continue;
}
// Eliminate nested arrays
foreach ($arrFile as $k => $v) {
$arrFile[$k] = is_array($v) ? $v[1] : $v;
}
// Split file path
$arrFile['file_basename'] = basename($arrFile['file_name']);
$arrFile['file_dirname'] = ($path = dirname($arrFile['file_name'])) != '.' ? $path : '';
// Add UNIX time
$arrFile['last_mod_file_unix'] = $this->decToUnix((int) $arrFile['last_mod_file_time'], (int) $arrFile['last_mod_file_date']);
// Read next signature
$strSignature = @fread($this->resFile, 4);
$this->arrFiles[] = $arrFile;
}
$this->intLast = count($this->arrFiles) - 1;
// Restore the mbstring encoding (see #5842)
$strMbCharset && mb_internal_encoding($strMbCharset);
}