1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 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: 26: 27: 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: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 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:
81: $position += $head_size;
82: break;
83:
84: case 0x74:
85:
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: 112:
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: