Location: PHPKode > scripts > gzip > gzip/gzip.php
<?
/**********************************************************************************

 gzip - PHP gzip compression library
               Version 1.3

 Copyright (c) 2001, 2002 Moiseenko V. Maxim <hide@address.com>
 All Rights Reserved.

 This library is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or any
 later version.

 This library is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.



 Official ZIP file format: http://www.pkware.com/appnote.txt
**********************************************************************************/


define("_GZIP",true);
define("_GZIP_VER", 1.3);
define("_GZIP_BUILD", '03.04.2002');


###################################################################################
class gzip {

  # Array to store compressed data
  # private string[]
  var $_datasec = array();


  # îòîáðàæàòü îòëàäî÷íîå èíôî.
  # public boolean
  var $debug = true;


  /******************************************************************************
  * êîíñòðóêòîð êëàññà
  * public void
  */
  function gzip(){
  }



  /******************************************************************************
  * Adds "file content" to archive
  *
  * public void
  * string @data - file contents
  * string @name - name of the file in the archive (may contains the path)
  */
  function add($data, $name){
    $unc_len = strlen($data);
    $crc     = crc32($data);
    $zdata = gzdeflate($data,9);
    $c_len = strlen($zdata);

    $fr=
      "\x1f".                    # ID1                              1
      "\x8B".                    # ID2                              1
      "\x08".                    # Compression Method "deflate"     1
      "\x08".                    # FLaGs "FNAME"                    1
      "\x00\x00\x00\x00".        # last mod time & date             4
      "\x00".                    # eXtra FLags "2"-max "4"-fast     1
      "\x00".                    # OS "\x00" - FAT                  1
      $name.                     # orig. file name                var
      "\x00".                    # zero term.                       1
      $zdata.
      $this->_pack($crc, 4).      # crc32                           4
      $this->_pack($unc_len, 4);  # uncompressed filesize           4


    $this->_datasec[] = $fr;
  }




  /********************************************************************************
  * ðàñïàêîâàâàåò ñîäåðæèìîå àðõèâà
  * public object
  */
  function extract($name){
    if(!file_exists($name))return null;
    $fd = fopen($name,'rb');
    if(! $content = fread($fd, filesize($name)) ) return null;
    @fclose($fd);


    $ret = new stdClass;

    # ìàññèâ äëÿ ðàñïàêîâàíîãî ñîäåðæèìîãî
    $ret->part = array();




    # óêàçàòåëü ïîçèöèè ÷òåíèÿ
    $pointer=0;
    # íîìåð ôàéëà
    $fpointer = 0;
    $ret->part[$fpointer]->head = array();


    if("\x1f\x8b" != substr($content, $pointer,2) ){
      $this->_debug("It's not .gzip format");
      return null;
    }
    $pointer+=2;

    if("\x08" != substr($content, $pointer,1) ){
      $this->_debug("Compression method must be 'deflate'");
      return null;
    }
    $pointer++;


    # This flag byte is divided into individual bits as follows: 
    # bit 0   FTEXT
    # bit 1   FHCRC
    # bit 2   FEXTRA
    # bit 3   FNAME
    # bit 4   FCOMMENT
    switch( substr($content, $pointer,1) ){
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # FNAME
      case "\x08":

        $pointer++;

        # Modification time
        $ret->part[$fpointer]->head['mod_time'] =
          $this->_unpack( substr($content, $pointer,2) );
        $pointer+=2;

        # Modification date
        $ret->part[$fpointer]->head['mod_date'] =
          $this->_unpack( substr($content, $pointer,2) );
        $pointer+=2;

        # eXtra FLags
        # 2 - compressor used maximum compression, slowest algorithm
        # 4 - compressor used fastest algorithm
        $ret->part[$fpointer]->head['xfl'] =
          $this->_unpack( substr($content, $pointer,1) );
        $pointer++;

        # Operating System
        # 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
        # 3 - Unix
        # 7 - Macintosh
        # 11 - NTFS filesystem (NT)
        # 255 - unknown
        $ret->part[$fpointer]->head['os'] = $this->_unpack( substr($content, $pointer,1) );
        $pointer++;

        #file name
        for($ret->part[$fpointer]->head['file_name']=""; substr($content, $pointer,1) != "\x00"; $pointer++)
          $ret->part[$fpointer]->head['file_name'] .= substr($content, $pointer,1);
        $pointer++;

        # compressed blocks...
        $zdata = substr($content, $pointer, -8);
        $pointer = strlen($content) - 8;

        # Cyclic Redundancy Check
        $ret->part[$fpointer]->head['crc32'] =
          $this->_unpack( substr($content, $pointer,4) );
        $pointer+=4;

        # size of the original (uncompressed) input data modulo 2^32
        $ret->part[$fpointer]->head['uncompressed_filesize'] =
          $this->_unpack( substr($content, $pointer,4) );
        $pointer+=4;


        # decompress data and store it at array
        $ret->part[$fpointer]->body = gzinflate($zdata);

        break;


      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      default:
        return null;

    }#switch

    return $ret;
  }









  /******************************************************************************
  * Dumps out file
  *
  * public string - the gzipped file
  */
  function file(){
    $data = implode('', $this->_datasec);
    return $data;
  }




  /******************************************************************************
  * print error message
  * public void
  */
  function _debug($str){
    if($this->debug) echo $str;
  }




  /********************************************************************************
  * pack data into binary string
  * private string
  */
  function _pack($val, $bytes=2){
    for($ret='', $i=0; $i<$bytes; $i++, $val=floor($val/256) )
      $ret .= chr($val % 256);
    return $ret;
  }


  /********************************************************************************
  * unpack data from binary string
  * private string
  */
  function _unpack($val){
    for($len = strlen($val), $ret=0, $i=0; $i < $len; $i++)
      $ret += (int)ord(substr($val,$i,1)) * pow(2, 8 * $i);
    return $ret;
  }



  /********************************************************************************
  * äîáàâëÿåò ñîäåðæèìîå ôàéëà â àðõèâ
  * public boolean
  */
  function add_file($name, $binary=false){
    if(!file_exists($name))return false;
    $fd = $binary? fopen($name,'rb') : fopen($name,'r');
    if(! $content = fread($fd, filesize($name)) )return false;
    fclose($fd);

    $this->add($content,$name);
    return true;
  }


  /********************************************************************************
  * ñîçäà¸ò .zip àðõèâ
  * public int
  */
  function write_file($name){
    $size = -1;
    if( $fd=fopen($name,'wb') ){
      $size = fwrite($fd,$this->file());
      fclose($fd);
    }
    return $size;
  }


}#class
###################################################################################
?>
Return current item: gzip