From 3ffb1c1fd60ff78d32beaed76a46eb3c543a8c89 Mon Sep 17 00:00:00 2001 From: Deon George Date: Mon, 14 Nov 2022 00:29:55 +1100 Subject: [PATCH] Support for ZIP archives --- app/Classes/FTN/Packet.php | 26 +-- app/Classes/File.php | 92 +++++++++++ app/Classes/File/Receive.php | 115 ++++++------- app/Console/Commands/PacketInfo.php | 67 ++++---- app/Console/Commands/PacketProcess.php | 21 ++- app/Http/Controllers/HomeController.php | 15 +- app/Traits/Import.php | 1 + resources/views/pkt.blade.php | 209 +++++++++++++----------- tests/Feature/PacketTest.php | 190 +++++++++++---------- 9 files changed, 441 insertions(+), 295 deletions(-) create mode 100644 app/Classes/File.php diff --git a/app/Classes/FTN/Packet.php b/app/Classes/FTN/Packet.php index c924b6d..e763a75 100644 --- a/app/Classes/FTN/Packet.php +++ b/app/Classes/FTN/Packet.php @@ -113,23 +113,26 @@ class Packet extends FTNBase implements \Iterator, \Countable } /** - * Open a packet file + * Process a packet file * - * @param File $file + * @param mixed $f + * @param string $name + * @param int $size * @param System|null $system * @param bool $use_cache * @return Packet * @throws InvalidPacketException */ - public static function open(File $file,System $system=NULL,bool $use_cache=TRUE): self - { - Log::debug(sprintf('%s:+ Opening Packet [%s]',self::LOGKEY,$file)); - $f = fopen($file,'r'); - $fstat = fstat($f); + public static function process(mixed $f,string $name,int $size,System $system=NULL,bool $use_cache=TRUE): self + { + Log::debug(sprintf('%s:+ Opening Packet [%s] with size [%d]',self::LOGKEY,$name,$size)); + + $read_ptr = 0; // PKT Header $header = fread($f,self::HEADER_LEN); + $read_ptr += strlen($header); // Could not read header if (strlen($header) != self::HEADER_LEN) @@ -142,10 +145,11 @@ class Packet extends FTNBase implements \Iterator, \Countable $o = new self; $o->use_cache = $use_cache; - $o->name = (string)$file; + $o->name = $name; $o->header = unpack(self::unpackheader(self::v2header),$header); $x = fread($f,2); + $read_ptr += strlen($x); // End of Packet? if (strlen($x) == 2 and $x == "\00\00") @@ -171,6 +175,8 @@ class Packet extends FTNBase implements \Iterator, \Countable $last = ''; while ($buf_ptr || (! feof($f) && ($readbuf=fread($f,self::BLOCKSIZE)))) { + $read_ptr += strlen($readbuf); + if (strlen($message) < self::PACKED_MSG_HEADER_LEN) { $addchars = self::PACKED_MSG_HEADER_LEN-strlen($message); $message .= substr($readbuf,$buf_ptr,$addchars); @@ -204,7 +210,7 @@ class Packet extends FTNBase implements \Iterator, \Countable // In case our packet break is at the end of the buffer $last = substr($readbuf,-2); - if ((str_contains($last,"\x00")) && ($fstat['size']-ftell($f) > 2)) { + if ((str_contains($last,"\x00")) && ($size-$read_ptr > 2)) { $message .= substr($readbuf,$buf_ptr); $buf_ptr = 0; @@ -216,7 +222,7 @@ class Packet extends FTNBase implements \Iterator, \Countable } // See if we have found the end of the packet, if not read more. - if ($end === FALSE && (ftell($f) < $fstat['size'])) { + if ($end === FALSE && ($read_ptr < $size)) { $message .= substr($readbuf,$buf_ptr); $buf_ptr = 0; diff --git a/app/Classes/File.php b/app/Classes/File.php new file mode 100644 index 0000000..d95a509 --- /dev/null +++ b/app/Classes/File.php @@ -0,0 +1,92 @@ +guessExtension()) { + case 'zip': + $this->canHandle = TRUE; + $this->isArchive = TRUE; + $this->z = new \ZipArchive; + $this->z->open($this->getRealPath()); + break; + + case 'bin': + if ($this->getExtension() == 'pkt' || ($path instanceof UploadedFile && $path->getClientOriginalExtension() == 'pkt')) { + $this->canHandle = TRUE; + break; + }; + + default: + Log::alert(sprintf('%s:? Unknown file received: %s',self::LOGKEY,$x)); + } + } + + /* 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 */ + + 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(); + } +} \ No newline at end of file diff --git a/app/Classes/File/Receive.php b/app/Classes/File/Receive.php index 27448da..95df9e9 100644 --- a/app/Classes/File/Receive.php +++ b/app/Classes/File/Receive.php @@ -3,13 +3,13 @@ namespace App\Classes\File; use Exception; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; -use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; -use App\Classes\FTN\InvalidPacketException; -use App\Classes\FTN\Packet; +use App\Classes\File; +use App\Classes\FTN\{InvalidPacketException,Packet}; use App\Jobs\{MessageProcess,TicProcess}; use App\Models\Address; @@ -54,7 +54,7 @@ final class Receive extends Item case 'mtime': case 'name': case 'size': - return $this->receiving ? $this->receiving->{'file_'.$key} : NULL; + return $this->receiving?->{'file_'.$key}; case 'name_size_time': return sprintf('%s %lu %lu',$this->name,$this->size,$this->mtime); @@ -108,64 +108,67 @@ final class Receive extends Item // If we received a packet, we'll dispatch a job to process it if (! $this->receiving->incomplete) switch ($this->receiving->file_type) { + case self::IS_ARC: case self::IS_PKT: - Log::info(sprintf('%s: - Processing mail packet [%s]',self::LOGKEY,$this->file)); + Log::info(sprintf('%s: - Processing mail %s [%s]',self::LOGKEY,$this->receiving->file_type === self::IS_PKT ? 'PACKET' : 'ARCHIVE',$this->file)); try { - $po = Packet::open(new File($this->file),$this->ao->system); + $f = new File($this->file); + + foreach ($f as $packet) { + $po = Packet::process($packet,Arr::get(stream_get_meta_data($packet),'uri'),$f->itemSize(),$this->ao->system); + + // Check the messages are from the uplink + if ($this->ao->system->addresses->search(function($item) use ($po) { return $item->id == $po->fftn_o->id; }) === FALSE) { + Log::error(sprintf('%s: ! Packet [%s] is not from this link? [%d]',self::LOGKEY,$po->fftn_o->ftn,$this->ao->system_id)); + break; + } + + // Check the packet password + if ($this->ao->session('pktpass') != $po->password) { + Log::error(sprintf('%s: ! Packet from [%s] with password [%s] is invalid.',self::LOGKEY,$this->ao->ftn,$po->password)); + // @todo Generate message to system advising invalid password - that message should be sent without a packet password! + break; + } + + Log::info(sprintf('%s: - Packet has [%d] messages',self::LOGKEY,$po->count())); + + // Queue messages if there are too many in the packet. + if ($queue = ($po->count() > config('app.queue_msgs'))) + Log::info(sprintf('%s: - Messages will be sent to the queue for processing',self::LOGKEY)); + + $error = FALSE; + foreach ($po as $msg) { + Log::info(sprintf('%s: - Mail from [%s] to [%s]',self::LOGKEY,$msg->fftn,$msg->tftn)); + + // @todo Quick check that the packet should be processed by us. + // @todo validate that the packet's zone is in the domain. + + try { + // Dispatch job. + if ($queue) + MessageProcess::dispatch($msg); + else + MessageProcess::dispatchSync($msg); + + } catch (Exception $e) { + Log::error(sprintf('%s:! Got error dispatching message [%s] (%d:%s-%s).',self::LOGKEY,$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage())); + $error = TRUE; + } + } + + if ($po->errors->count() || $error) { + Log::info(sprintf('%s: - Not deleting packet [%s], as it has validation errors',self::LOGKEY,$this->file)); + + // If we want to keep the packet, we could do that logic here + } elseif (! config('app.packet_keep')) { + Log::debug(sprintf('%s: - Deleting processed packet [%s]',self::LOGKEY,$this->file)); + unlink($this->file); + } + } } catch (InvalidPacketException $e) { Log::error(sprintf('%s: - Not deleting packet [%s], as it generated an exception',self::LOGKEY,$this->file)); - - break; - } - - // Check the messages are from the uplink - if ($this->ao->system->addresses->search(function($item) use ($po) { return $item->id == $po->fftn_o->id; }) === FALSE) { - Log::error(sprintf('%s: ! Packet [%s] is not from this link? [%d]',self::LOGKEY,$po->fftn_o->ftn,$this->ao->system_id)); - break; - } - - // Check the packet password - if ($this->ao->session('pktpass') != $po->password) { - Log::error(sprintf('%s: ! Packet from [%s] with password [%s] is invalid.',self::LOGKEY,$this->ao->ftn,$po->password)); - // @todo Generate message to system advising invalid password - that message should be sent without a packet password! - break; - } - - Log::info(sprintf('%s: - Packet has [%d] messages',self::LOGKEY,$po->count())); - - // Queue messages if there are too many in the packet. - if ($queue = ($po->count() > config('app.queue_msgs'))) - Log::info(sprintf('%s: - Messages will be sent to the queue for processing',self::LOGKEY)); - - $error = FALSE; - foreach ($po as $msg) { - Log::info(sprintf('%s: - Mail from [%s] to [%s]',self::LOGKEY,$msg->fftn,$msg->tftn)); - - // @todo Quick check that the packet should be processed by us. - // @todo validate that the packet's zone is in the domain. - - try { - // Dispatch job. - if ($queue) - MessageProcess::dispatch($msg); - else - MessageProcess::dispatchSync($msg); - - } catch (Exception $e) { - Log::error(sprintf('%s:! Got error dispatching message [%s] (%d:%s-%s).',self::LOGKEY,$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage())); - $error = TRUE; - } - } - - if ($po->errors->count() || $error) { - Log::info(sprintf('%s: - Not deleting packet [%s], as it has validation errors',self::LOGKEY,$this->file)); - - // If we want to keep the packet, we could do that logic here - } elseif (! config('app.packet_keep')) { - Log::debug(sprintf('%s: - Deleting processed packet [%s]',self::LOGKEY,$this->file)); - unlink($this->file); } break; diff --git a/app/Console/Commands/PacketInfo.php b/app/Console/Commands/PacketInfo.php index b017ec1..5b47b4e 100644 --- a/app/Console/Commands/PacketInfo.php +++ b/app/Console/Commands/PacketInfo.php @@ -3,8 +3,9 @@ namespace App\Console\Commands; use Illuminate\Console\Command; -use Symfony\Component\HttpFoundation\File\File; +use Illuminate\Support\Arr; +use App\Classes\File; use App\Classes\FTN\Packet; use App\Models\System; @@ -16,7 +17,7 @@ class PacketInfo extends Command * @var string */ protected $signature = 'packet:info' - .' {pkt : Packet to process}' + .' {file : Packet to process}' .' {system? : Zone the packet is from}'; /** @@ -34,42 +35,48 @@ class PacketInfo extends Command */ public function handle() { - $f = new File($this->argument('pkt')); + $f = new File($this->argument('file')); $s = $this->argument('system') ? System::where('name',$this->argument('zone'))->singleOrFail() : NULL; - $pkt = Packet::open($f,$s); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$x=$f->itemName(),$f->itemSize(),$s); - $this->info(sprintf('Packet Type: %s',$pkt->type)); - $this->info(sprintf('From: %s to %s',$pkt->fftn,$pkt->tftn)); - $this->info(sprintf('Dated: %s',$pkt->date)); - $this->info(sprintf('Password: %s (%s)',$pkt->password,$pkt->password ? 'SET' : 'NOT set')); - $this->info(sprintf('Messages: %d',$pkt->messages->count())); - $this->info(sprintf('Tosser %d (%s) version %s',$pkt->software->code,$pkt->software->name,$pkt->software_ver)); - $this->info(sprintf('Capabilities: %x',$pkt->capability)); - $this->info(sprintf('Has Errors: %s',$pkt->errors->count() ? 'YES' : 'No')); - $this->info(sprintf('Messages: %d',$pkt->count())); + $this->alert(sprintf('File Name: %s',$x)); - foreach ($pkt as $msg) { - $this->warn(sprintf('- Date: %s',$msg->date)); - $this->warn(sprintf(' - FLAGS: %s',$msg->flags()->filter()->keys()->join(', '))); - $this->warn(sprintf(' - From: %s (%s)',$msg->user_from,$msg->fftn)); - $this->warn(sprintf(' - To: %s (%s)',$msg->user_to,$msg->tftn)); - $this->warn(sprintf(' - Subject: %s',$msg->subject)); + $this->info(sprintf('Packet Type: %s',$pkt->type)); + $this->info(sprintf('From: %s to %s',$pkt->fftn,$pkt->tftn)); + $this->info(sprintf('Dated: %s',$pkt->date)); + $this->info(sprintf('Password: %s (%s)',$pkt->password,$pkt->password ? 'SET' : 'NOT set')); + $this->info(sprintf('Messages: %d',$pkt->messages->count())); + $this->info(sprintf('Tosser %d (%s) version %s',$pkt->software->code,$pkt->software->name,$pkt->software_ver)); + $this->info(sprintf('Capabilities: %x',$pkt->capability)); + $this->info(sprintf('Has Errors: %s',$pkt->errors->count() ? 'YES' : 'No')); + $this->info(sprintf('Messages: %d',$pkt->count())); + + foreach ($pkt as $msg) { + $this->warn(sprintf('- Date: %s',$msg->date)); + $this->warn(sprintf(' - FLAGS: %s',$msg->flags()->filter()->keys()->join(', '))); + $this->warn(sprintf(' - From: %s (%s)',$msg->user_from,$msg->fftn)); + $this->warn(sprintf(' - To: %s (%s)',$msg->user_to,$msg->tftn)); + $this->warn(sprintf(' - Subject: %s',$msg->subject)); + + if ($msg->errors) + foreach ($msg->errors->errors()->all() as $error) + $this->line(' - '.$error); + } + + foreach ($pkt->errors as $msg) { + $this->error(sprintf('- Date: %s',$msg->date)); + $this->error(sprintf(' - FLAGS: %s',$msg->flags()->filter()->keys()->join(', '))); + $this->error(sprintf(' - From: %s (%s)',$msg->user_from,$msg->fftn)); + $this->error(sprintf(' - To: %s (%s)',$msg->user_to,$msg->tftn)); + $this->error(sprintf(' - Subject: %s',$msg->subject)); - if ($msg->errors) foreach ($msg->errors->errors()->all() as $error) $this->line(' - '.$error); - } + } - foreach ($pkt->errors as $msg) { - $this->error(sprintf('- Date: %s',$msg->date)); - $this->error(sprintf(' - FLAGS: %s',$msg->flags()->filter()->keys()->join(', '))); - $this->error(sprintf(' - From: %s (%s)',$msg->user_from,$msg->fftn)); - $this->error(sprintf(' - To: %s (%s)',$msg->user_to,$msg->tftn)); - $this->error(sprintf(' - Subject: %s',$msg->subject)); - - foreach ($msg->errors->errors()->all() as $error) - $this->line(' - '.$error); + $this->line("\n"); } } } diff --git a/app/Console/Commands/PacketProcess.php b/app/Console/Commands/PacketProcess.php index 3ce8317..787824c 100644 --- a/app/Console/Commands/PacketProcess.php +++ b/app/Console/Commands/PacketProcess.php @@ -3,8 +3,9 @@ namespace App\Console\Commands; use Illuminate\Console\Command; -use Symfony\Component\HttpFoundation\File\File; +use Illuminate\Support\Arr; +use App\Classes\File; use App\Classes\FTN\Packet; use App\Jobs\MessageProcess as Job; use App\Models\Address; @@ -17,7 +18,7 @@ class PacketProcess extends Command * @var string */ protected $signature = 'packet:process' - .' {pkt : Packet to process}' + .' {file : Packet to process}' .' {--N|nobot : Dont process bots}' .' {ftn? : System the packet is from}'; @@ -36,17 +37,19 @@ class PacketProcess extends Command */ public function handle() { - $f = new File($this->argument('pkt')); + $f = new File($this->argument('file')); $s = $this->argument('ftn') ? Address::findFTN($this->argument('ftn'))->system : NULL; - foreach (Packet::open($f,$s) as $msg) { - // @todo Quick check that the packet should be processed by us. - // @todo validate that the packet's zone is in the domain. + foreach ($f as $packet) { + foreach (Packet::process($packet,$f->itemName(),$f->itemSize(),$s) as $msg) { + // @todo Quick check that the packet should be processed by us. + // @todo validate that the packet's zone is in the domain. - $this->info(sprintf('Processing message from [%s] with msgid [%s]',$msg->fboss,$msg->msgid)); + $this->info(sprintf('Processing message from [%s] with msgid [%s]',$msg->fboss,$msg->msgid)); - // Dispatch job. - Job::dispatchSync($msg,$this->option('nobot')); + // Dispatch job. + Job::dispatchSync($msg,$this->option('nobot')); + } } } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index f440d0f..0ca1440 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Gate; +use App\Classes\File; use App\Classes\FTN\Packet; use App\Models\{Address,Domain,Echomail,Setup}; @@ -46,8 +47,9 @@ class HomeController extends Controller */ public function pkt(Request $request) { - $pkt = NULL; + $pkt = collect(); $file = NULL; + $f = NULL; if ($request->post()) { $request->validate([ @@ -57,10 +59,12 @@ class HomeController extends Controller foreach ($request->allFiles() as $key => $filegroup) { if ($key !== 'file') continue; - foreach ($filegroup as $file) { try { - $pkt = Packet::open($file); + $f = new File($file); + + foreach ($f as $packet) + $pkt->push([$f->itemName()=>Packet::process($packet,$f->itemName(),$f->itemSize())]); } catch (\Exception $e) { return redirect()->back()->withErrors(sprintf('%s (%s:%d)',$e->getMessage(),$e->getFile(),$e->getLine())); @@ -72,8 +76,9 @@ class HomeController extends Controller } return view('pkt') - ->with('file',$file) - ->with('result',$pkt) + ->with('file',$f) + ->with('filename',$f ? $file->getClientOriginalName() : NULL) + ->with('results',$pkt) ->with('hexdump',$file ? hex_dump(file_get_contents($file)) : ''); } diff --git a/app/Traits/Import.php b/app/Traits/Import.php index d5ce711..683df55 100644 --- a/app/Traits/Import.php +++ b/app/Traits/Import.php @@ -36,6 +36,7 @@ trait Import return $c; } + // @todo Consider merging this with File::openZipFile private function openFile(string $file,&$f): \ZipArchive { $z = new \ZipArchive; diff --git a/resources/views/pkt.blade.php b/resources/views/pkt.blade.php index fe05823..0c0a344 100644 --- a/resources/views/pkt.blade.php +++ b/resources/views/pkt.blade.php @@ -53,109 +53,126 @@ - @if($result) -

Packet Results

-

Packet {{ $file->getClientOriginalName() }} (type {{ $result->type }}) is from {{ $result->fftn }} to {{ $result->tftn }}, dated {{ $result->date }}.

-

This packet has {{ $result->messages->count() }} messages and {{ $result->password ? 'DOES' : 'does NOT' }} have a password.

-

Tosser: {{ $result->software->code }} ({{ $result->software->name }}), version {{ $result->software_ver }}. Capabilities: {{ $result->capability }}.

- @if ($result->messages->count() > 1) -

You can expand each one

- @endif -
-
- @foreach ($result as $msg) -
-
- + @if($results->count()) +

Archive Results: {{ $filename }}

-
+
+ @foreach($results as $item) + @foreach ($item as $file => $result) + +
- @if ($msg->errors) - @foreach ($msg->errors->messages()->all() as $error) -
- {{ $error }} +

Packet {{ $file }} (type {{ $result->type }}) is from {{ $result->fftn }} to {{ $result->tftn }}, dated {{ $result->date }}.

+

This packet has {{ $result->messages->count() }} messages and {{ $result->password ? 'DOES' : 'does NOT' }} have a password.

+

Tosser: {{ $result->software->code }} ({{ $result->software->name }}), version {{ $result->software_ver }}. Capabilities: {{ $result->capability }}.

+ @if ($result->messages->count() > 1) +

You can expand each one

+ @endif +
+
+ @foreach ($result as $msg) +
+
+ + +
+
+ @if ($msg->errors) + @foreach ($msg->errors->messages()->all() as $error) +
+ {{ $error }} +
+ @endforeach + @endif + +
+
+ DATE: {{ $msg->date }} +
+
+ FLAGS: {{ $msg->flags()->filter()->keys()->join(', ') }} +
+
+ +
+
+ FROM: {!! \App\Classes\FTN\Message::tr($msg->user_from) !!} ({{ $msg->fftn }}) +
+
+ TO: {!! \App\Classes\FTN\Message::tr($msg->user_to) !!}@if($msg->isNetmail()) ({{ $msg->tftn }}) @endif +
+
+ +
+
+ SUBJECT: {!! \App\Classes\FTN\Message::tr($msg->subject) !!} +
+
+ +
+
+
+
{!! \App\Classes\FTN\Message::tr($msg->message).sprintf("\r * Origin: %s",$msg->origin) !!}
+
+
+
+ + @if($msg->isNetmail()) +
+
+ VIA:
{!! $msg->via->join('
') !!} +
+
+ @else +
+
+ SEENBY:
{!! $msg->seenby->join('
') !!} +
+
+ +
+
+ PATH:
{!! $msg->path->join('
') !!} +
+
+ @endif + +
+
+ KLUDGES:
+ @foreach ($msg->kludge->sort(function($v,$k) { return $k; })->reverse() as $k => $v) + {{ $k }} {{ $v }}
+ @endforeach +
+
+
+
+ +
+
+
+
+ + +
+
+
+{{ hex_dump($msg) }}
+
+
+
+
@endforeach - @endif - -
-
- DATE: {{ $msg->date }} -
-
- FLAGS: {{ $msg->flags()->filter()->keys()->join(', ') }} -
-
- -
-
- FROM: {!! \App\Classes\FTN\Message::tr($msg->user_from) !!} ({{ $msg->fftn }}) -
-
- TO: {!! \App\Classes\FTN\Message::tr($msg->user_to) !!}@if($msg->isNetmail()) ({{ $msg->tftn }}) @endif -
-
- -
-
- SUBJECT: {!! \App\Classes\FTN\Message::tr($msg->subject) !!} -
-
- -
-
-
-
{!! \App\Classes\FTN\Message::tr($msg->message).sprintf("\r * Origin: %s",$msg->origin) !!}
-
-
-
- - @if($msg->isNetmail()) -
-
- VIA:
{!! $msg->via->join('
') !!} -
-
- @else -
-
- SEENBY:
{!! $msg->seenby->join('
') !!} -
-
- -
-
- PATH:
{!! $msg->path->join('
') !!} -
-
- @endif - -
-
- KLUDGES:
- @foreach ($msg->kludge->sort(function($v,$k) { return $k; })->reverse() as $k => $v) - {{ $k }} {{ $v }}
- @endforeach -
-
-
- @endforeach - - -
-
-
-{{ $hexdump }}
-
-
-
+ @endforeach + @endforeach
@endif @endsection \ No newline at end of file diff --git a/tests/Feature/PacketTest.php b/tests/Feature/PacketTest.php index 1071c4b..7ec7e74 100644 --- a/tests/Feature/PacketTest.php +++ b/tests/Feature/PacketTest.php @@ -2,9 +2,9 @@ namespace Tests\Feature; -use Symfony\Component\HttpFoundation\File\File; use Tests\TestCase; +use App\Classes\File; use App\Classes\FTN\Packet; use App\Models\{Address,Domain,System,Zone}; @@ -34,26 +34,28 @@ class PacketTest extends TestCase // This packet has an incorrect zone in the Origin $f = new File(__DIR__.'/data/test_nomsgid_origin.pkt'); - $pkt = Packet::open($f,NULL,FALSE); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$f->itemName(),$f->itemSize(),NULL,FALSE); - $this->assertEquals(1,$pkt->count()); + $this->assertEquals(1,$pkt->count()); - $messages = FALSE; - foreach ($pkt as $msg) { - $messages = TRUE; - $this->assertNotTrue($msg->isNetmail()); + $messages = FALSE; + foreach ($pkt as $msg) { + $messages = TRUE; + $this->assertNotTrue($msg->isNetmail()); - $this->assertNotFalse($msg->pathaddress->search($hub->id)); + $this->assertNotFalse($msg->pathaddress->search($hub->id)); - $this->assertCount(1,$msg->rogue_path); - $this->assertNotFalse($msg->rogue_path->search('21:999/1')); + $this->assertCount(1,$msg->rogue_path); + $this->assertNotFalse($msg->rogue_path->search('21:999/1')); - $this->assertCount(3,$msg->rogue_seenby); - $this->assertNotFalse($msg->rogue_seenby->search('21:999/1')); - $this->assertNotFalse($msg->rogue_seenby->search('21:999/999')); + $this->assertCount(3,$msg->rogue_seenby); + $this->assertNotFalse($msg->rogue_seenby->search('21:999/1')); + $this->assertNotFalse($msg->rogue_seenby->search('21:999/999')); + } + + $this->assertTrue($messages); } - - $this->assertTrue($messages); } public function test_nomsgid_noorigin() @@ -67,22 +69,24 @@ class PacketTest extends TestCase // This packet has an incorrect zone in the Origin $f = new File(__DIR__.'/data/test_nomsgid_noorigin.pkt'); - $pkt = Packet::open($f,$this->so,FALSE); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$f->itemName(),$f->itemSize(),$this->so,FALSE); - $this->assertEquals(1,$pkt->count()); + $this->assertEquals(1,$pkt->count()); - $messages = FALSE; - foreach ($pkt as $msg) { - $messages = TRUE; - $this->assertNotTrue($msg->isNetmail()); + $messages = FALSE; + foreach ($pkt as $msg) { + $messages = TRUE; + $this->assertNotTrue($msg->isNetmail()); - $this->assertCount(1,$msg->rogue_path); - $this->assertNotFalse($msg->rogue_path->search('10:1/1')); + $this->assertCount(1,$msg->rogue_path); + $this->assertNotFalse($msg->rogue_path->search('10:1/1')); - $this->assertCount(0,$msg->rogue_seenby); + $this->assertCount(0,$msg->rogue_seenby); + } + + $this->assertTrue($messages); } - - $this->assertTrue($messages); } public function test_msgid_origin() @@ -96,97 +100,105 @@ class PacketTest extends TestCase // This packet has an incorrect zone in the Origin $f = new File(__DIR__.'/data/test_msgid_origin.pkt'); - $pkt = Packet::open($f,$this->so,FALSE); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$f->itemName(),$f->itemSize(),$this->so,FALSE); - $this->assertEquals(1,$pkt->count()); + $this->assertEquals(1,$pkt->count()); - $messages = FALSE; - foreach ($pkt as $msg) { - $messages = TRUE; - $this->assertNotTrue($msg->isNetmail()); - $this->assertCount(0,$msg->rogue_path); + $messages = FALSE; + foreach ($pkt as $msg) { + $messages = TRUE; + $this->assertNotTrue($msg->isNetmail()); + $this->assertCount(0,$msg->rogue_path); - $this->assertCount(1,$msg->rogue_seenby); - $this->assertNotFalse($msg->rogue_seenby->search('10:1/1')); + $this->assertCount(1,$msg->rogue_seenby); + $this->assertNotFalse($msg->rogue_seenby->search('10:1/1')); - $this->assertNotFalse($msg->seenaddress->search($src->id)); + $this->assertNotFalse($msg->seenaddress->search($src->id)); + } + + $this->assertTrue($messages); } - - $this->assertTrue($messages); } public function test_packet_parse() { // This packet has a SOHSOH sequence $f = new File(__DIR__.'/data/test_binary_content-2.pkt'); - $pkt = Packet::open($f,NULL,FALSE); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$f->itemName(),$f->itemSize(),NULL,FALSE); - $this->assertEquals(1,$pkt->count()); + $this->assertEquals(1,$pkt->count()); - $messages = FALSE; - foreach ($pkt as $msg) { - $messages = TRUE; + $messages = FALSE; + foreach ($pkt as $msg) { + $messages = TRUE; - $this->assertNotTrue($msg->isNetmail()); - $this->assertSame('21:1/151 6189F64C',$msg->msgid); - $this->assertSame('a8791fd3d261734bb524bc5ed929aa4c',md5($msg->message)); - $this->assertSame('5b627ab5936b0550a97b738f4deff419',md5($msg->message_src)); - $this->assertCount(3,$msg->rogue_path); - $this->assertCount(170,$msg->rogue_seenby); - $this->assertContains('3/2744 4/100 106 5/100',$msg->seenby); - $this->assertContains('1/151 100 3/100',$msg->path); - $this->assertCount(11,$msg->seenby); - $this->assertCount(0,$msg->unknown); + $this->assertNotTrue($msg->isNetmail()); + $this->assertSame('21:1/151 6189F64C',$msg->msgid); + $this->assertSame('a8791fd3d261734bb524bc5ed929aa4c',md5($msg->message)); + $this->assertSame('5b627ab5936b0550a97b738f4deff419',md5($msg->message_src)); + $this->assertCount(3,$msg->rogue_path); + $this->assertCount(170,$msg->rogue_seenby); + $this->assertContains('3/2744 4/100 106 5/100',$msg->seenby); + $this->assertContains('1/151 100 3/100',$msg->path); + $this->assertCount(11,$msg->seenby); + $this->assertCount(0,$msg->unknown); + } + + $this->assertTrue($messages); } - $this->assertTrue($messages); - // This packet has SOH in the message content $f = new File(__DIR__.'/data/test_binary_content.pkt'); - $pkt = Packet::open($f,NULL,FALSE); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$f->itemName(),$f->itemSize(),NULL,FALSE); - $this->assertEquals(1,$pkt->count()); + $this->assertEquals(1,$pkt->count()); - $messages = FALSE; - foreach ($pkt as $msg) { - $messages = TRUE; + $messages = FALSE; + foreach ($pkt as $msg) { + $messages = TRUE; - $this->assertNotTrue($msg->isNetmail()); - $this->assertSame('21:1/126 eec6e958',$msg->msgid); - $this->assertSame('c0b00abfc3eff7e297bf14f5812a7261',md5($msg->message)); - $this->assertSame('a3193edcc68521d4ed07da6db2aeb0b6',md5($msg->message_src)); - $this->assertCount(3,$msg->rogue_path); - $this->assertCount(161,$msg->rogue_seenby); - $this->assertContains('1/995 2/100 116 1202 3/100 105 107 108 109 110 111 112 113 117 119',$msg->seenby); - $this->assertContains('1/126 100 3/100',$msg->path); - $this->assertCount(10,$msg->seenby); - $this->assertCount(0,$msg->unknown); + $this->assertNotTrue($msg->isNetmail()); + $this->assertSame('21:1/126 eec6e958',$msg->msgid); + $this->assertSame('c0b00abfc3eff7e297bf14f5812a7261',md5($msg->message)); + $this->assertSame('a3193edcc68521d4ed07da6db2aeb0b6',md5($msg->message_src)); + $this->assertCount(3,$msg->rogue_path); + $this->assertCount(161,$msg->rogue_seenby); + $this->assertContains('1/995 2/100 116 1202 3/100 105 107 108 109 110 111 112 113 117 119',$msg->seenby); + $this->assertContains('1/126 100 3/100',$msg->path); + $this->assertCount(10,$msg->seenby); + $this->assertCount(0,$msg->unknown); + } + + $this->assertTrue($messages); } - $this->assertTrue($messages); - // This packet has an incorrect zone in the Origin $f = new File(__DIR__.'/data/test_msgid_origin.pkt'); - $pkt = Packet::open($f,NULL,FALSE); + foreach ($f as $packet) { + $pkt = Packet::process($packet,$f->itemName(),$f->itemSize(),NULL,FALSE); - $this->assertEquals(1,$pkt->count()); + $this->assertEquals(1,$pkt->count()); - $messages = FALSE; - foreach ($pkt as $msg) { - $messages = TRUE; + $messages = FALSE; + foreach ($pkt as $msg) { + $messages = TRUE; - $this->assertNotTrue($msg->isNetmail()); - $this->assertSame('10:999/1 612aecda',$msg->msgid); - $this->assertSame('61078e680cda04c8b5eba0f712582e70',md5($msg->message)); - $this->assertSame('b9d65d4f7319ded282f3f1986276ae79',md5($msg->message_src)); - $this->assertCount(1,$msg->pathaddress); - $this->assertCount(1,$msg->rogue_seenby); - $this->assertContains('1/1 999/1 999',$msg->seenby); - $this->assertContains('999/1',$msg->path); - $this->assertCount(1,$msg->seenby); - $this->assertCount(0,$msg->unknown); + $this->assertNotTrue($msg->isNetmail()); + $this->assertSame('10:999/1 612aecda',$msg->msgid); + $this->assertSame('61078e680cda04c8b5eba0f712582e70',md5($msg->message)); + $this->assertSame('b9d65d4f7319ded282f3f1986276ae79',md5($msg->message_src)); + $this->assertCount(1,$msg->pathaddress); + $this->assertCount(1,$msg->rogue_seenby); + $this->assertContains('1/1 999/1 999',$msg->seenby); + $this->assertContains('999/1',$msg->path); + $this->assertCount(1,$msg->seenby); + $this->assertCount(0,$msg->unknown); + } + + $this->assertTrue($messages); } - - $this->assertTrue($messages); } }