'/', '/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(); $response->setContent($tpl->render($tpl->exists($path) ? $path : 'errors/master', [ 'http_error_code' => $code, 'http_error_title' => $text, ])); }); $router->get('/error/:code', function($response, $request, $code) { return intval($code); }); foreach(MKI_REDIRS as $source => $target) $router->get($source, function($response) use ($target) { $response->redirect($target); }); $router->use('/', function($response) { $response->setPoweredBy('Makai+Index'); }); $router->get('/header-bgs.json', function() { return json_encode(FM_BGS); }); $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; } } $db = $ctx->getDatabase(); return $ctx->getTemplating()->render('index', [ 'projects' => (new Projects($db))->getFeatured(), 'languages' => new Languages($db), 'contacts' => (new Contacts($db))->getHomePage(), ]); }); $router->get('/contact', function() use ($ctx) { return $ctx->getTemplating()->render('contact', [ 'contacts' => (new Contacts($ctx->getDatabase()))->getAll(), ]); }); $router->get('/projects', function() use ($ctx) { $db = $ctx->getDatabase(); $projects = (new Projects($db))->getAll(); $sections = [ 'projects' => [ 'title' => 'Active Projects', 'desc' => 'Projects that I work on on a fairly regular basis.', 'items' => [], ], 'tools' => [ 'title' => 'Tools', 'desc' => 'Personal quality of life tools that I update when I need something new from them.', 'items' => [], ], 'archives' => [ 'title' => 'Archived Projects', 'desc' => 'Past projects that I no longer work on.', 'items' => [], ], ]; foreach($projects as $project) { if($project->isArchived()) $sections['archives']['items'][] = $project; else { if($project->isTool()) $sections['tools']['items'][] = $project; else $sections['projects']['items'][] = $project; } } return $ctx->getTemplating()->render('projects', [ 'sections' => $sections, 'languages' => new Languages($db), ]); }); $router->get('/ascii', function() use ($ctx) { return $ctx->getTemplating()->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); 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(500); 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(100); 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(200); 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();