⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 class.zip.php

📁 php文件压缩类
💻 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 + -