2023-09-13 10:58:22 +00:00
< ? php
namespace App\Jobs ;
use Carbon\Carbon ;
use Illuminate\Bus\Queueable ;
use Illuminate\Contracts\Queue\ShouldQueue ;
use Illuminate\Foundation\Bus\Dispatchable ;
use Illuminate\Queue\InteractsWithQueue ;
use Illuminate\Queue\SerializesModels ;
use Illuminate\Support\Arr ;
use Illuminate\Support\Facades\Log ;
use Illuminate\Support\Facades\Notification ;
2023-09-22 04:45:44 +00:00
use Illuminate\Support\Facades\Storage ;
use League\Flysystem\UnableToMoveFile ;
2023-09-13 10:58:22 +00:00
use App\Classes\File ;
2024-05-17 12:10:54 +00:00
use App\Classes\FTN\Packet ;
use App\Exceptions\InvalidPacketException ;
2024-11-02 05:35:22 +00:00
use App\Models\ { Echomail , Netmail , System };
2024-11-20 06:31:11 +00:00
use App\Notifications\Netmails\ { PacketPasswordInvalid , UnexpectedPacketFromYou };
2023-09-13 10:58:22 +00:00
class PacketProcess implements ShouldQueue
{
private const LOGKEY = 'JPP' ;
use Dispatchable , InteractsWithQueue , Queueable , SerializesModels ;
2024-05-17 12:10:54 +00:00
private string $filename ;
2024-11-02 05:35:22 +00:00
private System $so ;
2023-09-13 10:58:22 +00:00
private Carbon $rcvd_time ;
2024-05-17 12:10:54 +00:00
private bool $interactive ;
private bool $nobot ;
2023-09-13 10:58:22 +00:00
2024-11-02 05:35:22 +00:00
public function __construct ( string $filename , System $so , bool $interactive = TRUE , Carbon $rcvd_time = NULL , bool $nobot = FALSE )
2023-09-13 10:58:22 +00:00
{
2024-05-17 12:10:54 +00:00
$this -> filename = $filename ;
2024-11-02 13:16:48 +00:00
$this -> so = $so -> withoutRelations ();
2024-05-17 12:10:54 +00:00
$this -> interactive = $interactive ;
$this -> rcvd_time = $rcvd_time ? : Carbon :: now ();
$this -> nobot = $nobot ;
2023-09-13 10:58:22 +00:00
}
public function __get ( $key ) : mixed
{
switch ( $key ) {
2024-05-21 11:10:58 +00:00
case 'jobname' :
2024-05-17 12:10:54 +00:00
return $this -> filename ;
2023-09-13 10:58:22 +00:00
default :
return NULL ;
}
}
/**
* When calling MessageProcess - we assume that the packet is from a valid source , and
* the destination ( netmail / echomail ) is also valid
*/
public function handle ()
{
2024-05-17 12:10:54 +00:00
Log :: info ( sprintf ( '%s:- Processing mail [%s]' , self :: LOGKEY , $this -> filename ));
2023-09-13 10:58:22 +00:00
2023-09-22 04:45:44 +00:00
$fs = Storage :: disk ( config ( 'fido.local_disk' ));
2023-10-04 11:22:01 +00:00
// @todo Catch files that we cannot process, eg: ARJ bundles.
2023-09-13 10:58:22 +00:00
try {
2024-05-17 12:10:54 +00:00
$f = new File ( $fs -> path ( $this -> filename ));
2023-09-13 10:58:22 +00:00
$processed = FALSE ;
2024-10-22 06:08:48 +00:00
$bad_archive = FALSE ;
2023-09-13 10:58:22 +00:00
foreach ( $f as $packet ) {
2024-10-22 06:08:48 +00:00
try {
2024-11-02 05:35:22 +00:00
$pkt = Packet :: process ( $packet , Arr :: get ( stream_get_meta_data ( $packet ), 'uri' ), $f -> itemSize (), $this -> so );
2024-05-17 12:10:54 +00:00
2024-10-22 06:08:48 +00:00
// Check that the packet is from a system that is defined in the DB
if ( ! $pkt -> fftn ) {
Log :: error ( sprintf ( '%s:! Packet [%s] is not from a system we know about? [%s]' , self :: LOGKEY , $this -> filename , $pkt -> fftn_t ));
2024-05-17 12:10:54 +00:00
2024-10-22 06:08:48 +00:00
break ;
}
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
// If we dont have the tftn in the DB, then packet cannot be to us
if ( ! $pkt -> tftn ) {
2024-11-20 06:31:11 +00:00
Log :: error ( sprintf ( '%s:! Packet [%s] is for a system [%s] we dont know about?' , self :: LOGKEY , $this -> filename , $pkt -> tftn_t ));
2024-07-11 13:33:17 +00:00
2024-10-22 06:08:48 +00:00
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketToUs($this->filename));
break ;
}
2024-05-17 12:10:54 +00:00
2024-10-22 06:08:48 +00:00
// Check the packet is to our address, if not we'll reject it.
if ( ! our_address ( $pkt -> tftn -> zone -> domain ) -> contains ( $pkt -> tftn )) {
Log :: error ( sprintf ( '%s:! Packet [%s] is not to our address? [%s]' , self :: LOGKEY , $this -> filename , $pkt -> tftn -> ftn ));
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketToUs($this->filename));
break ;
}
2023-09-13 10:58:22 +00:00
2024-11-20 06:31:11 +00:00
$netmail_only = FALSE ;
if ( ! our_nodes ( $pkt -> fftn -> zone -> domain ) -> contains ( $pkt -> fftn )) {
Log :: alert ( sprintf ( '%s:! Packet [%s] is from a system that is not configured with us, only NETMAIL processed [%s]' , self :: LOGKEY , $this -> filename , $pkt -> fftn_t ));
$netmail_only = TRUE ;
2024-10-22 06:08:48 +00:00
// Check the packet password
2024-11-20 06:31:11 +00:00
} elseif ( $pkt -> fftn -> pass_packet !== strtoupper ( $pkt -> password )) {
2024-10-22 06:08:48 +00:00
Log :: error ( sprintf ( '%s:! Packet from [%s] with password [%s] is invalid.' , self :: LOGKEY , $pkt -> fftn -> ftn , $pkt -> password ));
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
Notification :: route ( 'netmail' , $pkt -> fftn ) -> notify ( new PacketPasswordInvalid ( $pkt -> password , $f -> pktName ()));
break ;
}
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
Log :: info ( sprintf ( '%s:- Packet has [%d] messages' , self :: LOGKEY , $pkt -> count ()));
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
// Queue messages if there are too many in the packet.
if ( $queue = ( $pkt -> count () > config ( 'fido.queue_msgs' )))
Log :: info ( sprintf ( '%s:- Messages will be sent to the queue for processing' , self :: LOGKEY ));
2024-05-17 12:10:54 +00:00
2024-10-22 06:08:48 +00:00
$count = 0 ;
foreach ( $pkt as $msg ) {
if ( $msg instanceof Netmail )
Log :: info ( sprintf ( '%s:- Netmail from [%s] to [%s]' , self :: LOGKEY , $msg -> fftn -> ftn , $msg -> tftn -> ftn ));
2024-11-20 06:31:11 +00:00
elseif ( $msg instanceof Echomail ) {
2024-10-22 06:08:48 +00:00
Log :: info ( sprintf ( '%s:- Echomail from [%s]' , self :: LOGKEY , $msg -> fftn -> ftn ));
2024-05-17 12:10:54 +00:00
2024-11-20 06:31:11 +00:00
if ( $netmail_only ) {
Log :: alert ( sprintf ( '%s:! Echomail IGNORED as packet is from an unknown system [%s]' , self :: LOGKEY , $pkt -> fftn -> ftn ));
continue ;
}
}
2024-10-22 06:08:48 +00:00
if ( $msg -> errors -> count ()) {
Log :: error ( sprintf ( '%s:! Message [%s] has [%d] errors, unable to process' , self :: LOGKEY , $msg -> msgid , $msg -> errors -> count ()));
2024-05-17 12:10:54 +00:00
2024-10-22 06:08:48 +00:00
continue ;
}
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
$msg -> set_sender = $pkt -> fftn -> withoutRelations ();
// Record receiving packet and sender
$msg -> set_pkt = $f -> pktName ();
$msg -> set_recvtime = $this -> rcvd_time ;
2024-05-19 13:28:45 +00:00
2024-05-17 12:10:54 +00:00
if ( $queue || ( ! $this -> interactive ))
2024-10-22 06:08:48 +00:00
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 ))
MessageProcess :: dispatch ( $msg -> withoutRelations (), $this -> nobot );
else
MessageProcess :: dispatchSync ( $msg -> withoutRelations (), $this -> nobot );
2024-05-17 12:10:54 +00:00
2024-10-22 06:08:48 +00:00
$count ++ ;
2023-09-13 10:58:22 +00:00
2024-10-22 06:08:48 +00:00
} catch ( \Exception $e ) {
Log :: error ( sprintf ( '%s:! Got error [%s] dispatching message [%s] (%d:%s-%s).' , self :: LOGKEY , get_class ( $e ), $msg -> msgid , $e -> getLine (), $e -> getFile (), $e -> getMessage ()));
}
2023-09-13 10:58:22 +00:00
}
2024-10-22 06:08:48 +00:00
if ( $count === $pkt -> count ())
$processed = TRUE ;
2024-11-20 06:31:11 +00:00
elseif ( $netmail_only )
Notification :: route ( 'netmail' , $pkt -> fftn ) -> notify ( new UnexpectedPacketFromYou ( $f -> pktName ()));
2024-10-22 06:08:48 +00:00
} catch ( \Exception $e ) {
Log :: error ( sprintf ( '%s:! Got an exception [%s] processing packet' , self :: LOGKEY , $e -> getMessage ()));
$bad_archive = TRUE ;
}
2023-09-13 10:58:22 +00:00
}
2024-10-22 06:08:48 +00:00
if (( ! $processed ) || $bad_archive ) {
2024-05-17 12:10:54 +00:00
Log :: alert ( sprintf ( '%s:- Not deleting packet [%s], it doesnt seem to be processed?' , self :: LOGKEY , $this -> filename ));
2023-09-13 10:58:22 +00:00
2023-09-22 04:45:44 +00:00
} else {
2023-09-13 10:58:22 +00:00
// If we want to keep the packet, we could do that logic here
2023-09-22 04:45:44 +00:00
if ( config ( 'fido.packet_keep' )) {
2024-05-12 10:50:19 +00:00
$dir = sprintf ( '%s/%s/%s/%s' , config ( 'fido.dir' ),( $x = Carbon :: now ()) -> format ( 'Y' ), $x -> format ( 'm' ), $x -> format ( 'd' ));
2024-05-17 12:10:54 +00:00
Log :: debug ( sprintf ( '%s:- Moving processed packet [%s] to [%s]' , self :: LOGKEY , $this -> filename , $dir ));
2023-09-22 04:45:44 +00:00
try {
if ( $fs -> makeDirectory ( $dir )) {
2024-05-17 12:10:54 +00:00
$fs -> move ( $this -> filename , $x = sprintf ( '%s/%s' , $dir , $f -> itemName ()));
Log :: info ( sprintf ( '%s:- Moved processed packet [%s] to [%s]' , self :: LOGKEY , $this -> filename , $x ));
2023-09-22 04:45:44 +00:00
} else
Log :: error ( sprintf ( '%s:! Unable to create dir [%s]' , self :: LOGKEY , $dir ));
} catch ( UnableToMoveFile $e ) {
2024-05-17 12:10:54 +00:00
Log :: error ( sprintf ( '%s:! Unable to move packet [%s] to [%s] (%s)' , self :: LOGKEY , $this -> filename , $dir , $e -> getMessage ()));
2023-09-22 04:45:44 +00:00
} catch ( \Exception $e ) {
2024-05-17 12:10:54 +00:00
Log :: error ( sprintf ( '%s:! Failed moving packet [%s] to [%s] (%s)' , self :: LOGKEY , $this -> filename , $dir , $e -> getMessage ()));
2023-09-22 04:45:44 +00:00
}
} else {
2024-05-17 12:10:54 +00:00
Log :: debug ( sprintf ( '%s:- Deleting processed packet [%s]' , self :: LOGKEY , $this -> filename ));
2023-09-22 04:45:44 +00:00
2024-05-17 12:10:54 +00:00
$fs -> delete ( $this -> filename );
2023-09-22 04:45:44 +00:00
}
2023-09-13 10:58:22 +00:00
}
} catch ( InvalidPacketException $e ) {
2024-05-17 12:10:54 +00:00
Log :: error ( sprintf ( '%s:- Not deleting packet [%s], as it generated an InvalidPacketException' , self :: LOGKEY , $this -> filename ),[ 'e' => $e -> getMessage ()]);
2023-09-13 10:58:22 +00:00
} catch ( \Exception $e ) {
2024-05-17 12:10:54 +00:00
Log :: error ( sprintf ( '%s:- Not deleting packet [%s], as it generated an uncaught exception' , self :: LOGKEY , $this -> filename ),[ 'e' => $e -> getMessage (), 'l' => $e -> getLine (), 'f' => $e -> getFile ()]);
2023-09-13 10:58:22 +00:00
}
}
}