Work with netmail creation
This commit is contained in:
parent
188fd1a2cf
commit
9317f78a3a
@ -6,8 +6,9 @@ use App\Exceptions\InvalidFidoPacketException;
|
|||||||
|
|
||||||
class FTNMessage extends FTN
|
class FTNMessage extends FTN
|
||||||
{
|
{
|
||||||
private $src = NULL;
|
private $_src = NULL;
|
||||||
private $dst = NULL;
|
private $_dst = NULL;
|
||||||
|
|
||||||
private $flags = NULL;
|
private $flags = NULL;
|
||||||
private $cost = 0;
|
private $cost = 0;
|
||||||
|
|
||||||
@ -42,7 +43,36 @@ class FTNMessage extends FTN
|
|||||||
'tid' => 'TID: ',
|
'tid' => 'TID: ',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(string $header)
|
// Flags for messages
|
||||||
|
const FLAG_PRIVATE = 0b1;
|
||||||
|
const FLAG_CRASH = 0b10;
|
||||||
|
const FLAG_RECD = 0b100;
|
||||||
|
const FLAG_SENT = 0b1000;
|
||||||
|
const FLAG_FILEATTACH = 0b10000;
|
||||||
|
const FLAG_INTRANSIT = 0b100000;
|
||||||
|
const FLAG_ORPHAN = 0b1000000;
|
||||||
|
const FLAG_KILLSENT = 0b10000000;
|
||||||
|
const FLAG_LOCAL = 0b100000000;
|
||||||
|
const FLAG_HOLD = 0b1000000000;
|
||||||
|
const FLAG_UNUSED_10 = 0b10000000000;
|
||||||
|
const FLAG_FREQ = 0b100000000000;
|
||||||
|
const FLAG_RETRECEIPT = 0b1000000000000;
|
||||||
|
const FLAG_ISRETRECEIPT = 0b10000000000000;
|
||||||
|
const FLAG_AUDITREQ = 0b100000000000000;
|
||||||
|
const FLAG_FILEUPDATEREQ = 0b1000000000000000;
|
||||||
|
|
||||||
|
// FTS-0001.016 Message header 12 bytes
|
||||||
|
// node, net, flags, cost
|
||||||
|
private $struct = [
|
||||||
|
'onode'=>[0x00,'v',2],
|
||||||
|
'dnode'=>[0x02,'v',2],
|
||||||
|
'onet'=>[0x04,'v',2],
|
||||||
|
'dnet'=>[0x06,'v',2],
|
||||||
|
'flags'=>[0x08,'v',2],
|
||||||
|
'cost'=>[0x0a,'v',2],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(string $header=NULL)
|
||||||
{
|
{
|
||||||
// Initialise vars
|
// Initialise vars
|
||||||
$this->kludge = collect(); // The message kludge lines
|
$this->kludge = collect(); // The message kludge lines
|
||||||
@ -52,39 +82,8 @@ class FTNMessage extends FTN
|
|||||||
$this->_other = collect(); // Temporarily hold attributes we dont process yet.
|
$this->_other = collect(); // Temporarily hold attributes we dont process yet.
|
||||||
$this->unknown = collect(); // Temporarily hold attributes we have no logic for.
|
$this->unknown = collect(); // Temporarily hold attributes we have no logic for.
|
||||||
|
|
||||||
// FTS-0001.016 Message header 12 bytes
|
if ($header)
|
||||||
// node, net, flags, cost
|
$this->parseheader($header);
|
||||||
$struct = [
|
|
||||||
'onode'=>[0x00,'v',2],
|
|
||||||
'dnode'=>[0x02,'v',2],
|
|
||||||
'onet'=>[0x04,'v',2],
|
|
||||||
'dnet'=>[0x06,'v',2],
|
|
||||||
'flags'=>[0x08,'v',2],
|
|
||||||
'cost'=>[0x0a,'v',2],
|
|
||||||
];
|
|
||||||
|
|
||||||
$result = unpack($this->unpackheader($struct),$header);
|
|
||||||
|
|
||||||
// For Echomail this is the packet src.
|
|
||||||
$this->psn = array_get($result,'onet');
|
|
||||||
$this->psf = array_get($result,'onode');
|
|
||||||
|
|
||||||
$this->src = sprintf('%s/%s',
|
|
||||||
$this->psn,
|
|
||||||
$this->psf
|
|
||||||
);
|
|
||||||
|
|
||||||
// For Echomail this is the packet dst.
|
|
||||||
$this->pdn = array_get($result,'dnet');
|
|
||||||
$this->pdf = array_get($result,'dnode');
|
|
||||||
|
|
||||||
$this->dst = sprintf('%s/%s',
|
|
||||||
$this->pdn,
|
|
||||||
$this->pdf
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->flags = array_get($result,'flags');
|
|
||||||
$this->cost = array_get($result,'cost');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($k)
|
public function __get($k)
|
||||||
@ -110,44 +109,138 @@ class FTNMessage extends FTN
|
|||||||
{
|
{
|
||||||
switch ($k)
|
switch ($k)
|
||||||
{
|
{
|
||||||
case 'message':
|
case 'fqfa':
|
||||||
// Remove DOS \n\r
|
case 'fqda':
|
||||||
$v = preg_replace("/\n\r/","\r",$v);
|
$this->{$k} = $v;
|
||||||
|
|
||||||
$this->parsemessage($v);
|
if ($this->fqfa AND $this->fqda)
|
||||||
break;
|
$this->intl = sprintf('%s %s',$this->fqda,$this->fqfa);
|
||||||
|
|
||||||
case 'origin':
|
|
||||||
$this->parseorigin($v);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->{$k} = $v;
|
$this->{$k} = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function znfp(string $data,string $key)
|
/**
|
||||||
|
* Export an FTN message, ready for sending.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
switch ($key) {
|
$return = '';
|
||||||
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:
|
$return .= pack(join('',collect($this->struct)->pluck(1)->toArray()),
|
||||||
abort(500,'Unknown key: '.$key);
|
$this->ff,
|
||||||
|
$this->tf,
|
||||||
|
$this->fn,
|
||||||
|
$this->tn,
|
||||||
|
$this->flags,
|
||||||
|
0 // @todo cost
|
||||||
|
);
|
||||||
|
|
||||||
|
// @todo use pack for this.
|
||||||
|
$return .= $this->date->format('d M y H:i:s')."\00";
|
||||||
|
$return .= $this->to."\00";
|
||||||
|
$return .= $this->from."\00";
|
||||||
|
$return .= $this->subject."\00";
|
||||||
|
$return .= $this->message."\00";
|
||||||
|
|
||||||
|
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 array
|
||||||
|
*
|
||||||
|
* http://ftsc.org/docs/fsc-0001.000
|
||||||
|
* AttributeWord bit meaning
|
||||||
|
--- --------------------
|
||||||
|
0 + Private
|
||||||
|
1 + s Crash
|
||||||
|
2 Recd
|
||||||
|
3 Sent
|
||||||
|
4 + FileAttached
|
||||||
|
5 InTransit
|
||||||
|
6 Orphan
|
||||||
|
7 KillSent
|
||||||
|
8 Local
|
||||||
|
9 s HoldForPickup
|
||||||
|
10 + unused
|
||||||
|
11 s FileRequest
|
||||||
|
12 + s ReturnReceiptRequest
|
||||||
|
13 + s IsReturnReceipt
|
||||||
|
14 + s AuditRequest
|
||||||
|
15 s FileUpdateReq
|
||||||
|
|
||||||
|
s - this bit is supported by SEAdog only
|
||||||
|
+ - this bit is not zeroed before packeting
|
||||||
|
*/
|
||||||
|
public function flags(int $flags): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'private'=>$this->isFlagSet($flags,self::FLAG_PRIVATE),
|
||||||
|
'crash'=>$this->isFlagSet($flags,self::FLAG_CRASH),
|
||||||
|
'recd'=>$this->isFlagSet($flags,self::FLAG_RECD),
|
||||||
|
'sent'=>$this->isFlagSet($flags,self::FLAG_SENT),
|
||||||
|
'killsent'=>$this->isFlagSet($flags,self::FLAG_KILLSENT),
|
||||||
|
'local'=>$this->isFlagSet($flags,self::FLAG_LOCAL),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isFlagSet($value,$flag)
|
||||||
|
{
|
||||||
|
return (($value & $flag) == $flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the head of an FTN message
|
||||||
|
*
|
||||||
|
* @param string $header
|
||||||
|
*/
|
||||||
|
public function parseheader(string $header)
|
||||||
|
{
|
||||||
|
$result = unpack($this->unpackheader($this->struct),$header);
|
||||||
|
|
||||||
|
// For Echomail this is the packet src.
|
||||||
|
$this->psn = array_get($result,'onet');
|
||||||
|
$this->psf = array_get($result,'onode');
|
||||||
|
|
||||||
|
$this->_src = sprintf('%s/%s',
|
||||||
|
$this->psn,
|
||||||
|
$this->psf
|
||||||
|
);
|
||||||
|
|
||||||
|
// For Echomail this is the packet dst.
|
||||||
|
$this->pdn = array_get($result,'dnet');
|
||||||
|
$this->pdf = array_get($result,'dnode');
|
||||||
|
|
||||||
|
$this->_dst = sprintf('%s/%s',
|
||||||
|
$this->pdn,
|
||||||
|
$this->pdf
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->flags = array_get($result,'flags');
|
||||||
|
$this->cost = array_get($result,'cost');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parsemessage(string $message)
|
public function parsemessage(string $message)
|
||||||
{
|
{
|
||||||
|
// Remove DOS \n\r
|
||||||
|
$message = preg_replace("/\n\r/","\r",$message);
|
||||||
|
|
||||||
// Split out the <SOH> lines
|
// Split out the <SOH> lines
|
||||||
$result = collect(explode("\01",$message))->filter();
|
$result = collect(explode("\01",$message))->filter();
|
||||||
|
|
||||||
@ -165,7 +258,7 @@ class FTNMessage extends FTN
|
|||||||
if ($y = strpos($v,"\r * Origin: "))
|
if ($y = strpos($v,"\r * Origin: "))
|
||||||
{
|
{
|
||||||
$this->message .= substr($v,$x+1,$y-$x-1);
|
$this->message .= substr($v,$x+1,$y-$x-1);
|
||||||
$this->__set('origin',substr($v,$y));
|
$this->parseorigin(substr($v,$y));
|
||||||
$matches = [];
|
$matches = [];
|
||||||
|
|
||||||
preg_match('/^.*\((.*)\)$/',$this->origin,$matches);
|
preg_match('/^.*\((.*)\)$/',$this->origin,$matches);
|
||||||
@ -245,7 +338,7 @@ class FTNMessage extends FTN
|
|||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
*/
|
*/
|
||||||
public function parseorigin(string $message)
|
private function parseorigin(string $message)
|
||||||
{
|
{
|
||||||
// Split out each line
|
// Split out each line
|
||||||
$result = collect(explode("\r",$message))->filter();
|
$result = collect(explode("\r",$message))->filter();
|
||||||
@ -277,17 +370,6 @@ class FTNMessage extends FTN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function type()
|
public function type()
|
||||||
{
|
{
|
||||||
if ($this->echoarea)
|
if ($this->echoarea)
|
||||||
@ -298,4 +380,24 @@ class FTNMessage extends FTN
|
|||||||
|
|
||||||
return 'UNKNOWN';
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Classes;
|
namespace App\Classes;
|
||||||
|
|
||||||
use App\Exceptions\InvalidFidoPacketException;
|
use App\Exceptions\InvalidFidoPacketException;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class FTNPacket extends FTN
|
class FTNPacket extends FTN
|
||||||
{
|
{
|
||||||
@ -11,19 +12,142 @@ class FTNPacket extends FTN
|
|||||||
private $pktver = NULL;
|
private $pktver = NULL;
|
||||||
public $date = NULL;
|
public $date = NULL;
|
||||||
private $baud = NULL;
|
private $baud = NULL;
|
||||||
|
private $software = [];
|
||||||
|
private $cap = [];
|
||||||
private $proddata = NULL;
|
private $proddata = NULL;
|
||||||
private $password = NULL;
|
private $password = NULL;
|
||||||
|
|
||||||
public $filename = NULL;
|
private $sz = NULL;
|
||||||
public $messages = [];
|
private $dz = NULL;
|
||||||
|
private $sn = NULL;
|
||||||
|
private $dn = NULL;
|
||||||
|
private $sf = NULL;
|
||||||
|
private $df = NULL;
|
||||||
|
private $sp = NULL;
|
||||||
|
private $dp = NULL;
|
||||||
|
|
||||||
public function __construct(string $file)
|
public $filename = NULL;
|
||||||
|
public $messages = NULL;
|
||||||
|
|
||||||
|
// First part of header
|
||||||
|
private $pack1 = [
|
||||||
|
'onode'=>[0x00,'v',2],
|
||||||
|
'dnode'=>[0x02,'v',2],
|
||||||
|
'y'=>[0x04,'v',2],
|
||||||
|
'm'=>[0x06,'v',2],
|
||||||
|
'd'=>[0x08,'v',2],
|
||||||
|
'H'=>[0x0a,'v',2],
|
||||||
|
'M'=>[0x0c,'v',2],
|
||||||
|
'S'=>[0x0e,'v',2],
|
||||||
|
'baud'=>[0x10,'v',2],
|
||||||
|
'pktver'=>[0x12,'v',2],
|
||||||
|
'onet'=>[0x14,'v',2],
|
||||||
|
'dnet'=>[0x16,'v',2],
|
||||||
|
'prodcode-lo'=>[0x18,'C',1],
|
||||||
|
'prodrev-maj'=>[0x19,'C',1],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Second part of header
|
||||||
|
private $pack2 = [
|
||||||
|
'qozone'=>[0x22,'v',2],
|
||||||
|
'qdzone'=>[0x24,'v',2],
|
||||||
|
'filler'=>[0x26,'v',2],
|
||||||
|
'capvalid'=>[0x28,'v',2],
|
||||||
|
'prodcode-hi'=>[0x2a,'C',1],
|
||||||
|
'prodrev-min'=>[0x2b,'C',1],
|
||||||
|
'capword'=>[0x2c,'v',1],
|
||||||
|
'ozone'=>[0x2e,'v',2],
|
||||||
|
'dzone'=>[0x30,'v',2],
|
||||||
|
'opoint'=>[0x32,'v',2],
|
||||||
|
'dpoint'=>[0x34,'v',2],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(string $file=NULL)
|
||||||
{
|
{
|
||||||
|
$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) {
|
||||||
$this->filename = $file;
|
$this->filename = $file;
|
||||||
|
|
||||||
if ($file)
|
|
||||||
return $this->OpenFile($file);
|
return $this->OpenFile($file);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
$return = $this->createHeader();
|
||||||
|
|
||||||
|
foreach ($this->messages as $o)
|
||||||
|
$return .= "\02\00".(string)$o;
|
||||||
|
|
||||||
|
$return .= "\00\00";
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create our message packet header
|
||||||
|
*/
|
||||||
|
private function createHeader(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$a = pack(join('',collect($this->pack1)->pluck(1)->toArray()),
|
||||||
|
$this->sf,
|
||||||
|
$this->df,
|
||||||
|
$this->date->year,
|
||||||
|
$this->date->month,
|
||||||
|
$this->date->day,
|
||||||
|
$this->date->hour,
|
||||||
|
$this->date->minute,
|
||||||
|
$this->date->second,
|
||||||
|
$this->baud,
|
||||||
|
$this->pktver,
|
||||||
|
$this->sn,
|
||||||
|
$this->dn,
|
||||||
|
$this->software['prodcode-lo'], // @todo change to this software
|
||||||
|
$this->software['rev-maj'] // @todo change to this software
|
||||||
|
);
|
||||||
|
|
||||||
|
$b = pack(join('',collect($this->pack2)->pluck(1)->toArray()),
|
||||||
|
$this->sz,
|
||||||
|
$this->dz,
|
||||||
|
0x00, // Baud
|
||||||
|
$this->cap['valid'], // @todo to check
|
||||||
|
$this->software['prodcode-hi'], // @todo change to this software
|
||||||
|
$this->software['rev-min'], // @todo change to this software
|
||||||
|
$this->cap['word'], // @todo to check
|
||||||
|
$this->sz,
|
||||||
|
$this->dz,
|
||||||
|
$this->sp,
|
||||||
|
$this->dp
|
||||||
|
);
|
||||||
|
|
||||||
|
return $a.pack('a8',$this->password).$b."mbse"; // @todo change to this software
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addMessage(FTNMessage $o)
|
||||||
|
{
|
||||||
|
$this->messages->push($o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dump()
|
||||||
|
{
|
||||||
|
return hex_dump((string)$this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a packet file
|
* Open a packet file
|
||||||
@ -45,10 +169,9 @@ class FTNPacket extends FTN
|
|||||||
|
|
||||||
// Not a type 2 packet
|
// Not a type 2 packet
|
||||||
if (array_get(unpack('vv',substr($header,0x12)),'v') != 2)
|
if (array_get(unpack('vv',substr($header,0x12)),'v') != 2)
|
||||||
throw new InvalidFidoPacketException('Not a type 2 packet:'. $file);
|
throw new InvalidFidoPacketException('Not a type 2 packet in file: '. $file);
|
||||||
|
|
||||||
$this->setHeader($header);
|
$this->parseHeader($header);
|
||||||
$this->messages = collect();
|
|
||||||
|
|
||||||
while (! feof($f))
|
while (! feof($f))
|
||||||
{
|
{
|
||||||
@ -69,11 +192,12 @@ class FTNPacket extends FTN
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
$message = new FTNMessage(fread($f,0xc));
|
$message = new FTNMessage(fread($f,0xc));
|
||||||
$message->date = $this->readnullfield($f);
|
$message->date = Carbon::createFromFormat('d M y H:i:s',$this->readnullfield($f));
|
||||||
$message->to = $this->readnullfield($f);
|
$message->to = $this->readnullfield($f);
|
||||||
$message->from = $this->readnullfield($f);
|
$message->from = $this->readnullfield($f);
|
||||||
$message->subject = $this->readnullfield($f);
|
$message->subject = $this->readnullfield($f);
|
||||||
$message->message = $this->readnullfield($f);
|
|
||||||
|
$message->parsemessage($this->readnullfield($f));
|
||||||
|
|
||||||
$this->messages->push($message);
|
$this->messages->push($message);
|
||||||
}
|
}
|
||||||
@ -91,41 +215,12 @@ class FTNPacket extends FTN
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setHeader(string $header)
|
private function parseHeader(string $header)
|
||||||
{
|
{
|
||||||
$pack1 = [
|
$result1 = unpack($this->unpackheader($this->pack1),substr($header,0,0x1a));
|
||||||
'onode'=>[0x00,'v',2],
|
$this->password = array_get(unpack('a*p',substr($header,0x1a,8)),'p');
|
||||||
'dnode'=>[0x02,'v',2],
|
$result2 = unpack($this->unpackheader($this->pack2),substr($header,0x22,0x14));
|
||||||
'y'=>[0x04,'v',2],
|
$this->proddata = array_get(unpack('A*p',substr($header,0x36,4)),'p');
|
||||||
'm'=>[0x06,'v',2],
|
|
||||||
'd'=>[0x08,'v',2],
|
|
||||||
'H'=>[0x0a,'v',2],
|
|
||||||
'M'=>[0x0c,'v',2],
|
|
||||||
'S'=>[0x0e,'v',2],
|
|
||||||
'baud'=>[0x10,'v',2],
|
|
||||||
'pktver'=>[0x12,'v',2],
|
|
||||||
'onet'=>[0x14,'v',2],
|
|
||||||
'dnet'=>[0x16,'v',2],
|
|
||||||
'prodcode-lo'=>[0x18,'C',1],
|
|
||||||
'prodrev-maj'=>[0x19,'C',1],
|
|
||||||
];
|
|
||||||
|
|
||||||
$pack2 = [
|
|
||||||
'qozone'=>[0x22,'v',2],
|
|
||||||
'qdzone'=>[0x24,'v',2],
|
|
||||||
'filler'=>[0x26,'v',2],
|
|
||||||
'capvalid'=>[0x28,'v',2],
|
|
||||||
'prodcode-hi'=>[0x2a,'C',1],
|
|
||||||
'prodrev-min'=>[0x2b,'C',1],
|
|
||||||
'capword'=>[0x2c,'v',1],
|
|
||||||
'ozone'=>[0x2e,'v',2],
|
|
||||||
'dzone'=>[0x30,'v',2],
|
|
||||||
'opoint'=>[0x32,'v',2],
|
|
||||||
'dpoint'=>[0x34,'v',2],
|
|
||||||
];
|
|
||||||
|
|
||||||
$result1 = unpack($this->unpackheader($pack1),substr($header,0,0x1a));
|
|
||||||
$result2 = unpack($this->unpackheader($pack2),substr($header,0x22,0x14));
|
|
||||||
|
|
||||||
$this->sz = array_get($result2,'ozone');
|
$this->sz = array_get($result2,'ozone');
|
||||||
$this->sn = array_get($result1,'onet');
|
$this->sn = array_get($result1,'onet');
|
||||||
@ -149,7 +244,7 @@ class FTNPacket extends FTN
|
|||||||
$this->dp
|
$this->dp
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->date = sprintf ('%d-%d-%d %d:%d:%d',
|
$this->date = Carbon::create(
|
||||||
array_get($result1,'y'),
|
array_get($result1,'y'),
|
||||||
array_get($result1,'m'),
|
array_get($result1,'m'),
|
||||||
array_get($result1,'d'),
|
array_get($result1,'d'),
|
||||||
@ -160,8 +255,12 @@ class FTNPacket extends FTN
|
|||||||
|
|
||||||
$this->baud = array_get($result1,'baud');
|
$this->baud = array_get($result1,'baud');
|
||||||
$this->pktver = array_get($result1,'pktver');
|
$this->pktver = array_get($result1,'pktver');
|
||||||
|
$this->software['prodcode-lo'] = array_get($result1,'prodcode-lo');
|
||||||
$this->password = array_get(unpack('A*p',substr($header,0x1a,8)),'p');
|
$this->software['prodcode-hi'] = array_get($result2,'prodcode-hi');
|
||||||
$this->proddata = array_get(unpack('A*p',substr($header,0x36,4)),'p');
|
$this->software['rev-maj'] = array_get($result1,'prodrev-maj');
|
||||||
|
$this->software['rev-min'] = array_get($result2,'prodrev-min');
|
||||||
|
$this->cap['valid'] = array_get($result2,'capvalid');
|
||||||
|
$this->cap['word'] = array_get($result2,'capword');
|
||||||
|
// @todo filler
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ class FtnPkt extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'ftn:pkt {file : Fidonet Packet File PKT} {--dump : Dump packet}';
|
protected $signature = 'ftn:pkt {file : Fidonet Packet File PKT} {--dump : Dump packet} {--detail : Dump Detail}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
@ -51,21 +51,23 @@ class FtnPkt extends Command
|
|||||||
|
|
||||||
foreach ($pkt->messages as $o)
|
foreach ($pkt->messages as $o)
|
||||||
{
|
{
|
||||||
$this->warn(sprintf('-- From: %s(%s)->%s(%s), Type: %s, Size: %d, FQFA: %s',
|
$this->warn(sprintf('-- From: %s(%s)->%s(%s), Type: %s, Size: %d',
|
||||||
$o->from,
|
$o->from,
|
||||||
$o->src,
|
$o->fqfa,
|
||||||
$o->to,
|
$o->to,
|
||||||
$o->dst,
|
$o->fqda,
|
||||||
$o->description(),
|
$o->description(),
|
||||||
strlen($o->message),
|
strlen($o->message)
|
||||||
$o->fqfa
|
|
||||||
));
|
));
|
||||||
|
|
||||||
if ($o->unknown->count())
|
if ($o->unknown->count())
|
||||||
$this->error(sprintf('?? %s Unknown headers',$o->unknown->count()));
|
$this->error(sprintf('?? %s Unknown headers',$o->unknown->count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->option('detail'))
|
||||||
|
dd($o);
|
||||||
|
|
||||||
if ($this->option('dump'))
|
if ($this->option('dump'))
|
||||||
dump($o);
|
echo $pkt->dump();
|
||||||
}
|
}
|
||||||
}
|
}
|
54
app/helpers.php
Normal file
54
app/helpers.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate CCITT-CRC16 checksum
|
||||||
|
*/
|
||||||
|
if (! function_exists('crc16')) {
|
||||||
|
function crc16($data)
|
||||||
|
{
|
||||||
|
$crc = 0x0000;
|
||||||
|
for ($i = 0; $i < strlen($data); $i++)
|
||||||
|
{
|
||||||
|
$x = (($crc >> 8) ^ ord($data[$i])) & 0xFF;
|
||||||
|
$x ^= $x >> 4;
|
||||||
|
$crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x) & 0xFFFF;
|
||||||
|
}
|
||||||
|
return $crc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump out data into a hex dump
|
||||||
|
*/
|
||||||
|
if (! function_exists('hex_dump')) {
|
||||||
|
function hex_dump($data,$newline="\n",$width=16)
|
||||||
|
{
|
||||||
|
$result = '';
|
||||||
|
|
||||||
|
$pad = '.'; # padding for non-visible characters
|
||||||
|
$to = $from = '';
|
||||||
|
|
||||||
|
for ($i=0; $i<=0xFF; $i++)
|
||||||
|
{
|
||||||
|
$from .= chr($i);
|
||||||
|
$to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hex = str_split(bin2hex($data),$width*2);
|
||||||
|
$chars = str_split(strtr($data,$from,$to),$width);
|
||||||
|
|
||||||
|
$offset = 0;
|
||||||
|
foreach ($hex as $i => $line)
|
||||||
|
{
|
||||||
|
$result .= sprintf('%08X: %-48s [%s]%s',
|
||||||
|
$offset,
|
||||||
|
substr_replace(implode(' ',str_split($line,2)),' ',8*3,0),
|
||||||
|
$chars[$i],
|
||||||
|
$newline);
|
||||||
|
|
||||||
|
$offset += $width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,9 @@
|
|||||||
"phpunit/phpunit": "^7.0"
|
"phpunit/phpunit": "^7.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"app/helpers.php"
|
||||||
|
],
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"database/seeds",
|
"database/seeds",
|
||||||
"database/factories"
|
"database/factories"
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::get('/', function () {
|
#Route::get('/', function () {
|
||||||
return view('welcome');
|
# return view('welcome');
|
||||||
});
|
#});
|
||||||
|
Loading…
Reference in New Issue
Block a user