From 2050ba294b6b328815cb99d444549dc3fe1a07a5 Mon Sep 17 00:00:00 2001 From: flashwave Date: Thu, 12 Oct 2023 22:09:04 +0000 Subject: [PATCH] Some restructuring. --- makai.php | 6 +- public/assets/2021.css | 2 + public/index.php | 344 +--------------------------- src/AssetsRoutes.php | 16 ++ src/{ => Contacts}/ContactInfo.php | 2 +- src/{ => Contacts}/Contacts.php | 2 +- src/Contacts/ContactsRoutes.php | 28 +++ src/HomeRoutes.php | 89 +++++++ src/MakaiContext.php | 110 ++++----- src/NowListeningRoutes.php | 39 ++++ src/{ => Projects}/LanguageInfo.php | 2 +- src/{ => Projects}/ProjectInfo.php | 2 +- src/{ => Projects}/Projects.php | 2 +- src/Projects/ProjectsRoutes.php | 47 ++++ src/RoutingContext.php | 47 ++++ src/{ => SSHKeys}/SSHKeyInfo.php | 2 +- src/{ => SSHKeys}/SSHKeys.php | 2 +- src/SSHKeys/SSHKeysRoutes.php | 102 +++++++++ src/SiteInfo.php | 49 ++++ src/Tools/AsciiRoutes.php | 26 +++ src/Tools/RandomStringRoutes.php | 36 +++ src/Whois/WhoisRoutes.php | 59 +++++ templates/index.twig | 2 +- templates/master.twig | 6 +- 24 files changed, 611 insertions(+), 411 deletions(-) create mode 100644 src/AssetsRoutes.php rename src/{ => Contacts}/ContactInfo.php (98%) rename src/{ => Contacts}/Contacts.php (97%) create mode 100644 src/Contacts/ContactsRoutes.php create mode 100644 src/HomeRoutes.php create mode 100644 src/NowListeningRoutes.php rename src/{ => Projects}/LanguageInfo.php (97%) rename src/{ => Projects}/ProjectInfo.php (99%) rename src/{ => Projects}/Projects.php (99%) create mode 100644 src/Projects/ProjectsRoutes.php create mode 100644 src/RoutingContext.php rename src/{ => SSHKeys}/SSHKeyInfo.php (98%) rename src/{ => SSHKeys}/SSHKeys.php (98%) create mode 100644 src/SSHKeys/SSHKeysRoutes.php create mode 100644 src/SiteInfo.php create mode 100644 src/Tools/AsciiRoutes.php create mode 100644 src/Tools/RandomStringRoutes.php create mode 100644 src/Whois/WhoisRoutes.php diff --git a/makai.php b/makai.php index a1b66a3..af8becd 100644 --- a/makai.php +++ b/makai.php @@ -8,9 +8,7 @@ define('MKI_STARTUP', microtime(true)); define('MKI_ROOT', __DIR__); define('MKI_DEBUG', is_file(MKI_ROOT . '/.debug')); define('MKI_DIR_SRC', MKI_ROOT . '/src'); -define('MKI_DIR_LIB', MKI_ROOT . '/lib'); -define('MKI_DIR_PUB', MKI_ROOT . '/public'); -define('MKI_DIR_PAGES', MKI_ROOT . '/pages'); +define('MKI_DIR_PUBLIC', MKI_ROOT . '/public'); define('MKI_DIR_CONFIG', MKI_ROOT . '/config'); define('MKI_DIR_TEMPLATES', MKI_ROOT . '/templates'); @@ -32,4 +30,4 @@ try { $db->execute('SET SESSION time_zone = \'+00:00\', sql_mode = \'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION\''); -$ctx = new MakaiContext($db); +$makai = new MakaiContext($db); diff --git a/public/assets/2021.css b/public/assets/2021.css index c695ee3..72adf50 100644 --- a/public/assets/2021.css +++ b/public/assets/2021.css @@ -133,10 +133,12 @@ body { background-image: linear-gradient(180deg, #eee 0%, #ddd 50%, #ccc 50%, #aaa 100%); background-clip: text; -webkit-background-clip: text; + white-space: pre; } .header-wave { background-image: linear-gradient(0deg, #281430 0%, #392540 50%, #4a3650 50%, #6c5871 100%); -webkit-background-clip: text; + white-space: pre; } .header-right { display: flex; diff --git a/public/index.php b/public/index.php index ec0ba1f..3fcf49f 100644 --- a/public/index.php +++ b/public/index.php @@ -1,348 +1,6 @@ '/', - '/about.html' => '/', - '/about.php' => '/', - '/index.php' => '/', - '/index.html' => '/', - '/related.php' => '/', - '/related.html' => '/', - '/friends' => '/', - '/friends.php' => '/', - '/friends.html' => '/', - '/related' => '/', - '/etc.php' => '/', - '/etc.html' => '/', - '/etcetera' => '/', - '/etcetera.html' => '/', - '/etcetera.php' => '/', - '/misc' => '/', - '/misc.html' => '/', - '/misc.php' => '/', - '/etc' => '/', - '/365' => '/', - '/donate' => '/', - '/blog.php' => '/', - '/blog-post.php' => '/', - '/blog/:id' => '/', - '/old-blog' => '/', - '/old-blog/:id' => '/', - '/projects.php' => '/projects', - '/projects.html' => '/projects', - '/utilities' => '/projects', - '/utilities.php' => '/projects', - '/utilities.html' => '/projects', - '/contact.php' => '/contact', - '/contact.html' => '/contact', - '/nintendo' => '/contact', - '/nintendo.php' => '/contact', - '/ascii.php' => '/ascii', - '/key.php' => '/rngstr', -]); - -$router = new HttpFx; - -$router->setDefaultErrorHandler(function($response, $request, $code, $text) use ($ctx) { - $path = 'errors/' . $code; - $tpl = $ctx->getTemplating(); - $name = is_file(sprintf('%s/errors/%s.twig', MKI_DIR_TEMPLATES, $code)) ? sprintf('errors/%s.twig', $code) : 'errors/master'; - - $response->setContent($tpl->render($name, [ - 'http_error_code' => $code, - 'http_error_title' => $text, - ])); -}); - -$router->get('/error/:code', function($response, $request, string $code) { - return (int)$code; -}); - -foreach(MKI_REDIRS as $source => $target) - $router->get($source, function($response) use ($target) { - $response->redirect($target); - }); - -$router->use('/', function($response) { - $response->setPoweredBy('Makai'); -}); - -$router->get('/header-bgs.json', function() use ($ctx) { - return $ctx->getDefaultHeaders(); -}); - -$router->get('/now-listening', function() use ($ctx) { - return $ctx->getTemplating()->render('np', [ - 'header_offset' => (int)filter_input(INPUT_GET, 'offset', FILTER_SANITIZE_NUMBER_INT), - ]); -}); - -$router->get('/now-listening.json', function() { - $lfmInfo = json_decode(file_get_contents('https://now.flash.moe/get.php?u=flashwave_')); - - if(empty($lfmInfo[0]->name)) - return []; - - $lfmInfo = $lfmInfo[0]; - - return [ - 'name' => strval($lfmInfo->name), - 'now_playing' => !empty($lfmInfo->nowplaying), - 'url' => strval($lfmInfo->url), - 'cover' => !empty($lfmInfo->images->large) ? strval($lfmInfo->images->large) : '', - 'artist' => [ - 'name' => !empty($lfmInfo->artist->name) ? strval($lfmInfo->artist->name) : '', - 'url' => explode('/_/', strval($lfmInfo->url))[0], - ], - ]; -}); - -$router->get('/home', function() use ($ctx) { - return $ctx->getTemplating()->render('home/index'); -}); - -$router->get('/', function() use ($ctx) { - $legacyPage = (string)filter_input(INPUT_GET, 'p'); - if(!empty($legacyPage)) { - $legacyPages = [ - 'projects' => '/projects', - 'contact' => '/contact', - 'about' => '/', - 'etc' => '/etc', - 'hosted' => '/etc', - 'friends' => '/related', - ]; - - if(isset($legacyPages[$legacyPage])) { - header('Location: ' . $legacyPages[$legacyPage]); - return 302; - } - } - - $dbConn = $ctx->getDatabase(); - - $projects = new Projects($dbConn); - $projectInfos = $projects->getProjects( - featuredOnly: true, - deleted: false, - take: 3, - random: true, - ); - - $projectItems = []; - foreach($projectInfos as $projectInfo) - $projectItems[] = [ - 'info' => $projectInfo, - 'colour' => $projectInfo->hasColour() ? $projectInfo->getColour() : $projects->getProjectColour($projectInfo), - ]; - - $contacts = (new Contacts($dbConn))->getContacts( - homePageOnly: true, - take: 3, - ); - - return $ctx->getTemplating()->render('index', [ - 'projects' => $projectItems, - 'contacts' => $contacts, - ]); -}); - -$router->get('/contact', function() use ($ctx) { - return $ctx->getTemplating()->render('contact', [ - 'contacts' => (new Contacts($ctx->getDatabase()))->getContacts(), - ]); -}); - -$router->get('/projects', function() use ($ctx) { - $dbConn = $ctx->getDatabase(); - $projects = new Projects($dbConn); - $projectInfos = $projects->getProjects(deleted: false); - - $items = []; - foreach($projectInfos as $projectInfo) - $items[] = [ - 'info' => $projectInfo, - 'langs' => $projects->getLanguages(projectInfo: $projectInfo), - 'colour' => $projectInfo->hasColour() ? $projectInfo->getColour() : $projects->getProjectColour($projectInfo), - ]; - - $sections = [ - 'projects' => [ - 'title' => 'Projects', - 'desc' => '', - 'items' => $items, - ], - ]; - - return $ctx->getTemplating()->render('projects', [ - 'sections' => $sections, - ]); -}); - -$router->get('/ascii', function() use ($ctx) { - $templating = $ctx->getTemplating(); - $templating->addFilter('chr', 'chr'); - $templating->addFilter('decoct', 'decoct'); - $templating->addFilter('dechex', 'dechex'); - - return $templating->render('ascii'); -}); - -$router->get('/rngstr', function($response, $request) { - $response->setTypePlain(); - - $length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT); - if($length > 0 && $length <= 1024) - return XString::random($length); - - $out = '8: ' . XString::random(8) . PHP_EOL; - $out .= '16: ' . XString::random(16) . PHP_EOL; - $out .= '32: ' . XString::random(32) . PHP_EOL; - $out .= '64: ' . XString::random(64) . PHP_EOL; - $out .= '128: ' . XString::random(128) . PHP_EOL; - - return $out; -}); - -$router->get('/ssh.php', function() { - $query = ''; - - $minLevel = (int)filter_input(INPUT_GET, 'l', FILTER_SANITIZE_NUMBER_INT); - if($minLevel > 0) - $query .= sprintf('l=%d&', $minLevel); - - if(!empty($_GET['c'])) - $query .= 'c=1&'; - - if(!empty($_GET['j'])) - $query .= 'j=1&'; - - if($query !== '') - $query = '?' . substr($query, 0, -1); - - header('Location: /ssh_keys' . $query); - return 302; -}); - -$router->get('/ssh_keys', function() use ($db) { - $minLevel = (int)filter_input(INPUT_GET, 'l', FILTER_SANITIZE_NUMBER_INT); - $includeComment = !empty($_GET['c']); - $json = !empty($_GET['j']); - - $keys = (new SSHKeys($db))->getKeys(minLevel: $minLevel, deprecated: false); - - if($json) { - $items = []; - - foreach($keys as $key) { - $items[] = $item = new \stdClass; - $item->algo = $key->getAlgorithm(); - $item->key = $key->getBody(); - if($includeComment) { - $item->comment = (string)$key->getComment(); - $item->created = $key->getCreatedAt()->format(\DateTime::ATOM); - $item->level = $key->getLevel(); - } - } - - return $items; - } - - header('Content-Type: text/plain; charset=us-ascii'); - - $body = ''; - - foreach($keys as $key) - $body .= $key->toString($includeComment) . "\n"; - - return $body; -}); - -$router->get('/authorized_keys', function() use ($db) { - $keys = (new SSHKeys($db))->getKeys(minLevel: 500, deprecated: false); - - header('Content-Type: text/plain; charset=us-ascii'); - - $body = ''; - foreach($keys as $key) - $body .= $key->toString(true) . "\n"; - - return $body; -}); - -$router->get('/git_keys_ro', function() use ($db) { - $keys = (new SSHKeys($db))->getKeys(minLevel: 100, deprecated: false); - - header('Content-Type: text/plain; charset=us-ascii'); - - $body = ''; - foreach($keys as $key) - $body .= $key->toString(false) . "\n"; - - return $body; -}); - -$router->get('/git_keys_rw', function() use ($db) { - $keys = (new SSHKeys($db))->getKeys(minLevel: 200, deprecated: false); - - header('Content-Type: text/plain; charset=us-ascii'); - - $body = ''; - foreach($keys as $key) - $body .= $key->toString(false) . "\n"; - - return $body; -}); - -$router->get('/whois', function() use ($ctx) { - return $ctx->getTemplating()->render('whois'); -}); - -$router->get('/whois/lookup', function($response, $request) use ($ctx) { - $target = trim((string)$request->getParam('target')); - if(empty($target)) - return [ - 'error' => true, - 'text' => 'Missing input data.', - ]; - - $hash = hash('sha256', $target); - $prefix = 'fm:whois2:target:'; - $source = ''; - - try { - $redis = new \Redis; - $redis->connect('/var/run/redis/redis-server.sock'); - - $result = $redis->get($prefix . $hash); - - if(empty($result)) { - $client = new \Makai\Whois\WhoisClient; - $result = $client->lookup($target); - $redis->setEx($prefix . $hash, 1800, serialize($result)); - $source = 'fresh'; - } else { - $result = unserialize($result); - $source = 'cache'; - } - } catch (\RuntimeException $ex) { - return [ - 'error' => true, - 'text' => $ex->getMessage(), - ]; - } - - return [ - 'error' => false, - 'source' => $source, - 'result' => $result, - ]; -}); - -$router->dispatch(); +$makai->createRouting()->dispatch(); diff --git a/src/AssetsRoutes.php b/src/AssetsRoutes.php new file mode 100644 index 0000000..79eb773 --- /dev/null +++ b/src/AssetsRoutes.php @@ -0,0 +1,16 @@ +siteInfo->getHeaderImages(); + } +} diff --git a/src/ContactInfo.php b/src/Contacts/ContactInfo.php similarity index 98% rename from src/ContactInfo.php rename to src/Contacts/ContactInfo.php index 84cbc67..a7c3b1a 100644 --- a/src/ContactInfo.php +++ b/src/Contacts/ContactInfo.php @@ -1,5 +1,5 @@ templating->render('contact', [ + 'contacts' => $this->contacts->getContacts(), + ]); + } + + #[Route('GET', '/contact.php')] + #[Route('GET', '/contact.html')] + #[Route('GET', '/nintendo')] + #[Route('GET', '/nintendo.php')] + public function getRedirect($response): void { + $response->redirect('/contact', true); + } +} diff --git a/src/HomeRoutes.php b/src/HomeRoutes.php new file mode 100644 index 0000000..b36e0e6 --- /dev/null +++ b/src/HomeRoutes.php @@ -0,0 +1,89 @@ +getParam('p'); + if($request->hasParam('p')) { + $response->redirect(match($request->getParam('p')) { + 'projects' => '/projects', + 'contact' => '/contacts', + 'about' => '/', + 'etc' => '/', + 'hosted' => '/', + 'friends' => '/', + default => '/', + }, true); + return; + } + + $projectInfos = $this->projects->getProjects( + featuredOnly: true, + deleted: false, + take: 3, + random: true, + ); + + $projects = []; + foreach($projectInfos as $projectInfo) + $projects[] = [ + 'info' => $projectInfo, + 'colour' => $projectInfo->hasColour() ? $projectInfo->getColour() : $this->projects->getProjectColour($projectInfo), + ]; + + $contacts = $this->contacts->getContacts( + homePageOnly: true, + take: 3, + ); + + return $this->templating->render('index', [ + 'projects' => $projects, + 'contacts' => $contacts, + ]); + } + + #[Route('GET', '/home')] + public function getPersonalHome(): string { + return $this->templating->render('home/index'); + } + + // wow this is pretty quirky + #[Route('GET', '/about')] + #[Route('GET', '/about.html')] + #[Route('GET', '/about.php')] + #[Route('GET', '/index.php')] + #[Route('GET', '/index.html')] + #[Route('GET', '/related.php')] + #[Route('GET', '/related.html')] + #[Route('GET', '/friends')] + #[Route('GET', '/friends.php')] + #[Route('GET', '/friends.html')] + #[Route('GET', '/related')] + #[Route('GET', '/etc.php')] + #[Route('GET', '/etc.html')] + #[Route('GET', '/etcetera')] + #[Route('GET', '/etcetera.html')] + #[Route('GET', '/etcetera.php')] + #[Route('GET', '/misc')] + #[Route('GET', '/misc.html')] + #[Route('GET', '/misc.php')] + #[Route('GET', '/etc')] + #[Route('GET', '/365')] + #[Route('GET', '/donate')] + public function getRedirect($response): void { + $response->redirect('/', true); + } +} diff --git a/src/MakaiContext.php b/src/MakaiContext.php index 63768bd..1394b60 100644 --- a/src/MakaiContext.php +++ b/src/MakaiContext.php @@ -7,75 +7,79 @@ use Sasae\SasaeEnvironment; final class MakaiContext { private IDbConnection $dbConn; - private ?SasaeEnvironment $templating = null; + private SasaeEnvironment $templating; + + private SiteInfo $siteInfo; + + private Contacts\Contacts $contacts; + private Projects\Projects $projects; + private SSHKeys\SSHKeys $sshKeys; public function __construct(IDbConnection $dbConn) { $this->dbConn = $dbConn; + $this->siteInfo = new SiteInfo; + + $this->startTemplating(); + + $this->contacts = new Contacts\Contacts($dbConn); + $this->projects = new Projects\Projects($dbConn); + $this->sshKeys = new SSHKeys\SSHKeys($dbConn); } public function getDatabase(): IDbConnection { return $this->dbConn; } + public function getSiteInfo(): SiteInfo { + return $this->siteInfo; + } + + public function getContacts(): Contacts\Contacts { + return $this->contacts; + } + + public function getProjects(): Projects\Projects { + return $this->projects; + } + + public function getSSHKeys(): SSHKeys\SSHKeys { + return $this->sshKeys; + } + public function getTemplating(): SasaeEnvironment { - if($this->templating === null) { - $isDebug = Environment::isDebug(); - - $this->templating = new SasaeEnvironment( - MKI_DIR_TEMPLATES, - cache: $isDebug ? null : ['Makai', GitInfo::hash(true)], - debug: $isDebug, - ); - $this->templating->addGlobal('header_nav', $this->getDefaultNavigation()); - $this->templating->addGlobal('header_bgs', $this->getDefaultHeaders()); - $this->templating->addGlobal('footer_quotes', $this->getFooterQuotes()); - } - return $this->templating; } - public function getDefaultNavigation(): array { - return [ - ['title' => 'Home', 'link' => '/'], - ['title' => 'Projects', 'link' => '/projects'], - ['title' => 'Contact', 'link' => '/contact'], - ]; + public function startTemplating(): void { + $isDebug = Environment::isDebug(); + + $this->templating = new SasaeEnvironment( + MKI_DIR_TEMPLATES, + cache: $isDebug ? null : ['Makai', GitInfo::hash(true)], + debug: $isDebug, + ); + $this->templating->addGlobal('globals', [ + 'siteInfo' => $this->siteInfo, + ]); } - public function getDefaultHeaders(): array { - return [ - '/assets/headers/krk-000.jpg', '/assets/headers/krk-001.jpg', '/assets/headers/krk-002.jpg', - '/assets/headers/krk-003.jpg', '/assets/headers/krk-004.jpg', '/assets/headers/krk-005.jpg', - '/assets/headers/krk-006.jpg', '/assets/headers/krk-007.jpg', '/assets/headers/krk-008.jpg', + public function createRouting(): RoutingContext { + $routingCtx = new RoutingContext($this->templating); + $routingCtx->registerDefaultErrorPages(); - '/assets/headers/mkt-000.jpg', '/assets/headers/mkt-001.jpg', '/assets/headers/mkt-002.jpg', - '/assets/headers/mkt-003.jpg', '/assets/headers/mkt-004.jpg', '/assets/headers/mkt-005.jpg', - '/assets/headers/mkt-006.jpg', '/assets/headers/mkt-007.jpg', '/assets/headers/mkt-008.jpg', - '/assets/headers/mkt-009.jpg', '/assets/headers/mkt-010.jpg', '/assets/headers/mkt-011.jpg', - '/assets/headers/mkt-012.jpg', '/assets/headers/mkt-013.jpg', '/assets/headers/mkt-014.jpg', - '/assets/headers/mkt-015.jpg', '/assets/headers/mkt-016.jpg', '/assets/headers/mkt-017.jpg', - '/assets/headers/mkt-018.jpg', '/assets/headers/mkt-019.jpg', '/assets/headers/mkt-020.jpg', - '/assets/headers/mkt-021.jpg', '/assets/headers/mkt-022.jpg', '/assets/headers/mkt-023.jpg', - '/assets/headers/mkt-024.jpg', '/assets/headers/mkt-025.jpg', '/assets/headers/mkt-026.jpg', - '/assets/headers/mkt-027.jpg', '/assets/headers/mkt-028.jpg', '/assets/headers/mkt-029.jpg', - '/assets/headers/mkt-030.jpg', '/assets/headers/mkt-031.jpg', '/assets/headers/mkt-032.jpg', - '/assets/headers/mkt-033.jpg', '/assets/headers/mkt-034.jpg', '/assets/headers/mkt-035.jpg', - '/assets/headers/mkt-036.jpg', '/assets/headers/mkt-037.jpg', '/assets/headers/mkt-038.jpg', - '/assets/headers/mkt-039.jpg', '/assets/headers/mkt-040.jpg', '/assets/headers/mkt-041.jpg', - '/assets/headers/mkt-042.jpg', '/assets/headers/mkt-043.jpg', '/assets/headers/mkt-044.jpg', - '/assets/headers/mkt-045.jpg', '/assets/headers/mkt-046.jpg', '/assets/headers/mkt-047.jpg', - '/assets/headers/mkt-048.jpg', '/assets/headers/mkt-049.jpg', '/assets/headers/mkt-050.jpg', - '/assets/headers/mkt-051.jpg', '/assets/headers/mkt-052.jpg', '/assets/headers/mkt-053.jpg', - '/assets/headers/mkt-054.jpg', '/assets/headers/mkt-055.jpg', '/assets/headers/mkt-056.jpg', - '/assets/headers/mkt-057.jpg', '/assets/headers/mkt-058.jpg', '/assets/headers/mkt-059.jpg', - '/assets/headers/mkt-060.jpg', '/assets/headers/mkt-061.jpg', '/assets/headers/mkt-062.jpg', - '/assets/headers/mkt-063.jpg', - ]; - } + $routingCtx->register(new HomeRoutes($this->templating, $this->contacts, $this->projects)); + $routingCtx->register(new Contacts\ContactsRoutes($this->templating, $this->contacts)); + $routingCtx->register(new Projects\ProjectsRoutes($this->templating, $this->projects)); - public function getFooterQuotes(): array { - return [ - 'if it ain\'t broke, i\'ll break it', - ]; + $routingCtx->register(new AssetsRoutes($this->siteInfo)); + $routingCtx->register(new NowListeningRoutes($this->templating)); + $routingCtx->register(new Whois\WhoisRoutes($this->templating)); + + $routingCtx->register(new SSHKeys\SSHKeysRoutes($this->sshKeys)); + + $routingCtx->register(new Tools\AsciiRoutes($this->templating)); + $routingCtx->register(new Tools\RandomStringRoutes); + + return $routingCtx; } } diff --git a/src/NowListeningRoutes.php b/src/NowListeningRoutes.php new file mode 100644 index 0000000..c81ab83 --- /dev/null +++ b/src/NowListeningRoutes.php @@ -0,0 +1,39 @@ +templating->render('np', [ + 'header_offset' => (int)$request->getParam('offset', FILTER_SANITIZE_NUMBER_INT), + ]); + } + + #[Route('GET', '/now-listening.json')] + public function getJson(): array { + $info = json_decode(file_get_contents('https://now.flash.moe/get.php?u=flashwave_')); + if(empty($info[0]?->name)) + return []; + + $info = $info[0]; + + return [ + 'name' => $info->name, + 'now_playing' => !empty($info->nowplaying), + 'url' => $info->url, + 'cover' => $info->images?->large ?? '', + 'artist' => [ + 'name' => $info->artist?->name ?? '', + 'url' => explode('/_/', $info->url)[0], + ], + ]; + } +} diff --git a/src/LanguageInfo.php b/src/Projects/LanguageInfo.php similarity index 97% rename from src/LanguageInfo.php rename to src/Projects/LanguageInfo.php index da9e984..7b0e7d4 100644 --- a/src/LanguageInfo.php +++ b/src/Projects/LanguageInfo.php @@ -1,5 +1,5 @@ projects->getProjects(deleted: false); + + $items = []; + foreach($projectInfos as $projectInfo) + $items[] = [ + 'info' => $projectInfo, + 'langs' => $this->projects->getLanguages(projectInfo: $projectInfo), + 'colour' => $projectInfo->hasColour() ? $projectInfo->getColour() : $this->projects->getProjectColour($projectInfo), + ]; + + $sections = [ + 'projects' => [ + 'title' => 'Projects', + 'desc' => '', + 'items' => $items, + ], + ]; + + return $this->templating->render('projects', [ + 'sections' => $sections, + ]); + } + + #[Route('GET', '/projects.php')] + #[Route('GET', '/projects.html')] + #[Route('GET', '/utilities')] + #[Route('GET', '/utilities.php')] + #[Route('GET', '/utilities.html')] + public function getRedirect($response): void { + $response->redirect('/projects', true); + } +} diff --git a/src/RoutingContext.php b/src/RoutingContext.php new file mode 100644 index 0000000..d89754d --- /dev/null +++ b/src/RoutingContext.php @@ -0,0 +1,47 @@ +templating = $templating; + $this->router = new HttpFx; + $this->router->use('/', fn($resp) => $resp->setPoweredBy('Makai')); + } + + public function getRouter(): IRouter { + return $this->router; + } + + private function defaultErrorHandler($response, $request, $code, $text): void { + $name = sprintf('errors/%s', $code); + if(!is_file(sprintf('%s/%s.twig', MKI_DIR_TEMPLATES, $name))) + $name = 'errors/master'; + + $response->setContent($this->templating->render($name, [ + 'http_error_code' => $code, + 'http_error_title' => $text, + ])); + } + + public function registerDefaultErrorPages(): void { + $this->router->setDefaultErrorHandler($this->defaultErrorHandler(...)); + $this->router->get('/error/:code', fn($response, $request, string $code) => max(min((int)$code, 599), 400)); + } + + public function register(IRouteHandler $handler): void { + $this->router->register($handler); + } + + public function dispatch(?HttpRequest $request = null): void { + $this->router->dispatch($request); + } +} diff --git a/src/SSHKeyInfo.php b/src/SSHKeys/SSHKeyInfo.php similarity index 98% rename from src/SSHKeyInfo.php rename to src/SSHKeys/SSHKeyInfo.php index 188c006..eb0bb20 100644 --- a/src/SSHKeyInfo.php +++ b/src/SSHKeys/SSHKeyInfo.php @@ -1,5 +1,5 @@ getParam('l', FILTER_SANITIZE_NUMBER_INT); + $includeComment = $request->hasParam('c'); + $json = $request->hasParam('j'); + + $keys = $this->sshKeys->getKeys(minLevel: $minLevel, deprecated: false); + + if($json) { + $items = []; + + foreach($keys as $key) { + $items[] = $item = new \stdClass; + $item->algo = $key->getAlgorithm(); + $item->key = $key->getBody(); + if($includeComment) { + $item->comment = (string)$key->getComment(); + $item->created = $key->getCreatedAt()->format(\DateTime::ATOM); + $item->level = $key->getLevel(); + } + } + + return $items; + } + + $response->setTypePlain(); + $body = ''; + + foreach($keys as $key) + $body .= $key->toString($includeComment) . "\n"; + + return $body; + } + + #[Route('GET', '/authorized_keys')] + public function getAuthorisedKeys($response, $request): string { + $response->setTypePlain(); + $body = ''; + + $keys = $this->sshKeys->getKeys(minLevel: 500, deprecated: false); + foreach($keys as $key) + $body .= $key->toString(true) . "\n"; + + return $body; + } + + #[Route('GET', '/git_keys_ro')] + public function getGitKeysReadOnly($response, $request): string { + $response->setTypePlain(); + $body = ''; + + $keys = $this->sshKeys->getKeys(minLevel: 100, deprecated: false); + foreach($keys as $key) + $body .= $key->toString(false) . "\n"; + + return $body; + } + + #[Route('GET', '/git_keys_rw')] + public function getGitKeysReadWrite($response, $request): string { + $response->setTypePlain(); + $body = ''; + + $keys = $this->sshKeys->getKeys(minLevel: 200, deprecated: false); + foreach($keys as $key) + $body .= $key->toString(false) . "\n"; + + return $body; + } + + #[Route('GET', '/ssh.php')] + public function getSshPhp($response, $request): void { + $query = []; + + $minLevel = (int)$request->getParam('l', FILTER_SANITIZE_NUMBER_INT); + if($minLevel > 0) + $query['l'] = $minLevel; + + if($request->hasParam('c')) + $query['c'] = 1; + + if($request->hasParam('j')) + $query['j'] = 1; + + $url = '/ssh_keys'; + if(!empty($query)) + $url .= '?' . http_build_query($query, encoding_type: PHP_QUERY_RFC3986); + + $response->redirect($url, true); + } +} diff --git a/src/SiteInfo.php b/src/SiteInfo.php new file mode 100644 index 0000000..e702fe3 --- /dev/null +++ b/src/SiteInfo.php @@ -0,0 +1,49 @@ + 'Home', 'link' => '/'], + ['title' => 'Projects', 'link' => '/projects'], + ['title' => 'Contact', 'link' => '/contact'], + ]; + } + + public function getHeaderImages(): array { + return [ + '/assets/headers/krk-000.jpg', '/assets/headers/krk-001.jpg', '/assets/headers/krk-002.jpg', + '/assets/headers/krk-003.jpg', '/assets/headers/krk-004.jpg', '/assets/headers/krk-005.jpg', + '/assets/headers/krk-006.jpg', '/assets/headers/krk-007.jpg', '/assets/headers/krk-008.jpg', + + '/assets/headers/mkt-000.jpg', '/assets/headers/mkt-001.jpg', '/assets/headers/mkt-002.jpg', + '/assets/headers/mkt-003.jpg', '/assets/headers/mkt-004.jpg', '/assets/headers/mkt-005.jpg', + '/assets/headers/mkt-006.jpg', '/assets/headers/mkt-007.jpg', '/assets/headers/mkt-008.jpg', + '/assets/headers/mkt-009.jpg', '/assets/headers/mkt-010.jpg', '/assets/headers/mkt-011.jpg', + '/assets/headers/mkt-012.jpg', '/assets/headers/mkt-013.jpg', '/assets/headers/mkt-014.jpg', + '/assets/headers/mkt-015.jpg', '/assets/headers/mkt-016.jpg', '/assets/headers/mkt-017.jpg', + '/assets/headers/mkt-018.jpg', '/assets/headers/mkt-019.jpg', '/assets/headers/mkt-020.jpg', + '/assets/headers/mkt-021.jpg', '/assets/headers/mkt-022.jpg', '/assets/headers/mkt-023.jpg', + '/assets/headers/mkt-024.jpg', '/assets/headers/mkt-025.jpg', '/assets/headers/mkt-026.jpg', + '/assets/headers/mkt-027.jpg', '/assets/headers/mkt-028.jpg', '/assets/headers/mkt-029.jpg', + '/assets/headers/mkt-030.jpg', '/assets/headers/mkt-031.jpg', '/assets/headers/mkt-032.jpg', + '/assets/headers/mkt-033.jpg', '/assets/headers/mkt-034.jpg', '/assets/headers/mkt-035.jpg', + '/assets/headers/mkt-036.jpg', '/assets/headers/mkt-037.jpg', '/assets/headers/mkt-038.jpg', + '/assets/headers/mkt-039.jpg', '/assets/headers/mkt-040.jpg', '/assets/headers/mkt-041.jpg', + '/assets/headers/mkt-042.jpg', '/assets/headers/mkt-043.jpg', '/assets/headers/mkt-044.jpg', + '/assets/headers/mkt-045.jpg', '/assets/headers/mkt-046.jpg', '/assets/headers/mkt-047.jpg', + '/assets/headers/mkt-048.jpg', '/assets/headers/mkt-049.jpg', '/assets/headers/mkt-050.jpg', + '/assets/headers/mkt-051.jpg', '/assets/headers/mkt-052.jpg', '/assets/headers/mkt-053.jpg', + '/assets/headers/mkt-054.jpg', '/assets/headers/mkt-055.jpg', '/assets/headers/mkt-056.jpg', + '/assets/headers/mkt-057.jpg', '/assets/headers/mkt-058.jpg', '/assets/headers/mkt-059.jpg', + '/assets/headers/mkt-060.jpg', '/assets/headers/mkt-061.jpg', '/assets/headers/mkt-062.jpg', + '/assets/headers/mkt-063.jpg', + ]; + } + + public function getFooterQuotes(): array { + return [ + 'if it ain\'t broke, i\'ll break it', + ]; + } +} diff --git a/src/Tools/AsciiRoutes.php b/src/Tools/AsciiRoutes.php new file mode 100644 index 0000000..557a813 --- /dev/null +++ b/src/Tools/AsciiRoutes.php @@ -0,0 +1,26 @@ +templating->addFilter('chr', 'chr'); + $this->templating->addFilter('decoct', 'decoct'); + $this->templating->addFilter('dechex', 'dechex'); + + return $this->templating->render('ascii'); + } + + #[Route('GET', '/ascii.php')] + public function getAsciiPHP($response, $request): void { + $response->redirect('/ascii', true); + } +} diff --git a/src/Tools/RandomStringRoutes.php b/src/Tools/RandomStringRoutes.php new file mode 100644 index 0000000..07df8a2 --- /dev/null +++ b/src/Tools/RandomStringRoutes.php @@ -0,0 +1,36 @@ +setTypePlain(); + + $length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT); + if($length > 0 && $length <= 1024) + return XString::random($length); + + $out = '8: ' . XString::random(8) . PHP_EOL; + $out .= '16: ' . XString::random(16) . PHP_EOL; + $out .= '32: ' . XString::random(32) . PHP_EOL; + $out .= '64: ' . XString::random(64) . PHP_EOL; + $out .= '128: ' . XString::random(128) . PHP_EOL; + + return $out; + } + + #[Route('GET', '/key.php')] + public function getKeyPHP($response, $request): void { + $url = '/rngstr'; + + $length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT); + if($length > 0 && $length <= 1024) + $url .= sprintf('?length=%s', $length); + + $response->redirect($url, true); + } +} diff --git a/src/Whois/WhoisRoutes.php b/src/Whois/WhoisRoutes.php new file mode 100644 index 0000000..bc996f7 --- /dev/null +++ b/src/Whois/WhoisRoutes.php @@ -0,0 +1,59 @@ +templating->render('whois'); + } + + #[Route('GET', '/whois/lookup')] + public function getLookup($response, $request): array { + $target = trim((string)$request->getParam('target')); + if(empty($target)) + return [ + 'error' => true, + 'text' => 'Missing input data.', + ]; + + $hash = hash('sha256', $target); + $prefix = 'fm:whois2:target:'; + $source = ''; + + try { + $redis = new \Redis; + $redis->connect('/var/run/redis/redis-server.sock'); + + $result = $redis->get($prefix . $hash); + + if(empty($result)) { + $client = new WhoisClient; + $result = $client->lookup($target); + $redis->setEx($prefix . $hash, 1800, serialize($result)); + $source = 'fresh'; + } else { + $result = unserialize($result); + $source = 'cache'; + } + } catch (\RuntimeException $ex) { + return [ + 'error' => true, + 'text' => $ex->getMessage(), + ]; + } + + return [ + 'error' => false, + 'source' => $source, + 'result' => $result, + ]; + } +} diff --git a/templates/index.twig b/templates/index.twig index f491225..1f44a6e 100644 --- a/templates/index.twig +++ b/templates/index.twig @@ -6,7 +6,7 @@ {% block container %}
- {% for link in header_nav|slice(1) %} + {% for link in globals.siteInfo.headerNavigation|slice(1) %} {{ link.title }} {% endfor %}
diff --git a/templates/master.twig b/templates/master.twig index 2ed13a5..ef08c4b 100644 --- a/templates/master.twig +++ b/templates/master.twig @@ -11,7 +11,7 @@
- +
0 %}style="padding-bottom: {{ header_offset }}px"{% endif %}>
{{ link.title }} {% endfor %}
@@ -44,7 +44,7 @@ {% endblock %} {% if footer_onload is defined %}