<?php
class store_rar {
private $id = null;
private $tree = array();
public function create($filename) {
$this->id = fopen($filename, "wb");
if (!$this->id)
return false;
$this->tree = array();
$this->writeHeader(0x72, 0x1a21);
$this->writeHeader(0x73, 0x0000, array(array(0, 2), array(0, 4)));
return true;
}
public function close() {
fclose($this->id);
}
public function addDirectory($name) {
$name = str_replace("/", "\\", $name);
if ($name[0] == "\\") $name = substr($name, 1);
if ($name[strlen($name) - 1] == "\\") $name = substr($name, 0, -1);
$parts = explode("\\", $name);
$c = &$this->tree;
$cname = ""; $delim = "";
for ($i = 0; $i < count($parts); $i++) {
$cname .= $delim.$parts[$i];
if (!isset($c[$parts[$i]])) {
$c[$parts[$i]] = array();
$this->writeHeader(0x74, $this->setBits(array(5, 6, 7, 15)), array(
array(0, 4),
array(0, 4),
array(0, 1),
array(0, 4),
array($this->getDateTime(), 4),
array(20, 1),
array(0x30, 1),
array(strlen($cname), 2),
array(0x10, 4),
$cname,
));
}
$c = &$c[$parts[$i]];
$delim = "\\";
}
return $name;
}
public function addFile($name, $dir = null) {
if (!file_exists($name))
return false;
$c = &$this->tree;
if (!is_null($dir)) {
$dir = $this->addDirectory($dir);
$parts = explode("\\", $dir);
for($i = 0; $i < count($parts); $i++)
$c = &$c[$parts[$i]];
}
$fname = pathinfo($name, PATHINFO_BASENAME);
if (in_array($fname, $c))
return true;
$data = file_get_contents($name);
$size = strlen($data);
if (!is_null($dir))
$fname = $dir."\\".$name;
$this->writeHeader(0x74, $this->setBits(array(15)), array(
array($size, 4),
array($size, 4),
array(0, 1),
array(crc32($data), 4),
array($this->getDateTime(filemtime($name)), 4),
array(20, 1),
array(0x30, 1),
array(strlen($fname), 2),
array(0x20, 4),
$fname,
));
fwrite($this->id, $data);
$c[] = $fname;
return true;
}
private function writeHeader($headType, $headFlags, $data = array()) {
if (!in_array($headType, array(0x72, 0x73, 0x74)))
return false;
$headSize = 2 + 1 + 2 + 2;
foreach ($data as $key => $value)
$headSize += is_array($value) ? $value[1] : strlen($value);
$header = $this->writeBytesToString(array_merge(array($headType, array($headFlags, 2), array($headSize, 2)), $data));
$header = ($headType == 0x72 ? "Ra" : $this->getCRC($header)).$header;
fwrite($this->id, $header);
}
private function getCRC($string) {
$crc = crc32($string);
return chr($crc & 0xFF).chr(($crc >> 8) & 0xFF);
}
private function getBytes($data, $bytes = 0) {
$output = "";
if (!$bytes)
$bytes = strlen($bytes);
if (is_int($data) || is_float($data)) {
$data = sprintf("%0".($bytes * 2)."x", $data);
for ($i = 0; $i < strlen($data); $i += 2)
$output = chr(hexdec(substr($data, $i, 2))).$output;
} else
$output = $data;
return $output;
}
private function writeBytesToString($data) {
$output = "";
for ($i = 0; $i < count($data); $i++) {
if (is_array($data[$i]))
$output .= $this->getBytes($data[$i][0], $data[$i][1]);
else
$output .= $this->getBytes($data[$i]);
}
return $output;
}
private function setBits($bits) {
$out = 0;
if (is_int($bits))
$bits[] = $bits;
for ($i = 0; $i < count($bits); $i++)
$out |= 1 << $bits[$i];
return $out;
}
private function getDateTime($time = null) {
if (!is_null($time))
$time = time();
$dt = getdate();
$out = $dt["seconds"] | ($dt["minutes"] << 5) | ($dt["hours"] << 11) | ($dt["mday"] << 16) | ($dt["mon"] << 21) | (($dt["year"] - 1980) << 25);
return $out;
}
};
?>