Skip to content

Instantly share code, notes, and snippets.

@vakata
Created October 11, 2021 22:21
Show Gist options
  • Select an option

  • Save vakata/e098651e2ed75a0c24fcf86e1ecd62aa to your computer and use it in GitHub Desktop.

Select an option

Save vakata/e098651e2ed75a0c24fcf86e1ecd62aa to your computer and use it in GitHub Desktop.
<?php
namsepace vakata\zip;
class Zip
{
protected $compression = false;
protected $data = [];
protected $ctrl = [];
protected $offset = 0;
public function __construct(bool $compression = false)
{
$this->compression = $compression;
}
protected function ZipTime(int $time = null) {
$data = !isset($time) ? getdate() : getdate($time);
if ($data['year'] < 1980) {
$data['year'] = 1980;
$data['mon'] = 1;
$data['mday'] = 1;
$data['hours'] = 0;
$data['minutes'] = 0;
$data['seconds'] = 0;
}
$data['year'] -= 1980;
return '' .
pack('v', ($data['hours'] << 11) | ($data['minutes'] << 5) | ($data['seconds'] >> 1)) .
pack('v', ($data['year'] << 9) | ($data['mon'] << 5) | ($data['mday']));
}
public function addFromString(string $name, string $content, int $time = null): static
{
if (!isset($time)) {
$time = time();
}
$name = str_replace('\\', '/', $name);
$time = $this->ZipTime($time);
$ln1 = strlen($content);
$ln2 = $ln1;
$crc = crc32($content);
if ($this->compression) {
$content = gzcompress($content);
$content = substr(substr($content, 0, strlen($content) - 4), 2);
$ln2 = strlen($content);
}
$data = "\x50\x4b\x03\x04\x14\x00\x00\x00" .
($this->compression ? "\x08\x00" : "\x00\x00") .
$time .
pack('V', $crc) . pack('V', $ln2) . pack('V', $ln1) . pack('v', strlen($name)) . pack('v', 0) .
$name . $content;
$this->data[] = $data;
$ctrl = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00" .
($this->compression ? "\x08\x00" : "\x00\x00") .
$time .
pack('V', $crc) . pack('V', $ln2) . pack('V', $ln1) . pack('v', strlen($name)) . pack('v', 0) .
pack('v', 0) . pack('v', 0) . pack('v', 0) . pack('V', 32) . pack('V', $this->offset) .
$name;
$this->ctrl[] = $ctrl;
$this->offset += strlen($data);
return $this;
}
public function addFile(string $name, string $path, int $time = null): static
{
if (!isset($time)) {
$time = @filemtime($path);
if (!$time) {
$time = null;
}
}
return $this->addFromString($name, file_get_contents($path), $time);
}
public function contents(): string
{
$data = implode('', $this->data);
$ctrl = implode('', $this->ctrl);
return '' .
$data .
$ctrl .
"\x50\x4b\x05\x06\x00\x00\x00\x00" .
pack('v', count($this->ctrl)) .
pack('v', count($this->ctrl)) .
pack('V', strlen($ctrl)) .
pack('V', strlen($data)) .
"\x00\x00";
}
public function __toString()
{
return $this->contents();
}
}
// header('Content-Type: application/zip');
// header('Content-Disposition: attachment; filename=test.zip');
// $z = new Zip(true);
// $z->addFromString('test.txt', 'asdf', 0);
// $z->addFile('test.log', 'index.php');
// echo $z;
// die();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment