Just optimisations
This commit is contained in:
parent
9317f78a3a
commit
df849c0cfd
@ -2,16 +2,25 @@
|
|||||||
|
|
||||||
namespace App\Classes;
|
namespace App\Classes;
|
||||||
|
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
use App\Exceptions\InvalidFidoPacketException;
|
use App\Exceptions\InvalidFidoPacketException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FTNMessage
|
||||||
|
* NOTE: FTN Echomail Messages are ZONE agnostic.
|
||||||
|
*
|
||||||
|
* @package App\Classes
|
||||||
|
*/
|
||||||
class FTNMessage extends FTN
|
class FTNMessage extends FTN
|
||||||
{
|
{
|
||||||
private $_src = NULL;
|
private $src = NULL; // SRC N/F from packet
|
||||||
private $_dst = NULL;
|
private $dst = NULL; // DST N/F from packet
|
||||||
|
|
||||||
private $flags = NULL;
|
private $flags = NULL; // Flags from packet
|
||||||
private $cost = 0;
|
private $cost = 0; // Cost from packet
|
||||||
|
|
||||||
|
// @todo need to validate these string lengths when creating packet.
|
||||||
private $from = NULL; // FTS-0001.016 From Name: upto 36 chars null terminated
|
private $from = NULL; // FTS-0001.016 From Name: upto 36 chars null terminated
|
||||||
private $to = NULL; // FTS-0001.016 To Name: upto 36 chars null terminated
|
private $to = NULL; // FTS-0001.016 To Name: upto 36 chars null terminated
|
||||||
private $subject = NULL; // FTS-0001.016 Subject: upto 72 chars null terminated
|
private $subject = NULL; // FTS-0001.016 Subject: upto 72 chars null terminated
|
||||||
@ -31,8 +40,9 @@ class FTNMessage extends FTN
|
|||||||
private $_other = [];
|
private $_other = [];
|
||||||
private $unknown = [];
|
private $unknown = [];
|
||||||
|
|
||||||
private $fqfa = NULL; // Fully qualified fidonet source where packet originated
|
// We auto create these values - they are used to create packets.
|
||||||
private $fqda = NULL; // Fully qualified fidonet destination address (Netmail)
|
private $_fqfa = NULL; // Fully qualified fidonet source where packet originated
|
||||||
|
private $_fqda = NULL; // Fully qualified fidonet destination address (Netmail)
|
||||||
|
|
||||||
// Single value kludge items
|
// Single value kludge items
|
||||||
private $_kludge = [
|
private $_kludge = [
|
||||||
@ -90,15 +100,30 @@ class FTNMessage extends FTN
|
|||||||
{
|
{
|
||||||
switch ($k)
|
switch ($k)
|
||||||
{
|
{
|
||||||
case 'fz': return $this->znfp($this->fqfa,'z');
|
case 'fz': return ftn_address_split($this->_fqfa,'z');
|
||||||
case 'fn': return $this->znfp($this->fqfa,'n');
|
case 'fn': return ftn_address_split($this->_fqfa,'n');
|
||||||
case 'ff': return $this->znfp($this->fqfa,'f');
|
case 'ff': return ftn_address_split($this->_fqfa,'f');
|
||||||
case 'fp': return $this->znfp($this->fqfa,'p');
|
case 'fp': return ftn_address_split($this->_fqfa,'p');
|
||||||
|
|
||||||
case 'tz': return $this->znfp($this->fqda,'z');
|
case 'fqfa': return $this->_fqfa;
|
||||||
case 'tn': return $this->znfp($this->fqda,'n');
|
|
||||||
case 'tf': return $this->znfp($this->fqda,'f');
|
// Echomails dont have a fully qualified from address
|
||||||
case 'tp': return $this->znfp($this->fqda,'p');
|
case 'tz': return ftn_address_split($this->_fqda,'z');
|
||||||
|
case 'tn': return ftn_address_split($this->_fqda,'n');
|
||||||
|
case 'tf': return ftn_address_split($this->_fqda,'f');
|
||||||
|
case 'tp': return ftn_address_split($this->_fqda,'p');
|
||||||
|
|
||||||
|
case 'tearline':
|
||||||
|
return '--- FTNHub';
|
||||||
|
|
||||||
|
case 'type':
|
||||||
|
if ($this->echoarea)
|
||||||
|
return 'echomail';
|
||||||
|
|
||||||
|
if ($this->intl)
|
||||||
|
return 'netmail';
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return isset($this->{$k}) ? $this->{$k} : NULL;
|
return isset($this->{$k}) ? $this->{$k} : NULL;
|
||||||
@ -111,10 +136,17 @@ class FTNMessage extends FTN
|
|||||||
{
|
{
|
||||||
case 'fqfa':
|
case 'fqfa':
|
||||||
case 'fqda':
|
case 'fqda':
|
||||||
$this->{$k} = $v;
|
$this->{'_'.$k} = $v;
|
||||||
|
|
||||||
if ($this->fqfa AND $this->fqda)
|
if ($this->_fqfa AND $this->_fqda)
|
||||||
$this->intl = sprintf('%s %s',$this->fqda,$this->fqfa);
|
$this->intl = sprintf('%s %s',$this->_fqda,$this->_fqfa);
|
||||||
|
|
||||||
|
case 'origin':
|
||||||
|
if (! $this->_fqfa)
|
||||||
|
throw new \Exception('Must set from address before origin');
|
||||||
|
|
||||||
|
$this->origin = sprintf(' * Origin: %s (%s)',$v,$this->_fqfa);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->{$k} = $v;
|
$this->{$k} = $v;
|
||||||
@ -128,6 +160,7 @@ class FTNMessage extends FTN
|
|||||||
*/
|
*/
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
|
// if (f->net == 65535) { /* Point packet - Get Net from auxNet */
|
||||||
$return = '';
|
$return = '';
|
||||||
|
|
||||||
$return .= pack(join('',collect($this->struct)->pluck(1)->toArray()),
|
$return .= pack(join('',collect($this->struct)->pluck(1)->toArray()),
|
||||||
@ -136,7 +169,7 @@ class FTNMessage extends FTN
|
|||||||
$this->fn,
|
$this->fn,
|
||||||
$this->tn,
|
$this->tn,
|
||||||
$this->flags,
|
$this->flags,
|
||||||
0 // @todo cost
|
$this->cost
|
||||||
);
|
);
|
||||||
|
|
||||||
// @todo use pack for this.
|
// @todo use pack for this.
|
||||||
@ -144,22 +177,45 @@ class FTNMessage extends FTN
|
|||||||
$return .= $this->to."\00";
|
$return .= $this->to."\00";
|
||||||
$return .= $this->from."\00";
|
$return .= $this->from."\00";
|
||||||
$return .= $this->subject."\00";
|
$return .= $this->subject."\00";
|
||||||
$return .= $this->message."\00";
|
|
||||||
|
// Add some kludges
|
||||||
|
$return .= "\01MSGID ".$this->_fqfa." 1"."\r";
|
||||||
|
|
||||||
|
foreach ($this->_kludge as $k=>$v)
|
||||||
|
{
|
||||||
|
if ($x=$this->kludge->get($k))
|
||||||
|
$return .= chr(1).$v.$x."\r";
|
||||||
|
}
|
||||||
|
|
||||||
|
$return .= $this->message."\r";
|
||||||
|
$return .= $this->tearline."\r";
|
||||||
|
$return .= $this->origin."\r";
|
||||||
|
|
||||||
|
switch ($this->type)
|
||||||
|
{
|
||||||
|
case 'echomail':
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'netmail':
|
||||||
|
foreach ($this->via as $k=>$v)
|
||||||
|
$return .= "\01Via: ".$v."\r";
|
||||||
|
|
||||||
|
// @todo Set product name/version as var
|
||||||
|
$return .= sprintf('%sVia: %s @%s.UTC %s %i.%i',
|
||||||
|
chr(1),
|
||||||
|
'10:0/0',
|
||||||
|
now('UTC')->format('Ymd.His'),
|
||||||
|
'FTNHub',
|
||||||
|
1,1)."\r";
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$return .= "\00";
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
switch ($this->type())
|
|
||||||
{
|
|
||||||
case 'echomail': return sprintf('Echomail: '.$this->echoarea);
|
|
||||||
case 'netmail': return sprintf('Netmail: %s->%s',$this->fqfa,$this->fqda);
|
|
||||||
default:
|
|
||||||
return 'UNKNOWN';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of flag descriptions
|
* Return an array of flag descriptions
|
||||||
*
|
*
|
||||||
@ -215,25 +271,25 @@ class FTNMessage extends FTN
|
|||||||
$result = unpack($this->unpackheader($this->struct),$header);
|
$result = unpack($this->unpackheader($this->struct),$header);
|
||||||
|
|
||||||
// For Echomail this is the packet src.
|
// For Echomail this is the packet src.
|
||||||
$this->psn = array_get($result,'onet');
|
$this->psn = Arr::get($result,'onet');
|
||||||
$this->psf = array_get($result,'onode');
|
$this->psf = Arr::get($result,'onode');
|
||||||
|
|
||||||
$this->_src = sprintf('%s/%s',
|
$this->src = sprintf('%s/%s',
|
||||||
$this->psn,
|
$this->psn,
|
||||||
$this->psf
|
$this->psf
|
||||||
);
|
);
|
||||||
|
|
||||||
// For Echomail this is the packet dst.
|
// For Echomail this is the packet dst.
|
||||||
$this->pdn = array_get($result,'dnet');
|
$this->pdn = Arr::get($result,'dnet');
|
||||||
$this->pdf = array_get($result,'dnode');
|
$this->pdf = Arr::get($result,'dnode');
|
||||||
|
|
||||||
$this->_dst = sprintf('%s/%s',
|
$this->dst = sprintf('%s/%s',
|
||||||
$this->pdn,
|
$this->pdn,
|
||||||
$this->pdf
|
$this->pdf
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->flags = array_get($result,'flags');
|
$this->flags = Arr::get($result,'flags');
|
||||||
$this->cost = array_get($result,'cost');
|
$this->cost = Arr::get($result,'cost');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parsemessage(string $message)
|
public function parsemessage(string $message)
|
||||||
@ -259,14 +315,33 @@ class FTNMessage extends FTN
|
|||||||
{
|
{
|
||||||
$this->message .= substr($v,$x+1,$y-$x-1);
|
$this->message .= substr($v,$x+1,$y-$x-1);
|
||||||
$this->parseorigin(substr($v,$y));
|
$this->parseorigin(substr($v,$y));
|
||||||
|
|
||||||
|
// If this is netmail, the FQFA will have been set by the INTL line, we can skip the rest of this
|
||||||
$matches = [];
|
$matches = [];
|
||||||
|
|
||||||
|
// Capture the fully qualified 4D name from the Origin Line - it tells us the ZONE.
|
||||||
preg_match('/^.*\((.*)\)$/',$this->origin,$matches);
|
preg_match('/^.*\((.*)\)$/',$this->origin,$matches);
|
||||||
|
|
||||||
if (($this->type() == 'Netmail' AND array_get($matches,1) != $this->fqfa) OR ! array_get($matches,1))
|
// Double check we have an address in the origin line
|
||||||
throw new InvalidFidoPacketException(sprintf('Source address mismatch? [%s,%s]',$this->fqfa,array_get($matches,1)));
|
if (! Arr::get($matches,1))
|
||||||
|
throw new InvalidFidoPacketException(sprintf('No address in Origin?',$matches));
|
||||||
|
|
||||||
$this->fqfa = array_get($matches,1);
|
// Double check, our src and origin match
|
||||||
|
if (! preg_match('#^[0-9]+:'.$this->src.'#',$matches[1]))
|
||||||
|
throw new InvalidFidoPacketException(sprintf('Source address mismatch? [%s,%s]',$this->_fqfa,$matches[1]));
|
||||||
|
|
||||||
|
// If this is netmail, a double check our FQFA matches
|
||||||
|
if ($this->type == 'netmail') {
|
||||||
|
if ($this->_fqfa != $matches[1])
|
||||||
|
throw new InvalidFidoPacketException(sprintf('Source address mismatch? [%s,%s]',$this->_fqfa,$matches[1]));
|
||||||
|
|
||||||
|
// For other types, this is our only way of getting a FQFA
|
||||||
|
} else {
|
||||||
|
$this->_fqfa = $matches[1];
|
||||||
|
|
||||||
|
// Our FQDA is not available, we'll assume its the same zone as our FQFA
|
||||||
|
$this->_fqda = sprintf('%d:%s',ftn_address_split($this->_fqfa,'z'),$this->dst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$v = substr($v,0,$x+1);
|
$v = substr($v,0,$x+1);
|
||||||
@ -299,7 +374,7 @@ class FTNMessage extends FTN
|
|||||||
elseif ($t = $this->kludge('INTL ',$v))
|
elseif ($t = $this->kludge('INTL ',$v))
|
||||||
{
|
{
|
||||||
$this->intl = $t;
|
$this->intl = $t;
|
||||||
list($this->fqda,$this->fqfa) = explode(' ',$t);
|
list($this->_fqda,$this->_fqfa) = explode(' ',$t);
|
||||||
}
|
}
|
||||||
|
|
||||||
elseif ($t = $this->kludge('MSGID: ',$v))
|
elseif ($t = $this->kludge('MSGID: ',$v))
|
||||||
@ -344,10 +419,9 @@ class FTNMessage extends FTN
|
|||||||
$result = collect(explode("\r",$message))->filter();
|
$result = collect(explode("\r",$message))->filter();
|
||||||
|
|
||||||
foreach ($result as $k => $v) {
|
foreach ($result as $k => $v) {
|
||||||
|
|
||||||
foreach ($this->_kludge as $a => $b) {
|
foreach ($this->_kludge as $a => $b) {
|
||||||
if ($t = $this->kludge($b, $v)) {
|
if ($t = $this->kludge($b,$v)) {
|
||||||
$this->kludge->put($a, $t);
|
$this->kludge->put($a,$t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,35 +443,4 @@ class FTNMessage extends FTN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function type()
|
|
||||||
{
|
|
||||||
if ($this->echoarea)
|
|
||||||
return 'echomail';
|
|
||||||
|
|
||||||
if ($this->intl)
|
|
||||||
return 'netmail';
|
|
||||||
|
|
||||||
return 'UNKNOWN';
|
|
||||||
}
|
|
||||||
|
|
||||||
private function znfp(string $data,string $key)
|
|
||||||
{
|
|
||||||
switch ($key) {
|
|
||||||
case 'z':
|
|
||||||
return substr($data,0,strpos($data,':'));
|
|
||||||
case 'n':
|
|
||||||
$x = strpos($data,':')+1;
|
|
||||||
return substr($data,$x,strpos($data,'/')-$x);
|
|
||||||
case 'f':
|
|
||||||
$x = strpos($data,'/')+1;
|
|
||||||
return substr($data,$x,strpos($data,'.') ?: strlen($data)-$x);
|
|
||||||
case 'p':
|
|
||||||
$x = strpos($data,'.');
|
|
||||||
return $x ? substr($data,$x+1) : 0;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort(500,'Unknown key: '.$key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -66,16 +66,6 @@ class FTNPacket extends FTN
|
|||||||
{
|
{
|
||||||
$this->messages = collect();
|
$this->messages = collect();
|
||||||
|
|
||||||
// @todo - is this appropriate to set here
|
|
||||||
$this->date = now();
|
|
||||||
$this->software['prodcode-lo'] = 0;
|
|
||||||
$this->software['prodcode-hi'] = 1;
|
|
||||||
$this->software['rev-maj'] = 2;
|
|
||||||
$this->software['rev-min'] = 3;
|
|
||||||
$this->cap['valid'] = 0; // @todo this is wrong
|
|
||||||
$this->cap['word'] = 0; // @todo this is wrong
|
|
||||||
$this->pktver = 0x02;
|
|
||||||
|
|
||||||
if ($file) {
|
if ($file) {
|
||||||
$this->filename = $file;
|
$this->filename = $file;
|
||||||
|
|
||||||
@ -83,8 +73,42 @@ class FTNPacket extends FTN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __get($k)
|
||||||
|
{
|
||||||
|
switch ($k)
|
||||||
|
{
|
||||||
|
case 'fz': return ftn_address_split($this->pktsrc,'z');
|
||||||
|
case 'fn': return ftn_address_split($this->pktsrc,'n');
|
||||||
|
case 'ff': return ftn_address_split($this->pktsrc,'f');
|
||||||
|
case 'fp': return ftn_address_split($this->pktsrc,'p');
|
||||||
|
|
||||||
|
case 'tz': return ftn_address_split($this->pktdst,'z');
|
||||||
|
case 'tn': return ftn_address_split($this->pktdst,'n');
|
||||||
|
case 'tf': return ftn_address_split($this->pktdst,'f');
|
||||||
|
case 'tp': return ftn_address_split($this->pktdst,'p');
|
||||||
|
|
||||||
|
default:
|
||||||
|
return isset($this->{$k}) ? $this->{$k} : NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
|
// @todo - is this appropriate to set here
|
||||||
|
$this->date = now();
|
||||||
|
$this->pktsrc = '10:1/5.0';
|
||||||
|
$this->pktdst = '10:1/0.0';
|
||||||
|
|
||||||
|
$this->software['prodcode-lo'] = 0x00;
|
||||||
|
$this->software['prodcode-hi'] = 0xde;
|
||||||
|
$this->software['rev-maj'] = 0x00;
|
||||||
|
$this->software['rev-min'] = 0x01;
|
||||||
|
|
||||||
|
// Type 2+ Packet
|
||||||
|
$this->cap['valid'] = 0x0100;
|
||||||
|
$this->cap['word'] = 0x0001;
|
||||||
|
$this->pktver = 0x0002;
|
||||||
|
|
||||||
$return = $this->createHeader();
|
$return = $this->createHeader();
|
||||||
|
|
||||||
foreach ($this->messages as $o)
|
foreach ($this->messages as $o)
|
||||||
@ -102,8 +126,8 @@ class FTNPacket extends FTN
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$a = pack(join('',collect($this->pack1)->pluck(1)->toArray()),
|
$a = pack(join('',collect($this->pack1)->pluck(1)->toArray()),
|
||||||
$this->sf,
|
$this->ff,
|
||||||
$this->df,
|
$this->tf,
|
||||||
$this->date->year,
|
$this->date->year,
|
||||||
$this->date->month,
|
$this->date->month,
|
||||||
$this->date->day,
|
$this->date->day,
|
||||||
@ -112,27 +136,27 @@ class FTNPacket extends FTN
|
|||||||
$this->date->second,
|
$this->date->second,
|
||||||
$this->baud,
|
$this->baud,
|
||||||
$this->pktver,
|
$this->pktver,
|
||||||
$this->sn,
|
$this->fn, // @todo if point, this needs to be 0xff
|
||||||
$this->dn,
|
$this->tn,
|
||||||
$this->software['prodcode-lo'], // @todo change to this software
|
$this->software['prodcode-lo'], // @todo change to this software
|
||||||
$this->software['rev-maj'] // @todo change to this software
|
$this->software['rev-maj'] // @todo change to this software
|
||||||
);
|
);
|
||||||
|
|
||||||
$b = pack(join('',collect($this->pack2)->pluck(1)->toArray()),
|
$b = pack(join('',collect($this->pack2)->pluck(1)->toArray()),
|
||||||
$this->sz,
|
0x0000, // @note: Type 2 packet this is $this->sz,
|
||||||
$this->dz,
|
0x0000, // @note: Type 2 packet this is $this->dz,
|
||||||
0x00, // Baud
|
0x0000, // Filler $this->>sn if message to point.
|
||||||
$this->cap['valid'], // @todo to check
|
$this->cap['valid'], // @todo to check
|
||||||
$this->software['prodcode-hi'], // @todo change to this software
|
$this->software['prodcode-hi'], // @todo change to this software
|
||||||
$this->software['rev-min'], // @todo change to this software
|
$this->software['rev-min'], // @todo change to this software
|
||||||
$this->cap['word'], // @todo to check
|
$this->cap['word'], // @todo to check
|
||||||
$this->sz,
|
$this->fz,
|
||||||
$this->dz,
|
$this->tz,
|
||||||
$this->sp,
|
$this->fp, // @note: point address, type 2+ packets
|
||||||
$this->dp
|
$this->tp // @note: point address, type 2+ packets
|
||||||
);
|
);
|
||||||
|
|
||||||
return $a.pack('a8',$this->password).$b."mbse"; // @todo change to this software
|
return $a.pack('a8',strtoupper($this->password)).$b."mbse"; // @todo change to this software
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return $e->getMessage();
|
return $e->getMessage();
|
||||||
@ -185,7 +209,7 @@ class FTNPacket extends FTN
|
|||||||
|
|
||||||
// Messages start with 02H 00H
|
// Messages start with 02H 00H
|
||||||
if (strlen($x) == 2 AND $x != "\02\00")
|
if (strlen($x) == 2 AND $x != "\02\00")
|
||||||
throw new InvalidFidoPacketException('Not a valid packet: '.$x);
|
throw new InvalidFidoPacketException('Not a valid packet: '.bin2hex($x));
|
||||||
|
|
||||||
// No message attached
|
// No message attached
|
||||||
else if (! strlen($x))
|
else if (! strlen($x))
|
||||||
@ -222,6 +246,7 @@ class FTNPacket extends FTN
|
|||||||
$result2 = unpack($this->unpackheader($this->pack2),substr($header,0x22,0x14));
|
$result2 = unpack($this->unpackheader($this->pack2),substr($header,0x22,0x14));
|
||||||
$this->proddata = array_get(unpack('A*p',substr($header,0x36,4)),'p');
|
$this->proddata = array_get(unpack('A*p',substr($header,0x36,4)),'p');
|
||||||
|
|
||||||
|
// @todo replcae these vars with the tz/fz
|
||||||
$this->sz = array_get($result2,'ozone');
|
$this->sz = array_get($result2,'ozone');
|
||||||
$this->sn = array_get($result1,'onet');
|
$this->sn = array_get($result1,'onet');
|
||||||
$this->sf = array_get($result1,'onode');
|
$this->sf = array_get($result1,'onode');
|
||||||
|
@ -56,7 +56,7 @@ class FtnPkt extends Command
|
|||||||
$o->fqfa,
|
$o->fqfa,
|
||||||
$o->to,
|
$o->to,
|
||||||
$o->fqda,
|
$o->fqda,
|
||||||
$o->description(),
|
$o->type,
|
||||||
strlen($o->message)
|
strlen($o->message)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class ImportNodelist extends Command
|
|||||||
default:
|
default:
|
||||||
$this->error(sprintf('Unhandled first field [%s]',$fields[0]));
|
$this->error(sprintf('Unhandled first field [%s]',$fields[0]));
|
||||||
$bar->advance();
|
$bar->advance();
|
||||||
continue;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $zone)
|
if (! $zone)
|
||||||
|
@ -2,23 +2,22 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
use App\Traits\{GetNode,ParseNodes,ParseZNFPDomain};
|
use App\Traits\{GetNode,ParseNodes};
|
||||||
use App\Classes\FTNPacket;
|
use App\Classes\FTNPacket;
|
||||||
use App\Models\{Echomail,Netmail,Zone};
|
use App\Models\{Echomail,Netmail,Zone};
|
||||||
|
|
||||||
class ImportPacket extends Command
|
class ImportPacket extends Command
|
||||||
{
|
{
|
||||||
use GetNode,ParseNodes,ParseZNFPDomain;
|
use GetNode,ParseNodes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'import:pkt {file : Packet File}';
|
protected $signature = 'import:pkt {file : Packet File} {--f|force : Force import of duplicates}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
@ -49,60 +48,78 @@ class ImportPacket extends Command
|
|||||||
|
|
||||||
foreach ($pkt->messages as $o)
|
foreach ($pkt->messages as $o)
|
||||||
{
|
{
|
||||||
switch ($o->type())
|
$o->date->setTimezone(($o->tzutc >= 0 ? '+' : '').substr_replace($o->tzutc,':',2,0));
|
||||||
|
|
||||||
|
switch ($o->type)
|
||||||
{
|
{
|
||||||
case 'echomail':
|
case 'echomail':
|
||||||
$date = Carbon::createFromFormat('d M y H:i:s',$o->date,($o->tzutc >= 0 ? '+' : '').substr_replace($o->tzutc,':',2,0));
|
|
||||||
|
|
||||||
// See if we already have this message.
|
// See if we already have this message.
|
||||||
$eo = Echomail::firstOrNew([
|
$oo = Echomail::firstOrNew([
|
||||||
'date'=>$date,
|
'date'=>$o->date,
|
||||||
'from_ftn'=>$this->get_node($o->fz,$o->fn,$o->ff,$o->fp)->id,
|
'from_ftn'=>$this->get_node(['z'=>$o->fz,'n'=>$o->fn,'f'=>$o->ff,'p'=>$o->fp])->id,
|
||||||
'msgid'=>$o->msgid,
|
'msgid'=>$o->msgid,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (md5(utf8_decode($eo->message)) == md5($o->message))
|
$oo->area = $o->echoarea;
|
||||||
{
|
|
||||||
$this->warn(sprintf('Duplicate message: %s@%s with id: %s',$o->from,$o->fqfa,$o->msgid));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$eo->pkt_from = $this->get_node($pkt->sz,$pkt->sn,$pkt->sf,$pkt->sp)->id;
|
break;
|
||||||
$eo->pkt_to = $this->get_node($pkt->dz,$pkt->dn,$pkt->df,$pkt->dp)->id;
|
|
||||||
$eo->pkt = $pkt->filename;
|
|
||||||
$eo->pkt_date = $pkt->date;
|
|
||||||
|
|
||||||
$eo->flags = $o->flags;
|
case 'netmail':
|
||||||
$eo->cost = $o->cost;
|
// See if we already have this message.
|
||||||
$eo->from_user = utf8_encode($o->from);
|
$oo = Netmail::firstOrNew([
|
||||||
$eo->to_user = utf8_encode($o->to);
|
'date'=>$o->date,
|
||||||
$eo->subject = utf8_encode($o->subject);
|
'from_ftn'=>$this->get_node(['z'=>$o->fz,'n'=>$o->fn,'f'=>$o->ff,'p'=>$o->fp])->id,
|
||||||
$eo->tz = $o->tzutc;
|
'msgid'=>$o->msgid,
|
||||||
|
]);
|
||||||
|
|
||||||
$eo->area = $o->echoarea;
|
$oo->to_ftn = $this->get_node(['z'=>$o->tz,'n'=>$o->tn,'f'=>$o->tf,'p'=>$o->tp])->id;
|
||||||
$eo->replyid = $o->replyid;
|
|
||||||
$eo->message = utf8_encode($o->message);
|
|
||||||
|
|
||||||
$eo->origin = utf8_encode($o->origin);
|
break;
|
||||||
//$eo->original = (string)$o;
|
|
||||||
|
|
||||||
$eo->save();
|
default:
|
||||||
|
abort(500,'Unknown type: '.$o->type);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($o->kludge as $k=>$v)
|
if (md5(utf8_decode($oo->message)) == md5($o->message))
|
||||||
{
|
{
|
||||||
$eo->kludges()->attach($k,['value'=>json_encode($v)]);
|
$this->warn(sprintf('Duplicate message: %s@%s with id: %s',$o->from,$o->fqfa,$o->msgid));
|
||||||
}
|
if (! $this->option('force'))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($o->unknown as $v)
|
$oo->pkt_from = $this->get_node(['z'=>$pkt->sz,'n'=>$pkt->sn,'f'=>$pkt->sf,'p'=>$pkt->sp])->id;
|
||||||
{
|
$oo->pkt_to = $this->get_node(['z'=>$pkt->dz,'n'=>$pkt->dn,'f'=>$pkt->df,'p'=>$pkt->dp])->id;
|
||||||
$eo->kludges()->attach('UNKNOWN',['value'=>json_encode($v)]);
|
$oo->pkt = $pkt->filename;
|
||||||
}
|
$oo->pkt_date = $pkt->date;
|
||||||
|
$oo->flags = $o->flags;
|
||||||
|
$oo->cost = $o->cost;
|
||||||
|
$oo->from_user = utf8_encode($o->from);
|
||||||
|
$oo->to_user = utf8_encode($o->to);
|
||||||
|
$oo->subject = utf8_encode($o->subject);
|
||||||
|
$oo->tz = $o->tzutc;
|
||||||
|
$oo->replyid = $o->replyid;
|
||||||
|
$oo->message = utf8_encode($o->message);
|
||||||
|
$oo->origin = utf8_encode($o->origin);
|
||||||
|
$oo->save();
|
||||||
|
|
||||||
|
foreach ($o->kludge as $k=>$v)
|
||||||
|
{
|
||||||
|
$oo->kludges()->attach($k,['value'=>json_encode($v)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($o->unknown as $v)
|
||||||
|
{
|
||||||
|
$oo->kludges()->attach('UNKNOWN',['value'=>json_encode($v)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish off the import
|
||||||
|
switch($o->type) {
|
||||||
|
case 'echomail':
|
||||||
foreach ($o->seenby as $v)
|
foreach ($o->seenby as $v)
|
||||||
{
|
{
|
||||||
foreach ($this->parse_nodes(Zone::findOrFail($pkt->sz),$v) as $no)
|
foreach ($this->parse_nodes(Zone::findOrFail($pkt->sz),$v) as $no)
|
||||||
{
|
{
|
||||||
$eo->seenbys()->attach($no->id);
|
$oo->seenbys()->attach($no->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,71 +128,25 @@ class ImportPacket extends Command
|
|||||||
{
|
{
|
||||||
foreach ($this->parse_nodes(Zone::findOrFail($pkt->sz),$v) as $no)
|
foreach ($this->parse_nodes(Zone::findOrFail($pkt->sz),$v) as $no)
|
||||||
{
|
{
|
||||||
$eo->paths()->attach($no->id,['sequence'=>$seq++]);
|
$oo->paths()->attach($no->id,['sequence'=>$seq++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case 'netmail':
|
|
||||||
$date = Carbon::createFromFormat('d M y H:i:s',$o->date,($o->tzutc >= 0 ? '+' : '').substr_replace($o->tzutc,':',2,0));
|
|
||||||
|
|
||||||
// See if we already have this message.
|
|
||||||
$no = Netmail::firstOrNew([
|
|
||||||
'date'=>$date,
|
|
||||||
'from_ftn'=>$this->get_node($o->fz,$o->fn,$o->ff,$o->fp)->id,
|
|
||||||
'msgid'=>$o->msgid,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (md5(utf8_decode($no->message)) == md5($o->message))
|
|
||||||
{
|
|
||||||
$this->warn(sprintf('Duplicate message: %s@%s with id: %s',$o->from,$o->fqfa,$o->msgid));
|
|
||||||
//continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$no->pkt_from = $this->get_node($pkt->sz,$pkt->sn,$pkt->sf,$pkt->sp)->id;
|
|
||||||
$no->pkt_to = $this->get_node($pkt->dz,$pkt->dn,$pkt->df,$pkt->dp)->id;
|
|
||||||
$no->pkt = $pkt->filename;
|
|
||||||
$no->pkt_date = $pkt->date;
|
|
||||||
|
|
||||||
$no->flags = $o->flags;
|
|
||||||
$no->cost = $o->cost;
|
|
||||||
$no->from_user = utf8_encode($o->from);
|
|
||||||
$no->to_user = utf8_encode($o->to);
|
|
||||||
$no->to_ftn = $this->get_node($o->tz,$o->tn,$o->tf,$o->tp)->id;
|
|
||||||
$no->subject = utf8_encode($o->subject);
|
|
||||||
$no->tz = $o->tzutc;
|
|
||||||
|
|
||||||
$no->replyid = $o->replyid;
|
|
||||||
$no->message = utf8_encode($o->message);
|
|
||||||
|
|
||||||
$no->origin = utf8_encode($o->origin);
|
|
||||||
|
|
||||||
$no->save();
|
|
||||||
|
|
||||||
foreach ($o->kludge as $k=>$v)
|
|
||||||
{
|
|
||||||
$no->kludges()->attach($k,['value'=>json_encode($v)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($o->unknown as $v)
|
|
||||||
{
|
|
||||||
$no->kludges()->attach('UNKNOWN',['value'=>json_encode($v)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$seq = 0;
|
|
||||||
foreach ($o->via as $v)
|
|
||||||
{
|
|
||||||
dump($v);
|
|
||||||
$data = preg_split('/\s/',$v);
|
|
||||||
$ftno = $this->parse_znfp_domain($data[0]);
|
|
||||||
unset($data[0]);
|
|
||||||
|
|
||||||
$no->paths()->attach($ftno->id,['sequence'=>$seq++,'value'=>json_encode($data)]);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 'netmail':
|
||||||
abort(500,'Unknown type: '.$o->type());
|
$seq = 0;
|
||||||
|
|
||||||
|
foreach ($o->via as $v)
|
||||||
|
{
|
||||||
|
$data = preg_split('/\s/',$v);
|
||||||
|
$ftno = $this->get_node(ftn_address_split($data[0]));
|
||||||
|
unset($data[0]);
|
||||||
|
|
||||||
|
$oo->paths()->attach($ftno->id,['sequence'=>$seq++,'value'=>json_encode($data)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ class Netmail extends Model
|
|||||||
{
|
{
|
||||||
protected $dates = ['date'];
|
protected $dates = ['date'];
|
||||||
protected $fillable = ['date','msgid','from_ftn'];
|
protected $fillable = ['date','msgid','from_ftn'];
|
||||||
|
public $timestamps = FALSE; // @todo Remove, seems an issue with cockroach updating tables.
|
||||||
|
|
||||||
public function kludges()
|
public function kludges()
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Traits;
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
use App\Models\{Node,Zone};
|
use App\Models\{Node,Zone};
|
||||||
|
|
||||||
trait GetNode
|
trait GetNode
|
||||||
@ -10,11 +12,19 @@ trait GetNode
|
|||||||
* Get an FTN record
|
* Get an FTN record
|
||||||
* If the record doesnt exist, we'll create it
|
* If the record doesnt exist, we'll create it
|
||||||
*/
|
*/
|
||||||
protected function get_node($z,$n,$f,$p=0,$create=TRUE)
|
protected function get_node(array $address,$create=TRUE)
|
||||||
{
|
{
|
||||||
|
if (! $z=Arr::get($address,'z'))
|
||||||
|
throw new \Exception('Zone cannot be zero');
|
||||||
|
|
||||||
$zo = Zone::firstOrCreate(['id'=>$z]);
|
$zo = Zone::firstOrCreate(['id'=>$z]);
|
||||||
|
|
||||||
$no = Node::firstOrNew(['zone_id'=>$zo->id,'host_id'=>$n,'node_id'=>$f,'point_id'=>$p]);
|
$no = Node::firstOrNew([
|
||||||
|
'zone_id'=>$zo->id,
|
||||||
|
'host_id'=>Arr::get($address,'n'),
|
||||||
|
'node_id'=>Arr::get($address,'f'),
|
||||||
|
'point_id'=>Arr::get($address,'p',0)
|
||||||
|
]);
|
||||||
|
|
||||||
if (! $no->exists AND $create)
|
if (! $no->exists AND $create)
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ trait ParseNodes
|
|||||||
/**
|
/**
|
||||||
* Parse a seenby or path list and return node models
|
* Parse a seenby or path list and return node models
|
||||||
*/
|
*/
|
||||||
protected function parse_nodes(Zone $zone,string $line,$create=TRUE)
|
protected function parse_nodes(Zone $zo,string $line,$create=TRUE)
|
||||||
{
|
{
|
||||||
$net = FALSE;
|
$net = FALSE;
|
||||||
$result = collect();
|
$result = collect();
|
||||||
@ -24,7 +24,7 @@ trait ParseNodes
|
|||||||
if (! $net)
|
if (! $net)
|
||||||
throw new \Exception('Missing Net?',$node);
|
throw new \Exception('Missing Net?',$node);
|
||||||
|
|
||||||
$result->push($this->get_node($zone->id,$net,$node,0,$create));
|
$result->push($this->get_node(['z'=>$zo->id,'n'=>$net,'f'=>$node,'p'=>0],$create));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Traits;
|
|
||||||
|
|
||||||
trait ParseZNFPDomain
|
|
||||||
{
|
|
||||||
private function parse_znfp_domain(string $data,$create=TRUE)
|
|
||||||
{
|
|
||||||
$z = substr($data,0,strpos($data,':'));
|
|
||||||
|
|
||||||
$x = strpos($data,':')+1;
|
|
||||||
$n = substr($data,$x,strpos($data,'/')-$x);
|
|
||||||
|
|
||||||
$x = strpos($data,'/')+1;
|
|
||||||
$f = substr($data,$x,(strpos($data,'.') OR strpos($data,'@')) ?: strlen($data)-$x);
|
|
||||||
|
|
||||||
$x = strpos($data,'.');
|
|
||||||
$p = $x ? substr($data,$x+1,strpos($data,'@') ?: strlen($data)-$x) : 0;
|
|
||||||
|
|
||||||
// @todo We dont handle domain yet.
|
|
||||||
$x = strpos($data,'@');
|
|
||||||
$d = $x ? substr($data,$x+1) : 0;
|
|
||||||
|
|
||||||
return $this->get_node($z,$n,$f,$p,$create);
|
|
||||||
}
|
|
||||||
}
|
|
@ -51,4 +51,59 @@ if (! function_exists('hex_dump')) {
|
|||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split out an FTN address into its parts
|
||||||
|
*
|
||||||
|
* This function takes a fully qualified FTN address and splits it out into
|
||||||
|
* its components:
|
||||||
|
* Z:N/F.P@D
|
||||||
|
*/
|
||||||
|
if (! function_exists('ftn_address_split')) {
|
||||||
|
function ftn_address_split(string $address,$key=NULL)
|
||||||
|
{
|
||||||
|
if ($key AND ! in_array($key,['z','n','f','p','d']))
|
||||||
|
{
|
||||||
|
throw new \Exception('Unknown key :'.$key.' for '.$address);
|
||||||
|
}
|
||||||
|
|
||||||
|
//$data = "10:12/909";
|
||||||
|
//$data = "10:12/909.5";
|
||||||
|
//$data = "10:12/909@foo";
|
||||||
|
//$data = "10:12/909.5@foo";
|
||||||
|
$z = substr($address,0,strpos($address,':'));
|
||||||
|
|
||||||
|
if ($key == 'z')
|
||||||
|
return $z;
|
||||||
|
|
||||||
|
$x = strpos($address,':')+1;
|
||||||
|
$n = substr($address,$x,strpos($address,'/')-$x);
|
||||||
|
|
||||||
|
if ($key == 'n')
|
||||||
|
return $n;
|
||||||
|
|
||||||
|
$x = strpos($address,'/')+1;
|
||||||
|
$f = substr($address,$x,
|
||||||
|
(strpos($address,'.') ?:
|
||||||
|
(strpos($address,'@') ?: strlen($address)))-$x);
|
||||||
|
|
||||||
|
if ($key == 'f')
|
||||||
|
return $f;
|
||||||
|
|
||||||
|
$x = strpos($address,'.');
|
||||||
|
$p = $x ? substr($address,$x+1,(strpos($address,'@') ?: strlen($address))-$x-1) : 0;
|
||||||
|
|
||||||
|
if ($key == 'p')
|
||||||
|
return $p;
|
||||||
|
|
||||||
|
// @todo We dont handle domain yet.
|
||||||
|
$x = strpos($address,'@');
|
||||||
|
$d = $x ? substr($address,$x+1) : NULL;
|
||||||
|
|
||||||
|
if ($key == 'd')
|
||||||
|
return $d;
|
||||||
|
|
||||||
|
return ['z'=>$z,'n'=>$n,'f'=>$f,'p'=>$p,'d'=>$d];
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3",
|
"php": "^7.1.3",
|
||||||
"fideloper/proxy": "^4.0",
|
"fideloper/proxy": "^4.0",
|
||||||
"laravel/framework": "5.7.*",
|
"laravel/framework": "5.8.*",
|
||||||
"laravel/tinker": "^1.0",
|
"laravel/tinker": "^1.0",
|
||||||
"nbj/cockroachdb-laravel": "^0.0.6@alpha"
|
"nbj/cockroachdb-laravel": "^0.0.6@alpha"
|
||||||
},
|
},
|
||||||
@ -16,8 +16,8 @@
|
|||||||
"filp/whoops": "^2.0",
|
"filp/whoops": "^2.0",
|
||||||
"fzaninotto/faker": "^1.4",
|
"fzaninotto/faker": "^1.4",
|
||||||
"mockery/mockery": "^1.0",
|
"mockery/mockery": "^1.0",
|
||||||
"nunomaduro/collision": "^2.0",
|
"nunomaduro/collision": "^3.0",
|
||||||
"phpunit/phpunit": "^7.0"
|
"phpunit/phpunit": "^7.5"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
|
837
composer.lock
generated
837
composer.lock
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user