Changed to using new Address Model, Implemented Setup, Some minor CSS changes
This commit is contained in:
parent
ec6594b701
commit
d1ca78d372
@ -3,12 +3,11 @@
|
|||||||
namespace App\Classes;
|
namespace App\Classes;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
use App\Models\Node as NodeModel;
|
use App\Models\Address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object representing the node we are communicating with
|
* Object representing the node we are communicating with
|
||||||
@ -64,7 +63,7 @@ class Node
|
|||||||
|
|
||||||
// The nodes password
|
// The nodes password
|
||||||
case 'password':
|
case 'password':
|
||||||
return ($this->ftns_authed->count() && $x=$this->ftns_authed->first()->sespass) ? $x : '-';
|
return ($this->ftns_authed->count() && ($x=$this->ftns_authed->first()->session('sespass'))) ? $x : '-';
|
||||||
|
|
||||||
// Return how long our session has been connected
|
// Return how long our session has been connected
|
||||||
case 'session_time':
|
case 'session_time':
|
||||||
@ -102,8 +101,8 @@ class Node
|
|||||||
{
|
{
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'ftn':
|
case 'ftn':
|
||||||
if (! is_object($value) OR ! $value instanceof NodeModel)
|
if (! is_object($value) OR ! $value instanceof Address)
|
||||||
throw new Exception('Not a node object: '.(is_object($value) ? get_class($value) : serialize($value)));
|
throw new Exception('Not an Address object: '.(is_object($value) ? get_class($value) : serialize($value)));
|
||||||
|
|
||||||
// Ignore any duplicate FTNs that we get
|
// Ignore any duplicate FTNs that we get
|
||||||
if ($this->ftns->search(function($item) use ($value) { return $item->id === $value->id; }) !== FALSE) {
|
if ($this->ftns->search(function($item) use ($value) { return $item->id === $value->id; }) !== FALSE) {
|
||||||
@ -154,11 +153,11 @@ class Node
|
|||||||
throw new Exception('Already authed');
|
throw new Exception('Already authed');
|
||||||
|
|
||||||
foreach ($this->ftns as $o) {
|
foreach ($this->ftns as $o) {
|
||||||
if (! $o->sespass)
|
if (! $o->session('sespass'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If we have challenge, then we are doing MD5
|
// If we have challenge, then we are doing MD5
|
||||||
$exp_pwd = $challenge ? $this->md5_challenge($o->sespass,$challenge) : $o->sespass;
|
$exp_pwd = $challenge ? $this->md5_challenge($o->session('sespass'),$challenge) : $o->session('sespass');
|
||||||
|
|
||||||
if ($exp_pwd === $password)
|
if ($exp_pwd === $password)
|
||||||
$this->ftns_authed->push($o);
|
$this->ftns_authed->push($o);
|
||||||
@ -208,11 +207,10 @@ class Node
|
|||||||
* When we originate a call to a node, we need to store the node we are connecting with in the ftns_authed, so
|
* When we originate a call to a node, we need to store the node we are connecting with in the ftns_authed, so
|
||||||
* authentication proceeds when we send our M_pwd
|
* authentication proceeds when we send our M_pwd
|
||||||
*
|
*
|
||||||
* @param NodeModel $o
|
* @param Address $o
|
||||||
*/
|
*/
|
||||||
public function originate(NodeModel $o): void
|
public function originate(Address $o): void
|
||||||
{
|
{
|
||||||
$this->ftns->push($o);
|
|
||||||
$this->ftns_authed->push($o);
|
$this->ftns_authed->push($o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,7 @@ use Illuminate\Support\Facades\Log;
|
|||||||
use App\Classes\File\{Receive,Send};
|
use App\Classes\File\{Receive,Send};
|
||||||
use App\Classes\Sock\SocketClient;
|
use App\Classes\Sock\SocketClient;
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Models\Node as NodeModel;
|
use App\Models\{Address,Setup};
|
||||||
use App\Models\Setup;
|
|
||||||
|
|
||||||
abstract class Protocol
|
abstract class Protocol
|
||||||
{
|
{
|
||||||
@ -79,7 +78,7 @@ abstract class Protocol
|
|||||||
protected const MO_CHAT = 4;
|
protected const MO_CHAT = 4;
|
||||||
|
|
||||||
protected SocketClient $client; /* Our socket details */
|
protected SocketClient $client; /* Our socket details */
|
||||||
protected Setup $setup; /* Our setup */
|
protected ?Setup $setup; /* Our setup */
|
||||||
protected Node $node; /* The node we are communicating with */
|
protected Node $node; /* The node we are communicating with */
|
||||||
protected Send $send; /* The list of files we are sending */
|
protected Send $send; /* The list of files we are sending */
|
||||||
protected Receive $recv; /* The list of files we are receiving */
|
protected Receive $recv; /* The list of files we are receiving */
|
||||||
@ -92,6 +91,14 @@ abstract class Protocol
|
|||||||
abstract protected function protocol_init(): int;
|
abstract protected function protocol_init(): int;
|
||||||
abstract protected function protocol_session(): int;
|
abstract protected function protocol_session(): int;
|
||||||
|
|
||||||
|
public function __construct(Setup $o=NULL)
|
||||||
|
{
|
||||||
|
if ($o && ! $o->system->addresses->count())
|
||||||
|
throw new Exception('We dont have any FTN addresses assigned');
|
||||||
|
|
||||||
|
$this->setup = $o;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@ -181,11 +188,11 @@ abstract class Protocol
|
|||||||
*
|
*
|
||||||
* @param int $type
|
* @param int $type
|
||||||
* @param SocketClient $client
|
* @param SocketClient $client
|
||||||
* @param NodeModel|null $o
|
* @param Address|null $o
|
||||||
* @return int
|
* @return int
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function session(int $type,SocketClient $client,NodeModel $o=NULL): int
|
public function session(int $type,SocketClient $client,Address $o=NULL): int
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('%s: + Start [%d]',__METHOD__,$type));
|
Log::debug(sprintf('%s: + Start [%d]',__METHOD__,$type));
|
||||||
|
|
||||||
@ -198,9 +205,6 @@ abstract class Protocol
|
|||||||
$this->recv = new Receive;
|
$this->recv = new Receive;
|
||||||
|
|
||||||
if ($o) {
|
if ($o) {
|
||||||
// Our configuration and initialise values
|
|
||||||
$this->setup = Setup::findOrFail(self::setup);
|
|
||||||
|
|
||||||
// The node we are communicating with
|
// The node we are communicating with
|
||||||
$this->node = new Node;
|
$this->node = new Node;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use League\Flysystem\UnreadableFileException;
|
|||||||
use App\Classes\Protocol as BaseProtocol;
|
use App\Classes\Protocol as BaseProtocol;
|
||||||
use App\Classes\Sock\SocketClient;
|
use App\Classes\Sock\SocketClient;
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Models\Node;
|
use App\Models\Address;
|
||||||
|
|
||||||
final class Binkd extends BaseProtocol
|
final class Binkd extends BaseProtocol
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ final class Binkd extends BaseProtocol
|
|||||||
{
|
{
|
||||||
// If our parent returns a PID, we've forked
|
// If our parent returns a PID, we've forked
|
||||||
if (! parent::onConnect($client)) {
|
if (! parent::onConnect($client)) {
|
||||||
$this->session(self::SESSION_BINKP,$client,(new Node));
|
$this->session(self::SESSION_BINKP,$client,(new Address));
|
||||||
$this->client->close();
|
$this->client->close();
|
||||||
Log::info(sprintf('%s: = End - Connection closed [%s]',__METHOD__,$client->getAddress()));
|
Log::info(sprintf('%s: = End - Connection closed [%s]',__METHOD__,$client->getAddress()));
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ final class Binkd extends BaseProtocol
|
|||||||
// If we are originating, we'll show the remote our address in the same network
|
// If we are originating, we'll show the remote our address in the same network
|
||||||
// @todo Implement hiding our AKAs not in this network.
|
// @todo Implement hiding our AKAs not in this network.
|
||||||
if ($this->originate)
|
if ($this->originate)
|
||||||
$this->msgs(self::BPM_ADR,join(' ',$this->setup->nodes->pluck('ftn')->toArray()));
|
$this->msgs(self::BPM_ADR,join(' ',$this->setup->system->addresses->pluck('ftn')->toArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -291,6 +291,7 @@ final class Binkd extends BaseProtocol
|
|||||||
// @todo We maybe should count these and abort if there are too many?
|
// @todo We maybe should count these and abort if there are too many?
|
||||||
if ($this->DEBUG)
|
if ($this->DEBUG)
|
||||||
Log::debug(sprintf('%s: - Socket EAGAIN',__METHOD__));
|
Log::debug(sprintf('%s: - Socket EAGAIN',__METHOD__));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +305,7 @@ final class Binkd extends BaseProtocol
|
|||||||
// @todo Check that this is correct.
|
// @todo Check that this is correct.
|
||||||
Log::debug(sprintf('%s: - Was the socket closed by the remote?',__METHOD__));
|
Log::debug(sprintf('%s: - Was the socket closed by the remote?',__METHOD__));
|
||||||
$this->error = -2;
|
$this->error = -2;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,7 +594,7 @@ final class Binkd extends BaseProtocol
|
|||||||
Log::debug(sprintf('%s: - Parsing AKA [%s]',__METHOD__,$rem_aka));
|
Log::debug(sprintf('%s: - Parsing AKA [%s]',__METHOD__,$rem_aka));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (! ($o = Node::findFTN($rem_aka))) {
|
if (! ($o = Address::findFTN($rem_aka))) {
|
||||||
Log::debug(sprintf('%s: ? AKA is UNKNOWN [%s]',__METHOD__,$rem_aka));
|
Log::debug(sprintf('%s: ? AKA is UNKNOWN [%s]',__METHOD__,$rem_aka));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -608,10 +610,10 @@ final class Binkd extends BaseProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the remote has our AKA
|
// Check if the remote has our AKA
|
||||||
if ($this->setup->nodes->pluck('ftn')->search($o->ftn) !== FALSE) {
|
if ($this->setup->system->addresses->pluck('ftn')->search($rem_aka) !== FALSE) {
|
||||||
Log::error(sprintf('%s: ! AKA is OURS [%s]',__METHOD__,$o->ftn));
|
Log::error(sprintf('%s: ! AKA is OURS [%s]',__METHOD__,$rem_aka));
|
||||||
|
|
||||||
$this->msgs(self::BPM_ERR,sprintf('Sorry that is my AKA [%s]',$o->ftn));
|
$this->msgs(self::BPM_ERR,sprintf('Sorry that is my AKA [%s]',$rem_aka));
|
||||||
$this->rc = self::S_FAILURE;
|
$this->rc = self::S_FAILURE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -671,7 +673,7 @@ final class Binkd extends BaseProtocol
|
|||||||
// If we are not the originator, we'll show our addresses in common.
|
// If we are not the originator, we'll show our addresses in common.
|
||||||
// @todo make this an option to hideAKAs or not
|
// @todo make this an option to hideAKAs or not
|
||||||
if (! $this->originate)
|
if (! $this->originate)
|
||||||
$this->msgs(self::BPM_ADR,join(' ',$this->setup->nodes->pluck('ftn')->toArray()));
|
$this->msgs(self::BPM_ADR,join(' ',$this->setup->system->addresses->pluck('ftn')->toArray()));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Log;
|
|||||||
use App\Classes\Protocol as BaseProtocol;
|
use App\Classes\Protocol as BaseProtocol;
|
||||||
use App\Classes\Sock\SocketClient;
|
use App\Classes\Sock\SocketClient;
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Models\Node;
|
use App\Models\Address;
|
||||||
use App\Interfaces\CRC as CRCInterface;
|
use App\Interfaces\CRC as CRCInterface;
|
||||||
use App\Interfaces\Zmodem as ZmodemInterface;
|
use App\Interfaces\Zmodem as ZmodemInterface;
|
||||||
use App\Traits\CRC as CRCTrait;
|
use App\Traits\CRC as CRCTrait;
|
||||||
@ -80,7 +80,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
{
|
{
|
||||||
// If our parent returns a PID, we've forked
|
// If our parent returns a PID, we've forked
|
||||||
if (! parent::onConnect($client)) {
|
if (! parent::onConnect($client)) {
|
||||||
$this->session(self::SESSION_AUTO,$client,(new Node));
|
$this->session(self::SESSION_AUTO,$client,(new Address));
|
||||||
$this->client->close();
|
$this->client->close();
|
||||||
Log::info(sprintf('%s: = End - Connection closed [%s]',__METHOD__,$client->getAddress()));
|
Log::info(sprintf('%s: = End - Connection closed [%s]',__METHOD__,$client->getAddress()));
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
// Site address, password and compatibility
|
// Site address, password and compatibility
|
||||||
// @todo Only show the AKAs that is relevant to the node we are connecting to
|
// @todo Only show the AKAs that is relevant to the node we are connecting to
|
||||||
$makedata .= sprintf('{EMSI}{%s}{%s}{%s}{%s}',
|
$makedata .= sprintf('{EMSI}{%s}{%s}{%s}{%s}',
|
||||||
join(' ',$this->setup->nodes->pluck('ftn')->toArray()),
|
join(' ',$this->setup->system->addresses->pluck('ftn')->toArray()),
|
||||||
$this->node->password == '-' ? '' : $this->node->password,
|
$this->node->password == '-' ? '' : $this->node->password,
|
||||||
join(',',$link_codes),
|
join(',',$link_codes),
|
||||||
join(',',$compat_codes),
|
join(',',$compat_codes),
|
||||||
@ -295,7 +295,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
Log::debug(sprintf('%s: - Parsing AKA [%s]',__METHOD__,$rem_aka));
|
Log::debug(sprintf('%s: - Parsing AKA [%s]',__METHOD__,$rem_aka));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (! ($o = Node::findFTN($rem_aka))) {
|
if (! ($o = Address::findFTN($rem_aka))) {
|
||||||
Log::debug(sprintf('%s: ? AKA is UNKNOWN [%s]',__METHOD__,$rem_aka));
|
Log::debug(sprintf('%s: ? AKA is UNKNOWN [%s]',__METHOD__,$rem_aka));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -307,7 +307,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the remote has our AKA
|
// Check if the remote has our AKA
|
||||||
if ($this->setup->nodes->pluck('ftn')->search($o->ftn) !== FALSE) {
|
if ($this->setup->system->addresses->pluck('ftn')->search($o->ftn) !== FALSE) {
|
||||||
Log::error(sprintf('%s: ! AKA is OURS [%s]',__METHOD__,$o->ftn));
|
Log::error(sprintf('%s: ! AKA is OURS [%s]',__METHOD__,$o->ftn));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -338,9 +338,9 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! $c) {
|
if (! $c) {
|
||||||
Log::info(sprintf('%s: - Remote has password [%s] on us',__METHOD__,$p));
|
Log::info(sprintf('%s: - Remote has password [%s] on us, and we expect [%s]',__METHOD__,$p,$this->node->password));
|
||||||
|
|
||||||
if ($p)
|
if ($p || $this->node->password)
|
||||||
$this->node->optionSet(self::O_BAD);
|
$this->node->optionSet(self::O_BAD);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -861,7 +861,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
if ($gotreq++)
|
if ($gotreq++)
|
||||||
return self::OK;
|
return self::OK;
|
||||||
|
|
||||||
$this->client->buffer_add(self::EMSI_INQ);
|
$this->client->buffer_add(self::EMSI_INQ.self::CR);
|
||||||
$this->client->buffer_flush(5);
|
$this->client->buffer_flush(5);
|
||||||
|
|
||||||
} elseif ($p && strstr($p,self::EMSI_BEG) && strstr($p,self::EMSI_ARGUS1)) {
|
} elseif ($p && strstr($p,self::EMSI_BEG) && strstr($p,self::EMSI_ARGUS1)) {
|
||||||
|
@ -5,10 +5,10 @@ namespace App\Console\Commands;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
use App\Classes\Protocol\Binkd as BinkdClass;
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Classes\Sock\SocketServer;
|
use App\Classes\Sock\SocketServer;
|
||||||
|
use App\Models\Setup;
|
||||||
use App\Classes\Protocol\Binkd as BinkdClass;
|
|
||||||
|
|
||||||
class BinkpReceive extends Command
|
class BinkpReceive extends Command
|
||||||
{
|
{
|
||||||
@ -35,8 +35,8 @@ class BinkpReceive extends Command
|
|||||||
{
|
{
|
||||||
Log::info('Listening for BINKP connections...');
|
Log::info('Listening for BINKP connections...');
|
||||||
|
|
||||||
$server = new SocketServer(24554,'0.0.0.0');
|
$server = new SocketServer(Setup::BINKP_PORT,Setup::BINKP_BIND);
|
||||||
$server->setConnectionHandler([new BinkdClass,'onConnect']);
|
$server->setConnectionHandler([new BinkdClass(Setup::findOrFail(config('app.id'))),'onConnect']);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$server->listen();
|
$server->listen();
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
use App\Classes\Protocol\Binkd as BinkdClass;
|
use App\Classes\Protocol\Binkd as BinkdClass;
|
||||||
use App\Classes\Sock\SocketClient;
|
use App\Classes\Sock\SocketClient;
|
||||||
use App\Models\Node;
|
use App\Models\{Address,Setup};
|
||||||
|
|
||||||
class BinkpSend extends Command
|
class BinkpSend extends Command
|
||||||
{
|
{
|
||||||
@ -36,11 +36,19 @@ class BinkpSend extends Command
|
|||||||
{
|
{
|
||||||
Log::info('Call BINKP send');
|
Log::info('Call BINKP send');
|
||||||
|
|
||||||
$no = Node::findFTN($this->argument('ftn'));
|
$no = Address::findFTN($this->argument('ftn'));
|
||||||
|
if (! $no)
|
||||||
|
throw new ModelNotFoundException('Unknown node: '.$this->argument('ftn'));
|
||||||
|
|
||||||
$client = SocketClient::create($no->address,$no->port);
|
if ($no->system->mailer_type != Setup::O_BINKP)
|
||||||
|
throw new \Exception(sprintf('Node [%s] doesnt support BINKD',$this->argument('ftn')));
|
||||||
|
|
||||||
$o = new BinkdClass;
|
if ((! $no->system->mailer_address) || (! $no->system->mailer_port))
|
||||||
|
throw new \Exception(sprintf('Unable to poll [%s] missing mailer details',$this->argument('ftn')));
|
||||||
|
|
||||||
|
$client = SocketClient::create($no->system->mailer_address,$no->system->mailer_port);
|
||||||
|
|
||||||
|
$o = new BinkdClass(Setup::findOrFail(config('app.id')));
|
||||||
$o->session(BinkdClass::SESSION_BINKP,$client,$no);
|
$o->session(BinkdClass::SESSION_BINKP,$client,$no);
|
||||||
|
|
||||||
Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]);
|
Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]);
|
||||||
|
@ -5,10 +5,10 @@ namespace App\Console\Commands;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
use App\Classes\Protocol\EMSI as EMSIClass;
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Classes\Sock\SocketServer;
|
use App\Classes\Sock\SocketServer;
|
||||||
|
use App\Models\Setup;
|
||||||
use App\Classes\Protocol\EMSI as EMSIClass;
|
|
||||||
|
|
||||||
class EMSIReceive extends Command
|
class EMSIReceive extends Command
|
||||||
{
|
{
|
||||||
@ -35,8 +35,8 @@ class EMSIReceive extends Command
|
|||||||
{
|
{
|
||||||
Log::info('Listening for EMSI connections...');
|
Log::info('Listening for EMSI connections...');
|
||||||
|
|
||||||
$server = new SocketServer(60179,'0.0.0.0');
|
$server = new SocketServer(Setup::EMSI_PORT,Setup::EMSI_BIND);
|
||||||
$server->setConnectionHandler([new EMSIClass,'onConnect']);
|
$server->setConnectionHandler([new EMSIClass(Setup::findOrFail(config('app.id'))),'onConnect']);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$server->listen();
|
$server->listen();
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Node;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
use App\Classes\Sock\SocketClient;
|
|
||||||
|
|
||||||
use App\Classes\Protocol\EMSI as EMSIClass;
|
use App\Classes\Protocol\EMSI as EMSIClass;
|
||||||
|
use App\Classes\Sock\SocketClient;
|
||||||
|
use App\Models\{Address,Setup};
|
||||||
|
|
||||||
class EMSISend extends Command
|
class EMSISend extends Command
|
||||||
{
|
{
|
||||||
@ -36,11 +36,19 @@ class EMSISend extends Command
|
|||||||
{
|
{
|
||||||
Log::info('Call EMSI send');
|
Log::info('Call EMSI send');
|
||||||
|
|
||||||
$no = Node::findFTN($this->argument('ftn'));
|
$no = Address::findFTN($this->argument('ftn'));
|
||||||
|
if (! $no)
|
||||||
|
throw new ModelNotFoundException('Unknown node: '.$this->argument('ftn'));
|
||||||
|
|
||||||
$client = SocketClient::create($no->address,$no->port,38400);
|
if ($no->system->mailer_type != Setup::O_EMSI)
|
||||||
|
throw new \Exception(sprintf('Node [%s] doesnt support EMSI',$this->argument('ftn')));
|
||||||
|
|
||||||
$o = new EMSIClass;
|
if ((! $no->system->mailer_address) || (! $no->system->mailer_port))
|
||||||
|
throw new \Exception(sprintf('Unable to poll [%s] missing mailer details',$this->argument('ftn')));
|
||||||
|
|
||||||
|
$client = SocketClient::create($no->system->mailer_address,$no->system->mailer_port,38400);
|
||||||
|
|
||||||
|
$o = new EMSIClass(Setup::findOrFail(config('app.id')));
|
||||||
$o->session(EMSIClass::SESSION_AUTO,$client,$no);
|
$o->session(EMSIClass::SESSION_AUTO,$client,$no);
|
||||||
|
|
||||||
Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]);
|
Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]);
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Classes\Protocol\Binkd;
|
|
||||||
use App\Classes\Protocol\EMSI;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
use App\Classes\Protocol\{Binkd,EMSI};
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Classes\Sock\SocketServer;
|
use App\Classes\Sock\SocketServer;
|
||||||
|
use App\Models\Setup;
|
||||||
use App\Classes\Protocol\EMSI as EMSIClass;
|
|
||||||
|
|
||||||
class StartServer extends Command
|
class StartServer extends Command
|
||||||
{
|
{
|
||||||
@ -35,18 +33,20 @@ class StartServer extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
$o = Setup::findOrFail(config('app.id'));
|
||||||
|
|
||||||
// @todo This should be a config item.
|
// @todo This should be a config item.
|
||||||
$start = [
|
$start = [
|
||||||
'emsi' => [
|
'emsi' => [
|
||||||
'address'=>'0.0.0.0',
|
'address'=>Setup::EMSI_BIND,
|
||||||
'port'=>60179,
|
'port'=>Setup::EMSI_PORT,
|
||||||
'class'=>new EMSI,
|
'class'=>new EMSI($o),
|
||||||
|
|
||||||
],
|
],
|
||||||
'binkp' => [
|
'binkp' => [
|
||||||
'address'=>'0.0.0.0',
|
'address'=>Setup::BINKP_BIND,
|
||||||
'port'=>24554,
|
'port'=>Setup::BINKP_PORT,
|
||||||
'class'=>new Binkd,
|
'class'=>new Binkd($o),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
use App\Models\Domain;
|
use App\Models\{Domain,Setup};
|
||||||
|
|
||||||
class HomeController extends Controller
|
class HomeController extends Controller
|
||||||
{
|
{
|
||||||
@ -28,8 +29,34 @@ class HomeController extends Controller
|
|||||||
*
|
*
|
||||||
* @note: Protected by Route
|
* @note: Protected by Route
|
||||||
*/
|
*/
|
||||||
public function setup()
|
public function setup(Request $request)
|
||||||
{
|
{
|
||||||
return view('setup');
|
$o = Setup::findOrNew(config('app.id'));
|
||||||
|
|
||||||
|
if ($request->post()) {
|
||||||
|
$request->validate([
|
||||||
|
'system_id' => 'required|exists:systems,id',
|
||||||
|
'binkp' => 'nullable|array',
|
||||||
|
'binkp.*' => 'nullable|numeric',
|
||||||
|
'options' => 'nullable|array',
|
||||||
|
'options.*' => 'nullable|numeric',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (! $o->exists) {
|
||||||
|
$o->id = config('app.id');
|
||||||
|
$o->zmodem = 0;
|
||||||
|
$o->emsi_protocols = 0;
|
||||||
|
$o->protocols = 0;
|
||||||
|
$o->permissions = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$o->binkp = collect($request->post('binkp'))->sum();
|
||||||
|
$o->options = collect($request->post('options'))->sum();
|
||||||
|
$o->system_id = $request->post('system_id');
|
||||||
|
$o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('setup')
|
||||||
|
->with('o',$o);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -193,10 +193,14 @@ class SystemController extends Controller
|
|||||||
'sysop' => 'required|min:3',
|
'sysop' => 'required|min:3',
|
||||||
'address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i',
|
'address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i',
|
||||||
'port' => 'nullable|digits_between:2,5',
|
'port' => 'nullable|digits_between:2,5',
|
||||||
|
'method' => 'nullable|numeric',
|
||||||
|
'mailer_type' => 'nullable|numeric',
|
||||||
|
'mailer_address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i',
|
||||||
|
'mailer_port' => 'nullable|digits_between:2,5',
|
||||||
'active' => 'required|boolean',
|
'active' => 'required|boolean',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach (['name','location','sysop','address','port','active','method','notes'] as $key)
|
foreach (['name','location','sysop','address','port','active','method','notes','mailer_type','mailer_address','mailer_port'] as $key)
|
||||||
$o->{$key} = $request->post($key);
|
$o->{$key} = $request->post($key);
|
||||||
|
|
||||||
$o->save();
|
$o->save();
|
||||||
|
@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
use App\Http\Controllers\DomainController;
|
use App\Http\Controllers\DomainController;
|
||||||
|
use App\Traits\ScopeActive;
|
||||||
|
|
||||||
class Address extends Model
|
class Address extends Model
|
||||||
{
|
{
|
||||||
|
use ScopeActive;
|
||||||
|
|
||||||
/* RELATIONS */
|
/* RELATIONS */
|
||||||
|
|
||||||
public function system()
|
public function system()
|
||||||
@ -49,4 +53,65 @@ class Address extends Model
|
|||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GENERAL METHODS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a record in the DB for a node string, eg: 10:1/1.0
|
||||||
|
*
|
||||||
|
* @param string $ftn
|
||||||
|
* @return Node|null
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function findFTN(string $ftn): ?self
|
||||||
|
{
|
||||||
|
$matches = [];
|
||||||
|
|
||||||
|
// http://ftsc.org/docs/frl-1028.002
|
||||||
|
if (! preg_match('#^([0-9]+):([0-9]+)/([0-9]+)(.([0-9]+))?(@([a-z0-9\-_~]{0,8}))?$#',strtolower($ftn),$matches))
|
||||||
|
throw new Exception('Invalid FTN: '.$ftn);
|
||||||
|
|
||||||
|
// Check our numbers are correct.
|
||||||
|
foreach ([1,2,3] as $i) {
|
||||||
|
if (! $matches[$i] || ($matches[$i] > DomainController::NUMBER_MAX))
|
||||||
|
throw new Exception('Invalid FTN: '.$ftn);
|
||||||
|
}
|
||||||
|
if (isset($matches[5]) AND $matches[5] > DomainController::NUMBER_MAX)
|
||||||
|
throw new Exception('Invalid FTN: '.$ftn);
|
||||||
|
|
||||||
|
$o = (new self)->active()
|
||||||
|
->select('addresses.*')
|
||||||
|
->where('zones.zone_id',$matches[1])
|
||||||
|
->where('host_id',$matches[2])
|
||||||
|
->join('zones',['zones.id'=>'addresses.zone_id'])
|
||||||
|
->join('domains',['domains.id'=>'zones.domain_id'])
|
||||||
|
->where('zones.active',TRUE)
|
||||||
|
->where('domains.active',TRUE)
|
||||||
|
->where('addresses.active',TRUE)
|
||||||
|
->where('node_id',$matches[3])
|
||||||
|
->where('point_id',(isset($matches[5]) AND $matches[5]) ? $matches[5] : 0)
|
||||||
|
->when(isset($matches[7]),function($query) use ($matches) {
|
||||||
|
$query->where('domains.name',$matches[7]);
|
||||||
|
})
|
||||||
|
->when((! isset($matches[7]) OR ! $matches[7]),function($query) {
|
||||||
|
$query->where('domains.default',TRUE);
|
||||||
|
})
|
||||||
|
->single();
|
||||||
|
|
||||||
|
return ($o && $o->system->active) ? $o : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function session(string $type): ?string
|
||||||
|
{
|
||||||
|
static $session = NULL;
|
||||||
|
|
||||||
|
if (is_null($session)) {
|
||||||
|
$session = (new AddressZone)
|
||||||
|
->where('zone_id',$this->zone_id)
|
||||||
|
->where('system_id',$this->system_id)
|
||||||
|
->single();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $session ? $session->{$type} : NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
10
app/Models/AddressZone.php
Normal file
10
app/Models/AddressZone.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class AddressZone extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'address_zone';
|
||||||
|
}
|
@ -16,22 +16,60 @@ use Illuminate\Support\Facades\File;
|
|||||||
*/
|
*/
|
||||||
class Setup extends Model
|
class Setup extends Model
|
||||||
{
|
{
|
||||||
|
public const S_DOMAIN = 1<<1; // Users can create Domains
|
||||||
|
public const S_SYSTEM = 1<<2; // Users can create Systems
|
||||||
|
|
||||||
|
public const BINKP_OPT_CHT = 1<<1; /* CHAT mode - not implemented */
|
||||||
|
public const BINKP_OPT_CR = 1<<2; /* Crypt mode - not implemented */
|
||||||
|
public const BINKP_OPT_MB = 1<<3; /* Multi-Batch mode */
|
||||||
|
public const BINKP_OPT_MD = 1<<4; /* CRAM-MD5 mode */
|
||||||
|
public const BINKP_OPT_ND = 1<<5; /* http://ftsc.org/docs/fsp-1027.001: No-dupes mode */
|
||||||
|
public const BINKP_OPT_NDA = 1<<6; /* http://ftsc.org/docs/fsp-1027.001: Asymmetric ND mode */
|
||||||
|
public const BINKP_OPT_NR = 1<<7; /* http://ftsc.org/docs/fsp-1027.001: Non-Reliable mode */
|
||||||
|
public const BINKP_OPT_MPWD = 1<<8; /* Multi-Password mode - not implemented */
|
||||||
|
|
||||||
|
public const BINKP_PORT = 24554;
|
||||||
|
public const BINKP_BIND = '0.0.0.0';
|
||||||
|
public const EMSI_PORT = 60179;
|
||||||
|
public const EMSI_BIND = self::BINKP_BIND;
|
||||||
|
|
||||||
|
public const O_BINKP = 1<<1; /* Listen for BINKD connections */
|
||||||
|
public const O_EMSI = 1<<2; /* Listen for EMSI connections */
|
||||||
|
public const O_HIDEAKA = 1<<3; /* Hide AKAs to different Zones */
|
||||||
|
|
||||||
// Our non model attributes and values
|
// Our non model attributes and values
|
||||||
private array $internal = [];
|
private array $internal = [];
|
||||||
|
|
||||||
|
/* RELATIONS */
|
||||||
|
|
||||||
|
public function system()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(System::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ATTRIBUTES */
|
||||||
|
|
||||||
|
public function getLocationAttribute()
|
||||||
|
{
|
||||||
|
return $this->system->location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSysopAttribute()
|
||||||
|
{
|
||||||
|
return $this->system->sysop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSystemNameAttribute()
|
||||||
|
{
|
||||||
|
return $this->system->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* METHODS */
|
||||||
|
|
||||||
public function __construct(array $attributes = [])
|
public function __construct(array $attributes = [])
|
||||||
{
|
{
|
||||||
parent::__construct($attributes);
|
parent::__construct($attributes);
|
||||||
|
|
||||||
// @todo This should go in a config file in the config dir
|
|
||||||
$this->opt_cht = 0; /* CHAT mode - not implemented*/
|
|
||||||
$this->opt_cr = 0; /* Crypt mode - not implemented*/
|
|
||||||
$this->opt_mb = 1; /* Multi-Batch mode */
|
|
||||||
$this->opt_md = 0; /* CRAM-MD5 mode */
|
|
||||||
$this->opt_nd = 0; /* http://ftsc.org/docs/fsp-1027.001: No-dupes mode */
|
|
||||||
$this->opt_nda = 1; /* http://ftsc.org/docs/fsp-1027.001: Asymmetric ND mode */
|
|
||||||
$this->opt_mpwd = 0; /* Multi-Password mode - not implemented */
|
|
||||||
$this->opt_nr = 1; /* http://ftsc.org/docs/fsp-1027.001: Non-Reliable mode */
|
|
||||||
$this->binkp_options = ['m','d','r','b'];
|
$this->binkp_options = ['m','d','r','b'];
|
||||||
|
|
||||||
/* EMSI SETTINGS */
|
/* EMSI SETTINGS */
|
||||||
@ -43,32 +81,6 @@ class Setup extends Model
|
|||||||
$this->inbound = '/tmp';
|
$this->inbound = '/tmp';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RELATIONS */
|
|
||||||
|
|
||||||
public function nodes()
|
|
||||||
{
|
|
||||||
return $this->belongsToMany(Node::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ATTRIBUTES */
|
|
||||||
|
|
||||||
public function getLocationAttribute()
|
|
||||||
{
|
|
||||||
return $this->nodes->first()->location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSysopAttribute()
|
|
||||||
{
|
|
||||||
return $this->nodes->first()->sysop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSystemNameAttribute()
|
|
||||||
{
|
|
||||||
return $this->nodes->first()->system;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* METHODS */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@ -78,15 +90,15 @@ class Setup extends Model
|
|||||||
case 'binkp_options':
|
case 'binkp_options':
|
||||||
case 'ignore_nrq':
|
case 'ignore_nrq':
|
||||||
case 'inbound':
|
case 'inbound':
|
||||||
case 'opt_nr':
|
case 'opt_nr': // @todo - this keys are now in #binkp as bits
|
||||||
case 'opt_nd':
|
case 'opt_nd':
|
||||||
case 'opt_nda':
|
case 'opt_nda':
|
||||||
case 'opt_md':
|
case 'opt_md':
|
||||||
case 'opt_cr':
|
case 'opt_cr':
|
||||||
case 'opt_mb':
|
case 'opt_mb':
|
||||||
case 'opt_cht':
|
case 'opt_cht':
|
||||||
|
case 'opt_mpwd':
|
||||||
case 'do_prevent':
|
case 'do_prevent':
|
||||||
case 'options':
|
|
||||||
return $this->internal[$key] ?? FALSE;
|
return $this->internal[$key] ?? FALSE;
|
||||||
|
|
||||||
case 'version':
|
case 'version':
|
||||||
@ -113,13 +125,43 @@ class Setup extends Model
|
|||||||
case 'opt_cr':
|
case 'opt_cr':
|
||||||
case 'opt_mb':
|
case 'opt_mb':
|
||||||
case 'opt_cht':
|
case 'opt_cht':
|
||||||
|
case 'opt_mpwd':
|
||||||
case 'do_prevent':
|
case 'do_prevent':
|
||||||
case 'options':
|
|
||||||
$this->internal[$key] = $value;
|
$this->internal[$key] = $value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
parent::__get($key);
|
parent::__set($key,$value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function binkpOptionClear(int $key): void
|
||||||
|
{
|
||||||
|
$this->binkp &= ~$key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function binkpOptionGet(int $key): int
|
||||||
|
{
|
||||||
|
return ($this->binkp & $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function binkpOptionSet(int $key): void
|
||||||
|
{
|
||||||
|
$this->binkp |= $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function optionClear(int $key): void
|
||||||
|
{
|
||||||
|
$this->options &= ~$key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function optionGet(int $key): int
|
||||||
|
{
|
||||||
|
return ($this->options & $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function optionSet(int $key): void
|
||||||
|
{
|
||||||
|
$this->options |= $key;
|
||||||
|
}
|
||||||
}
|
}
|
@ -11,8 +11,6 @@ class System extends Model
|
|||||||
{
|
{
|
||||||
use HasFactory,ScopeActive;
|
use HasFactory,ScopeActive;
|
||||||
|
|
||||||
/* SCOPES */
|
|
||||||
|
|
||||||
/* RELATIONS */
|
/* RELATIONS */
|
||||||
|
|
||||||
public function addresses()
|
public function addresses()
|
||||||
@ -23,6 +21,4 @@ class System extends Model
|
|||||||
->orderBy('node_id')
|
->orderBy('node_id')
|
||||||
->orderBy('point_id');
|
->orderBy('point_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CASTS */
|
|
||||||
}
|
}
|
@ -14,6 +14,7 @@ return [
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
'name' => env('APP_NAME', 'Laravel'),
|
'name' => env('APP_NAME', 'Laravel'),
|
||||||
|
'id' => env('APP_SETUP_ID', 1),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddSystemToSetups extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('setups', function (Blueprint $table) {
|
||||||
|
$table->integer('options');
|
||||||
|
$table->integer('system_id');
|
||||||
|
$table->foreign('system_id')->references('id')->on('systems');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('setups', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['system_id']);
|
||||||
|
$table->dropColumn(['system_id','options']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddMailerToSystem extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('systems', function (Blueprint $table) {
|
||||||
|
$table->string('mailer_address')->nullable();
|
||||||
|
$table->integer('mailer_port')->nullable();
|
||||||
|
$table->integer('mailer_type')->nullable();
|
||||||
|
$table->string('zt_id',10)->nullable()->unique();
|
||||||
|
|
||||||
|
$table->unique(['mailer_type','mailer_address','mailer_port']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('zones', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['ztid']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('zones', function (Blueprint $table) {
|
||||||
|
$table->string('zt_id',16)->unique()->nullable();
|
||||||
|
|
||||||
|
$table->ipAddress('zt_ipv4')->nullable();
|
||||||
|
$table->integer('zt_ipv4_mask')->nullable();
|
||||||
|
$table->unique(['zt_ipv4','zt_ipv4_mask']);
|
||||||
|
$table->ipAddress('zt_ipv6')->nullable();
|
||||||
|
$table->integer('zt_ipv6_mask')->nullable();
|
||||||
|
$table->unique(['zt_ipv6','zt_ipv6_mask']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('address_zone', function (Blueprint $table) {
|
||||||
|
$table->string('sespass')->nullable();
|
||||||
|
$table->string('pktpass',8)->nullable();
|
||||||
|
$table->string('ticpass')->nullable();
|
||||||
|
$table->string('fixpass')->nullable();
|
||||||
|
|
||||||
|
$table->ipAddress('zt_ipv4')->nullable();
|
||||||
|
$table->ipAddress('zt_ipv6')->nullable();
|
||||||
|
|
||||||
|
$table->integer('system_id');
|
||||||
|
$table->foreign('system_id')->references('id')->on('systems');
|
||||||
|
$table->integer('zone_id');
|
||||||
|
$table->foreign('zone_id')->references('id')->on('zones');
|
||||||
|
|
||||||
|
$table->unique(['system_id','zone_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('address_zone');
|
||||||
|
|
||||||
|
Schema::table('zones', function (Blueprint $table) {
|
||||||
|
$table->dropUnique(['zt_id']);
|
||||||
|
$table->dropColumn(['zt_id']);
|
||||||
|
$table->dropUnique(['zt_ipv4','zt_ipv4_mask']);
|
||||||
|
$table->dropUnique(['zt_ipv6','zt_ipv6_mask']);
|
||||||
|
$table->dropColumn(['zt_ipv4','zt_ipv4_mask']);
|
||||||
|
$table->dropColumn(['zt_ipv6','zt_ipv6_mask']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('zones', function (Blueprint $table) {
|
||||||
|
$table->string('ztid')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('systems', function (Blueprint $table) {
|
||||||
|
$table->dropUnique(['zt_id']);
|
||||||
|
$table->dropUnique(['mailer_type','mailer_address','mailer_port']);
|
||||||
|
$table->dropColumn(['mailer_address','mailer_port','mailer_type','zt_id']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
19
public/css/fixes.css
vendored
Normal file
19
public/css/fixes.css
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* Fixes for select 2 and our theme */
|
||||||
|
/*
|
||||||
|
.select2 .select2-container .select2-container--classic { width: 80% !important;}
|
||||||
|
*/
|
||||||
|
.select2-container .select2-selection--single { border-radius: 0 4px 4px 0; height: inherit;}
|
||||||
|
.select2-container .select2-selection--single .select2-selection__rendered { line-height: 36px; }
|
||||||
|
.select2-container--classic .select2-selection--single .select2-selection__arrow { line-height: 36px; }
|
||||||
|
.select2-results { color: #000; }
|
||||||
|
/*
|
||||||
|
.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable,
|
||||||
|
*/
|
||||||
|
.select2-container--default .select2-results__option--selected { background-color: #024cc4; color: #eeeeee;}
|
||||||
|
|
||||||
|
/* Bootstrap 5 fixes */
|
||||||
|
/* select import, round the right side */
|
||||||
|
.input-group .form-select {
|
||||||
|
border-top-right-radius: 4px !important;
|
||||||
|
border-bottom-right-radius: 4px !important;
|
||||||
|
}
|
10
public/oldschool/css/main.css
vendored
10
public/oldschool/css/main.css
vendored
@ -390,6 +390,11 @@ form div.row {
|
|||||||
--bs-gutter-x: 0;
|
--bs-gutter-x: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-check.form-switch .form-check-input {
|
||||||
|
top: -.15em;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.greyframe {
|
.greyframe {
|
||||||
position:relative;
|
position:relative;
|
||||||
background-color: #192124;
|
background-color: #192124;
|
||||||
@ -439,6 +444,11 @@ label.form-label {
|
|||||||
margin-bottom: 1px;
|
margin-bottom: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.list-group-item {
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin:0 0 1em;
|
margin:0 0 1em;
|
||||||
padding:0;
|
padding:0;
|
||||||
|
@ -40,7 +40,7 @@ If you have more than 1 BBS, then the Clearing House can receive all your mail f
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Supports BINKP network transfers</li>
|
<li>Supports BINKP network transfers</li>
|
||||||
<li>Supports EMSI network transfers</li>
|
<li>Supports EMSI network transfers</li>
|
||||||
<li>Manages ECHO areas and FILE areas <sup>To be implemented</sup></li
|
<li>Manages ECHO areas and FILE areas <sup>To be implemented</sup></li>
|
||||||
<li>Supports PING and TRACE responses <sup>To be implemented</sup></li>
|
<li>Supports PING and TRACE responses <sup>To be implemented</sup></li>
|
||||||
<li>Nodelist Management <sup>To be implemented</sup></li>
|
<li>Nodelist Management <sup>To be implemented</sup></li>
|
||||||
<li>Network Applications <sup>To be implemented</sup></li>
|
<li>Network Applications <sup>To be implemented</sup></li>
|
||||||
|
@ -4,5 +4,5 @@
|
|||||||
|
|
||||||
@if(file_exists('js/custom-auth.js'))
|
@if(file_exists('js/custom-auth.js'))
|
||||||
<!-- Any Custom JS -->
|
<!-- Any Custom JS -->
|
||||||
<script src="{{ asset('js/custom-auth.js') }}"></script>
|
<script type="text/javascript" src="{{ asset('js/custom-auth.js') }}"></script>
|
||||||
@endif
|
@endif
|
@ -111,10 +111,10 @@
|
|||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@can('admin',$o)
|
@can('admin',$o)
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
|
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
|
||||||
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script type="text/javascript">
|
||||||
var simplemde = new SimpleMDE({ element: $("#homepage")[0] });
|
var simplemde = new SimpleMDE({ element: $("#homepage")[0] });
|
||||||
</script>
|
</script>
|
||||||
@endcan
|
@endcan
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<h1>{{ $o->name }} <small class="push-right">Last Update: {{ $o->updated_at }}</small></h1>
|
<h1>{{ $o->name }} <small class="float-end pt-4">Last Update: {{ $o->updated_at->format('Y-m-d H:i') }}</small></h1>
|
||||||
|
|
||||||
|
<p class="float-end"><small>Expand each heading for information about this FTN network</small></p>
|
||||||
|
|
||||||
<div class="accordion" id="accordion_homepage">
|
<div class="accordion" id="accordion_homepage">
|
||||||
<!-- About -->
|
<!-- About -->
|
||||||
|
@ -9,10 +9,17 @@
|
|||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
<!-- CSS only -->
|
<!-- CSS only -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
|
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
|
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
|
||||||
|
|
||||||
<link href="{{ asset('oldschool/css/main.css') }}" rel="stylesheet" media="screen" type="text/css">
|
<link type="text/css" rel="stylesheet" href="{{ asset('oldschool/css/main.css') }}" media="screen">
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="{{ asset('favicon.ico') }}">
|
@yield('page-css')
|
||||||
|
|
||||||
|
@if(file_exists('css/fixes.css'))
|
||||||
|
<!-- CSS Fixes -->
|
||||||
|
<link rel="stylesheet" href="{{ asset('css/fixes.css') }}">
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<link type="image/png" rel="icon" href="{{ asset('favicon.ico') }}">
|
||||||
</head>
|
</head>
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
<script type="text/javascript" src="{{ asset('//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js') }}" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="{{ asset('//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js') }}" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<!-- JavaScript Bundle with Popper -->
|
<!-- JavaScript Bundle with Popper -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<script>
|
<script type="text/javascript">
|
||||||
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
||||||
(function () {
|
(function () {
|
||||||
'use strict'
|
'use strict'
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
@endauth
|
@endauth
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Expore Networks</dt>
|
<dt>Expore Networks</dt>
|
||||||
@foreach (\App\Models\Domain::active()->public()->get() as $o)
|
@foreach (\App\Models\Domain::active()->public()->orderBy('name')->get() as $o)
|
||||||
<dd><a href="{{ url('network',['id'=>$o->id]) }}" title="{{ $o->description }}">{{ $o->name }}</a></dd>
|
<dd><a href="{{ url('network',['id'=>$o->id]) }}" title="{{ $o->description }}">{{ $o->name }}</a></dd>
|
||||||
@endforeach
|
@endforeach
|
||||||
</dl>
|
</dl>
|
||||||
|
@ -1,8 +1,193 @@
|
|||||||
|
@php
|
||||||
|
use App\Models\Setup;
|
||||||
|
@endphp
|
||||||
|
|
||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
@section('htmlheader_title')
|
@section('htmlheader_title')
|
||||||
Setup
|
Setup
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
<h2>Site Setup</h2>
|
<h2>Site Setup</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row pt-0">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="greyframe titledbox shadow0xb0">
|
||||||
|
<h2 class="cap">@if($o->exists) Update @else Initial @endif Setup</h2>
|
||||||
|
|
||||||
|
<form class="row g-0 needs-validation" method="post" novalidate>
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4">
|
||||||
|
<label for="system_id" class="form-label">System</label>
|
||||||
|
<div class="input-group has-validation">
|
||||||
|
<span class="input-group-text"><i class="bi bi-tag-fill"></i></span>
|
||||||
|
<select style="width: 80%;" class="form-select @error('system_id') is-invalid @enderror" id="system_id" name="system_id" required @cannot('admin',$o)disabled @endcannot>
|
||||||
|
<option value=""> </option>
|
||||||
|
@foreach (\App\Models\System::active()->orderBy('name')->cursor() as $oo)
|
||||||
|
<option value="{{ $oo->id }}" @if(old('system_id',$o->system_id)==$oo->id)selected @endif>{{ $oo->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error('system_id')
|
||||||
|
{{ $message }}
|
||||||
|
@else
|
||||||
|
A system is required.
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
<span class="input-helper">Add a <a href="{{ url('ftn/system/addedit') }}">NEW System</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 ms-auto">
|
||||||
|
@if ($o->exists)
|
||||||
|
<table class="table monotable">
|
||||||
|
<thead>
|
||||||
|
<tr><th colspan="2">System Addresses</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($o->system->addresses->groupBy('zone_id') as $zones)
|
||||||
|
<tr>
|
||||||
|
<th>{{ $zones->first()->zone->domain->name }}</th>
|
||||||
|
<th class="text-end">{!! join('<br>',$zones->pluck('ftn')->toArray()) !!}</th>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>Site Permissions</h3>
|
||||||
|
<!-- @todo
|
||||||
|
* Inbound Working Dir
|
||||||
|
-->
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="hideaka" name="options[hideaka]" value="{{ Setup::O_HIDEAKA }}" @if(old('options.hideaka',$o->binkpOptionGet(Setup::O_HIDEAKA))) checked @endif disabled>
|
||||||
|
<label class="form-check-label" for="hideaka">Hide AKA to different Domains <sup>not implemented</sup></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>ZeroTier API</h3>
|
||||||
|
<!-- @todo
|
||||||
|
* Host/Port/Key
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4>Protocol Configuration</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>BINKP Settings</h3>
|
||||||
|
<p>Bink has been configured to listen on <strong>{{ Setup::BINKP_BIND }}</strong>:<strong>{{ Setup::BINKP_PORT }}</strong></p>
|
||||||
|
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="startbinkd" name="options[binkd]" value="{{ Setup::O_BINKP }}" @if(old('options.binkd',$o->optionGet(Setup::O_BINKP))) checked @endif>
|
||||||
|
<label class="form-check-label" for="startbinkd">Listen for BINKP connections</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_cht" name="binkp[cht]" value="{{ Setup::BINKP_OPT_CHT }}" @if(old('binkp.cht',$o->binkpOptionGet(Setup::BINKP_OPT_CHT))) checked @endif disabled>
|
||||||
|
<label class="form-check-label" for="opt_cht">Chat Mode <sup>not implemented</sup></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_md" name="binkp[md]" value="{{ Setup::BINKP_OPT_MD }}" @if(old('binkp.md',$o->binkpOptionGet(Setup::BINKP_OPT_MD))) checked @endif>
|
||||||
|
<label class="form-check-label" for="opt_md">CRAM-MD5 Mode</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_cr" name="binkp[cr]" value="{{ Setup::BINKP_OPT_CR }}" @if(old('binkp.cr',$o->binkpOptionGet(Setup::BINKP_OPT_CR))) checked @endif disabled>
|
||||||
|
<label class="form-check-label" for="opt_cr">Crypt mode <sup>not implemented</sup></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_mb" name="binkp[mb]" value="{{ Setup::BINKP_OPT_MB }}" @if(old('binkp.mb',$o->binkpOptionGet(Setup::BINKP_OPT_MB))) checked @endif>
|
||||||
|
<label class="form-check-label" for="opt_mb">Multi-Batch mode<sup>*</sup></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_mpwd" name="binkp[mpwd]" value="{{ Setup::BINKP_OPT_MPWD }}" @if(old('binkp.mpwd',$o->binkpOptionGet(Setup::BINKP_OPT_MPWD))) checked @endif disabled>
|
||||||
|
<label class="form-check-label" for="opt_mpwd">Multi-Password Mode <sup>not implemented</sup></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_nd" name="binkp[nd]" value="{{ Setup::BINKP_OPT_ND }}" @if(old('binkp.nd',$o->binkpOptionGet(Setup::BINKP_OPT_ND))) checked @endif>
|
||||||
|
<label class="form-check-label" for="opt_nd">No Dupes Mode</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_nda" name="binkp[nda]" value="{{ Setup::BINKP_OPT_NDA }}" @if(old('binkp.nda',$o->binkpOptionGet(Setup::BINKP_OPT_NDA))) checked @endif>
|
||||||
|
<label class="form-check-label" for="opt_nda">No Dupes Mode - Asymmetric<sup>*</sup></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="opt_nr" name="binkp[nr]" value="{{ Setup::BINKP_OPT_NR }}" @if(old('binkp.nr',$o->binkpOptionGet(Setup::BINKP_OPT_NR))) checked @endif>
|
||||||
|
<label class="form-check-label" for="opt_nr">Non-Reliable Mode<sup>*</sup></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="pt-3"><sup>*</sup> Recommended Defaults</p>
|
||||||
|
|
||||||
|
<table class="table monotable">
|
||||||
|
{{--
|
||||||
|
$this->binkp_options = ['m','d','r','b'];
|
||||||
|
--}}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-6">
|
||||||
|
<h3>EMSI Settings</h3>
|
||||||
|
<p>Bink has been configured to listen on <strong>{{ Setup::EMSI_BIND }}</strong>:<strong>{{ Setup::EMSI_PORT }}</strong></p>
|
||||||
|
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" id="startemsi" name="options[emsi]" value="{{ Setup::O_EMSI }}" @if(old('options.emsi',$o->optionGet(Setup::O_EMSI))) checked @endif>
|
||||||
|
<label class="form-check-label" for="startemsi">Listen for EMSI connections</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<a href="{{ url('ftn/domain') }}" class="btn btn-danger">Cancel</a>
|
||||||
|
@if($errors->count())
|
||||||
|
<span class="pl-5 btn btn-sm btn-danger" role="alert">
|
||||||
|
There were errors with the submission.
|
||||||
|
@dump($errors)
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
@can('admin',$o)
|
||||||
|
<button type="submit" name="submit" class="btn btn-success mr-0 float-end">@if ($o->exists)Save @else Add @endif</button>
|
||||||
|
@endcan
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@section('page-css')
|
||||||
|
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">
|
||||||
|
@append
|
||||||
|
@section('page-scripts')
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#system_id').select2();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
@php
|
||||||
|
use App\Models\Setup;
|
||||||
|
@endphp
|
||||||
|
|
||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('htmlheader_title')
|
@section('htmlheader_title')
|
||||||
@ -39,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-4">
|
<div class="col-2">
|
||||||
<label for="active" class="form-label">Active</label>
|
<label for="active" class="form-label">Active</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
@ -51,6 +55,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-2">
|
||||||
|
ZeroTier ID
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -86,6 +94,47 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4>Mailer Details</h4>
|
||||||
|
|
||||||
|
<div class="pt-0 row">
|
||||||
|
<div class="col-4">
|
||||||
|
<label for="method" class="form-label">Connection Method</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
|
||||||
|
<select class="form-select @error('method') is-invalid @enderror" id="mailer_type" name="mailer_type" @cannot('admin',$o)disabled @endcannot>
|
||||||
|
<option></option>
|
||||||
|
<option value="{{ Setup::O_BINKP }}" @if(old('mailer_type',$o->mailer_type) == Setup::O_BINKP)selected @endif)}}>BINKP</option>
|
||||||
|
<option value="{{ Setup::O_EMSI }}" @if(old('mailer_type',$o->mailer_type) == Setup::O_EMSI)selected @endif)}}>EMSI</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-8">
|
||||||
|
<label for="address" class="form-label">Address</label>
|
||||||
|
<div class="input-group has-validation">
|
||||||
|
<span class="input-group-text"><i class="bi bi-globe"></i></span>
|
||||||
|
<input type="text" class="w-75 form-control @error('mailer_address') is-invalid @enderror" id="mailer_address" placeholder="FQDN" name="mailer_address" value="{{ old('mailer_address',$o->mailer_address) }}" @cannot('admin',$o)disabled @endcannot>
|
||||||
|
<input type="text" class="form-control @error('mailer_port') is-invalid @enderror" id="mailer_port" placeholder="Port" name="mailer_port" value="{{ old('mailer_port',$o->mailer_port) }}" @cannot('admin',$o)disabled @endcannot>
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
@error('mailer_address')
|
||||||
|
{{ $message }}
|
||||||
|
@enderror
|
||||||
|
@error('mailer_port')
|
||||||
|
{{ $message }}
|
||||||
|
@enderror
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<h4>BBS Details</h4>
|
||||||
|
|
||||||
|
<div class="pt-0 row">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<label for="method" class="form-label">Connection Method</label>
|
<label for="method" class="form-label">Connection Method</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@ -116,6 +165,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@ -408,7 +459,6 @@
|
|||||||
@if($errors->count())
|
@if($errors->count())
|
||||||
<span class="pl-5 btn btn-sm btn-danger" role="alert">
|
<span class="pl-5 btn btn-sm btn-danger" role="alert">
|
||||||
There were errors with the submission.
|
There were errors with the submission.
|
||||||
@dump($errors)
|
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</span>
|
</span>
|
||||||
@ -422,7 +472,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
@else
|
@else
|
||||||
This system does not currently belong to any Fido networks. You'll need to ask an admin to assign addresses.
|
This system does not currently belong to any Fido networks. You'll need to ask an admin to assign addresses.
|
||||||
@ -489,6 +538,26 @@
|
|||||||
|
|
||||||
$('#region_id').on('change',function() {
|
$('#region_id').on('change',function() {
|
||||||
switch(this.value) {
|
switch(this.value) {
|
||||||
|
case '':
|
||||||
|
if (! $('#region-address').hasClass('d-none'))
|
||||||
|
$('#region-address').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#host-select').hasClass('d-none'))
|
||||||
|
$('#host-select').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#host-address').hasClass('d-none'))
|
||||||
|
$('#host-address').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#hub-select').hasClass('d-none'))
|
||||||
|
$('#hub-select').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#hub-checkbox').hasClass('d-none'))
|
||||||
|
$('#hub-checkbox').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#node-address').hasClass('d-none'))
|
||||||
|
$('#node-address').addClass('d-none');
|
||||||
|
break;
|
||||||
|
|
||||||
case 'new':
|
case 'new':
|
||||||
if (! $('#host-select').hasClass('d-none'))
|
if (! $('#host-select').hasClass('d-none'))
|
||||||
$('#host-select').addClass('d-none');
|
$('#host-select').addClass('d-none');
|
||||||
@ -500,7 +569,7 @@
|
|||||||
$('#region-address').removeClass('d-none');
|
$('#region-address').removeClass('d-none');
|
||||||
|
|
||||||
if (! $('#hub-select').hasClass('d-none'))
|
if (! $('#hub-select').hasClass('d-none'))
|
||||||
$('#hub-select').addClass('d-none')
|
$('#hub-select').addClass('d-none');
|
||||||
|
|
||||||
if (! $('#hub-checkbox').hasClass('d-none'))
|
if (! $('#hub-checkbox').hasClass('d-none'))
|
||||||
$('#hub-checkbox').addClass('d-none');
|
$('#hub-checkbox').addClass('d-none');
|
||||||
@ -521,7 +590,7 @@
|
|||||||
$('#region-address').addClass('d-none');
|
$('#region-address').addClass('d-none');
|
||||||
|
|
||||||
if (! $('#hub-select').hasClass('d-none'))
|
if (! $('#hub-select').hasClass('d-none'))
|
||||||
$('#hub-select').addClass('d-none')
|
$('#hub-select').addClass('d-none');
|
||||||
|
|
||||||
if (! $('#hub-checkbox').hasClass('d-none'))
|
if (! $('#hub-checkbox').hasClass('d-none'))
|
||||||
$('#hub-checkbox').addClass('d-none');
|
$('#hub-checkbox').addClass('d-none');
|
||||||
@ -558,12 +627,26 @@
|
|||||||
|
|
||||||
$('#host_id').on('change',function() {
|
$('#host_id').on('change',function() {
|
||||||
switch(this.value) {
|
switch(this.value) {
|
||||||
|
case '':
|
||||||
|
if (! $('#host-address').hasClass('d-none'))
|
||||||
|
$('#host-address').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#hub-select').hasClass('d-none'))
|
||||||
|
$('#hub-select').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#hub-checkbox').hasClass('d-none'))
|
||||||
|
$('#hub-checkbox').addClass('d-none');
|
||||||
|
|
||||||
|
if (! $('#node-address').hasClass('d-none'))
|
||||||
|
$('#node-address').addClass('d-none');
|
||||||
|
break;
|
||||||
|
|
||||||
case 'new':
|
case 'new':
|
||||||
if ($('#host-address').hasClass('d-none'))
|
if ($('#host-address').hasClass('d-none'))
|
||||||
$('#host-address').removeClass('d-none');
|
$('#host-address').removeClass('d-none');
|
||||||
|
|
||||||
if (! $('#hub-select').hasClass('d-none'))
|
if (! $('#hub-select').hasClass('d-none'))
|
||||||
$('#hub-select').addClass('d-none')
|
$('#hub-select').addClass('d-none');
|
||||||
|
|
||||||
if (! $('#hub-checkbox').hasClass('d-none'))
|
if (! $('#hub-checkbox').hasClass('d-none'))
|
||||||
$('#hub-checkbox').addClass('d-none');
|
$('#hub-checkbox').addClass('d-none');
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-9">
|
<div class="col-10">
|
||||||
<p>This system is aware of the following systems:</p>
|
<p>This system is aware of the following systems:</p>
|
||||||
|
|
||||||
@if (\App\Models\System::count() == 0)
|
@if (\App\Models\System::count() == 0)
|
||||||
@ -30,6 +30,7 @@
|
|||||||
<th>Sysop</th>
|
<th>Sysop</th>
|
||||||
<th>Location</th>
|
<th>Location</th>
|
||||||
<th>Active</th>
|
<th>Active</th>
|
||||||
|
<th>ZeroTier ID</th>
|
||||||
<th>Connect</th>
|
<th>Connect</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -37,7 +38,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
@can('admin',(new \App\Models\System))
|
@can('admin',(new \App\Models\System))
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6"><a href="{{ url('ftn/system/addedit') }}">Add New System</a></td>
|
<td colspan="7"><a href="{{ url('ftn/system/addedit') }}">Add New System</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
@endcan
|
@endcan
|
||||||
@foreach (\App\Models\System::orderBy('name')->cursor() as $oo)
|
@foreach (\App\Models\System::orderBy('name')->cursor() as $oo)
|
||||||
@ -47,6 +48,7 @@
|
|||||||
<td>{{ $oo->sysop }}</td>
|
<td>{{ $oo->sysop }}</td>
|
||||||
<td>{{ $oo->location }}</td>
|
<td>{{ $oo->location }}</td>
|
||||||
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
|
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
|
||||||
|
<td>-</td>
|
||||||
<td>
|
<td>
|
||||||
@switch($oo->method)
|
@switch($oo->method)
|
||||||
@case(23)<a href="telnet://{{ $oo->address }}:{{ $oo->port }}">Telnet</a>@break
|
@case(23)<a href="telnet://{{ $oo->address }}:{{ $oo->port }}">Telnet</a>@break
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<label for="ztid" class="form-label">ZeroTier ID</label>
|
<label for="ztid" class="form-label">ZeroTier Network ID</label>
|
||||||
<div class="input-group has-validation">
|
<div class="input-group has-validation">
|
||||||
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
|
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
|
||||||
<input type="text" class="form-control @error('ztid') is-invalid @enderror" id="ztid" placeholder="ZeroTier" name="ztid" value="{{ old('ztid',$o->ztid) }}" @cannot('admin',$o)disabled @endcannot>
|
<input type="text" class="form-control @error('ztid') is-invalid @enderror" id="ztid" placeholder="ZeroTier" name="ztid" value="{{ old('ztid',$o->ztid) }}" @cannot('admin',$o)disabled @endcannot>
|
||||||
|
@ -55,15 +55,15 @@
|
|||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
{{--
|
{{--
|
||||||
<link href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css" rel="stylesheet" media="screen" type="text/css">
|
<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.min.css" media="screen">
|
||||||
<link href="https://cdn.datatables.net/rowgroup/1.1.2/css/rowGroup.dataTables.min.css" rel="stylesheet" media="screen" type="text/css">
|
<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/rowgroup/1.1.2/css/rowGroup.dataTables.min.css" media="screen">
|
||||||
--}}
|
--}}
|
||||||
<link href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css" rel="stylesheet" media="screen" type="text/css">
|
<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css" media="screen" >
|
||||||
<link href="{{ asset('plugin/dataTables/dataTables.bootstrap5.css') }}" rel="stylesheet" media="screen" type="text/css">
|
<link type="text/css" rel="stylesheet" href="{{ asset('plugin/dataTables/dataTables.bootstrap5.css') }}" media="screen">
|
||||||
|
|
||||||
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
|
<script type="text/javascript" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
|
||||||
<script src="https://cdn.datatables.net/rowgroup/1.1.2/js/dataTables.rowGroup.min.js"></script>
|
<script type="text/javascript" src="https://cdn.datatables.net/rowgroup/1.1.2/js/dataTables.rowGroup.min.js"></script>
|
||||||
<script src="https://cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js"></script>
|
<script type="text/javascript" src="https://cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
@ -54,7 +54,7 @@ Route::get('network/{o}',[HomeController::class,'network']);
|
|||||||
Route::get('permissions',[HomeController::class,'permissions']);
|
Route::get('permissions',[HomeController::class,'permissions']);
|
||||||
|
|
||||||
Route::middleware(['auth','can:admin'])->group(function () {
|
Route::middleware(['auth','can:admin'])->group(function () {
|
||||||
Route::get('setup',[HomeController::class,'setup']);
|
Route::match(['get','post'],'setup',[HomeController::class,'setup']);
|
||||||
|
|
||||||
Route::get('user/list',[UserController::class,'home']);
|
Route::get('user/list',[UserController::class,'home']);
|
||||||
Route::match(['get','post'],'user/addedit/{o?}',[UserController::class,'add_edit'])
|
Route::match(['get','post'],'user/addedit/{o?}',[UserController::class,'add_edit'])
|
||||||
|
Loading…
Reference in New Issue
Block a user