📄 class.zip.php
字号:
<?php
/** 文件名: zip.lib.php
* 描述: PKZIP 压缩与解压缩类.
*/
class PKZIP
{
var $zip_name = '';
var $file_name= ''; //临时文件名
var $zip_temp = ''; //ZIP临时目录
var $user_func_mkdir; //返回函数
var $user_func_endwrite;
var $user_func_getziplist;
var $user_func_getfileptr;
var $zip_ptr = NULL;
var $cd_fp = NULL; //临时目录文件指针
var $err_info = '';
function CheckArchiveBySeek($size)
{
fseek($this->zip_ptr, $size); // -1 or 0
if (ftell($this->zip_ptr) !== $size) { //FALSE or offset
$this->err_info .= "文件存在错误";
$this->ProcessError();
}
}
function ReadEndCentralDir(&$central_dir)
{
$zip_size = filesize($this->zip_name); //FALSE or size
$this->CheckArchiveBySeek($zip_size);
$end_is_found = FALSE;
if ($zip_size > 26) {
//fseek($this->zip_ptr, $zip_size-22);
$this->CheckArchiveBySeek($zip_size-22);
$end_signature = unpack('Vid', fread($this->zip_ptr, 4));
if ($end_signature['id'] == 0x06054b50) {
$end_is_found =TRUE;
}
$pos = ftell($this->zip_ptr);
}
if (!$end_is_found) {
$max_size = ($zip_size < 65557)?$zip_size:65557; //0xFFFF+22
//fseek($this->zip_ptr, $zip_size-$max_size);
$this->CheckArchiveBySeek($zip_size-$max_size);
//$pos = ftell($this->zip_ptr);
$pos = $zip_size - $max_size;
$bytes = 0x0;
while ($pos < $zip_size) {
$byte = fread($this->zip_ptr, 1);
$bytes=($bytes << 8) | Ord($byte);
$pos++;
if ($bytes == 0x504b0506) {
break;
}
}
if ($pos == $zip_size) {
$this->err_info .= "end record of centeral dir is Not found.";
$this->ProcessError();
}
}
$data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',
fread($this->zip_ptr, 18));
//$central_dir['comment']=(0 != $data['comment_size'])?
// fread($this->zip_ptr, $data['comment_size']):'';
if (0 != $data['comment_size'])
fseek($this->zip_ptr, $data['comment_size'], SEEK_CUR);
$central_dir['entries'] = $data['entries'];
$central_dir['disk_entries'] = $data['disk_entries'];
$central_dir['offset'] = $data['offset'];
$central_dir['disk_start'] = $data['disk_start'];
$central_dir['size'] = $data['size'];
$central_dir['disk'] = $data['disk'];
}
function ReadCentralFileHeader(&$header)
{
$header_signature = unpack('Vid', fread($this->zip_ptr, 4));
if ($header_signature['id'] != 0x02014b50) {
$this->err_info .= "中心的头错误";
$this->ProcessError();
}
$binary_data = fread($this->zip_ptr, 42);
$header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $binary_data);
$header['filename']=($header['filename_len'] != 0)?fread($this->zip_ptr, $header['filename_len']):'';
//$header['extra']=($header['extra_len'] != 0)?fread($this->zip_ptr, $header['extra_len']):'';
//$header['comment'] = ($header['comment_len'] != 0)?fread($this->zip_ptr, $header['comment_len']):'';
if ($header['extra_len'] != 0) fseek($this->zip_ptr, $header['extra_len'],SEEK_CUR);
if ($header['comment_len'] != 0) fseek($this->zip_ptr, $header['comment_len'],SEEK_CUR);
/*
if ($header['mdate'] && $header['mtime'])
{
$hour = ($header['mtime'] & 0xF800) >> 11;
$minute = ($header['mtime'] & 0x07E0) >> 5;
$seconde = ($header['mtime'] & 0x001F)*2;
$year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
$month = ($header['mdate'] & 0x01E0) >> 5;
$day = $header['mdate'] & 0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
}
else
{
$header['mtime'] = time();
}
*/
$header['stored_filename'] = $header['filename'];
$header['status'] = 'ok';
if (substr($header['filename'], -1) == '/')
//$header['external'] = 0x41FF0010;
$header['external'] = 0x00000010;
}
function ReadLocalFileHeader(&$header)
{
$local_signature = unpack('Vid', fread($this->zip_ptr, 4));
if ($local_signature['id'] != 0x04034b50){
$this->err_info .= "Local Header Signature Error";
$this->ProcessError();
}
$binary_data = fread($this->zip_ptr, 26);
$data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
$header['filename'] = fread($this->zip_ptr, $data['filename_len']);
//$header['extra']=($data['extra_len'] != 0)?fread($this->zip_ptr, $data['extra_len']):'';
if ($data['extra_len'] != 0) fseek($this->zip_ptr, $data['extra_len'], SEEK_CUR);
$header['version_extracted'] = $data['version'];
$header['compression'] = $data['compression'];
$header['size'] = $data['size'];
$header['compressed_size'] = $data['compressed_size'];
$header['crc'] = $data['crc'];
$header['flag'] = $data['flag'];
/*
$header['mdate'] = $data['mdate'];
$header['mtime'] = $data['mtime'];
if ($header['mdate'] && $header['mtime'])
{
$hour=($header['mtime']&0xF800)>>11;
$minute=($header['mtime']&0x07E0)>>5;
$seconde=($header['mtime']&0x001F)*2;
$year=(($header['mdate']&0xFE00)>>9)+1980;
$month=($header['mdate']&0x01E0)>>5;
$day=$header['mdate']&0x001F;
$header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
}
else
{
$header['mtime'] = time();
}
*/
$header['stored_filename'] = $header['filename'];
$header['status'] = "ok";
}
function VerifyFileHeaders(&$local_header, &$central_header)
{
if (($local_header['flag'] & 8) == 8) {
$local_header['size'] = $central_header['size'];
$local_header['compressed_size'] = $central_header['compressed_size'];
$local_header['crc'] = $central_header['crc'];
}
}
//向ZIP压缩包中添加文件.....
function PackLocalFile($is_dir)
{
$offset = ftell($this->zip_ptr);
$date = getdate();
$mtime = ($date['hours']<<11) + ($date['minutes']<<5) + $date['seconds']/2;
$mdate = (($date['year']-1980)<<9) + ($date['mon']<<5) + $date['mday'];
$filename_len = strlen($this->file_name);
$size = 0;
if (!$is_dir) { //file
$fp = call_user_func($this->user_func_getfileptr,$this,&$size);
$content = ($size>0)?fread($fp, $size):'';
fclose($fp);
$crc = crc32($content);
$content_compressed = gzdeflate($content);
$compressed_size = strlen($content_compressed);
unset($content);
$pack_method = 0x08;
$external = 0x0;
} else {
$compressed_size = 0;
$crc = 0;
$pack_method = 0x0;
$external = 0x10;
}
$binary_data = pack("VvvvvvVVVvv", 0x04034b50,
0x14, 0x0,$pack_method, $mtime, $mdate,
$crc, $compressed_size,$size,
$filename_len,0x0);
$binary_data .= $this->file_name ;
//LocalFileHeader
fwrite($this->zip_ptr, $binary_data, 30+$filename_len);
if(!$is_dir) {
$binary_data = pack('a'.$compressed_size,$content_compressed);
//Local File Data(Compressed)
fwrite($this->zip_ptr, $binary_data, $compressed_size);
}
//Central Dir Header
$binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
0x14, 0x0a, 0x0, $pack_method,
$mtime, $mdate,
$crc, $compressed_size, $size,
$filename_len,0x0, 0x0, 0x0, 0x0,
$external, $offset);
$binary_data .= $this->file_name ;
fwrite($this->cd_fp, $binary_data, 46+$filename_len );
}
function ZipDir($dir)
{
$entries = 0;
$stack[] = $dir;
while ($stack) {
$current_dir = array_pop($stack);
$this->file_name = $current_dir."/";
$this->PackLocalFile(TRUE);
$entries ++;
$file_list= call_user_func($this->user_func_getziplist,$current_dir);
foreach($file_list as $file) {
$this->file_name = "{$current_dir}/{$file['name']}";
if ($file['type'] == 1) {
$stack[] = $this->file_name;
} else {
$this->PackLocalFile(FALSE);
$entries ++;
}
}
}
return $entries;
}
function AddCenteralDir($entries_count)
{
$centeral_offset = ftell($this->zip_ptr);
$centeral_dir_size = ftell($this->cd_fp);
fclose($this->cd_fp);
//$centeral_dir_size =filesize("{$this->zip_temp}/centeral.dir");
$this->cd_fp = fopen("{$this->zip_temp}/centeral.dir","rb");
$binary_data = fread($this->cd_fp, $centeral_dir_size);
if (FALSE == fwrite($this->zip_ptr,$binary_data, $centeral_dir_size)){
$this->err_info .= "添加目录出现错误";
$this->ProcessError();
}
$binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $entries_count,
$entries_count, $centeral_dir_size, $centeral_offset, 0);
fwrite($this->zip_ptr, $binary_data, 22);
$this->CloseZip();
unlink("{$this->zip_temp}/centeral.dir");
}
function CreateZip($filename)
{
if (FALSE == ($this->zip_ptr = fopen($this->zip_temp.$filename, 'wb'))){
$this->err_info .= "不能建立文件:".$filename;
$this->ProcessError();
}
$this->zip_name = $filename;
if (FALSE == ($this->cd_fp = fopen("{$this->zip_temp}/centeral.dir","wb"))){
$this->err_info .= "不能创建临时目录";
$this->ProcessError();
}
}
function ExtractFile(&$entry)
{
$header = array();
$this->ReadLocalFileHeader($header);
$this->VerifyFileHeaders($header,$entry);
if ( ($entry['external']&0x00000010)==0x00000010 ) {
$is_dir = TRUE;
$path_name = $header['filename'];
} else {
$is_dir = FALSE;
$path_name = dirname($header['filename']);
}
call_user_func($this->user_func_mkdir,$path_name);
//unset($path_name);
if($is_dir == FALSE) {
//prepare write file
$dst_file = $this->zip_temp.basename($header['filename']);
if(($fp = fopen($dst_file, 'wb'))== NULL) {
$this->err_info .= "不能建立文件:".$dst_file;
}
//unset($dst_file);
$size = $header['compressed_size'];
//write file
if ($header['compression'] == 0) {
while ($size != 0) {
$read_size = ($size < 2048) ? $size : 2048;
$buffer = fread($this->zip_ptr, $read_size);
$binary_data = pack('a'.$read_size, $buffer); //NUL-padded string
fwrite($fp, $binary_data, $read_size);
$size -= $read_size;
}
} else {
$buffer = fread($this->zip_ptr, $size);
$file_content = gzinflate($buffer);
unset($buffer);
if ($file_content === FALSE) {
$header['status'] = "error";
$this->err_info .= "<br> Deflat Error";
$this->ProcessError();
}
fwrite($fp, $file_content, $header['size']);
unset($file_content);
}
fclose($fp);
call_user_func($this->user_func_endwrite,$header['filename'],$dst_file);
}
}
function X_Archive()
{
$central_dir = array();
$this->ReadEndCentralDir($central_dir);
$pos_entry = $central_dir['offset'];
for ($i=0; $i<$central_dir['entries']; $i++)
{
//rewind($this->zip_ptr);
fseek($this->zip_ptr, $pos_entry);
$header = array();
$this->ReadCentralFileHeader($header);
$header['index'] = $i;
$pos_entry = ftell($this->zip_ptr);
if ( ($header['compression'] != 8)
&& ($header['compression'] != 0)){
$this->err_info .= "不支持压缩方法";
$this->ProcessError();
}
if (($header['flag'] & 1) == 1){
$this->err_info .= "不支持加密";
$this->ProcessError();
}
//rewind($this->zip_ptr);
fseek($this->zip_ptr, $header['offset']);
$this->ExtractFile($header);
}
$this->CloseZip();
}
function GetList(&$info)
{
$central_dir = array();
$this->ReadEndCentralDir($central_dir);
rewind($this->zip_ptr);
$this->CheckArchiveBySeek($central_dir['offset']);
$header = array();
for ($i=0; $i<$central_dir['entries']; $i++){
$this->ReadCentralFileHeader($header);
$info[$i]['filename'] = $header['filename'];
$info[$i]['stored_filename'] = $header['stored_filename'];
$info[$i]['size'] = $header['size'];
$info[$i]['compressed_size']=$header['compressed_size'];
//$info[$i]['crc'] = strtoupper(dechex( $header['crc'] ));
//$info[$i]['mtime'] = $header['mtime'];
//$info[$i]['comment'] = $header['comment'];
//$info['folder'] = ($header['external']==0x41FF0010||$header['external']==16)?1:0;
$info[$i]['folder'] = (($header['external']&0x00000010)==0x00000010);
$info[$i]['index'] = $i;
$info[$i]['status'] = $header['status'];
}
$this->CloseZip();
}
function OpenZip($filename)
{
if (($this->zip_ptr = fopen($filename, 'rb')) == 0){
$this->err_info .= "不能打开文件";
$this->ProcessError();
}
$this->zip_name = $filename;
}
function CloseZip()
{
if ($this->zip_ptr!= NULL){
fclose($this->zip_ptr);
$this->zip_ptr = NULL;
$this->zip_name = '';
}
if (NULL !== $this->cd_fp)
fclose($this->cd_fp);
}
function GetErrorInfo()
{
return $this->err_info;
}
function ProcessError()
{
$this->CloseZip();
echo $this->err_info; //just debug,remove it
exit(-1);
}
function SetZipTemp($temp_dir)
{
$this->zip_temp = $temp_dir;
}
function RegisterCBFunc($mkdir,$endw,$getlist,$getptr)
{
$this->user_func_mkdir = $mkdir;
$this->user_func_endwrite = $endw;
$this->user_func_getziplist = $getlist;
$this->user_func_getfileptr = $getptr;
}
}
?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -