设为首页 收藏本站
云服务器等爆品抢先购,低至4.2元/月
查看: 526|回复: 0

[经验分享] PHP生成.cab安装包

[复制链接]

尚未签到

发表于 2017-3-27 12:28:35 | 显示全部楼层 |阅读模式
  用php来生成.cab格式的压缩包,能在线制作windows 的安装文件包.
  MakeCAB.class.php
  <?php/** * @package MakeCAB * @example  /examplecab.php  Example 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、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-356149-1-1.html 上篇帖子: php 指定时间段内 下篇帖子: PHP使用xpath解析XML实例教程
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表