Upload via GUI (258 Dateien)
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* Eigenständiger ZIP-Writer ohne php_zip Erweiterung.
|
||||
* Implementiert ZIP-Format (PKZIP 2.0) direkt in PHP.
|
||||
*/
|
||||
class SimpleZip
|
||||
{
|
||||
private string $path;
|
||||
private $fh;
|
||||
private array $entries = [];
|
||||
private int $offset = 0;
|
||||
|
||||
public function __construct(string $path)
|
||||
{
|
||||
$this->path = $path;
|
||||
$this->fh = fopen($path, 'wb');
|
||||
if (!$this->fh) throw new RuntimeException("Kann ZIP nicht erstellen: $path");
|
||||
}
|
||||
|
||||
public function addFromString(string $localName, string $data): void
|
||||
{
|
||||
$this->addData($localName, $data, time());
|
||||
}
|
||||
|
||||
public function addFile(string $filePath, string $localName): void
|
||||
{
|
||||
$data = file_get_contents($filePath);
|
||||
$mtime = filemtime($filePath);
|
||||
$this->addData($localName, $data, $mtime);
|
||||
}
|
||||
|
||||
private function addData(string $localName, string $data, int $mtime): void
|
||||
{
|
||||
$localName = str_replace('\\', '/', $localName);
|
||||
$crc = crc32($data);
|
||||
$size = strlen($data);
|
||||
$compressed = gzdeflate($data, 6);
|
||||
$compSize = strlen($compressed);
|
||||
|
||||
// Lokaler Header
|
||||
$dosTime = $this->dosTime(filemtime($filePath));
|
||||
$nameLen = strlen($localName);
|
||||
|
||||
$localHeader = pack('VvvvvVVVvv',
|
||||
0x04034b50, // Signatur
|
||||
20, // Version needed
|
||||
0, // Flags
|
||||
8, // Deflate
|
||||
$dosTime, // Mod time
|
||||
$crc,
|
||||
$compSize,
|
||||
$size,
|
||||
$nameLen,
|
||||
0 // Extra length
|
||||
) . $localName;
|
||||
|
||||
fwrite($this->fh, $localHeader);
|
||||
fwrite($this->fh, $compressed);
|
||||
|
||||
$this->entries[] = [
|
||||
'name' => $localName,
|
||||
'crc' => $crc,
|
||||
'size' => $size,
|
||||
'compSize' => $compSize,
|
||||
'offset' => $this->offset,
|
||||
'dosTime' => $dosTime,
|
||||
];
|
||||
|
||||
$this->offset += strlen($localHeader) + $compSize;
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
$cdOffset = $this->offset;
|
||||
$cdSize = 0;
|
||||
|
||||
foreach ($this->entries as $e) {
|
||||
$nameLen = strlen($e['name']);
|
||||
$cd = pack('VvvvvVVVvvvvvVV',
|
||||
0x02014b50, // CD Signatur
|
||||
20, // Version made by
|
||||
20, // Version needed
|
||||
0, // Flags
|
||||
8, // Deflate
|
||||
$e['dosTime'],
|
||||
$e['crc'],
|
||||
$e['compSize'],
|
||||
$e['size'],
|
||||
$nameLen,
|
||||
0, // Extra length
|
||||
0, // Comment length
|
||||
0, // Disk start
|
||||
0, // Internal attr
|
||||
0, // External attr
|
||||
$e['offset']
|
||||
) . $e['name'];
|
||||
|
||||
fwrite($this->fh, $cd);
|
||||
$cdSize += strlen($cd);
|
||||
}
|
||||
|
||||
// End of central directory
|
||||
$count = count($this->entries);
|
||||
fwrite($this->fh, pack('VvvvvVVv',
|
||||
0x06054b50, // EOCD Signatur
|
||||
0, // Disk number
|
||||
0, // Disk with CD
|
||||
$count, // Entries on disk
|
||||
$count, // Total entries
|
||||
$cdSize,
|
||||
$cdOffset,
|
||||
0 // Comment length
|
||||
));
|
||||
|
||||
fclose($this->fh);
|
||||
}
|
||||
|
||||
private function dosTime(int $unixTime): int
|
||||
{
|
||||
$d = getdate($unixTime);
|
||||
return (($d['year'] - 1980) << 25)
|
||||
| ($d['mon'] << 21)
|
||||
| ($d['mday'] << 16)
|
||||
| ($d['hours'] << 11)
|
||||
| ($d['minutes'] << 5)
|
||||
| ($d['seconds'] >> 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user