2021-07-15 14:54:23 +00:00
< ? php
namespace App\Jobs ;
2021-10-18 12:10:15 +00:00
use Carbon\Carbon ;
2021-07-15 14:54:23 +00:00
use Illuminate\Bus\Queueable ;
use Illuminate\Contracts\Queue\ShouldQueue ;
use Illuminate\Foundation\Bus\Dispatchable ;
use Illuminate\Queue\InteractsWithQueue ;
use Illuminate\Queue\SerializesModels ;
2021-07-23 14:53:35 +00:00
use Illuminate\Support\Facades\Log ;
2023-07-23 07:27:52 +00:00
use Illuminate\Support\Facades\Notification ;
2021-07-15 14:54:23 +00:00
2023-07-23 07:27:52 +00:00
use App\Classes\FTN\Message ;
2024-05-19 13:28:45 +00:00
use App\Models\ { Echomail , Netmail , User };
use App\Notifications\Netmails\ { EchoareaNotExist , EchoareaNotSubscribed , EchoareaNoWrite , NetmailForward , NetmailHubNoUser };
2024-06-01 00:46:02 +00:00
use App\Traits\ParseAddresses ;
2021-07-15 14:54:23 +00:00
2021-09-06 13:39:32 +00:00
class MessageProcess implements ShouldQueue
2021-07-15 14:54:23 +00:00
{
2021-09-11 14:07:02 +00:00
private const LOGKEY = 'JMP' ;
2021-08-18 14:20:34 +00:00
2024-06-01 00:46:02 +00:00
use Dispatchable , InteractsWithQueue , Queueable , SerializesModels , ParseAddresses ;
2021-07-15 14:54:23 +00:00
2024-05-17 12:10:54 +00:00
private Echomail | Netmail | string $mo ;
2021-09-10 14:38:11 +00:00
private bool $skipbot ;
2021-07-15 14:54:23 +00:00
2024-05-17 12:10:54 +00:00
/**
* Process a message from a packet
*
* @ param Echomail | Netmail $mo The message object
* @ param bool $skipbot Dont trigger bot actions
*/
public function __construct ( Echomail | Netmail $mo , bool $skipbot = FALSE )
2021-07-15 14:54:23 +00:00
{
2024-05-17 12:10:54 +00:00
// @todo We need to serialize this model here, because laravel has an error unserializing it (Model Not Found)
2024-11-02 13:16:48 +00:00
$this -> mo = utf8_encode ( serialize ( $mo -> withoutRelations ()));
2023-07-15 00:46:19 +00:00
$this -> skipbot = $skipbot ;
2021-07-15 14:54:23 +00:00
}
2023-09-05 07:42:41 +00:00
public function __get ( $key ) : mixed
{
switch ( $key ) {
2024-05-21 11:10:58 +00:00
case 'jobname' :
$mo = unserialize ( $this -> mo );
return sprintf ( '%s-%s-%s' , $mo -> set -> get ( 'set_pkt' ), $mo -> set -> get ( 'set_sender' ) -> ftn , $mo -> msgid );
2023-09-05 07:42:41 +00:00
default :
return NULL ;
}
}
2021-07-15 14:54:23 +00:00
/**
2024-05-17 12:10:54 +00:00
* At this point , we know that the packet is from a system we know about , and the packet is to us :
* + From a system that is configured with us , and the password has been validated
* + From a system that is not configured with us , and it may have netmails for us
2021-07-15 14:54:23 +00:00
*/
public function handle ()
{
2024-06-05 11:57:16 +00:00
$this -> mo = unserialize ( utf8_decode ( $this -> mo ));
2024-05-17 12:10:54 +00:00
2021-07-15 14:54:23 +00:00
// Load our details
2023-12-18 04:13:16 +00:00
$ftns = our_address ();
2021-07-15 14:54:23 +00:00
// If we are a netmail
2024-05-17 12:10:54 +00:00
if ( $this -> mo instanceof Netmail ) {
// @todo generate exception when netmail to system that doesnt exist (node/point) and its this host's responsibility
2023-07-15 00:46:19 +00:00
Log :: info ( sprintf ( '%s:- Processing Netmail [%s] to (%s) [%s] from (%s) [%s].' ,
2023-01-25 05:26:10 +00:00
self :: LOGKEY ,
2024-10-20 00:54:52 +00:00
$this -> mo -> msgid ? : '*NO MSGID*' ,
2024-05-17 12:10:54 +00:00
$this -> mo -> to , $this -> mo -> tftn -> ftn ,
$this -> mo -> from , $this -> mo -> fftn -> ftn ,
2023-01-25 05:26:10 +00:00
));
2021-07-15 14:54:23 +00:00
// @todo Enable checks to reject old messages
2023-07-15 00:46:19 +00:00
// Check for duplicate messages
// FTS-0009.001
2024-05-17 12:10:54 +00:00
if ( $this -> mo -> msgid ) {
Log :: debug ( sprintf ( '%s:- Checking for duplicate from host [%s].' , self :: LOGKEY , $this -> mo -> fftn -> ftn ));
$o = Netmail :: where ( 'msgid' , $this -> mo -> msgid )
2024-09-08 04:14:37 +00:00
-> where ( 'fftn_id' , $this -> mo -> fftn_id )
2023-07-15 00:46:19 +00:00
-> where ( 'datetime' , '>' , Carbon :: now () -> subYears ( 3 ))
-> single ();
if ( $o ) {
2024-05-17 12:10:54 +00:00
Log :: alert ( sprintf ( '%s:! Duplicate netmail #%d [%s] from (%s) [%s] to (%s) - ignoring.' ,
2023-07-15 00:46:19 +00:00
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$o -> id ,
$this -> mo -> msgid ,
$this -> mo -> from , $this -> mo -> fftn -> ftn ,
$this -> mo -> to ,
2023-07-15 00:46:19 +00:00
));
return ;
}
}
2021-07-23 14:53:35 +00:00
// @todo Enable checks to see if this is a file request or file send
2021-07-15 14:54:23 +00:00
2023-07-20 10:04:41 +00:00
// Strip any local/transit flags
2024-05-17 12:10:54 +00:00
$this -> mo -> flags &= ~ ( Message :: FLAG_LOCAL | Message :: FLAG_INTRANSIT );
2023-01-24 11:37:41 +00:00
2021-07-15 14:54:23 +00:00
// Determine if the message is to this system, or in transit
2024-05-17 12:10:54 +00:00
if ( $ftns -> contains ( $this -> mo -> tftn )) {
2021-07-15 14:54:23 +00:00
$processed = FALSE ;
// If the message is to a bot, we'll process it
2021-09-10 14:38:11 +00:00
if ( ! $this -> skipbot )
foreach ( config ( 'process.robots' ) as $class ) {
2024-05-17 12:10:54 +00:00
if ( $processed = $class :: handle ( $this -> mo )) {
$this -> mo -> flags |= Message :: FLAG_RECD ;
$this -> mo -> save ();
2023-01-25 05:35:58 +00:00
2023-07-17 06:36:53 +00:00
Log :: info ( sprintf ( '%s:= Netmail [%s] from (%s:%s) - was processed by us internally [%d]' ,
2023-07-15 12:10:05 +00:00
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$this -> mo -> msgid ,
$this -> mo -> from ,
$this -> mo -> fftn -> ftn ,
$this -> mo -> id ,
2023-07-15 12:10:05 +00:00
));
2024-05-17 12:10:54 +00:00
2021-09-10 14:38:11 +00:00
break ;
}
2021-07-15 14:54:23 +00:00
}
2023-08-02 12:42:59 +00:00
if ( ! $processed ) {
// Check if the netmail is to a user, with netmail forwarding enabled
$uo = User :: active ()
-> where ( function ( $query ) {
2024-06-01 00:46:02 +00:00
return $query -> whereRaw ( sprintf ( " LOWER(name)='%s' " , strtolower ( utf8_encode ( $this -> mo -> to ))))
-> orWhereRaw ( sprintf ( " LOWER(alias)='%s' " , strtolower ( utf8_encode ( $this -> mo -> to ))));
2023-08-02 12:42:59 +00:00
})
-> whereNotNull ( 'system_id' )
-> single ();
2024-05-17 12:10:54 +00:00
if ( $uo && ( $ao = $uo -> system -> match ( $this -> mo -> tftn -> zone ) ? -> pop ())) {
2024-10-20 06:25:45 +00:00
Log :: info ( sprintf ( '%s:- Forwarding Netmail [%s] to (%s) [%s] from (%s) [%s].' ,
self :: LOGKEY ,
$this -> mo -> msgid ? : '*NO MSGID*' ,
$this -> mo -> to , $ao -> ftn ,
$this -> mo -> from , $this -> mo -> fftn -> ftn ,
));
2023-08-02 12:42:59 +00:00
$note = " +--[ FORWARDED MESSAGE ]----------------------------------+ \r " ;
$note .= " + This message has been forwarded to you, it was originally sent to you \r " ;
2024-05-17 12:10:54 +00:00
$note .= sprintf ( " + at [%s] \r " , $this -> mo -> tftn -> ftn );
2023-08-02 12:42:59 +00:00
$note .= " +---------------------------------------------------------+ \r \r " ;
2024-05-17 12:10:54 +00:00
2024-10-20 06:25:45 +00:00
$this -> mo -> msg_src = $note . $this -> mo -> content ;
2024-05-17 12:10:54 +00:00
$this -> mo -> tftn_id = $ao -> id ;
$this -> mo -> flags |= Message :: FLAG_INTRANSIT ;
$this -> mo -> save ();
2023-08-02 12:42:59 +00:00
$processed = TRUE ;
// Dont send an advisement to an areabot
2024-05-17 12:10:54 +00:00
if ( ! in_array ( strtolower ( $this -> mo -> from ), config ( 'fido.areabots' )))
Notification :: route ( 'netmail' , $this -> mo -> fftn ) -> notify ( new NetmailForward ( $this -> mo , $ao ));
2023-08-02 12:42:59 +00:00
// We'll ignore messages from *fix users
2024-05-17 12:10:54 +00:00
} elseif ( in_array ( strtolower ( $this -> mo -> from ), config ( 'fido.areabots' ))) {
$this -> mo -> flags |= Message :: FLAG_RECD ;
$this -> mo -> save ();
2023-08-02 12:42:59 +00:00
Log :: alert ( sprintf ( '%s:! Ignoring Netmail [%s] to the Hub from (%s:%s) - its from a bot [%d]' ,
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$this -> mo -> msgid ,
$this -> mo -> from ,
$this -> mo -> fftn -> ftn ,
$this -> mo -> id ,
2023-08-02 12:42:59 +00:00
));
$processed = TRUE ;
}
2021-08-14 14:21:04 +00:00
}
2021-07-15 14:54:23 +00:00
// If not processed, no users here!
if ( ! $processed ) {
2024-05-17 12:10:54 +00:00
Log :: alert ( sprintf ( '%s:! Netmail to the Hub from (%s) [%s] but no users here.' , self :: LOGKEY , $this -> mo -> from , $this -> mo -> fftn -> ftn ));
2021-07-23 14:53:35 +00:00
2024-05-19 13:28:45 +00:00
Notification :: route ( 'netmail' , $this -> mo -> fftn ) -> notify ( new NetmailHubNoUser ( $this -> mo ));
2021-07-15 14:54:23 +00:00
}
// If in transit, store for collection
} else {
// @todo In transit loop checking
// @todo In transit TRACE response
2024-05-17 12:10:54 +00:00
$this -> mo -> flags |= Message :: FLAG_INTRANSIT ;
$this -> mo -> save ();
2023-01-24 11:37:41 +00:00
2023-07-15 00:46:19 +00:00
Log :: info ( sprintf ( '%s:= Netmail [%s] in transit to (%s:%s) from (%s:%s) [%d].' ,
2023-01-24 11:37:41 +00:00
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$this -> mo -> msgid ,
$this -> mo -> to , $this -> mo -> tftn -> ftn ,
$this -> mo -> from , $this -> mo -> fftn -> ftn ,
$this -> mo -> id ,
2023-01-24 11:37:41 +00:00
));
2021-07-15 14:54:23 +00:00
}
// Else we are echomail
} else {
2024-05-17 12:10:54 +00:00
// The packet sender
$sender = $this -> mo -> set -> get ( 'set_sender' );
2023-01-01 02:50:12 +00:00
2024-09-08 04:14:37 +00:00
// @todo Check that this does evaluate to true if a message has been rescanned
2024-05-17 12:10:54 +00:00
$rescanned = $this -> mo -> kludges -> get ( 'RESCANNED' , FALSE );
2023-01-01 02:50:12 +00:00
2024-05-17 12:10:54 +00:00
// Echoarea doesnt exist, cant import the message
if ( ! $this -> mo -> echoarea ) {
Log :: alert ( sprintf ( '%s:! Echoarea [%s] doesnt exist for zone [%d@%s]' , self :: LOGKEY , $this -> mo -> set -> get ( 'set_echoarea' ), $sender -> zone -> zone_id , $sender -> zone -> domain -> name ));
2021-08-11 13:45:30 +00:00
2024-05-17 12:10:54 +00:00
Notification :: route ( 'netmail' , $sender ) -> notify ( new EchoareaNotExist ( $this -> mo ));
2022-02-11 23:21:46 +00:00
return ;
}
2024-05-17 12:10:54 +00:00
Log :: debug ( sprintf ( '%s:- Processing echomail [%s] in [%s] from [%s].' , self :: LOGKEY , $this -> mo -> msgid , $this -> mo -> echoarea -> name , $sender -> ftn ));
2021-11-24 11:34:40 +00:00
2024-05-17 12:10:54 +00:00
// Message from zone is incorrect for echoarea
if ( ! $this -> mo -> echoarea -> domain -> zones -> contains ( $this -> mo -> fftn -> zone )) {
2023-09-20 10:29:23 +00:00
Log :: alert ( sprintf ( '%s:! The message [%s] is from a different zone [%d] than the packet sender [%d] - not importing' ,
2023-09-17 05:46:09 +00:00
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$this -> mo -> msgid ,
$this -> mo -> fftn -> zone -> zone_id ,
$this -> mo -> fftn -> zone -> zone_id ));
2023-09-20 10:29:23 +00:00
return ;
2023-09-17 05:46:09 +00:00
}
2021-08-18 14:20:34 +00:00
// Check for duplicate messages
2021-10-18 12:10:15 +00:00
// FTS-0009.001
2024-05-17 12:10:54 +00:00
if ( $this -> mo -> msgid ) {
2024-09-08 04:14:37 +00:00
Log :: debug ( sprintf ( '%s:- Checking for duplicate from host id [%d], with msgid [%s] between [%s] and [%s].' ,
self :: LOGKEY ,
$this -> mo -> fftn_id ,
$this -> mo -> msgid ,
$this -> mo -> datetime -> clone () -> subYears ( 3 ),
$this -> mo -> datetime ,
));
2021-11-24 11:34:40 +00:00
2024-11-27 07:41:27 +00:00
$x = Echomail :: where ( 'msgid' , $this -> mo -> msgid )
-> where ( 'fftn_id' , $this -> mo -> fftn_id )
-> where ( 'datetime' , '>=' , $this -> mo -> datetime -> clone () -> subYears ( 3 ))
-> where ( 'datetime' , '<=' , $this -> mo -> datetime );
2024-09-08 04:14:37 +00:00
if ( $x -> count ()) {
2024-05-17 12:10:54 +00:00
// @todo Actually update seenby
2024-09-08 04:14:37 +00:00
Log :: alert ( sprintf ( '%s:! Duplicate echomail (%s) in [%s] from (%s) [%s] to (%s) - ignoring.' ,
2021-08-18 14:20:34 +00:00
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$this -> mo -> msgid ,
$this -> mo -> echoarea -> name ,
$this -> mo -> from , $this -> mo -> fftn -> ftn ,
$this -> mo -> to ,
2021-08-18 14:20:34 +00:00
));
2021-11-25 10:22:36 +00:00
// @todo This duplicate message may have gone via a different path, be nice to record it.
2022-01-15 02:06:15 +00:00
// @todo if we have an export for any of the seenby addresses, remove it
2024-05-17 12:10:54 +00:00
2021-08-18 14:20:34 +00:00
return ;
}
}
2021-11-24 11:34:40 +00:00
// Find another message with the same msg_crc
2024-05-17 12:10:54 +00:00
if ( $this -> mo -> msg_crc ) {
$o = Echomail :: where ( 'msg_crc' , $xx = md5 ( $this -> mo -> msg_crc ))
2024-09-08 04:14:37 +00:00
-> where ( 'fftn_id' , $this -> mo -> fftn_id )
2021-11-24 11:34:40 +00:00
-> where ( 'datetime' , '>' , Carbon :: now () -> subWeek ())
-> get ();
if ( $o -> count ())
Log :: alert ( sprintf ( '%s:! Duplicate message CRC [%s] in [%s].' ,
self :: LOGKEY ,
$xx ,
$o -> pluck ( 'id' ) -> join ( '|' )
));
}
2023-07-29 03:17:36 +00:00
// Can the system send messages to this area?
2024-05-17 12:10:54 +00:00
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 ));
if ( ! $rescanned )
Notification :: route ( 'netmail' , $sender ) -> notify ( new EchoareaNoWrite ( $this -> mo ));
2023-09-17 05:46:09 +00:00
2023-07-29 03:17:36 +00:00
return ;
}
2024-05-19 13:28:45 +00:00
// 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 ));
}
2021-07-15 14:54:23 +00:00
// We know about this area, store it
2024-05-17 12:10:54 +00:00
$this -> mo -> save ();
2021-07-30 14:35:52 +00:00
2023-07-15 00:46:19 +00:00
Log :: info ( sprintf ( '%s:= Echomail [%s] in [%s] from (%s) [%s] to (%s) - [%s].' ,
2021-08-19 13:35:48 +00:00
self :: LOGKEY ,
2024-05-17 12:10:54 +00:00
$this -> mo -> msgid ,
$this -> mo -> echoarea -> name ,
$this -> mo -> from , $this -> mo -> fftn -> ftn ,
$this -> mo -> to ,
$this -> mo -> id ,
2021-08-19 13:35:48 +00:00
));
2021-09-13 13:02:39 +00:00
// If the message is to a bot, but not rescanned, or purposely skipbot set, we'll process it
2024-05-17 12:10:54 +00:00
if (( ! $this -> skipbot ) && ( ! $rescanned ))
2021-09-10 14:38:11 +00:00
foreach ( config ( 'process.echomail' ) as $class ) {
2024-05-17 12:10:54 +00:00
if ( $class :: handle ( $this -> mo )) {
2021-09-10 14:38:11 +00:00
break ;
}
2021-07-30 14:35:52 +00:00
}
2021-07-15 14:54:23 +00:00
}
}
}