'/', '/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();