Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.91 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * @author     bouchon
  5.  * @link       http://dev.maxg.info
  6.  * @link       http://forum.maxg.info
  7.  *
  8.  * Modified for Dokuwiki
  9.  * @author    Christopher Smith <chris@jalakai.co.uk>
  10.  */
  11. class ZipLib {
  12.  
  13.     var $datasec;
  14.     var $ctrl_dir = array();
  15.     var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
  16.     var $old_offset = 0;
  17.     var $dirs = Array(".");
  18.  
  19.     function get_List($zip_name) {
  20.         $zip = @fopen($zip_name, 'rb');
  21.         if(!$zip) return(0);
  22.         $centd = $this->ReadCentralDir($zip,$zip_name);
  23.  
  24.         @rewind($zip);
  25.         @fseek($zip, $centd['offset']);
  26.  
  27.         for ($i=0; $i<$centd['entries']; $i++) {
  28.             $header = $this->ReadCentralFileHeaders($zip);
  29.             $header['index'] = $i;
  30.  
  31.             $info['filename']        = $header['filename'];
  32.             $info['stored_filename'] = $header['stored_filename'];
  33.             $info['size']            = $header['size'];
  34.             $info['compressed_size'] = $header['compressed_size'];
  35.             $info['crc']             = strtoupper(dechex( $header['crc'] ));
  36.             $info['mtime']           = $header['mtime'];
  37.             $info['comment']         = $header['comment'];
  38.             $info['folder']          = ($header['external']==0x41FF0010||$header['external']==16)?1:0;
  39.             $info['index']           = $header['index'];
  40.             $info['status']          = $header['status'];
  41.             $ret[]=$info;
  42.  
  43.             unset($header);
  44.         }
  45.         return $ret;
  46.     }
  47.  
  48.     function Add($files,$compact) {
  49.         if(!is_array($files[0])) $files=Array($files);
  50.  
  51.         for($i=0;$files[$i];$i++){
  52.             $fn = $files[$i];
  53.             if(!in_Array(dirname($fn[0]),$this->dirs))
  54.                 $this->add_Dir(dirname($fn[0]));
  55.             if(utf8_basename($fn[0]))
  56.                 $ret[utf8_basename($fn[0])]=$this->add_File($fn[1],$fn[0],$compact);
  57.         }
  58.         return $ret;
  59.     }
  60.  
  61.     /**
  62.      * Zips recursively the $folder directory, from the $basedir directory
  63.      */
  64.     function Compress($folder, $basedir=null, $parent=null) {
  65.         $full_path = $basedir."/".$parent.$folder;
  66.         $zip_path = $parent.$folder;
  67.         if ($zip_path) {
  68.             $zip_path .= "/";
  69.             $this->add_dir($zip_path);
  70.         }
  71.         $dir = new DirectoryIterator($full_path);
  72.         foreach($dir as $file) {
  73.             if(!$file->isDot()) {
  74.                 $filename = $file->getFilename();
  75.                 if($file->isDir()) {
  76.                     $this->Compress($filename, $basedir, $zip_path);
  77.                 } else {
  78.                     $content = join('', file($full_path.'/'.$filename));
  79.                     $this->add_File($content, $zip_path.$filename);
  80.                 }
  81.             }
  82.         }
  83.     }
  84.  
  85.     /**
  86.      * Returns the Zip file
  87.      */
  88.     function get_file() {
  89.         $data = implode('', $this -> datasec);
  90.         $ctrldir = implode('', $this -> ctrl_dir);
  91.  
  92.         return $data . $ctrldir . $this -> eof_ctrl_dir .
  93.             pack('v', count($this->ctrl_dir)).pack('v', count($this->ctrl_dir)).
  94.             pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";
  95.     }
  96.  
  97.     function add_dir($name) {
  98.         $name = str_replace("\\", "/", $name);
  99.         $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
  100.  
  101.         $fr .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
  102.         $fr .= pack("v", 0 ).$name.pack("V", 0).pack("V", 0).pack("V", 0);
  103.         $this -> datasec[] = $fr;
  104.  
  105.         $new_offset = strlen(implode("", $this->datasec));
  106.  
  107.         $cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
  108.         $cdrec .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
  109.         $cdrec .= pack("v", 0 ).pack("v", 0 ).pack("v", 0 ).pack("v", 0 );
  110.         $ext = "\xff\xff\xff\xff";
  111.         $cdrec .= pack("V", 16 ).pack("V", $this -> old_offset ).$name;
  112.  
  113.         $this -> ctrl_dir[] = $cdrec;
  114.         $this -> old_offset = $new_offset;
  115.         $this -> dirs[] = $name;
  116.     }
  117.  
  118.     /**
  119.      * Add a file named $name from a string $data
  120.      */
  121.     function add_File($data, $name, $compact = 1) {
  122.         $name     = str_replace('\\', '/', $name);
  123.         $dtime    = dechex($this->DosTime());
  124.  
  125.         $hexdtime = pack('H*',$dtime[6].$dtime[7].
  126.                               $dtime[4].$dtime[5].
  127.                               $dtime[2].$dtime[3].
  128.                               $dtime[0].$dtime[1]);
  129.  
  130.         if($compact){
  131.             $fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;
  132.         }else{
  133.             $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00".$hexdtime;
  134.         }
  135.         $unc_len = strlen($data);
  136.         $crc = crc32($data);
  137.  
  138.         if($compact){
  139.             $zdata = gzcompress($data);
  140.             $c_len = strlen($zdata);
  141.             $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
  142.         }else{
  143.             $zdata = $data;
  144.         }
  145.         $c_len=strlen($zdata);
  146.         $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
  147.         $fr .= pack('v', strlen($name)).pack('v', 0).$name.$zdata;
  148.  
  149.         $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
  150.  
  151.         $this -> datasec[] = $fr;
  152.         $new_offset        = strlen(implode('', $this->datasec));
  153.         if($compact) {
  154.             $cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";
  155.         } else {
  156.             $cdrec = "\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00";
  157.         }
  158.         $cdrec .= $hexdtime.pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
  159.         $cdrec .= pack('v', strlen($name) ).pack('v', 0 ).pack('v', 0 );
  160.         $cdrec .= pack('v', 0 ).pack('v', 0 ).pack('V', 32 );
  161.         $cdrec .= pack('V', $this -> old_offset );
  162.  
  163.         $this -> old_offset = $new_offset;
  164.         $cdrec .= $name;
  165.         $this -> ctrl_dir[] = $cdrec;
  166.         return true;
  167.     }
  168.  
  169.     function DosTime() {
  170.         $timearray = getdate();
  171.         if ($timearray['year'] < 1980) {
  172.             $timearray['year']    = 1980;
  173.             $timearray['mon']     = 1;
  174.             $timearray['mday']    = 1;
  175.             $timearray['hours']   = 0;
  176.             $timearray['minutes'] = 0;
  177.             $timearray['seconds'] = 0;
  178.         }
  179.         return (($timearray['year'] - 1980) << 25) |
  180.                 ($timearray['mon'] << 21) |
  181.                 ($timearray['mday'] << 16) |
  182.                 ($timearray['hours'] << 11) |
  183.                 ($timearray['minutes'] << 5) |
  184.                 ($timearray['seconds'] >> 1);
  185.     }
  186.  
  187.     /**
  188.      * Extract a zip file $zn to the $to directory
  189.      */
  190.     function Extract ( $zn, $to, $index = Array(-1) ) {
  191.         if(!@is_dir($to)) $this->_mkdir($to);
  192.         $ok = 0;
  193.         $zip = @fopen($zn,'rb');
  194.         if(!$zip) return(-1);
  195.         $cdir = $this->ReadCentralDir($zip,$zn);
  196.         $pos_entry = $cdir['offset'];
  197.  
  198.         if(!is_array($index)){
  199.             $index = array($index);
  200.         }
  201.         for($i=0; isset($index[$i]);$i++){
  202.             if(intval($index[$i])!=$index[$i]||$index[$i]>$cdir['entries'])
  203.                 return(-1);
  204.         }
  205.  
  206.         for ($i=0; $i<$cdir['entries']; $i++) {
  207.             @fseek($zip, $pos_entry);
  208.             $header = $this->ReadCentralFileHeaders($zip);
  209.             $header['index'] = $i;
  210.             $pos_entry = ftell($zip);
  211.             @rewind($zip);
  212.             fseek($zip, $header['offset']);
  213.             if(in_array("-1",$index)||in_array($i,$index)){
  214.                 $stat[$header['filename']]=$this->ExtractFile($header, $to, $zip);
  215.             }
  216.         }
  217.         fclose($zip);
  218.         return $stat;
  219.     }
  220.  
  221.     function ReadFileHeader($zip, $header) {
  222.         $binary_data = fread($zip, 30);
  223.         $data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
  224.  
  225.         $header['filename'] = fread($zip, $data['filename_len']);
  226.         if ($data['extra_len'] != 0) {
  227.             $header['extra'] = fread($zip, $data['extra_len']);
  228.         } else {
  229.             $header['extra'] = '';
  230.         }
  231.  
  232.         $header['compression'] = $data['compression'];
  233.         foreach (array('size','compressed_size','crc') as $hd) { // On ODT files, these headers are 0. Keep the previous value.
  234.             if ($data[$hd] != 0) $header[$hd] = $data[$hd];
  235.         }
  236.         $header['flag']  = $data['flag'];
  237.         $header['mdate'] = $data['mdate'];
  238.         $header['mtime'] = $data['mtime'];
  239.  
  240.         if ($header['mdate'] && $header['mtime']){
  241.             $hour    = ($header['mtime']&0xF800)>>11;
  242.             $minute  = ($header['mtime']&0x07E0)>>5;
  243.             $seconde = ($header['mtime']&0x001F)*2;
  244.             $year    = (($header['mdate']&0xFE00)>>9)+1980;
  245.             $month   = ($header['mdate']&0x01E0)>>5;
  246.             $day     = $header['mdate']&0x001F;
  247.             $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
  248.         } else {
  249.             $header['mtime'] = time();
  250.         }
  251.  
  252.         $header['stored_filename'] = $header['filename'];
  253.         $header['status'] = "ok";
  254.         return $header;
  255.     }
  256.  
  257.     function ReadCentralFileHeaders($zip){
  258.         $binary_data = fread($zip, 46);
  259.         $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);
  260.  
  261.         if ($header['filename_len'] != 0){
  262.             $header['filename'] = fread($zip,$header['filename_len']);
  263.         }else{
  264.             $header['filename'] = '';
  265.         }
  266.  
  267.         if ($header['extra_len'] != 0){
  268.             $header['extra'] = fread($zip, $header['extra_len']);
  269.         }else{
  270.             $header['extra'] = '';
  271.         }
  272.  
  273.         if ($header['comment_len'] != 0){
  274.             $header['comment'] = fread($zip, $header['comment_len']);
  275.         }else{
  276.             $header['comment'] = '';
  277.         }
  278.  
  279.         if ($header['mdate'] && $header['mtime']) {
  280.             $hour    = ($header['mtime'] & 0xF800) >> 11;
  281.             $minute  = ($header['mtime'] & 0x07E0) >> 5;
  282.             $seconde = ($header['mtime'] & 0x001F)*2;
  283.             $year    = (($header['mdate'] & 0xFE00) >> 9) + 1980;
  284.             $month   = ($header['mdate'] & 0x01E0) >> 5;
  285.             $day     = $header['mdate'] & 0x001F;
  286.             $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
  287.         } else {
  288.             $header['mtime'] = time();
  289.         }
  290.  
  291.         $header['stored_filename'] = $header['filename'];
  292.         $header['status'] = 'ok';
  293.         if (substr($header['filename'], -1) == '/') $header['external'] = 0x41FF0010;
  294.  
  295.         return $header;
  296.     }
  297.  
  298.     function ReadCentralDir($zip,$zip_name) {
  299.         $size = filesize($zip_name);
  300.         if ($size < 277){
  301.             $maximum_size = $size;
  302.         } else {
  303.             $maximum_size=277;
  304.         }
  305.  
  306.         @fseek($zip, $size-$maximum_size);
  307.         $pos   = ftell($zip);
  308.         $bytes = 0x00000000;
  309.  
  310.         while ($pos < $size) {
  311.             $byte = @fread($zip, 1);
  312.             $bytes=(($bytes << 8) & 0xFFFFFFFF) | Ord($byte);
  313.             if ($bytes == 0x504b0506){
  314.                 $pos++;
  315.                 break;
  316.             }
  317.             $pos++;
  318.         }
  319.  
  320.         $data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',
  321.                 fread($zip, 18));
  322.  
  323.         if ($data['comment_size'] != 0){
  324.             $centd['comment'] = fread($zip, $data['comment_size']);
  325.         } else {
  326.             $centd['comment'] = '';
  327.         }
  328.         $centd['entries']      = $data['entries'];
  329.         $centd['disk_entries'] = $data['disk_entries'];
  330.         $centd['offset']       = $data['offset'];
  331.         $centd['disk_start']   = $data['disk_start'];
  332.         $centd['size']         = $data['size'];
  333.         $centd['disk']         = $data['disk'];
  334.         return $centd;
  335.     }
  336.  
  337.     function ExtractFile($header,$to,$zip) {
  338.         $header = $this->readfileheader($zip, $header);
  339.  
  340.         if(substr($to,-1)!="/") $to.="/";
  341.         if(substr($header['filename'],-1)=="/") {
  342.             $this->_mkdir($to.$header['filename']);
  343.             return +2;
  344.         }
  345.  
  346.         if (!$this->_mkdir($to.dirname($header['filename']))) return (-1);
  347.  
  348.         if (!array_key_exists("external", $header) || (!($header['external']==0x41FF0010)&&!($header['external']==16))) {
  349.             if ($header['compression']==0) {
  350.                 $fp = @fopen($to.$header['filename'], 'wb');
  351.                 if(!$fp) return(-1);
  352.                 $size = $header['compressed_size'];
  353.  
  354.                 while ($size != 0) {
  355.                     $read_size = ($size < 2048 ? $size : 2048);
  356.                     $buffer = fread($zip, $read_size);
  357.                     $binary_data = pack('a'.$read_size, $buffer);
  358.                     @fwrite($fp, $binary_data, $read_size);
  359.                     $size -= $read_size;
  360.                 }
  361.                 fclose($fp);
  362.                 touch($to.$header['filename'], $header['mtime']);
  363.  
  364.             }else{
  365.                 if (!is_dir(dirname($to.$header['filename']))) $this->_mkdir(dirname($to.$header['filename']));
  366.                 $fp = fopen($to.$header['filename'].'.gz','wb');
  367.                 if(!$fp) return(-1);
  368.                 $binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']),
  369.                         Chr(0x00), time(), Chr(0x00), Chr(3));
  370.  
  371.                 fwrite($fp, $binary_data, 10);
  372.                 $size = $header['compressed_size'];
  373.  
  374.                 while ($size != 0) {
  375.                     $read_size = ($size < 1024 ? $size : 1024);
  376.                     $buffer = fread($zip, $read_size);
  377.                     $binary_data = pack('a'.$read_size, $buffer);
  378.                     @fwrite($fp, $binary_data, $read_size);
  379.                     $size -= $read_size;
  380.                 }
  381.  
  382.                 $binary_data = pack('VV', $header['crc'], $header['size']);
  383.                 fwrite($fp, $binary_data,8);
  384.                 fclose($fp);
  385.  
  386.                 $gzp = @gzopen($to.$header['filename'].'.gz','rb');
  387.                 if(!$gzp){
  388.                     @gzclose($gzp);
  389.                     @unlink($to.$header['filename']);
  390.                     die("Archive is compressed whereas ZLIB is not enabled.");
  391.                 }
  392.                 $fp = @fopen($to.$header['filename'],'wb');
  393.                 if(!$fp) return(-1);
  394.                 $size = $header['size'];
  395.  
  396.                 while ($size != 0) {
  397.                     $read_size   = ($size < 2048 ? $size : 2048);
  398.                     $buffer      = gzread($gzp, $read_size);
  399.                     $binary_data = pack('a'.$read_size, $buffer);
  400.                     @fwrite($fp, $binary_data, $read_size);
  401.                     $size -= $read_size;
  402.                 }
  403.                 fclose($fp);
  404.                 gzclose($gzp);
  405.  
  406.                 touch($to.$header['filename'], $header['mtime']);
  407.                 @unlink($to.$header['filename'].'.gz');
  408.             }
  409.         }
  410.         return true;
  411.     }
  412.  
  413.     /**
  414.      * centralize mkdir calls and use dokuwiki io functions
  415.      *
  416.      * @author Christopher Smith <chris@jalakai.co.uk>
  417.      */
  418.     function _mkdir($d) {
  419.         return io_mkdir_p($d);
  420.     }
  421.  
  422.  
  423.     function ExtractStr($zn, $name) {
  424.         $ok = 0;
  425.         $zip = @fopen($zn,'rb');
  426.         if(!$zip) return(null);
  427.         $cdir = $this->ReadCentralDir($zip,$zn);
  428.         $pos_entry = $cdir['offset'];
  429.  
  430.         for ($i=0; $i<$cdir['entries']; $i++) {
  431.             @fseek($zip, $pos_entry);
  432.             $header = $this->ReadCentralFileHeaders($zip);
  433.             $header['index'] = $i;
  434.             $pos_entry = ftell($zip);
  435.             @rewind($zip);
  436.             fseek($zip, $header['offset']);
  437.             if ($name == $header['stored_filename'] || $name == $header['filename']) {
  438.                 $str = $this->ExtractStrFile($header, $zip);
  439.                 fclose($zip);
  440.                 return $str;
  441.             }
  442.  
  443.         }
  444.         fclose($zip);
  445.         return null;
  446.     }
  447.  
  448.     function ExtractStrFile($header,$zip) {
  449.         $hdr = $this->readfileheader($zip);
  450.         $binary_data = '';
  451.         if (!($header['external']==0x41FF0010) && !($header['external']==16)) {
  452.             if ($header['compression']==0) {
  453.                 while ($size != 0) {
  454.                     $read_size = ($size < 2048 ? $size : 2048);
  455.                     $buffer = fread($zip, $read_size);
  456.                     $binary_data .= pack('a'.$read_size, $buffer);
  457.                     $size -= $read_size;
  458.                 }
  459.                 return $binary_data;
  460.             } else {
  461.                 $size = $header['compressed_size'];
  462.                 if ($size == 0) {
  463.                     return '';
  464.                 }
  465.                 //Just in case
  466.                 if ($size > ($this->_ret_bytes(ini_get('memory_limit'))/2)) {
  467.                     die("Compressed file is to huge to be uncompress in memory.");
  468.                 }
  469.                 while ($size != 0)
  470.                 {
  471.                     $read_size = ($size < 2048 ? $size : 2048);
  472.                     $buffer = fread($zip, $read_size);
  473.                     $binary_data .= pack('a'.$read_size, $buffer);
  474.                     $size -= $read_size;
  475.                 }
  476.                 $str = gzinflate($binary_data, $header['size']);
  477.                 if ($header['crc'] == crc32($str)) {
  478.                     return $str;
  479.                 } else {
  480.                     die("Crc Error");
  481.                 }
  482.             }
  483.         }
  484.         return null;
  485.     }
  486.  
  487.     function _ret_bytes($val) {
  488.         $val = trim($val);
  489.         $last = $val{strlen($val)-1};
  490.         switch($last) {
  491.             case 'k':
  492.             case 'K':
  493.                 return (int) $val * 1024;
  494.                 break;
  495.             case 'm':
  496.             case 'M':
  497.                 return (int) $val * 1048576;
  498.                 break;
  499.             default:
  500.                 return $val;
  501.         }
  502.     }
  503. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement