Overview

Packages

  • Compress

Classes

  • Horde_Compress
  • Horde_Compress_Base
  • Horde_Compress_Dbx
  • Horde_Compress_Exception
  • Horde_Compress_Gzip
  • Horde_Compress_Rar
  • Horde_Compress_Tar
  • Horde_Compress_Tnef
  • Horde_Compress_Translation
  • Horde_Compress_Zip
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * This class allows rar files to be read.
  4:  *
  5:  * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author   Michael Cochrane <mike@graftonhall.co.nz>
 11:  * @author   Michael Slusarz <slusarz@horde.org>
 12:  * @category Horde
 13:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 14:  * @package  Compress
 15:  */
 16: class Horde_Compress_Rar extends Horde_Compress_Base
 17: {
 18:     const BLOCK_START = "\x52\x61\x72\x21\x1a\x07\x00";
 19: 
 20:     /**
 21:      */
 22:     public $canDecompress = true;
 23: 
 24:     /**
 25:      * Rar compression methods
 26:      *
 27:      * @var array
 28:      */
 29:     protected $_methods = array(
 30:         0x30 => 'Store',
 31:         0x31 => 'Fastest',
 32:         0x32 => 'Fast',
 33:         0x33 => 'Normal',
 34:         0x34 => 'Good',
 35:         0x35 => 'Best'
 36:     );
 37: 
 38:     /**
 39:      * @return array  Info on the compressed file:
 40:      * <pre>
 41:      * KEY: Position in RAR archive
 42:      * VALUES:
 43:      *   attr - File attributes
 44:      *   date - File modification time
 45:      *   csize - Compressed file size
 46:      *   method - Compression method
 47:      *   name - Filename
 48:      *   size - Original file size
 49:      * </pre>
 50:      *
 51:      * @throws Horde_Compress_Exception
 52:      */
 53:     public function decompress($data, array $params = array())
 54:     {
 55:         $blockStart = strpos($data, self::BLOCK_START);
 56:         if ($blockStart === false) {
 57:             throw new Horde_Compress_Exception(Horde_Compress_Translation::t("Invalid RAR data."));
 58:         }
 59: 
 60:         $data_len = strlen($data);
 61:         $position = $blockStart + 7;
 62:         $return_array = array();
 63: 
 64:         while ($position < $data_len) {
 65:             if ($position + 7 > $data_len) {
 66:                 throw new Horde_Compress_Exception(Horde_Compress_Translation::t("Invalid RAR data."));
 67:             }
 68:             $head_crc = substr($data, $position + 0, 2);
 69:             $head_type = ord(substr($data, $position + 2, 1));
 70:             $head_flags = unpack('vFlags', substr($data, $position + 3, 2));
 71:             $head_flags = $head_flags['Flags'];
 72:             $head_size = unpack('vSize', substr($data, $position + 5, 2));
 73:             $head_size = $head_size['Size'];
 74: 
 75:             $position += 7;
 76:             $head_size -= 7;
 77: 
 78:             switch ($head_type) {
 79:             case 0x73:
 80:                 /* Archive header */
 81:                 $position += $head_size;
 82:                 break;
 83: 
 84:             case 0x74:
 85:                 /* File Header */
 86:                 $info = unpack('VPacked/VUnpacked/COS/VCRC32/VTime/CVersion/CMethod/vLength/vAttrib', substr($data, $position));
 87: 
 88:                 $return_array[] = array(
 89:                     'name' => substr($data, $position + 25, $info['Length']),
 90:                     'size' => $info['Unpacked'],
 91:                     'csize' => $info['Packed'],
 92:                     'date' => mktime((($info['Time'] >> 11) & 0x1f),
 93:                                      (($info['Time'] >> 5) & 0x3f),
 94:                                      (($info['Time'] << 1) & 0x3e),
 95:                                      (($info['Time'] >> 21) & 0x07),
 96:                                      (($info['Time'] >> 16) & 0x1f),
 97:                                      ((($info['Time'] >> 25) & 0x7f) + 80)),
 98:                     'method' => $this->_methods[$info['Method']],
 99:                     'attr' => (($info['Attrib'] & 0x10) ? 'D' : '-') .
100:                               (($info['Attrib'] & 0x20) ? 'A' : '-') .
101:                               (($info['Attrib'] & 0x03) ? 'S' : '-') .
102:                               (($info['Attrib'] & 0x02) ? 'H' : '-') .
103:                               (($info['Attrib'] & 0x01) ? 'R' : '-')
104:                 );
105: 
106:                 $position += $head_size + $info['Packed'];
107:                 break;
108: 
109:             default:
110:                 if ($head_size == -7) {
111:                     /* We've already added 7 bytes above. If we remove those
112:                      * same 7 bytes, we will enter an infinite loop. */
113:                     throw new Horde_Compress_Exception(Horde_Compress_Translation::t("Invalid RAR data."));
114:                 }
115:                 $position += $head_size;
116:                 break;
117:             }
118:         }
119: 
120:         return $return_array;
121:     }
122: }
123: 
API documentation generated by ApiGen