clrghouz/app/Classes/File.php

135 lines
3.1 KiB
PHP

<?php
namespace App\Classes;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\File\File as FileBase;
class File extends FileBase implements \Iterator
{
private const LOGKEY = 'F--';
private int $counter = 0;
private bool $isArchive = FALSE;
private bool $canHandle = FALSE;
private \ZipArchive $z;
private array $zipfile = [];
public function __construct(mixed $path,bool $checkPath=true)
{
parent::__construct($path,$checkPath);
switch($x=$this->guessExtension()) {
case 'zip':
$this->canHandle = TRUE;
$this->isArchive = TRUE;
$this->z = new \ZipArchive;
$this->z->open($this->getRealPath());
break;
case NULL:
case 'bin':
if ($this->isPacket() || ($path instanceof UploadedFile && (strcasecmp($path->getClientOriginalExtension(),'pkt') === 0))) {
$this->canHandle = TRUE;
break;
}
default:
Log::alert(sprintf('%s:? Unknown file received: %s (%s) [%s]',self::LOGKEY,$x,$this->getExtension(),$path instanceof UploadedFile ? $path->getClientOriginalExtension() : '-'));
}
}
/* ITERATOR */
public function current()
{
if ($this->isArchive) {
$this->zipfile = $this->z->statIndex($this->counter,\ZipArchive::FL_UNCHANGED);
$f = $this->z->getStream($this->zipfile['name']);
if (! $f)
throw new \Exception(sprintf('%s:Failed getting ZipArchive::stream (%s)',self::LOGKEY,$this->z->getStatusString()));
return $f;
} else {
return fopen($this->getRealPath(),'r+');
}
}
public function next()
{
$this->counter++;
}
public function key()
{
return $this->counter;
}
public function valid()
{
// If we have a pkt file, then counter can only be 1.
return $this->canHandle && (($this->isArchive && ($this->counter < $this->z->numFiles)) || $this->counter === 0);
}
public function rewind()
{
$this->counter = 0;
}
/* METHODS */
/**
* Determine if the file is a mail packet
*
* @return bool
*/
private function isPacket(): bool
{
return (strcasecmp($this->getExtension(),'pkt') === 0);
}
public function itemName(): string
{
return ($this->isArchive && $this->valid()) ? Arr::get(stream_get_meta_data($this->current()),'uri') : $this->getFilename();
}
public function itemSize(): int
{
return $this->isArchive ? Arr::get($this->zipfile,'size') : $this->getSize();
}
/**
* Return the name of the file, without a node ID prefix
*
* @return string
*/
public function rawName(): string
{
return preg_replace('/^[0-9A-F]{4}-/','',$this->getFilename());
}
/**
* Return the packet name
*
* @return string|null
* @throws \Exception
*/
public function pktName(): ?string
{
if ($this->isArchive) {
$this->zipfile = $this->z->statIndex($this->counter,\ZipArchive::FL_UNCHANGED);
$f = $this->z->getStream($this->zipfile['name']);
if (! $f)
throw new \Exception(sprintf('%s:Failed getting ZipArchive::stream (%s)',self::LOGKEY,$this->z->getStatusString()));
return preg_replace('/.pkt$/i','',Arr::get(stream_get_meta_data($f),'uri'));
} else {
return $this->isPacket() ? preg_replace('/.pkt$/i','',$this->rawName()) : NULL;
}
}
}