clrghouz/app/Classes/FTNPacket.php

266 lines
6.2 KiB
PHP
Raw Normal View History

2019-03-03 14:29:35 +00:00
<?php
namespace App\Classes;
use App\Exceptions\InvalidFidoPacketException;
2019-05-11 01:17:56 +00:00
use Carbon\Carbon;
2019-03-03 14:29:35 +00:00
class FTNPacket extends FTN
{
public $pktsrc = NULL;
public $pktdst = NULL;
private $pktver = NULL;
public $date = NULL;
private $baud = NULL;
2019-05-11 01:17:56 +00:00
private $software = [];
private $cap = [];
2019-03-03 14:29:35 +00:00
private $proddata = NULL;
private $password = NULL;
2019-05-11 01:17:56 +00:00
private $sz = NULL;
private $dz = NULL;
private $sn = NULL;
private $dn = NULL;
private $sf = NULL;
private $df = NULL;
private $sp = NULL;
private $dp = NULL;
2019-03-03 14:29:35 +00:00
public $filename = NULL;
2019-05-11 01:17:56 +00:00
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],
];
2019-03-03 14:29:35 +00:00
2019-05-11 01:17:56 +00:00
public function __construct(string $file=NULL)
2019-03-03 14:29:35 +00:00
{
2019-05-11 01:17:56 +00:00
$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;
2019-03-03 14:29:35 +00:00
return $this->OpenFile($file);
2019-05-11 01:17:56 +00:00
}
}
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);
2019-03-03 14:29:35 +00:00
}
/**
* Open a packet file
*
* @param string $file
* @throws InvalidFidoPacketException
*/
private function OpenFile(string $file)
{
$f = fopen($file,'r');
// $fstat = fstat($f);
// PKT Header
$header = fread($f,0x3a);
// Could not read header
if (strlen($header) != 0x3a)
throw new InvalidFidoPacketException('Length of Header too short: '.$file);
// Not a type 2 packet
if (array_get(unpack('vv',substr($header,0x12)),'v') != 2)
2019-05-11 01:17:56 +00:00
throw new InvalidFidoPacketException('Not a type 2 packet in file: '. $file);
2019-03-03 14:29:35 +00:00
2019-05-11 01:17:56 +00:00
$this->parseHeader($header);
2019-03-03 14:29:35 +00:00
while (! feof($f))
{
$x = fread($f,2);
// End of Packet?
if (strlen($x) == 2 and $x == "\00\00")
{
break;
}
// Messages start with 02H 00H
if (strlen($x) == 2 AND $x != "\02\00")
throw new InvalidFidoPacketException('Not a valid packet: '.$x);
// No message attached
else if (! strlen($x))
break;
$message = new FTNMessage(fread($f,0xc));
2019-05-11 01:17:56 +00:00
$message->date = Carbon::createFromFormat('d M y H:i:s',$this->readnullfield($f));
2019-03-03 14:29:35 +00:00
$message->to = $this->readnullfield($f);
$message->from = $this->readnullfield($f);
$message->subject = $this->readnullfield($f);
2019-05-11 01:17:56 +00:00
$message->parsemessage($this->readnullfield($f));
2019-03-03 14:29:35 +00:00
$this->messages->push($message);
}
}
private function readnullfield($f)
{
$result = '';
while (($x = fgetc($f) OR strlen($x)) AND $x !== "\00")
{
$result .= $x;
}
return $result;
}
2019-05-11 01:17:56 +00:00
private function parseHeader(string $header)
2019-03-03 14:29:35 +00:00
{
2019-05-11 01:17:56 +00:00
$result1 = unpack($this->unpackheader($this->pack1),substr($header,0,0x1a));
$this->password = array_get(unpack('a*p',substr($header,0x1a,8)),'p');
$result2 = unpack($this->unpackheader($this->pack2),substr($header,0x22,0x14));
$this->proddata = array_get(unpack('A*p',substr($header,0x36,4)),'p');
2019-03-03 14:29:35 +00:00
2019-04-27 13:57:39 +00:00
$this->sz = array_get($result2,'ozone');
$this->sn = array_get($result1,'onet');
$this->sf = array_get($result1,'onode');
$this->sp = array_get($result2,'dpoint');
2019-03-03 14:29:35 +00:00
$this->pktsrc = sprintf('%s:%s/%s.%s',
2019-04-27 13:57:39 +00:00
$this->sz,
$this->sn,
$this->sf,
$this->sp
2019-03-03 14:29:35 +00:00
);
2019-04-27 13:57:39 +00:00
$this->dz = array_get($result2,'dzone');
$this->dn = array_get($result1,'dnet');
$this->df = array_get($result1,'dnode');
$this->dp = array_get($result2,'dpoint');
2019-03-03 14:29:35 +00:00
$this->pktdst = sprintf('%s:%s/%s.%s',
2019-04-27 13:57:39 +00:00
$this->dz,
$this->dn,
$this->df,
$this->dp
2019-03-03 14:29:35 +00:00
);
2019-05-11 01:17:56 +00:00
$this->date = Carbon::create(
2019-03-03 14:29:35 +00:00
array_get($result1,'y'),
array_get($result1,'m'),
array_get($result1,'d'),
array_get($result1,'H'),
array_get($result1,'M'),
array_get($result1,'S')
);
$this->baud = array_get($result1,'baud');
$this->pktver = array_get($result1,'pktver');
2019-05-11 01:17:56 +00:00
$this->software['prodcode-lo'] = array_get($result1,'prodcode-lo');
$this->software['prodcode-hi'] = array_get($result2,'prodcode-hi');
$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
2019-03-03 14:29:35 +00:00
}
}