Files
server/usr/share/psa-pear/pear/php/Horde/Compress/Rar.php
2026-01-07 20:52:11 +01:00

142 lines
4.7 KiB
PHP

<?php
/**
* Copyright 2008-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Michael Cochrane <mike@graftonhall.co.nz>
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Compress
*/
/**
* This class allows rar files to be read.
*
* @author Michael Cochrane <mike@graftonhall.co.nz>
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2008-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Compress
*/
class Horde_Compress_Rar extends Horde_Compress_Base
{
const BLOCK_START = "\x52\x61\x72\x21\x1a\x07\x00";
/**
*/
public $canDecompress = true;
/**
* Rar compression methods
*
* @var array
*/
protected $_methods = array(
0x30 => 'Store',
0x31 => 'Fastest',
0x32 => 'Fast',
0x33 => 'Normal',
0x34 => 'Good',
0x35 => 'Best'
);
/**
* @return array Info on the compressed file:
* <pre>
* KEY: Position in RAR archive
* VALUES:
* attr - File attributes
* date - File modification time
* csize - Compressed file size
* method - Compression method
* name - Filename
* size - Original file size
* </pre>
*
* @throws Horde_Compress_Exception
*/
public function decompress($data, array $params = array())
{
$blockStart = strpos($data, self::BLOCK_START);
if ($blockStart === false) {
throw new Horde_Compress_Exception(Horde_Compress_Translation::t("Invalid RAR data."));
}
$data_len = strlen($data);
$position = $blockStart + 7;
$return_array = array();
while ($position < $data_len) {
if ($position + 7 > $data_len) {
throw new Horde_Compress_Exception(Horde_Compress_Translation::t("Invalid RAR data."));
}
//$head_crc = substr($data, $position, 2);
$head_type = ord(substr($data, $position + 2, 1));
$head_flags = unpack('vFlags', substr($data, $position + 3, 2));
$head_flags = $head_flags['Flags'];
$head_size = unpack('vSize', substr($data, $position + 5, 2));
$head_size = $head_size['Size'];
$position += 7;
$head_size -= 7;
switch ($head_type) {
case 0x73:
/* Archive header */
$position += $head_size;
break;
case 0x74:
/* File Header */
$info = unpack(
'VPacked/VUnpacked/COS/VCRC32/VTime/CVersion/CMethod/vLength/vAttrib',
substr($data, $position)
);
$year = (($info['Time'] >> 25) & 0x7f) + 80;
$name = substr($data, $position + 25, $info['Length']);
if ($unicode = strpos($name, "\0")) {
$name = substr($name, 0, $unicode);
}
$return_array[] = array(
'name' => $name,
'size' => $info['Unpacked'],
'csize' => $info['Packed'],
'date' => mktime(
(($info['Time'] >> 11) & 0x1f),
(($info['Time'] >> 5) & 0x3f),
(($info['Time'] << 1) & 0x3e),
(($info['Time'] >> 21) & 0x07),
(($info['Time'] >> 16) & 0x1f),
$year < 1900 ? $year + 1900 : $year
),
'method' => $this->_methods[$info['Method']],
'attr' => (($info['Attrib'] & 0x10) ? 'D' : '-') .
(($info['Attrib'] & 0x20) ? 'A' : '-') .
(($info['Attrib'] & 0x03) ? 'S' : '-') .
(($info['Attrib'] & 0x02) ? 'H' : '-') .
(($info['Attrib'] & 0x01) ? 'R' : '-')
);
$position += $head_size + $info['Packed'];
break;
default:
if ($head_size == -7) {
/* We've already added 7 bytes above. If we remove those
* same 7 bytes, we will enter an infinite loop. */
throw new Horde_Compress_Exception(Horde_Compress_Translation::t("Invalid RAR data."));
}
$position += $head_size;
break;
}
}
return $return_array;
}
}