sele 发表于 2017-3-27 12:28:35

PHP生成.cab安装包

  用php来生成.cab格式的压缩包,能在线制作windows 的安装文件包.
  MakeCAB.class.php
  <?php/** * @package MakeCAB * @example/examplecab.phpExample usage of this class.* @category   File Formats* @author Sam Shull <samshull@samshull.com>* @copyright Copyright (c) 2007, Sam Shull* @license http://www.samshull.com/bsdlicense.txt BSD License* @link       http://samshull.com/examplecab.php* @version    0.9* @access   public*/class MakeCAB{/*** Absolute / Relative Path to cab file** @var string* @access protected*/var $cabfile;/*** Array of files to be added to archive** @var array* @access protected*/var $cabfiles          =array();/*** Array of data for CAB folder** @var array* @access protected*/var $cabfolder         =array('offset'   => 44,## offset of data'numblocks'=> 0,   ## number of blocks'typecmp'    => 1,   ## 0 = no compression; 1 = MSZIP; LZX'fileoffset' => 0);/*** Array of data for CAB Header** @var array* @access protected*/var $cabheader         =array('sig'      => "MSCF",## signature'res1'       => 0,          ## reserved space'size'       => 44,## total size of cab file'res2'       => 0,'offset'   => 44,## offset of first data block'res3'       => 0,'vmaj'       => 1,## cab file format major version number 1'vmin'       => 3,## cab file format minor version number 3'numfolders' => 1,## must have at least one folder NewCABFolder()'numfiles'   => 0,## number of files in cab file'flags'      => 0,      ## not supported'setid'      => 1234,## set ID (not supported)'cabid'      => 0,   ##cab id not supported);/*** Max data block size** @var integer* @access protected*/var $BLOCKSIZE      =32768;/*** Linux Seperator** @var string* @access protected*/var $LINSEP         ='/';/*** Windows Seperator** @var string* @access protected*/var $WINSEP         ='//';/*** Method: MakeCAB __construct*   Construct* @param string $file- file that will be written to* @param int $typecmp- level of compression*/function MakeCAB($file,$typecmp=1){$this->cabfile = $file;$this->cabfolder['typecmp'] = ($typecmp > 0 && extension_loaded('zlib')) ? $typecmp : 0;}/*** Method: WriteCab*   Write the data to a file*/function WriteCAB(){$this->cabfolder['numblocks'] = ceil($this->cabfolder['fileoffset']/$this->BLOCKSIZE);$this->cabheader['size'] += ($this->cabfolder['numblocks'] * 8);if(false !== ($res = fopen( $this->cabfile, "w+b" ))){$this->WriteHeader($res);$this->WriteFolder($res);$this->WriteFiles($res);$this->WriteData($res);$this->UpdateCABsize($res);fclose( $res );} else {die("Failed to open ".$this->cabfile);}}//Update the file size in the header (occassional errors with filesize caused by compression & using strlen as a byte counter)function UpdateCABsize($res){$t = ftell($res);fseek($res,8);$this->WriteDword( $res, $t );}/*** Method: addfile*   Add a local file system file to your cab file* @param string $file - path preferably absolute path* @param bool|string $strip- if string is used parser will leave on the path what it is told to *                              e.g.: $file="/usr/path/data/file" $strip="/path" will result in an archive entry="/path/data/file"*                              a strip value of (bool) false then would result in archive entry= "/usr/path/data/file"* @param int $atribs - e.g hidden, read-only- see sdk*/function addfile($file,$strip=true,$atribs=32){$filename = $strip==false ? $this->MakeWinPath( $file ) : $this->StripPath($file,$strip);$m=stat($file);$newcabfile = array('ucomp' => $m['size'],'offset' => $this->cabfolder['fileoffset'],'date' => $this->MakeCabFileDate($m['mtime']),'time' => $this->MakeCabFileTime($m['mtime']),'atribs' => $atribs,'name' => $this->MakeWinPath($filename)."/0",'path' => $file,'size' => $m['size'] );$this->cabfolder['fileoffset'] += $m['size'];$this->cabfolder['offset'] += 17 + strlen( $filename );$this->cabheader['size'] += 17 + strlen( $filename ) + $m['size'];$this->cabheader['numfiles']++;$this->cabfiles[]=$newcabfile;clearstatcache();}/*** Method: addurl*   Add a file from a url using any stream that can be handled by PHP*    for parameter descriptions see addfile descriptions* @param string $file* @param bool|string $strip* @param int $atribs*/ function addurl($file,$strip=true,$atribs=32){$x = file_get_contents($file);$filename = $strip==false ? $this->MakeWinPath( preg_replace("@^.*://@","/",$file) ) : $this->StripPath($file,$strip);$filen = dirname(__FILE__).$this->StripPath($file,true).".cabtemp";file_put_contents($filen,$x);$m=stat($filen);$newcabfile = array('ucomp' => $m['size'],'offset' => $this->cabfolder['fileoffset'],'date' => $this->MakeCabFileDate($m['mtime']),'time' => $this->MakeCabFileTime($m['mtime']),'atribs' => $atribs,'name' => $this->MakeWinPath($filename)."/0",'path' => $filen,'size' => $m['size'] );$this->cabfolder['fileoffset'] += $m['size'];$this->cabfolder['offset'] += 17 + strlen( $filename );$this->cabheader['size'] += 17 + strlen( $filename ) + $m['size'];$this->cabheader['numfiles']++;$this->cabfiles[]=$newcabfile;clearstatcache();}/*** Method: adddir*   Add an entire file system directory to your cab file*    for parameter descriptions see addfile descriptions* @param string $dir* @param bool|string $strip* @param int $atribs*/function adddir($dir,$strip=true,$atribs=32){$dir = preg_match("/(//|////)$/",$dir) ? $dir : $dir.$this->LINSEP;if($d = opendir($dir) ){while(false !== ($file = readdir($d)) ){if(is_file($dir.$file)){$filename = $strip==false ? $this->MakeWinPath( $dir.$file ) : $this->StripPath($dir.$file,$strip);$m=stat($dir.$file);$newcabfile = array('ucomp' => $m['size'],'offset' => $this->cabfolder['fileoffset'],'date' => $this->MakeCabFileDate($m['mtime']),'time' => $this->MakeCabFileTime($m['mtime']),'atribs' => $atribs,'name' => $this->MakeWinPath($filename)."/0",'path' => $dir.$file,'size' => $m['size'] );$this->cabfolder['fileoffset'] += $m['size'];$this->cabfolder['offset'] += 17 + strlen( $filename );$this->cabheader['size'] += 17 + strlen( $filename ) + $m['size']; ## + 1 for /0 !$this->cabheader['numfiles']++;$this->cabfiles[]=$newcabfile;}//end ifclearstatcache();}//end whileclosedir($d);}}## strip the pathfunction StripPath($path,$strip){$one = preg_match("@".$this->LINSEP."@x", $path) ? 1 : 0;$path = $strip === true ? substr($path,strrpos($path,$this->LINSEP)+$one) : ($strip != false ? substr($path,strpos($path,$strip)) : $path);return $path;}## make win pathfunction MakeWinPath ($path){if(preg_match("@".$this->LINSEP."@x", $path) )$path = preg_replace("'".$this->LINSEP."'s", $this->WINSEP, $path);return $path;}## make cabinet file date from certain filefunction MakeCabFileDate($seconds){$s = localtime($seconds, true);$res = ( ($s['tm_year'] - 80 ) << 9 ) + ( ($s['tm_mon']+1) << 5 ) + $s['tm_mday'];return $res;}## make cabinet file datefunction MakeCabFileTime($seconds){$s = localtime($seconds, true);$res = ( $s['tm_hour'] << 11 ) + ( $s['tm_min'] << 5 ) + ( $s['tm_sec'] / 2 );return $res;}################# WRITING ################### write the headerfunction WriteHeader($res){$this->WriteByteBuffer( $res, $this->cabheader['sig'] );$this->WriteDword( $res, $this->cabheader['res1'] );$this->WriteDword( $res, $this->cabheader['size'] );$this->WriteDword( $res, $this->cabheader['res2'] );$this->WriteDword( $res, $this->cabheader['offset'] );$this->WriteDword( $res, $this->cabheader['res3'] );$this->WriteByte( $res, $this->cabheader['vmin'] );$this->WriteByte( $res, $this->cabheader['vmaj'] );$this->WriteWord( $res, $this->cabheader['numfolders'] );$this->WriteWord( $res, $this->cabheader['numfiles'] );$this->WriteWord( $res, $this->cabheader['flags'] );$this->WriteWord( $res, $this->cabheader['setid'] );$this->WriteWord( $res, $this->cabheader['cabid'] );}function WriteByteBuffer($res, $scalar){fwrite( $res, $scalar );}## write (unsigned long int) dword;function WriteDword($res, $scalar){if( preg_match("/[ //a-zA-Z]/", $scalar) ){$f = array();for($i=0; $i<strlen($scalar); ++$i ){$f[$i] = ord( substr($scalar,$i,1) );}$fmt = "L".strlen($scalar);fwrite( $res, pack( "$fmt", $f ) );return;}fwrite( $res, pack("L",$scalar) );}## write (unsigned char) single byte with pack;function WriteByte($res, $scalar){fwrite( $res, pack("C",$scalar) );}## write (unsigned short int) word;function WriteWord($res, $scalar){if( preg_match("/[ //a-zA-Z]/", $scalar) ){$f = array();for($i=0; $i<strlen($scalar); ++$i ){$f[$i] = ord( substr($scalar,$i,1) );}$fmt = "S".strlen($scalar);fwrite( $res, pack( "$fmt", $f ) );return;}fwrite( $res, pack("S",$scalar) );}## write the folderfunction WriteFolder($res){$this->WriteDword( $res, $this->cabfolder['offset'] );$this->WriteWord( $res, $this->cabfolder['numblocks'] );$this->WriteWord( $res, $this->cabfolder['typecmp'] );}## write the filesfunction WriteFiles($res){foreach ( $this->cabfiles as$file ){$this->WriteDword( $res, $file['ucomp'] );$this->WriteDword( $res, $file['offset'] );$this->WriteWord( $res, $file['index'] );$this->WriteWord( $res, $file['date'] );$this->WriteWord( $res, $file['time'] );$this->WriteWord( $res, $file['fileattr'] );$this->WriteByteBuffer( $res, $file['name'] );}}function WriteData($res){$datasize = $this->cabfolder['fileoffset'];$blocksize = $datasize > $this->BLOCKSIZE ? $this->BLOCKSIZE : $datasize;$block = $blocksize;$newblock = false;foreach ( $this->cabfiles as $file ){if(false !== ($res1 = @fopen( $file['path'], "rb" ))){$read_this_time = 0;$read_last_time = 0;while(!feof($res1)){$buffer .= fread($res1,$block);$read = ftell($res1);$read_this_time = $read - $read_last_time;$read_last_time = $read;$datasize -= $read_this_time;if($read_this_time == $blocksize){$block = $this->BLOCKSIZE;$newblock = true;} else {$block -= $read_this_time;$newblock = false;if($block <= 0){$block = $this->BLOCKSIZE;$newblock = true;}}if( $newblock ){$data = $this->cabfolder['typecmp'] == 1 ? $this->compressdata($buffer) : array('cbytes'=>$blocksize,'data'=>$buffer);$this->WriteDword( $res, 0 );$this->WriteWord( $res, $data['cbytes'] );$this->WriteWord( $res, $blocksize );$this->WriteByteBuffer( $res, $data['data'] );$blocksize = $datasize > $this->BLOCKSIZE ? $this->BLOCKSIZE : $datasize;$buffer = "";}}## close input filefclose( $res1 );if(preg_match("'/.cabtemp$'",$file['path'])) unlink($file['path']);} else {die("Failed to open ".$file);}}}//*/function compressdata($buffer){$data['data'] = pack("C",0x43) . pack("C", 0x4B) . gzdeflate($buffer,$this->cabfolder['typecmp']);$data['cbytes']=$this->bytelen($data['data']);return $data;}function bytelen($data) {return strlen($data."A") - 1;}/*An unused method to compute the csum, not finishedfunction CSUMCompute($pv, $cb, $seed=0){//$csumpartial = $this->CSUMCompute(0,$data['cbytes'],0);//$csum = $this->CSUMCompute($data['cbytes'],sizeof(CFDATA) ?sizeof($csum),$csumpartial);//int         cUlong;               // Number of ULONGs in block//CHECKSUM    csum;                   // Checksum accumulator//BYTE       *pb;//ULONG       ul;$cUlong = $cb / 4;                  // Number of ULONGs$csum = $seed;                        // Init checksum$pb = $pv;                            // Start at front of data block//** Checksum integral multiple of ULONGswhile ($cUlong-- > 0) {//** NOTE: Build ULONG in big/little-endian independent manner$ul = $pb++;                     // Get low-order byte$ul |= (($pb++) <<8); // Add 2nd byte$ul |= (($pb++) << 16); // Add 3nd byte$ul |= (($pb++) << 24); // Add 4th byte$csum ^= $ul;                     // Update checksum}//** Checksum remainder bytes$ul = 0;switch ($cb % 4) {case 3:$ul |= (($pb++) << 16); // Add 3nd bytecase 2:$ul |= (($pb++) <<8); // Add 2nd bytecase 1:$ul |= $pb++;                  // Get low-order bytedefault:break;}$csum ^= $ul;                         // Update checksum//** Return computed checksumreturn $csum;}//*/}?>
  example.php
  调用实例:
  <?php//Send the MSCAB MIME typeheader("Content-Type: application/vnd.ms-cab-compressed");//Make it an attachmentheader('Content-Disposition: attachment; filename="test.cab"');//include the class fileinclude("MakeCAB.class.php");//create object$cab = new MakeCAB("test.cab");//add a local file system file$cab->addfile("BuildingTradesProposal2.doc");//add a file from a url$cab->addurl("http://greaterfortwayne.net/favicon.ico");//add all of the contents of a local file system directory, leaving the base directory$cab->adddir("K:/xampp/htdocs/data/","data/");//Make the file$cab->WriteCAB();//output the filereadfile("test.cab");//delete the fileunlink("test.cab");?>
页: [1]
查看完整版本: PHP生成.cab安装包