More complete rework of packet parsing and packet generation with 29710c

This commit is contained in:
Deon George 2024-05-19 23:28:45 +10:00
parent 46f52dd56d
commit f279d85b08
43 changed files with 412 additions and 291 deletions

View File

@ -12,9 +12,9 @@ use Illuminate\Validation\Validator as ValidatorResult;
use App\Classes\FTN as FTNBase;
use App\Exceptions\InvalidPacketException;
use App\Models\{Address,Domain,Echomail,Netmail,Zone};
use App\Models\{Address,Domain,Echomail,Netmail,Setup,Zone};
use App\Rules\{TwoByteInteger,TwoByteIntegerWithZero};
use App\Traits\{EncodeUTF8,ObjectIssetFix};
use App\Traits\ObjectIssetFix;
/**
* Class Message
@ -91,6 +91,7 @@ class Message extends FTNBase
private array $header; // Message Header
private int $tzutc = 0; // TZUTC that needs to be converted to be used by Carbon @see self::kludges
private Echomail|Netmail $mo; // The object storing this packet message
private Address $us; // Our address for this message
/** @deprecated Not sure why this is needed? */
public bool $packed = FALSE; // Has the message been packed successfully
@ -156,6 +157,7 @@ class Message extends FTNBase
{
$oo = new self($o->fftn->zone);
$oo->mo = $o;
$oo->us = our_address($o->tftn);
return $oo;
}
@ -507,6 +509,8 @@ class Message extends FTNBase
*/
public function __toString(): string
{
$s = Setup::findOrFail(config('app.id'));
$return = pack(collect(self::HEADER)->pluck(1)->join(''),
$this->mo->fftn->node_id, // Originating Node
$this->mo->tftn->node_id, // Destination Node
@ -521,22 +525,26 @@ class Message extends FTNBase
$return .= $this->mo->from."\00";
$return .= $this->mo->subject."\00";
if (($this->mo instanceof Netmail) && $this->mo->isFlagSet(self::FLAG_LOCAL)) {
// If there isnt an INTL kludge, we'll add it
if (! $this->mo->kludges->has('INTL'))
$this->mo->kludges->put('INTL',sprintf('%s %s',$this->mo->tftn->ftn3d,$this->mo->fftn->ftn3d));
if ((! $this->mo->kludges->has('FMPT')) && $this->mo->fftn->point_id)
$this->mo->kludges->put('FMPT',$this->mo->fftn->point_id);
if ((! $this->mo->kludges->has('TOPT')) && $this->mo->tftn->point_id)
$this->mo->kludges->put('TOPT',$this->mo->tftn->point_id);
}
if ($this->mo->isFlagSet(self::FLAG_LOCAL))
$this->mo->kludges->put('PID',sprintf('clrghouz %s',$s->version));
else
$this->mo->kludges->put('TID',sprintf('clrghouz %s',$s->version));
if ($this->mo instanceof Echomail)
$return .= sprintf("AREA:%s\r",strtoupper($this->mo->echoarea->name));
if ($this->mo instanceof Netmail) {
// @todo If the message is local, then our kludges are not in the msg itself, we'll add them
if ($this->isFlagSet(self::FLAG_LOCAL))
Log::debug(sprintf('%s:^ Local message, we may need to set our INTL/FMPT/TOPT',self::LOGKEY));
$return .= sprintf("\01INTL %s\r",$this->mo->kludges->get('INTL'));
if ($this->mo->kludges->has('FMPT'))
$return .= sprintf("\01FMPT %d\r",$this->mo->kludges->get('FMPT'));
if ($this->mo->kludges->has('TOPT'))
$return .= sprintf("\01TOPT %d\r",$this->mo->kludges->get('TOPT'));
}
// Add some kludges
$return .= sprintf("\01TZUTC: %s\r",str_replace('+','',$this->mo->date->getOffsetString('')));
@ -551,11 +559,15 @@ class Message extends FTNBase
$return .= $this->mo->content;
if ($this->mo instanceof Netmail) {
// @todo automatically include our address in the path
foreach ($this->mo->path as $ao)
$return .= sprintf("\x01Via %s\r",$this->mo->via($ao));
// Add our address
$return .= sprintf("\x01Via %s @%s.UTC %s (%04X)\r",
$this->us->ftn3d,
Carbon::now()->format('Ymd.His'),
Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
} else {
// FTS-0004.001/FSC-0068.001 The message SEEN-BY lines
// FTS-0004.001/FSC-0068.001 The message PATH lines

View File

@ -50,6 +50,20 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
protected Collection $messages; // Messages in the Packet
public Collection $errors; // Messages that fail validation
protected int $index; // Our array index
protected $pass_p = NULL; // Overwrite the packet password (when packing messages)
/* ABSTRACT */
/**
* This function is intended to be implemented in child classes to test if the packet
* is defined by the child object
*
* @see self::PACKET_TYPES
* @param string $header
* @return bool
*/
abstract public static function is_type(string $header): bool;
abstract protected function header(): string;
/* STATIC */
@ -63,16 +77,6 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
return collect(static::HEADER)->sum(function($item) { return Arr::get($item,2); });
}
/**
* This function is intended to be implemented in child classes to test if the packet
* is defined by the child object
*
* @see self::PACKET_TYPES
* @param string $header
* @return bool
*/
abstract public static function is_type(string $header): bool;
/**
* Process a packet file
*
@ -261,6 +265,9 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
case 'name':
return $this->{$key} ?: sprintf('%08x',timew());
case 'messages':
return $this->{$key};
default:
throw new \Exception('Unknown key: '.$key);
}
@ -274,6 +281,12 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
*/
public function __toString(): string
{
if (empty($this->messages))
throw new InvalidPacketException('Refusing to make an empty packet');
if (empty($this->tftn_p) || empty($this->fftn_p))
throw new InvalidPacketException('Cannot generate a packet without a destination address');
$return = $this->header();
foreach ($this->messages as $o)
@ -379,18 +392,18 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
/**
* Generate a packet
*
* @param Collection $msgs
* @return string
* @throws InvalidPacketException
*/
public function generate(Collection $msgs): string
public function generate(): string
{
return (string)$this;
}
public function mail(Collection $msgs): self
{
$this->messages = $msgs;
if (empty($this->tftn_p) || empty($this->fftn_p))
throw new InvalidPacketException('Cannot generate a packet without a destination address');
return (string)$this;
return $this;
}
/**
@ -500,6 +513,20 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
$this->messages->push($msg);
}
/**
* Overwrite the packet password
*
* @param string|null $password
* @return self
*/
public function password(string $password=NULL): self
{
if ($password && (strlen($password) < 9))
$this->pass_p = $password;
return $this;
}
/** @deprecated Is this used? */
public function pluck(string $key): Collection
{

View File

@ -59,11 +59,10 @@ final class FSC48 extends Packet
/**
* Create our message packet header
* // @todo add the ability to overwrite the password
*/
protected function header(): string
{
$oldest = $this->messages->sortBy(function($item) { return $item->datetime; })->last();
$oldest = $this->messages->sortBy('datetime')->last();
try {
return pack(collect(self::HEADER)->pluck(1)->join(''),
@ -77,14 +76,14 @@ final class FSC48 extends Packet
$oldest->datetime->format('s'), // Second
0, // Baud
2, // Packet Version (should be 2)
$this->fftn_p->point_id ? 0xffff : $this->fftn_p->node_id, // Orig Net (0xFFFF when OrigPoint != 0)
$this->fftn_p->point_id ? 0xffff : $this->fftn_p->host_id, // Orig Net (0xFFFF when OrigPoint != 0)
$this->tftn_p->host_id, // Dest Net
(Setup::PRODUCT_ID & 0xff), // Product Code Lo
Setup::PRODUCT_VERSION_MAJ, // Product Version Major
$this->tftn_p->session('pktpass'), // Packet Password
$this->pass_p ?: $this->tftn_p->session('pktpass'), // Packet Password
$this->fftn_p->zone->zone_id, // Orig Zone
$this->tftn_p->zone->zone_id, // Dest Zone
$this->fftn_p->point_id ? $this->fftn_p->node_id : 0x00, // Aux Net
$this->fftn_p->point_id ? $this->fftn_p->host_id : 0x00, // Aux Net
1<<0, // fsc-0039.004 (copy of 0x2c)
((Setup::PRODUCT_ID >> 8) & 0xff), // Product Code Hi
Setup::PRODUCT_VERSION_MIN, // Product Version Minor

View File

@ -9,11 +9,9 @@ use App\Models\{Echoarea,Echomail,Netmail};
*/
abstract class Process
{
public static function canProcess(string $echoarea): bool
public static function canProcess(Echoarea $eao): bool
{
$eao = Echoarea::where('name',$echoarea)->single();
return $eao && $eao->automsgs;
return $eao->automsgs;
}
/**

View File

@ -27,9 +27,9 @@ final class Test extends Process
|| (! in_array(strtolower($mo->subject),self::testing)))
return FALSE;
Log::info(sprintf('%s:- Processing TEST message from (%s) [%s] in [%s]',self::LOGKEY,$msg->user_from,$msg->fftn,$msg->echoarea));
Log::info(sprintf('%s:- Processing TEST message from (%s) [%s] in [%s]',self::LOGKEY,$mo->from,$mo->fftn->ftn,$mo->echoarea->name));
Notification::route('echomail',$mo->echoarea)->notify(new TestNotification($msg));
Notification::route('echomail',$mo->echoarea->withoutRelations())->notify(new TestNotification($mo));
return TRUE;
}

View File

@ -5,7 +5,8 @@ namespace App\Classes\FTN\Process\Netmail;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\{Message,Process};
use App\Classes\FTN\Process;
use App\Models\{Echomail,Netmail};
use App\Notifications\Netmails\Areafix as AreafixNotification;
use App\Notifications\Netmails\Areafix\NotConfiguredHere as AreafixNotConfiguredHereNotification;
@ -18,18 +19,18 @@ final class Areafix extends Process
{
private const LOGKEY = 'RP-';
public static function handle(Message $msg): bool
public static function handle(Echomail|Netmail $mo): bool
{
if (strtolower($msg->user_to) !== 'areafix')
if (strtolower($mo->to) !== 'areafix')
return FALSE;
Log::info(sprintf('%s:- Processing AREAFIX message from (%s) [%s]',self::LOGKEY,$msg->user_from,$msg->fftn));
Log::info(sprintf('%s:- Processing AREAFIX message from (%s) [%s]',self::LOGKEY,$mo->from,$mo->fftn));
// If this is not a node we manage, then respond with a sorry can help you
if ($msg->fftn_o->system->sessions->count())
Notification::route('netmail',$msg->fftn_o)->notify(new AreafixNotification($msg));
if ($mo->fftn->system->sessions->count())
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification($mo));
else
Notification::route('netmail',$msg->fftn_o)->notify(new AreafixNotConfiguredHereNotification($msg));
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotConfiguredHereNotification($mo));
return TRUE;
}

View File

@ -5,7 +5,8 @@ namespace App\Classes\FTN\Process\Netmail;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\{Message,Process};
use App\Classes\FTN\Process;
use App\Models\{Echomail,Netmail};
use App\Notifications\Netmails\Ping as PingNotification;
/**
@ -17,14 +18,14 @@ final class Ping extends Process
{
private const LOGKEY = 'RP-';
public static function handle(Message $msg): bool
public static function handle(Echomail|Netmail $mo): bool
{
if (strtolower($msg->user_to) !== 'ping')
if (strtolower($mo->to) !== 'ping')
return FALSE;
Log::info(sprintf('%s:- Processing PING message from (%s) [%s]',self::LOGKEY,$msg->user_from,$msg->fftn));
Log::info(sprintf('%s:- Processing PING message from (%s) [%s]',self::LOGKEY,$mo->from,$mo->fftn->ftn));
Notification::route('netmail',$msg->fftn_o)->notify(new PingNotification($msg));
Notification::route('netmail',$mo->fftn)->notify(new PingNotification($mo));
return TRUE;
}

View File

@ -32,7 +32,7 @@ final class Mail extends Send
public function __get($key) {
switch ($key) {
case 'dbids':
return $this->f->messages->pluck('dbid');
return $this->f->messages->pluck('id');
case 'name':
return sprintf('%08x',timew($this->youngest()));
@ -111,7 +111,7 @@ final class Mail extends Send
return TRUE;
}
public function youngest(): Carbon
private function youngest(): Carbon
{
return $this->f->messages->pluck('date')->sort()->last();
}

View File

@ -128,13 +128,12 @@ class Receive extends Base
// If packet is greater than a size, lets queue it
if ($this->queue || ($this->receiving->size > config('fido.queue_size',0))) {
Log::info(sprintf('%s:- Packet [%s] will be sent to the queue for processing because its [%d] size, or queue forced',self::LOGKEY,$this->receiving->full_name,$this->receiving->size));
PacketProcess::dispatch($this->receiving,$this->ao->withoutRelations(),$rcvd_time);
PacketProcess::dispatch($this->receiving->rel_name,$this->ao->zone->domain,FALSE,$rcvd_time);
} else
PacketProcess::dispatchSync($this->receiving,$this->ao->withoutRelations(),$rcvd_time);
PacketProcess::dispatchSync($this->receiving->rel_name,$this->ao->zone->domain,TRUE,$rcvd_time);
} catch (\Exception $e) {
Log::error(sprintf('%s:! Got error dispatching packet [%s] (%d:%s-%s).',self::LOGKEY,$this->receiving->full_name,$e->getLine(),$e->getFile(),$e->getMessage()));
Log::error(sprintf('%s:! Got error dispatching packet [%s] (%d:%s-%s).',self::LOGKEY,$this->receiving->rel_name,$e->getLine(),$e->getFile(),$e->getMessage()));
}
break;

View File

@ -249,11 +249,10 @@ class Send extends Base
* Add our mail to the send queue
*
* @param Address $ao
* @param bool $update
* @return bool
* @throws Exception
*/
public function mail(Address $ao,bool $update=TRUE): bool
public function mail(Address $ao): bool
{
$mail = FALSE;
@ -265,7 +264,7 @@ class Send extends Base
}
// Netmail
if ($x=$ao->getNetmail($update)) {
if ($x=$ao->getNetmail()) {
Log::debug(sprintf('%s:- Netmail(s) added for sending to [%s]',self::LOGKEY,$ao->ftn));
$this->list->push(new Mail($x,self::T_NETMAIL));
@ -273,7 +272,7 @@ class Send extends Base
}
// Echomail
if ($x=$ao->getEchomail($update)) {
if ($x=$ao->getEchomail()) {
Log::debug(sprintf('%s:- Echomail(s) added for sending to [%s]',self::LOGKEY,$ao->ftn));
$this->list->push(new Mail($x,self::T_ECHOMAIL));

View File

@ -1009,6 +1009,9 @@ final class Binkp extends BaseProtocol
$this->send->close(TRUE,$this->node);
}
} else {
Log::error(sprintf('%s:! M_got[skip] not for our file? [%s]',self::LOGKEY,$buf));
}
} else {

View File

@ -50,7 +50,12 @@ class PacketAddress extends Command
exit(1);
}
echo hex_dump($ao->system->packet($ao)->generate($o->where('id',$this->argument('dbid'))->get()));
echo hex_dump($ao
->system
->packet($ao)
->mail($o->where('id',$this->argument('dbid'))->get())
->generate()
);
return Command::SUCCESS;
}

View File

@ -99,8 +99,8 @@ class PacketInfo extends Command
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(' - From: %s (%s)',$msg->from,$msg->fftn));
$this->error(sprintf(' - To: %s (%s)',$msg->to,$msg->tftn));
$this->error(sprintf(' - Subject: %s',$msg->subject));
foreach ($msg->errors->errors()->all() as $error)

View File

@ -10,6 +10,33 @@ use App\Classes\FTN\Packet;
use App\Jobs\PacketProcess as Job;
use App\Models\Address;
/**
* Things to test
* + Packet
* - Sender doesnt exist (try and send a bounce message in the same session)
* - Sender defined in DB by not ours
* - Sender has wrong password
* - Packet too old
*
* + Echomail
* - Area doesnt exist (to uplink)
* - Sender not subscribed (to uplink)
* - Sender cannot post (to uplink)
* - Sender has wrong address for echorea domain (to uplink)
* - Test message in echoarea
* - Echomail from address doesnt match packet envelope (to uplink)
* - Echomail too old (to uplink)
* - Rescanned dont generate notifications
* - Rescanned dont trigger bots
* - Some Notifications to an uplink should go to the admin instead?
*
* + Netmail
* - To hub, and user not defined (reject)
* - To hub, but user redirect (redirected)
* - To areafix (processed)
* - To ping (respond)
* - With trace turned on (respond)
*/
class PacketProcess extends Command
{
/**
@ -38,25 +65,25 @@ class PacketProcess extends Command
*/
public function handle()
{
$fs = Storage::disk(config('fido.local_disk'));
//$fs = Storage::disk(config('fido.local_disk'));
$rel_name = sprintf('%s/%s',config('fido.dir'),$this->argument('file'));
$f = new File($fs->path($rel_name));
//$f = new File($fs->path($rel_name));
$m = [];
if ($this->argument('ftn')) {
$a = Address::findFTN($this->argument('ftn'));
$ao = Address::findFTN($this->argument('ftn'));
} elseif (preg_match(sprintf('/^%s\.(.{3})$/',Packet::regex),$this->argument('file'),$m)) {
$a = Address::findOrFail(hexdec($m[1]));
$ao = Address::findOrFail(hexdec($m[1]));
} else {
$this->error('Unable to determine sender FTN address');
exit(1);
}
$x = Job::dispatchSync($rel_name,$a->zone->domain,$this->option('dontqueue'));
Job::dispatchSync($rel_name,$ao->zone->domain,$this->option('dontqueue'));
dd(['job completed'=>$x]);
return Command::SUCCESS;
}
}

View File

@ -4,7 +4,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\System;
use App\Models\Address;
class PacketSystem extends Command
{
@ -14,7 +14,7 @@ class PacketSystem extends Command
* @var string
*/
protected $signature = 'packet:system'
.' {sid : System ID}';
.' {ftn : System address}';
/**
* The console command description.
@ -31,15 +31,15 @@ class PacketSystem extends Command
*/
public function handle()
{
$so = System::findOrFail($this->argument('sid'));
$ao = Address::findFTN($this->argument('ftn'));
foreach ($so->addresses as $ao) {
$pkt = $ao->getEchomail(FALSE);
foreach ($ao->system->addresses as $o) {
$pkt = $o->getEchomail();
$this->info(sprintf('System address [%s] has [%d] messages.',$ao->ftn,$pkt?->count()));
if ($pkt) {
foreach ($pkt as $msg)
$this->warn(sprintf('- %s',$msg->msgid));
$this->warn(sprintf('- %s (%s)',$msg->msgid,$msg->id));
}
}
}

View File

@ -16,7 +16,7 @@ use Illuminate\Support\Facades\Notification;
use Illuminate\Support\ViewErrorBag;
use App\Classes\FTN\Message;
use App\Http\Requests\{AddressMerge,AreafixRequest,SystemRegister,SystemSessionRequest};
use App\Http\Requests\{AddressMerge,AreafixRequest,SystemEchoareaRequest,SystemRegister,SystemSessionRequest};
use App\Jobs\AddressPoll;
use App\Models\{Address,Echoarea,Echomail,Filearea,Netmail,Setup,System,Zone};
use App\Notifications\Netmails\AddressLink;
@ -694,30 +694,20 @@ class SystemController extends Controller
/**
* Update the systems echoareas
*
* @param Request $request
* @param SystemEchoareaRequest $request
* @param System $o
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
*/
public function echoareas(Request $request,System $o)
public function echoareas(SystemEchoareaRequest $request,System $o)
{
$ao = $o->addresses->firstWhere('id',$request->address_id);
if (($request->method() === 'POST') && $request->post()) {
session()->flash('accordion','echoarea');
if ($ao->trashed() && collect($request->get('id'))->diff($ao->echoareas->pluck('id'))->count())
return redirect()->back()->withErrors(sprintf('Address [%s] has been deleted, cannot add additional echos',$ao->ftn3d));
// Ensure we have session details for this address.
if (! $ao->session('sespass'))
return redirect()->back()->withErrors('System doesnt belong to this network');
$ao->echoareas()->syncWithPivotValues($request->get('id',[]),['subscribed'=>Carbon::now()]);
if (($request->method() === 'POST') && $request->validated()) {
$ao->echoareas()->syncWithPivotValues($request->validated('id',[]),['subscribed'=>Carbon::now()]);
return redirect()->back()->with('success','Echoareas updated');
}
// @todo Allow a NC/RC/ZC to override
$eo = Echoarea::active()
->where('domain_id',$ao->zone->domain_id)
->where(function($query) use ($ao) {
@ -869,7 +859,7 @@ class SystemController extends Controller
*/
public function session_del(System $o,Zone $zo)
{
$this->authorize('admin',$zo);
$this->authorize('update_nn',$o);
session()->flash('accordion','session');
$o->sessions()->detach($zo);

View File

@ -0,0 +1,71 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use App\Models\Domain;
/**
* Validation to register echoareas for a system
* o = System::class
*
* @note This validation only expects to be used with POST
* Variables:
* + "address_id" => "address" // address_id that will receive the echos
* + "domain_id" => "domain" // Of the echoareas
* + "id" => array of IDs // The echos being subscribed (or if absent, are removed)
*
* Rules:
* @see AddressAdd::class for description of authorisation
*/
class SystemEchoareaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return request()->isMethod('get')
|| Gate::allows('update_nn',$this->route('o'));
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(Request $request): array
{
if (request()->isMethod('get'))
return [];
session()->flash('accordion','echoarea');
return [
'address_id'=>[
'exists:addresses,id',
// Make sure we have session details for the area
function ($attribute,$value,$fail) use ($request) {
$ao = request()->route('o')->addresses->firstWhere('id',$request->address_id);
if ((! $ao) || (! $ao->active) || (! $ao->system->zones->pluck('domain_id')->contains($request->domain_id)))
$fail('Address must be ACTIVE, and have session details for the domain');
},
],
'domain_id'=>'exists:domains,id',
'id'=>[
'array',
'min:1',
// Make sure the echoareas are in the domain
function ($attribute,$value,$fail) use ($request) {
$do = Domain::findOrFail($request->domain_id);
if ($do->echoareas->pluck('id')->intersect($value)->count() !== count($value))
$fail('Some echaoreas dont exist in the domain?');
},
]
];
}
}

View File

@ -8,13 +8,12 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use App\Classes\FTN\Message;
use App\Models\{Echoarea,Echomail,Netmail,User};
use App\Notifications\Netmails\{EchoareaNotExist,EchoareaNotSubscribed,EchoareaNoWrite,NetmailForward,Reject};
use App\Models\{Echomail,Netmail,User};
use App\Notifications\Netmails\{EchoareaNotExist,EchoareaNotSubscribed,EchoareaNoWrite,NetmailForward,NetmailHubNoUser};
use App\Traits\ParseAddresses;
class MessageProcess implements ShouldQueue
@ -174,7 +173,7 @@ class MessageProcess implements ShouldQueue
if (! $processed) {
Log::alert(sprintf('%s:! Netmail to the Hub from (%s) [%s] but no users here.',self::LOGKEY,$this->mo->from,$this->mo->fftn->ftn));
Notification::route('netmail',$this->mo->fftn)->notify(new Reject($this->mo));
Notification::route('netmail',$this->mo->fftn)->notify(new NetmailHubNoUser($this->mo));
}
// If in transit, store for collection
@ -269,11 +268,11 @@ class MessageProcess implements ShouldQueue
// @todo if we have an export for any of the seenby addresses, remove it
$seenby = $this->parseAddresses('seenby',$this->mo->seenby,$sender->zone,$o->rogue_seenby);
$this->mo->seenby()->syncWithoutDetaching($seenby);
//$seenby = $this->parseAddresses('seenby',$this->mo->seenby,$sender->zone,$o->rogue_seenby);
//$this->mo->seenby()->syncWithoutDetaching($seenby);
// In case our rogue_seenby changed
$this->mo->save();
//$this->mo->save();
return;
}
@ -294,14 +293,6 @@ class MessageProcess implements ShouldQueue
));
}
// If the node is not subscribed
if ($sender->echoareas->search(function($item) { return $item->id === $this->mo->echoarea->id; }) === FALSE) {
Log::alert(sprintf('%s:! FTN [%s] is not subscribed to [%s] for [%s].',self::LOGKEY,$sender->ftn,$this->mo->echoarea->name,$this->mo->msgid));
if (! $rescanned)
Notification::route('netmail',$sender)->notify(new EchoareaNotSubscribed($this->mo));
}
// Can the system send messages to this area?
if (! $this->mo->echoarea->can_write($sender->security)) {
Log::alert(sprintf('%s:! FTN [%s] is not allowed to post [%s] to [%s].',self::LOGKEY,$sender->ftn,$this->mo->msgid,$this->mo->echoarea->name));
@ -311,6 +302,14 @@ class MessageProcess implements ShouldQueue
return;
}
// If the node is not subscribed, we'll accept it, but let them know
if (! $sender->echoareas->contains($this->mo->echoarea)) {
Log::alert(sprintf('%s:! FTN [%s] is not subscribed to [%s] for [%s].',self::LOGKEY,$sender->ftn,$this->mo->echoarea->name,$this->mo->msgid));
if (! $rescanned)
Notification::route('netmail',$sender)->notify(new EchoareaNotSubscribed($this->mo));
}
// We know about this area, store it
$this->mo->save();

View File

@ -32,7 +32,7 @@ class PacketProcess implements ShouldQueue
private bool $interactive;
private bool $nobot;
public function __construct(string $filename,Domain $do,bool $interactive=FALSE,Carbon $rcvd_time=NULL,bool $nobot=FALSE)
public function __construct(string $filename,Domain $do,bool $interactive=TRUE,Carbon $rcvd_time=NULL,bool $nobot=FALSE)
{
$this->filename = $filename;
$this->do = $do;
@ -98,7 +98,7 @@ class PacketProcess implements ShouldQueue
if (strtoupper($pkt->fftn->session('pktpass')) !== strtoupper($pkt->password)) {
Log::error(sprintf('%s:! Packet from [%s] with password [%s] is invalid.',self::LOGKEY,$pkt->fftn->ftn,$pkt->password));
Notification::route('netmail',$pkt->fftn)->notify(new PacketPasswordInvalid($pkt->password,$this->filename));
Notification::route('netmail',$pkt->fftn)->notify(new PacketPasswordInvalid($pkt->password,$f->pktName()));
break;
}
@ -126,6 +126,9 @@ class PacketProcess implements ShouldQueue
$msg->set_pkt = $f->pktName();
$msg->set_recvtime = $this->rcvd_time;
if ($queue || (! $this->interactive))
Log::info(sprintf('%s:! Message [%s] will be sent to the queue to process',self::LOGKEY,$msg->msgid));
try {
// Dispatch job.
if ($queue || (! $this->interactive))

View File

@ -978,47 +978,26 @@ class Address extends Model
/**
* Get echomail for this node
*
* @param bool $update
* @param Collection|null $echomail
* @return Packet|null
* @throws \Exception
* @todo If we export to uplink hubs without our address in the seenby, they should send the message back to
* us with their seenby's.
*/
public function getEchomail(bool $update=TRUE,Collection $echomail=NULL): ?Packet
public function getEchomail(): ?Packet
{
$pkt = NULL;
if ($echomail)
return $this->getPacket($echomail);
if (($num=$this->echomailWaiting())->count()) {
$s = Setup::findOrFail(config('app.id'));
$num = self::UncollectedEchomail()
->select('echomails.id')
->where('addresses.id',$this->id)
->groupBy(['echomails.id'])
->get();
if ($num->count()) {
// Limit to max messages
Log::info(sprintf('%s:= Got [%d] echomails for [%s] for sending',self::LOGKEY,$num->count(),$this->ftn));
// Limit to max messages
if ($num->count() > $s->msgs_pkt)
Log::notice(sprintf('%s:= Only sending [%d] echomails for [%s]',self::LOGKEY,$s->msgs_pkt,$this->ftn));
$x = $this->echomailWaiting($s->msgs_pkt);
$pkt = $this->getPacket($x);
if ($pkt && $pkt->count() && $update)
DB::table('echomail_seenby')
->whereIn('echomail_id',$x->pluck('id'))
->where('address_id',$this->id)
->whereNull('sent_at')
->whereNotNull('export_at')
->update(['sent_pkt'=>$pkt->name]);
return $this->system->packet($this)->mail($num->take($s->msgs_pkt));
}
return $pkt;
return NULL;
}
/**
@ -1036,54 +1015,47 @@ class Address extends Model
/**
* Get netmail for this node (including it's children)
*
* @param bool $update
* @return Packet|null
* @throws \Exception
*/
public function getNetmail(bool $update=FALSE): ?Packet
public function getNetmail(): ?Packet
{
$pkt = NULL;
if (($num=$this->netmailAlertWaiting())->count()) {
Log::debug(sprintf('%s:= Packaging [%d] netmail alerts to [%s]',self::LOGKEY,$num->count(),$this->ftn));
// Find any message that defines a packet password
$pass = $num
->map(function($item) {
$passpos = strpos($item->subject,':');
return (($passpos > 0) && ($passpos < 8)) ? substr($item->subject,0,$passpos) : NULL;
})
->filter()
->pop();
Log::debug(sprintf('%s:= Overwriting system packet password with [%s] for [%s]',self::LOGKEY,$pass,$this->ftn));
return $this->system->packet($this,$pass)->mail(
$num->filter(fn($item)=>preg_match("/^{$pass}:/",$item->subject))
->transform(function($item) use ($pass) {
$item->subject = preg_replace("/^{$pass}:/",'',$item->subject);
return $item;
})
);
}
if (($num=$this->netmailWaiting())->count()) {
$s = Setup::findOrFail(config('app.id'));
if (($x=$this->netmailAlertWaiting())->count()) {
Log::debug(sprintf('%s:= Packaging [%d] netmail alerts to [%s]',self::LOGKEY,$x->count(),$this->ftn));
$passpos = strpos($x->last()->subject,':');
Log::debug(sprintf('%s:= Got [%d] netmails for [%s] for sending',self::LOGKEY,$num->count(),$this->ftn));
if ($passpos > 8)
Log::alert(sprintf('%s:! Password would be greater than 8 chars? [%d]',self::LOGKEY,$passpos));
// Limit to max messages
if ($num->count() > $s->msgs_pkt)
Log::alert(sprintf('%s:= Only sending [%d] netmails for [%s]',self::LOGKEY,$num->count(),$this->ftn));
// @todo Do the strip pass where, if we dont want the password in the netmail
$pkt = $this->getPacket($x,substr($x->last()->subject,0,$passpos));
if ($pkt && $pkt->count() && $update)
DB::table('netmails')
->whereIn('id',$x->pluck('id'))
->update(['sent_pkt'=>$pkt->name]);
return $pkt;
return $this->system->packet($this)->mail($num->take($s->msgs_pkt));
}
if (($x=$this->netmailWaiting())
->count())
{
Log::debug(sprintf('%s:= Got [%d] netmails for [%s] for sending',self::LOGKEY,$x->count(),$this->ftn));
if ($x->count() > $s->msgs_pkt) {
$x = $x->take($s->msgs_pkt);
Log::alert(sprintf('%s:= Only sending [%d] netmails for [%s]',self::LOGKEY,$x->count(),$this->ftn));
}
$pkt = $this->getPacket($x);
if ($pkt && $pkt->count() && $update)
DB::table('netmails')
->whereIn('id',$x->pluck('id'))
->update(['sent_pkt'=>$pkt->name]);
}
return $pkt;
return NULL;
}
/**
@ -1154,6 +1126,7 @@ class Address extends Model
*
* @return Collection
* @throws \Exception
* @note The packet password to use is on the subject line for these alerts
*/
public function netmailAlertWaiting(): Collection
{

View File

@ -92,7 +92,6 @@ final class Netmail extends Model implements Packet
$nodes = collect();
// Parse PATH
// @todo dont save us in the path, we'll add it dynamically when we send out.
// <FTN Address> @YYYYMMDD.HHMMSS[.Precise][.Time Zone] <Program Name> <Version> [Serial Number]
if ($model->set->has('set_path')) {
foreach ($model->set->get('set_path') as $line) {
@ -123,8 +122,8 @@ final class Netmail extends Model implements Packet
}
// If there are no details (Mystic), we'll create a blank
} else {
$nodes->push(['node'=>$model->set->get('set_sender'),'datetime'=>Carbon::now(),'program'=>sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID)]);
} elseif ($model->set->has('set_sender')) {
$nodes->push(['node'=>$model->set->get('set_sender'),'datetime'=>Carbon::now(),'program'=>'Unknown']);
}
// Save the Path

View File

@ -253,14 +253,18 @@ class System extends Model
* Return the packet that this system uses
*
* @param Address $ao
* @param string|null $password
* @return Packet
*/
public function packet(Address $ao): Packet
public function packet(Address $ao,string $password=NULL): Packet
{
// @todo Check that the address is one of the system's addresses
return (new (collect(Packet::PACKET_TYPES)
->get($this->pkt_type ?: config('fido.packet_default'))))->for($ao);
return
(new (collect(Packet::PACKET_TYPES)
->get($this->pkt_type ?: config('fido.packet_default'))))
->for($ao)
->password($password);
}
public function poll(): ?Job

View File

@ -41,6 +41,6 @@ class EchomailChannel
$o = $notification->toEchomail($notifiable);
Log::info(sprintf('%s:= Posted echomail (%d) [%s] to [%s]',self::LOGKEY,$o->id,$o->msgid,$echoarea));
Log::info(sprintf('%s:= Posted echomail (%d) [%s] to [%s]',self::LOGKEY,$o->id,$o->msgid,$echoarea->name));
}
}

View File

@ -8,7 +8,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use App\Classes\FTN\Message;
use App\Models\{Echoarea, Echomail, Setup, System};
use App\Models\{Echoarea,Echomail,Setup};
abstract class Echomails extends Notification //implements ShouldQueue
{
@ -46,26 +46,24 @@ abstract class Echomails extends Notification //implements ShouldQueue
*/
abstract public function toEchomail(object $notifiable): Echomail;
protected function setupEchomail(Message $mo,object $notifiable): Echomail
protected function setupEchomail(Echomail $mo,object $notifiable): Echomail
{
$echoarea = $notifiable->routeNotificationFor(static::via);
$eo = Echoarea::where('name',$echoarea)->singleOrFail();
$o = new Echomail;
$o->init();
$o->from = Setup::PRODUCT_NAME;
$o->replyid = $mo->msgid;
$o->echoarea_id = $eo->id;
$o->echoarea_id = $echoarea->id;
$o->datetime = Carbon::now();
$o->tzoffset = $o->datetime->utcOffset();
$o->fftn_id = ($x=our_address($mo->fboss_o))->id;
$o->fftn_id = ($x=our_address($mo->fftn))->id;
$o->flags = (Message::FLAG_LOCAL);
$o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
$o->origin = sprintf('%s (%s)',Setup::PRODUCT_NAME,$x->ftn4d);
$o->kludges = collect(['chrs'=>$mo->kludge->get('chrs') ?: 'CP437 2']);
$o->kludges->put('CHRS:',$mo->kludges->get('chrs') ?: 'CP437 2');
return $o;
}

View File

@ -6,8 +6,8 @@ use Carbon\Carbon;
use Carbon\CarbonInterface;
use Illuminate\Support\Facades\Log;
use App\Classes\{Fonts\Thick,Fonts\Thin,FTN\Message,Page};
use App\Models\{Echomail,System};
use App\Classes\{Fonts\Thick,Fonts\Thin,Page};
use App\Models\Echomail;
use App\Notifications\Echomails;
use App\Traits\MessagePath;
@ -17,14 +17,14 @@ class Test extends Echomails
private const LOGKEY = 'NNP';
private Message $mo;
private Echomail $mo;
/**
* Reply to a netmail ping request.
*
* @param Message $mo
* @param Echomail $mo
*/
public function __construct(Message $mo)
public function __construct(Echomail $mo)
{
parent::__construct();
@ -43,9 +43,9 @@ class Test extends Echomails
$o = $this->setupEchomail($this->mo,$notifiable);
$echoarea = $notifiable->routeNotificationFor(static::via);
Log::info(sprintf('%s:+ Creating test echomail to [%s]',self::LOGKEY,$echoarea));
Log::info(sprintf('%s:+ Creating TEST echomail in [%s]',self::LOGKEY,$echoarea->name));
$o->to = $this->mo->user_from;
$o->to = $this->mo->from;
$o->subject = 'Test Reply';
// Message

View File

@ -52,14 +52,13 @@ abstract class Netmails extends Notification //implements ShouldQueue
$ao = $notifiable->routeNotificationFor(static::via);
$o = new Netmail;
$o->set_sender = our_address($ao);
$o->to = $ao->system->sysop;
$o->from = Setup::PRODUCT_NAME;
$o->datetime = Carbon::now();
$o->tzoffset = $o->datetime->utcOffset();
$o->fftn_id = $o->set->get('set_sender')->id;
$o->fftn_id = our_address($ao)->id;
$o->tftn_id = $ao->id;
$o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE);
$o->cost = 0;

View File

@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System,User};
use App\Models\{Netmail,User};
use App\Traits\PageTemplate;
class AddressLink extends Netmails

View File

@ -4,9 +4,8 @@ namespace App\Notifications\Netmails;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\{MessagePath,PageTemplate};
class Areafix extends Netmails
@ -15,14 +14,14 @@ class Areafix extends Netmails
private const LOGKEY = 'NAF';
private Message $mo;
private Netmail $mo;
/**
* Reply to an areafix request.
*
* @param Message $mo
* @param Netmail $mo
*/
public function __construct(Message $mo)
public function __construct(Netmail $mo)
{
parent::__construct();
@ -43,7 +42,7 @@ class Areafix extends Netmails
Log::info(sprintf('%s:+ Responding to areafix with netmail to [%s]',self::LOGKEY,$ao->ftn));
$o->to = $this->mo->user_from;
$o->to = $this->mo->from;
$o->replyid = $this->mo->msgid;
$o->subject = 'Areafix Reply';

View File

@ -4,9 +4,8 @@ namespace App\Notifications\Netmails\Areafix;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\{MessagePath,PageTemplate};
class NotConfiguredHere extends Netmails
@ -15,14 +14,14 @@ class NotConfiguredHere extends Netmails
private const LOGKEY = 'NCH';
private Message $mo;
private Netmail $mo;
/**
* Reply to a areafix, but the system isnt configured here.
*
* @param Message $mo
* @param Netmail $mo
*/
public function __construct(Message $mo)
public function __construct(Netmail $mo)
{
parent::__construct();
@ -43,7 +42,7 @@ class NotConfiguredHere extends Netmails
Log::info(sprintf('%s:+ Responding to areafix for a node [%s] not configured here',self::LOGKEY,$ao->ftn));
$o->to = $this->mo->user_from;
$o->to = $this->mo->from;
$o->replyid = $this->mo->msgid;
$o->subject = 'Areafix - Not Configured Here';

View File

@ -5,9 +5,8 @@ namespace App\Notifications\Netmails;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\{Echomail,Netmail};
use App\Traits\{MessagePath,PageTemplate};
class EchoareaNoWrite extends Netmails
@ -16,14 +15,14 @@ class EchoareaNoWrite extends Netmails
private const LOGKEY = 'NNW';
private Message $mo;
private Echomail $mo;
/**
* Send a sysop a message if they attempt to write to an area that they dont have permission.
*
* @param Message $mo
* @param Echomail $mo
*/
public function __construct(Message $mo)
public function __construct(Echomail $mo)
{
parent::__construct();
@ -42,9 +41,9 @@ class EchoareaNoWrite extends Netmails
$o = $this->setupNetmail($notifiable);
$ao = $notifiable->routeNotificationFor(static::via);
Log::info(sprintf('%s:+ Creating ECHOMAIL NO WRITE netmail to [%s]',self::LOGKEY,$ao->ftn));
Log::info(sprintf('%s:+ Creating ECHOAREA NO WRITE netmail to [%s]',self::LOGKEY,$ao->ftn));
$o->subject = 'Echomail rejected - '.$this->mo->msgid;
$o->subject = sprintf('Echomail #%s rejected to %s',$this->mo->msgid,$this->mo->echoarea->name);
// Message
$msg = $this->page(FALSE,'nowrite');
@ -52,13 +51,13 @@ class EchoareaNoWrite extends Netmails
$msg->addText(
sprintf("Your echomail with ID [%s] to [%s] here was received here on [%s] and it looks like you sent it on [%s].\r\r",
$this->mo->msgid,
$this->mo->user_to,
$this->mo->to,
Carbon::now()->utc()->toDateTimeString(),
$this->mo->date->utc()->toDateTimeString(),
)
);
$msg->addText(sprintf("It appears that you do not have permission to post in this echoarea using the address [%s], so the message from your system was rejected.\r\r",$ao->ftn));
$msg->addText(sprintf("It appears that you do not have permission to post in [%s] using the address [%s], so the message from your system was rejected.\r\r",$this->mo->echoarea->name,$ao->ftn));
$msg->addText("Please contact the ZC if you think this is a mistake.\r\r");
$msg->addText($this->message_path($this->mo));

View File

@ -42,7 +42,7 @@ class EchoareaNotExist extends Netmails
$o = $this->setupNetmail($notifiable);
$ao = $notifiable->routeNotificationFor(static::via);
Log::info(sprintf('%s:+ Creating ECHOMAIL NOT EXIST netmail to [%s]',self::LOGKEY,$ao->ftn));
Log::info(sprintf('%s:+ Creating ECHOAREA NOT EXIST netmail to [%s]',self::LOGKEY,$ao->ftn));
$o->subject = 'Echoarea doesnt exist - '.$this->mo->set->get('set_echoarea');
@ -58,7 +58,7 @@ class EchoareaNotExist extends Netmails
)
);
$msg->addText("It appears that the echoarea that this message is for doesnt exist, so the message from your system was rejected.\r\r");
$msg->addText(sprintf("It appears that the echoarea [%s] that this message is for doesnt exist, so the message from your system was rejected.\r\r",$this->mo->set->get('set_echoarea')));
$msg->addText("Please contact the ZC if you think this is a mistake.\r\r");
$msg->addText($this->message_path($this->mo));

View File

@ -5,9 +5,8 @@ namespace App\Notifications\Netmails;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\{Echomail,Netmail};
use App\Traits\{MessagePath,PageTemplate};
class EchoareaNotSubscribed extends Netmails
@ -16,14 +15,14 @@ class EchoareaNotSubscribed extends Netmails
private const LOGKEY = 'NNW';
private Message $mo;
private Echomail $mo;
/**
* Send a sysop a message if they write to an area that they hadnt previously subscribed to.
*
* @param Message $mo
* @param Echomail $mo
*/
public function __construct(Message $mo)
public function __construct(Echomail $mo)
{
parent::__construct();
@ -42,17 +41,17 @@ class EchoareaNotSubscribed extends Netmails
$o = $this->setupNetmail($notifiable);
$ao = $notifiable->routeNotificationFor(static::via);
Log::info(sprintf('%s:+ Creating ECHOMAIL NOT SUBSCRIBED netmail to [%s]',self::LOGKEY,$ao->ftn));
Log::info(sprintf('%s:+ Creating ECHOAREA NOT SUBSCRIBED netmail to [%s]',self::LOGKEY,$ao->ftn));
$o->subject = 'Echoarea not subscribed - '.$this->mo->echoarea;
$o->subject = 'Echoarea not subscribed - '.$this->mo->echoarea->name;
// Message
$msg = $this->page(FALSE,'nothere');
$msg = $this->page(FALSE,'nosub');
$msg->addText(
sprintf("Your echomail with ID [%s] to [%s] here was received here on [%s] and it looks like you sent it on [%s].\r\r",
$this->mo->msgid,
$this->mo->user_to,
$this->mo->to,
Carbon::now()->utc()->toDateTimeString(),
$this->mo->date->utc()->toDateTimeString(),
)

View File

@ -7,7 +7,7 @@ use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\{MessagePath,PageTemplate};
class EchomailBadAddress extends Netmails
@ -52,7 +52,7 @@ class EchomailBadAddress extends Netmails
$msg->addText(
sprintf("Your echomail with ID [%s] to [%s] here was received here on [%s] and it looks like you sent it on [%s].\r\r",
$this->mo->msgid,
$this->mo->user_to,
$this->mo->to,
Carbon::now()->utc()->toDateTimeString(),
$this->mo->date->utc()->toDateTimeString(),
)

View File

@ -4,9 +4,8 @@ namespace App\Notifications\Netmails;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Address,Netmail,System};
use App\Models\{Address,Netmail};
use App\Traits\{MessagePath,PageTemplate};
class NetmailForward extends Netmails
@ -16,15 +15,15 @@ class NetmailForward extends Netmails
private const LOGKEY = 'NNP';
private Address $ao;
private Message $mo;
private Netmail $mo;
/**
* Reply to a netmail ping request.
*
* @param Message $mo
* @param Netmail $mo
* @param Address $ao
*/
public function __construct(Message $mo,Address $ao)
public function __construct(Netmail $mo,Address $ao)
{
parent::__construct();
@ -44,9 +43,9 @@ class NetmailForward extends Netmails
$o = $this->setupNetmail($notifiable);
$ao = $notifiable->routeNotificationFor(static::via);
Log::info(sprintf('%s:+ Advising [%s@%s] that netmail to [%s] will be forwarded to [%s].',self::LOGKEY,$this->mo->user_from,$ao->ftn,$this->mo->user_to,$this->ao->ftn));
Log::info(sprintf('%s:+ Advising [%s@%s] that netmail to [%s] will be forwarded to [%s].',self::LOGKEY,$this->mo->from,$ao->ftn,$this->mo->to,$this->ao->ftn));
$o->to = $this->mo->user_from;
$o->to = $this->mo->from;
$o->replyid = $this->mo->msgid;
$o->subject = sprintf('Your netmail is being forwarded to %s',$this->ao->ftn3d);
@ -56,10 +55,10 @@ class NetmailForward extends Netmails
$msg->addText("Howdy, Clrghouz is not a BBS, so users cannot login to collect netmail.\r\r\r");
$msg->addText(sprintf("Never fear, your msg [%s] to [%s] has been forwarded, to [%s].\r\r",
$this->mo->msgid,
$this->mo->user_to,
$this->mo->to,
$this->ao->ftn3d,
));
$msg->addText(sprintf("To avoid receiving this netmail, send messages to [%s] to [%s].\r\r",$this->mo->user_to,$this->ao->ftn3d));
$msg->addText(sprintf("To avoid receiving this netmail, send messages to [%s] to [%s].\r\r",$this->mo->to,$this->ao->ftn3d));
$o->msg = $msg->render();
$o->tagline = 'Thank you so much for your mail. I love it already.';

View File

@ -5,25 +5,24 @@ namespace App\Notifications\Netmails;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\{MessagePath,PageTemplate};
class Reject extends Netmails
class NetmailHubNoUser extends Netmails
{
use MessagePath,PageTemplate;
private const LOGKEY = 'NNP';
private Message $mo;
private Netmail $mo;
/**
* Reply to a netmail ping request.
*
* @param Message $mo
* @param Netmail $mo
*/
public function __construct(Message $mo)
public function __construct(Netmail $mo)
{
parent::__construct();
@ -42,9 +41,9 @@ class Reject extends Netmails
$o = $this->setupNetmail($notifiable);
$ao = $notifiable->routeNotificationFor(static::via);
Log::info(sprintf('%s:+ Creating reject netmail to [%s]',self::LOGKEY,$ao->ftn));
Log::info(sprintf('%s:+ Creating HUB NO USER netmail to [%s]',self::LOGKEY,$ao->ftn));
$o->to = $this->mo->user_from;
$o->to = $this->mo->from;
$o->replyid = $this->mo->msgid;
$o->subject = 'Message Undeliverable - '.$this->mo->msgid;
@ -54,7 +53,7 @@ class Reject extends Netmails
$msg->addText(
sprintf("Your netmail with ID [%s] to [%s] here was received here on [%s] and it looks like you sent it on [%s].\r\r",
$this->mo->msgid,
$this->mo->user_to,
$this->mo->to,
Carbon::now()->utc()->toDateTimeString(),
$this->mo->date->utc()->toDateTimeString(),
)

View File

@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Log;
use App\Notifications\Netmails;
use App\Classes\FTN\Message;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\PageTemplate;
class PacketPasswordInvalid extends Netmails

View File

@ -8,7 +8,7 @@ use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\{MessagePath,PageTemplate};
class Ping extends Netmails
@ -17,14 +17,14 @@ class Ping extends Netmails
private const LOGKEY = 'NNP';
private Message $mo;
private Netmail $mo;
/**
* Reply to a netmail ping request.
*
* @param Message $mo
*/
public function __construct(Message $mo)
public function __construct(Netmail $mo)
{
parent::__construct();
@ -45,7 +45,7 @@ class Ping extends Netmails
Log::info(sprintf('%s:+ Creating PING netmail to [%s]',self::LOGKEY,$ao->ftn));
$o->to = $this->mo->user_from;
$o->to = $this->mo->from;
$o->replyid = $this->mo->msgid;
$o->subject = 'Ping Reply';

View File

@ -5,9 +5,8 @@ namespace App\Notifications\Netmails;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\Message;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\{MessagePath,PageTemplate};
class PollingFailed extends Netmails

View File

@ -5,7 +5,7 @@ namespace App\Notifications\Netmails;
use Illuminate\Support\Facades\Log;
use App\Notifications\Netmails;
use App\Models\{Netmail,System};
use App\Models\Netmail;
use App\Traits\PageTemplate;
class Test extends Netmails

View File

@ -89,7 +89,7 @@ trait EncodeUTF8
return $this->attributes[$key];
}
return parent::getAttribute($key);
return Arr::get($this->_encoded,$key) ? $this->attributes[$key] : parent::getAttribute($key);
}
public function setAttribute($key,$value)

View File

@ -70,26 +70,38 @@ trait MessageAttributes
public function getOriginAttribute(string $val=NULL): ?string
{
if ($this->exists && (! $val))
return $val;
// If $val is not set, then it may be an unsaved object
return ((! $this->exists) && $this->set->has('set_origin'))
? sprintf(' * Origin: %s',$this->set->get('set_origin'))
: $val;
return sprintf(' * Origin: %s',
((! $this->exists) && $this->set->has('set_origin'))
? $this->set->get('set_origin')
: $val);
}
public function getTaglineAttribute(string $val=NULL): ?string
{
if ($this->exists && (! $val))
return $val;
// If $val is not set, then it may be an unsaved object
return ((! $this->exists) && $this->set->has('set_tagline'))
? sprintf('... %s',$this->set->get('set_tagline'))
: $val;
return sprintf('... %s',
((! $this->exists) && $this->set->has('set_tagline'))
? $this->set->get('set_tagline')
: $val);
}
public function getTearlineAttribute(string $val=NULL): ?string
{
if ($this->exists && (! $val))
return $val;
// If $val is not set, then it may be an unsaved object
return ((! $this->exists) && $this->set->has('set_tearline'))
? sprintf('--- %s',$this->set->get('set_tearline'))
: $val;
return sprintf('--- %s',
((! $this->exists) && $this->set->has('set_tearline'))
? $this->set->get('set_tearline')
: $val);
}
/* METHODS */
@ -141,10 +153,11 @@ trait MessageAttributes
'receipt' => $this->isFlagSet(Message::FLAG_ISRETRECEIPT),
'audit' => $this->isFlagSet(Message::FLAG_AUDITREQ),
'fileupdate' => $this->isFlagSet(Message::FLAG_FILEUPDATEREQ),
'pktpasswd' => $this->isFlagSet(Message::FLAG_PKTPASSWD),
])->filter();
}
private function isFlagSet($flag): bool
public function isFlagSet($flag): bool
{
return ($this->flags & $flag);
}

View File

@ -27,20 +27,18 @@ trait MessagePath
$reply .= "+--[ PATH ]-------------------------------------------+\r";
if ($mo->path->count())
if ($mo instanceof Netmail) {
if ($mo->via->count())
foreach ($mo->via as $ao)
$reply .= sprintf("VIA: %s\r",$mo->via($ao));
else
$reply .= "No path information? This would be normal if this message came directly to the hub\r";
foreach ($mo->path as $o)
$reply .= sprintf("VIA: %s\r",$mo->via($o));
} else {
if ($mo->path->count())
foreach ($mo->path as $via)
$reply .= sprintf("VIA: %s\r",$via);
foreach ($mo->path as $o)
$reply .= sprintf("VIA: %s\r",$o->ftn);
}
else
$reply .= "No path information? This would be normal if this message came directly to the hub\r";
}
$reply .= "+--[ END MESSAGE ]------------------------------------+\r\r";

View File

@ -97,6 +97,17 @@ use App\Models\{Echomail,Netmail};
</div>
</div>
@if($msg instanceof Netmail)
<div class="col-8">
SENT:
@if($msg->sent_pkt && $msg->sent_at)
<strong class="highlight">{{ $msg->sent_at }}</strong> (<strong class="highlight">{{ $msg->sent_pkt }}.pkt</strong>)
@else
<strong class="highlight">NOT SENT</strong>
@endif
</div>
@endif
@section('page-scripts')
<script type="text/javascript" src="{{ asset('ansilove/ansilove.js') }}"></script>
@ -114,5 +125,4 @@ use App\Models\{Echomail,Netmail};
);
});
</script>
@append