<?
/********************
作者未知
整理:Longbill(www.longbill.cn;longbill.cn@gmail.com)
*********************/
classzip
{
var$datasec,$ctrl_dir=array();
var$eof_ctrl_dir="x50x4bx05x06x00x00x00x00";
var$old_offset=0;var$dirs=Array(".");
functionget_List($zip_name)
{
$zip=@fopen($zip_name,'rb');
if(!$zip)return(0);
$centd=$this->ReadCentralDir($zip,$zip_name);
@rewind($zip);
@fseek($zip,$centd['offset']);
for($i=0;$i<$centd['entries'];$i++)
{
$header=$this->ReadCentralFileHeaders($zip);
$header['index']=$i;$info['filename']=$header['filename'];
$info['stored_filename']=$header['stored_filename'];
$info['size']=$header['size'];$info['compressed_size']=$header['compressed_size'];
$info['crc']=strtoupper(dechex($header['crc']));
$info['mtime']=$header['mtime'];$info['comment']=$header['comment'];
$info['folder']=($header['external']==0x41FF0010||$header['external']==16)?1:0;
$info['index']=$header['index'];$info['status']=$header['status'];
$ret[]=$info;unset($header);
}
return$ret;
}
functionAdd($files,$compact)
{
if(!is_array($files[0]))$files=Array($files);
for($i=0;$files[$i];$i++){
$fn=$files[$i];
if(!in_Array(dirname($fn[0]),$this->dirs))
$this->add_Dir(dirname($fn[0]));
if(basename($fn[0]))
$ret[basename($fn[0])]=$this->add_File($fn[1],$fn[0],$compact);
}
return$ret;
}
functionget_file()
{
$data=implode('',$this->datasec);
$ctrldir=implode('',$this->ctrl_dir);
return$data.$ctrldir.$this->eof_ctrl_dir.
pack('v',sizeof($this->ctrl_dir)).pack('v',sizeof($this->ctrl_dir)).
pack('V',strlen($ctrldir)).pack('V',strlen($data))."x00x00";
}
functionadd_dir($name)
{
$name=str_replace("","/",$name);
$fr="x50x4bx03x04x0ax00x00x00x00x00x00x00x00x00";
$fr.=pack("V",0).pack("V",0).pack("V",0).pack("v",strlen($name));
$fr.=pack("v",0).$name.pack("V",0).pack("V",0).pack("V",0);
$this->datasec[]=$fr;
$new_offset=strlen(implode("",$this->datasec));
$cdrec="x50x4bx01x02x00x00x0ax00x00x00x00x00x00x00x00x00";
$cdrec.=pack("V",0).pack("V",0).pack("V",0).pack("v",strlen($name));
$cdrec.=pack("v",0).pack("v",0).pack("v",0).pack("v",0);
$ext="xffxffxffxff";
$cdrec.=pack("V",16).pack("V",$this->old_offset).$name;
$this->ctrl_dir[]=$cdrec;
$this->old_offset=$new_offset;
$this->dirs[]=$name;
}
functionadd_File($data,$name,$compact=1)
{
$name=str_replace('','/',$name);
$dtime=dechex($this->DosTime());
$hexdtime='x'.$dtime[6].$dtime[7].'x'.$dtime[4].$dtime[5]
.'x'.$dtime[2].$dtime[3].'x'.$dtime[0].$dtime[1];
eval('$hexdtime="'.$hexdtime.'";');
if($compact)
$fr="x50x4bx03x04x14x00x00x00x08x00".$hexdtime;
else$fr="x50x4bx03x04x0ax00x00x00x00x00".$hexdtime;
$unc_len=strlen($data);$crc=crc32($data);
if($compact){
$zdata=gzcompress($data);$c_len=strlen($zdata);
$zdata=substr(substr($zdata,0,strlen($zdata)-4),2);
}else{
$zdata=$data;
}
$c_len=strlen($zdata);
$fr.=pack('V',$crc).pack('V',$c_len).pack('V',$unc_len);
$fr.=pack('v',strlen($name)).pack('v',0).$name.$zdata;
$fr.=pack('V',$crc).pack('V',$c_len).pack('V',$unc_len);
$this->datasec[]=$fr;
$new_offset=strlen(implode('',$this->datasec));
if($compact)
$cdrec="x50x4bx01x02x00x00x14x00x00x00x08x00";
else$cdrec="x50x4bx01x02x14x00x0ax00x00x00x00x00";
$cdrec.=$hexdtime.pack('V',$crc).pack('V',$c_len).pack('V',$unc_len);
$cdrec.=pack('v',strlen($name)).pack('v',0).pack('v',0);
$cdrec.=pack('v',0).pack('v',0).pack('V',32);
$cdrec.=pack('V',$this->old_offset);
$this->old_offset=$new_offset;
$cdrec.=$name;
$this->ctrl_dir[]=$cdrec;
returntrue;
}
functionDosTime(){
$timearray=getdate();
if($timearray['year']<1980){
$timearray['year']=1980;$timearray['mon']=1;
$timearray['mday']=1;$timearray['hours']=0;
$timearray['minutes']=0;$timearray['seconds']=0;
}
return(($timearray['year']-1980)<<25)|($timearray['mon']<<21)|($timearray['mday']<<16)|($timearray['hours']<<11)|
($timearray['minutes']<<5)|($timearray['seconds']>>1);
}
functionExtract($zn,$to,$index=Array(-1))
{
$ok=0;$zip=@fopen($zn,'rb');
if(!$zip)return(-1);
$cdir=$this->ReadCentralDir($zip,$zn);
$pos_entry=$cdir['offset'];
if(!is_array($index)){$index=array($index);}
for($i=0;$index[$i];$i++){
if(intval($index[$i])!=$index[$i]||$index[$i]>$cdir['entries'])
return(-1);
}
for($i=0;$i<$cdir['entries'];$i++)
{
@fseek($zip,$pos_entry);
$header=$this->ReadCentralFileHeaders($zip);
$header['index']=$i;$pos_entry=ftell($zip);
@rewind($zip);fseek($zip,$header['offset']);
if(in_array("-1",$index)||in_array($i,$index))
$stat[$header['filename']]=$this->ExtractFile($header,$to,$zip);
}
fclose($zip);
return$stat;
}
functionReadFileHeader($zip)
{
$binary_data=fread($zip,30);
$data=unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len',$binary_data);
$header['filename']=fread($zip,$data['filename_len']);
if($data['extra_len']!=0){
$header['extra']=fread($zip,$data['extra_len']);
}else{$header['extra']='';}
$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";
return$header;
}
functionReadCentralFileHeaders($zip){
$binary_data=fread($zip,46);
$header=unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset',$binary_data);
if($header['filename_len']!=0)
$header['filename']=fread($zip,$header['filename_len']);
else$header['filename']='';
if($header['extra_len']!=0)
$header['extra']=fread($zip,$header['extra_len']);
else$header['extra']='';
if($header['comment_len']!=0)
$header['comment']=fread($zip,$header['comment_len']);
else$header['comment']='';
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;
return$header;
}
functionReadCentralDir($zip,$zip_name)
{
$size=filesize($zip_name);
if($size<277)$maximum_size=$size;
else$maximum_size=277;
@fseek($zip,$size-$maximum_size);
$pos=ftell($zip);$bytes=0x00000000;
while($pos<$size)
{
$byte=@fread($zip,1);$bytes=($bytes<<8)|Ord($byte);
if($bytes==0x504b0506){$pos++;break;}$pos++;
}
$data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',fread($zip,18));
if($data['comment_size']!=0)
$centd['comment']=fread($zip,$data['comment_size']);
else$centd['comment']='';$centd['entries']=$data['entries'];
$centd['disk_entries']=$data['disk_entries'];
$centd['offset']=$data['offset'];$centd['disk_start']=$data['disk_start'];
$centd['size']=$data['size'];$centd['disk']=$data['disk'];
return$centd;
}
functionExtractFile($header,$to,$zip)
{
$header=$this->readfileheader($zip);
if(substr($to,-1)!="/")$to.="/";
if(!@is_dir($to))@mkdir($to,0777);
$pth=explode("/",dirname($header['filename']));
for($i=0;isset($pth[$i]);$i++){
if(!$pth[$i])continue;$pthss.=$pth[$i]."/";
if(!is_dir($to.$pthss))@mkdir($to.$pthss,0777);
}
if(!($header['external']==0x41FF0010)&&!($header['external']==16))
{
if($header['compression']==0)
{
$fp=@fopen($to.$header['filename'],'wb');
if(!$fp)return(-1);
$size=$header['compressed_size'];
while($size!=0)
{
$read_size=($size<2048?$size:2048);
$buffer=fread($zip,$read_size);
$binary_data=pack('a'.$read_size,$buffer);
@fwrite($fp,$binary_data,$read_size);
$size-=$read_size;
}
fclose($fp);
touch($to.$header['filename'],$header['mtime']);
}else{
$fp=@fopen($to.$header['filename'].'.gz','wb');
if(!$fp)return(-1);
$binary_data=pack('va1a1Va1a1',0x8b1f,Chr($header['compression']),
Chr(0x00),time(),Chr(0x00),Chr(3));
fwrite($fp,$binary_data,10);
$size=$header['compressed_size'];
while($size!=0)
{
$read_size=($size<1024?$size:1024);
$buffer=fread($zip,$read_size);
$binary_data=pack('a'.$read_size,$buffer);
@fwrite($fp,$binary_data,$read_size);
$size-=$read_size;
}
$binary_data=pack('VV',$header['crc'],$header['size']);
fwrite($fp,$binary_data,8);fclose($fp);
$gzp=@gzopen($to.$header['filename'].'.gz','rb')ordie("Cettearchiveestcompress");
if(!$gzp)return(-2);
$fp=@fopen($to.$header['filename'],'wb');
if(!$fp)return(-1);
$size=$header['size'];
while($size!=0)
{
$read_size=($size<2048?$size:2048);
$buffer=gzread($gzp,$read_size);
$binary_data=pack('a'.$read_size,$buffer);
@fwrite($fp,$binary_data,$read_size);
$size-=$read_size;
}
fclose($fp);gzclose($gzp);
touch($to.$header['filename'],$header['mtime']);
@unlink($to.$header['filename'].'.gz');
}}
returntrue;
}
}
?>
打包文件下载