From d1ca78d372e0bf9b8d2fb1b8d93ac2acc6086414 Mon Sep 17 00:00:00 2001 From: Deon George Date: Thu, 24 Jun 2021 20:16:37 +1000 Subject: [PATCH] Changed to using new Address Model, Implemented Setup, Some minor CSS changes --- app/Classes/Node.php | 18 +- app/Classes/Protocol.php | 20 +- app/Classes/Protocol/Binkd.php | 18 +- app/Classes/Protocol/EMSI.php | 16 +- app/Console/Commands/BinkpReceive.php | 8 +- app/Console/Commands/BinkpSend.php | 18 +- app/Console/Commands/EMSIReceive.php | 8 +- app/Console/Commands/EMSISend.php | 20 +- app/Console/Commands/StartServer.php | 20 +- app/Http/Controllers/HomeController.php | 33 +++- app/Http/Controllers/SystemController.php | 6 +- app/Models/Address.php | 65 ++++++ app/Models/AddressZone.php | 10 + app/Models/Setup.php | 120 +++++++---- app/Models/System.php | 4 - config/app.php | 1 + ...2021_06_21_121910_add_system_to_setups.php | 35 ++++ ...2021_06_22_125420_add_mailer_to_system.php | 86 ++++++++ public/css/fixes.css | 19 ++ public/oldschool/css/main.css | 10 + resources/views/about.blade.php | 2 +- .../views/auth/partials/scripts.blade.php | 2 +- resources/views/domain/addedit.blade.php | 6 +- resources/views/domain/view.blade.php | 4 +- .../layouts/partials/htmlheader.blade.php | 15 +- .../views/layouts/partials/scripts.blade.php | 4 +- .../views/layouts/partials/sidebar.blade.php | 2 +- resources/views/setup.blade.php | 187 +++++++++++++++++- resources/views/system/addedit.blade.php | 157 +++++++++++---- resources/views/system/home.blade.php | 6 +- resources/views/zone/addedit.blade.php | 2 +- resources/views/zone/home.blade.php | 14 +- routes/web.php | 2 +- 33 files changed, 766 insertions(+), 172 deletions(-) create mode 100644 app/Models/AddressZone.php create mode 100644 database/migrations/2021_06_21_121910_add_system_to_setups.php create mode 100644 database/migrations/2021_06_22_125420_add_mailer_to_system.php create mode 100644 public/css/fixes.css diff --git a/app/Classes/Node.php b/app/Classes/Node.php index f1d6b04..be9669e 100644 --- a/app/Classes/Node.php +++ b/app/Classes/Node.php @@ -3,12 +3,11 @@ namespace App\Classes; use Carbon\Carbon; - use Exception; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; -use App\Models\Node as NodeModel; +use App\Models\Address; /** * Object representing the node we are communicating with @@ -64,7 +63,7 @@ class Node // The nodes 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 case 'session_time': @@ -102,8 +101,8 @@ class Node { switch ($key) { case 'ftn': - if (! is_object($value) OR ! $value instanceof NodeModel) - throw new Exception('Not a node object: '.(is_object($value) ? get_class($value) : serialize($value))); + if (! is_object($value) OR ! $value instanceof Address) + throw new Exception('Not an Address object: '.(is_object($value) ? get_class($value) : serialize($value))); // Ignore any duplicate FTNs that we get 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'); foreach ($this->ftns as $o) { - if (! $o->sespass) + if (! $o->session('sespass')) continue; // 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) $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 * 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); } diff --git a/app/Classes/Protocol.php b/app/Classes/Protocol.php index d087888..e0b75f6 100644 --- a/app/Classes/Protocol.php +++ b/app/Classes/Protocol.php @@ -8,8 +8,7 @@ use Illuminate\Support\Facades\Log; use App\Classes\File\{Receive,Send}; use App\Classes\Sock\SocketClient; use App\Classes\Sock\SocketException; -use App\Models\Node as NodeModel; -use App\Models\Setup; +use App\Models\{Address,Setup}; abstract class Protocol { @@ -79,7 +78,7 @@ abstract class Protocol protected const MO_CHAT = 4; 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 Send $send; /* The list of files we are sending */ 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_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 */ @@ -181,11 +188,11 @@ abstract class Protocol * * @param int $type * @param SocketClient $client - * @param NodeModel|null $o + * @param Address|null $o * @return int * @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)); @@ -198,9 +205,6 @@ abstract class Protocol $this->recv = new Receive; if ($o) { - // Our configuration and initialise values - $this->setup = Setup::findOrFail(self::setup); - // The node we are communicating with $this->node = new Node; diff --git a/app/Classes/Protocol/Binkd.php b/app/Classes/Protocol/Binkd.php index e57f878..9b45169 100644 --- a/app/Classes/Protocol/Binkd.php +++ b/app/Classes/Protocol/Binkd.php @@ -12,7 +12,7 @@ use League\Flysystem\UnreadableFileException; use App\Classes\Protocol as BaseProtocol; use App\Classes\Sock\SocketClient; use App\Classes\Sock\SocketException; -use App\Models\Node; +use App\Models\Address; final class Binkd extends BaseProtocol { @@ -100,7 +100,7 @@ final class Binkd extends BaseProtocol { // If our parent returns a PID, we've forked if (! parent::onConnect($client)) { - $this->session(self::SESSION_BINKP,$client,(new Node)); + $this->session(self::SESSION_BINKP,$client,(new Address)); $this->client->close(); 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 // @todo Implement hiding our AKAs not in this network. 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? if ($this->DEBUG) Log::debug(sprintf('%s: - Socket EAGAIN',__METHOD__)); + return 1; } @@ -304,6 +305,7 @@ final class Binkd extends BaseProtocol // @todo Check that this is correct. Log::debug(sprintf('%s: - Was the socket closed by the remote?',__METHOD__)); $this->error = -2; + return 0; } @@ -592,7 +594,7 @@ final class Binkd extends BaseProtocol Log::debug(sprintf('%s: - Parsing AKA [%s]',__METHOD__,$rem_aka)); try { - if (! ($o = Node::findFTN($rem_aka))) { + if (! ($o = Address::findFTN($rem_aka))) { Log::debug(sprintf('%s: ? AKA is UNKNOWN [%s]',__METHOD__,$rem_aka)); continue; @@ -608,10 +610,10 @@ final class Binkd extends BaseProtocol } // Check if the remote has our AKA - if ($this->setup->nodes->pluck('ftn')->search($o->ftn) !== FALSE) { - Log::error(sprintf('%s: ! AKA is OURS [%s]',__METHOD__,$o->ftn)); + if ($this->setup->system->addresses->pluck('ftn')->search($rem_aka) !== FALSE) { + 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; return 0; @@ -671,7 +673,7 @@ final class Binkd extends BaseProtocol // If we are not the originator, we'll show our addresses in common. // @todo make this an option to hideAKAs or not 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; } diff --git a/app/Classes/Protocol/EMSI.php b/app/Classes/Protocol/EMSI.php index b542991..5931feb 100644 --- a/app/Classes/Protocol/EMSI.php +++ b/app/Classes/Protocol/EMSI.php @@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Log; use App\Classes\Protocol as BaseProtocol; use App\Classes\Sock\SocketClient; use App\Classes\Sock\SocketException; -use App\Models\Node; +use App\Models\Address; use App\Interfaces\CRC as CRCInterface; use App\Interfaces\Zmodem as ZmodemInterface; 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 (! parent::onConnect($client)) { - $this->session(self::SESSION_AUTO,$client,(new Node)); + $this->session(self::SESSION_AUTO,$client,(new Address)); $this->client->close(); 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 // @todo Only show the AKAs that is relevant to the node we are connecting to $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, join(',',$link_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)); try { - if (! ($o = Node::findFTN($rem_aka))) { + if (! ($o = Address::findFTN($rem_aka))) { Log::debug(sprintf('%s: ? AKA is UNKNOWN [%s]',__METHOD__,$rem_aka)); continue; } @@ -307,7 +307,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface } // 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)); continue; @@ -338,9 +338,9 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface } 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); } else { @@ -861,7 +861,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface if ($gotreq++) return self::OK; - $this->client->buffer_add(self::EMSI_INQ); + $this->client->buffer_add(self::EMSI_INQ.self::CR); $this->client->buffer_flush(5); } elseif ($p && strstr($p,self::EMSI_BEG) && strstr($p,self::EMSI_ARGUS1)) { diff --git a/app/Console/Commands/BinkpReceive.php b/app/Console/Commands/BinkpReceive.php index 76b6b5e..d52ffc8 100644 --- a/app/Console/Commands/BinkpReceive.php +++ b/app/Console/Commands/BinkpReceive.php @@ -5,10 +5,10 @@ namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; +use App\Classes\Protocol\Binkd as BinkdClass; use App\Classes\Sock\SocketException; use App\Classes\Sock\SocketServer; - -use App\Classes\Protocol\Binkd as BinkdClass; +use App\Models\Setup; class BinkpReceive extends Command { @@ -35,8 +35,8 @@ class BinkpReceive extends Command { Log::info('Listening for BINKP connections...'); - $server = new SocketServer(24554,'0.0.0.0'); - $server->setConnectionHandler([new BinkdClass,'onConnect']); + $server = new SocketServer(Setup::BINKP_PORT,Setup::BINKP_BIND); + $server->setConnectionHandler([new BinkdClass(Setup::findOrFail(config('app.id'))),'onConnect']); try { $server->listen(); diff --git a/app/Console/Commands/BinkpSend.php b/app/Console/Commands/BinkpSend.php index 1b77985..0d34156 100644 --- a/app/Console/Commands/BinkpSend.php +++ b/app/Console/Commands/BinkpSend.php @@ -3,12 +3,12 @@ namespace App\Console\Commands; use Illuminate\Console\Command; -use Illuminate\Support\Facades\DB; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Facades\Log; use App\Classes\Protocol\Binkd as BinkdClass; use App\Classes\Sock\SocketClient; -use App\Models\Node; +use App\Models\{Address,Setup}; class BinkpSend extends Command { @@ -36,11 +36,19 @@ class BinkpSend extends Command { 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); Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]); diff --git a/app/Console/Commands/EMSIReceive.php b/app/Console/Commands/EMSIReceive.php index aa4cb7e..871b12b 100644 --- a/app/Console/Commands/EMSIReceive.php +++ b/app/Console/Commands/EMSIReceive.php @@ -5,10 +5,10 @@ namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; +use App\Classes\Protocol\EMSI as EMSIClass; use App\Classes\Sock\SocketException; use App\Classes\Sock\SocketServer; - -use App\Classes\Protocol\EMSI as EMSIClass; +use App\Models\Setup; class EMSIReceive extends Command { @@ -35,8 +35,8 @@ class EMSIReceive extends Command { Log::info('Listening for EMSI connections...'); - $server = new SocketServer(60179,'0.0.0.0'); - $server->setConnectionHandler([new EMSIClass,'onConnect']); + $server = new SocketServer(Setup::EMSI_PORT,Setup::EMSI_BIND); + $server->setConnectionHandler([new EMSIClass(Setup::findOrFail(config('app.id'))),'onConnect']); try { $server->listen(); diff --git a/app/Console/Commands/EMSISend.php b/app/Console/Commands/EMSISend.php index b65cd3f..f957f3d 100644 --- a/app/Console/Commands/EMSISend.php +++ b/app/Console/Commands/EMSISend.php @@ -2,13 +2,13 @@ namespace App\Console\Commands; -use App\Models\Node; use Illuminate\Console\Command; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Facades\Log; -use App\Classes\Sock\SocketClient; - use App\Classes\Protocol\EMSI as EMSIClass; +use App\Classes\Sock\SocketClient; +use App\Models\{Address,Setup}; class EMSISend extends Command { @@ -36,11 +36,19 @@ class EMSISend extends Command { 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); Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]); diff --git a/app/Console/Commands/StartServer.php b/app/Console/Commands/StartServer.php index e5b3134..a78e388 100644 --- a/app/Console/Commands/StartServer.php +++ b/app/Console/Commands/StartServer.php @@ -2,15 +2,13 @@ namespace App\Console\Commands; -use App\Classes\Protocol\Binkd; -use App\Classes\Protocol\EMSI; use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; +use App\Classes\Protocol\{Binkd,EMSI}; use App\Classes\Sock\SocketException; use App\Classes\Sock\SocketServer; - -use App\Classes\Protocol\EMSI as EMSIClass; +use App\Models\Setup; class StartServer extends Command { @@ -35,18 +33,20 @@ class StartServer extends Command */ public function handle() { + $o = Setup::findOrFail(config('app.id')); + // @todo This should be a config item. $start = [ 'emsi' => [ - 'address'=>'0.0.0.0', - 'port'=>60179, - 'class'=>new EMSI, + 'address'=>Setup::EMSI_BIND, + 'port'=>Setup::EMSI_PORT, + 'class'=>new EMSI($o), ], 'binkp' => [ - 'address'=>'0.0.0.0', - 'port'=>24554, - 'class'=>new Binkd, + 'address'=>Setup::BINKP_BIND, + 'port'=>Setup::BINKP_PORT, + 'class'=>new Binkd($o), ], ]; diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index d9df590..a6a31cf 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -2,9 +2,10 @@ namespace App\Http\Controllers; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; -use App\Models\Domain; +use App\Models\{Domain,Setup}; class HomeController extends Controller { @@ -28,8 +29,34 @@ class HomeController extends Controller * * @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); } } \ No newline at end of file diff --git a/app/Http/Controllers/SystemController.php b/app/Http/Controllers/SystemController.php index d3b2131..95a8baf 100644 --- a/app/Http/Controllers/SystemController.php +++ b/app/Http/Controllers/SystemController.php @@ -193,10 +193,14 @@ class SystemController extends Controller 'sysop' => 'required|min:3', 'address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i', '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', ]); - 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->save(); diff --git a/app/Models/Address.php b/app/Models/Address.php index 7aec4ad..887c250 100644 --- a/app/Models/Address.php +++ b/app/Models/Address.php @@ -2,12 +2,16 @@ namespace App\Models; +use Exception; use Illuminate\Database\Eloquent\Model; use App\Http\Controllers\DomainController; +use App\Traits\ScopeActive; class Address extends Model { + use ScopeActive; + /* RELATIONS */ public function system() @@ -49,4 +53,65 @@ class Address extends Model 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; + } } diff --git a/app/Models/AddressZone.php b/app/Models/AddressZone.php new file mode 100644 index 0000000..dfacb0a --- /dev/null +++ b/app/Models/AddressZone.php @@ -0,0 +1,10 @@ +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 = []) { 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']; /* EMSI SETTINGS */ @@ -43,32 +81,6 @@ class Setup extends Model $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 */ @@ -78,15 +90,15 @@ class Setup extends Model case 'binkp_options': case 'ignore_nrq': case 'inbound': - case 'opt_nr': + case 'opt_nr': // @todo - this keys are now in #binkp as bits case 'opt_nd': case 'opt_nda': case 'opt_md': case 'opt_cr': case 'opt_mb': case 'opt_cht': + case 'opt_mpwd': case 'do_prevent': - case 'options': return $this->internal[$key] ?? FALSE; case 'version': @@ -113,13 +125,43 @@ class Setup extends Model case 'opt_cr': case 'opt_mb': case 'opt_cht': + case 'opt_mpwd': case 'do_prevent': - case 'options': $this->internal[$key] = $value; break; 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; + } } \ No newline at end of file diff --git a/app/Models/System.php b/app/Models/System.php index 7a3f492..130911c 100644 --- a/app/Models/System.php +++ b/app/Models/System.php @@ -11,8 +11,6 @@ class System extends Model { use HasFactory,ScopeActive; - /* SCOPES */ - /* RELATIONS */ public function addresses() @@ -23,6 +21,4 @@ class System extends Model ->orderBy('node_id') ->orderBy('point_id'); } - - /* CASTS */ } \ No newline at end of file diff --git a/config/app.php b/config/app.php index d745617..c8a4d9e 100644 --- a/config/app.php +++ b/config/app.php @@ -14,6 +14,7 @@ return [ */ 'name' => env('APP_NAME', 'Laravel'), + 'id' => env('APP_SETUP_ID', 1), /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2021_06_21_121910_add_system_to_setups.php b/database/migrations/2021_06_21_121910_add_system_to_setups.php new file mode 100644 index 0000000..774bed2 --- /dev/null +++ b/database/migrations/2021_06_21_121910_add_system_to_setups.php @@ -0,0 +1,35 @@ +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']); + }); + } +} diff --git a/database/migrations/2021_06_22_125420_add_mailer_to_system.php b/database/migrations/2021_06_22_125420_add_mailer_to_system.php new file mode 100644 index 0000000..d9a0c30 --- /dev/null +++ b/database/migrations/2021_06_22_125420_add_mailer_to_system.php @@ -0,0 +1,86 @@ +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']); + }); + } +} diff --git a/public/css/fixes.css b/public/css/fixes.css new file mode 100644 index 0000000..46d0a77 --- /dev/null +++ b/public/css/fixes.css @@ -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; +} \ No newline at end of file diff --git a/public/oldschool/css/main.css b/public/oldschool/css/main.css index 6ad8ed6..2da5c66 100644 --- a/public/oldschool/css/main.css +++ b/public/oldschool/css/main.css @@ -390,6 +390,11 @@ form div.row { --bs-gutter-x: 0; } +.form-check.form-switch .form-check-input { + top: -.15em; + position: relative; +} + .greyframe { position:relative; background-color: #192124; @@ -439,6 +444,11 @@ label.form-label { margin-bottom: 1px; } +label.list-group-item { + background-color: inherit; + color: inherit; +} + p { margin:0 0 1em; padding:0; diff --git a/resources/views/about.blade.php b/resources/views/about.blade.php index c435850..1571c8d 100644 --- a/resources/views/about.blade.php +++ b/resources/views/about.blade.php @@ -40,7 +40,7 @@ If you have more than 1 BBS, then the Clearing House can receive all your mail f