'Home', 'link' => '/'], ['title' => 'Projects', 'link' => '/projects'], ['title' => 'Contact', 'link' => '/contact'], ]); define('FM_BGS', [ '/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', ]); define('FM_FEET', [ 'if it ain\'t broke, i\'ll break it', ]); define('FM_ERRS' , [ 403 => [ 'code' => 403, 'title' => 'Access Denied', 'image' => '/assets/errors/403.jpg', 'desc' => 'You are not supposed to be here.', ], 404 => [ 'code' => 404, 'title' => 'Not Found', 'image' => '/assets/errors/404.jpg', 'desc' => 'Whatever you\'re looking for is no longer here, or might not have been here in the first place.', ], 405 => [ 'code' => 405, 'title' => 'Method Not Supported', 'image' => '/assets/errors/405.jpg', 'desc' => 'You\'re up to something, aren\'t you?', ], ]); function fm_component(string $_component_name, array $vars = []): string { extract($vars); ob_start(); require __DIR__ . '/../components/' . $_component_name . '.php'; $meow = ob_get_contents(); ob_clean(); return $meow; } function first_paragraph(string $text, string $delimiter = "\n"): string { $index = mb_strpos($text, $delimiter); return $index === false ? $text : mb_substr($text, 0, $index); } function time_elapsed(int $since, bool $full = false): string { $now = new DateTime; $since = new DateTime(date('c', $since)); $diff = $now->diff($since); $diff->w = floor($diff->d / 7); $diff->d -= $diff->w * 7; $string = [ 'y' => 'year', 'm' => 'month', 'w' => 'week', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second', ]; foreach($string as $key => &$value) { if($diff->{$key}) $value = $diff->{$key} . ' ' . $value . ($diff->{$key} > 1 ? 's' : ''); else unset($string[$key]); } if(!$full) $string = array_slice($string, 0, 1); return $string ? implode(', ', $string) . ' ago' : 'just now'; } function cache_output(string $name, int $lifetime, callable $callable) { $path = sys_get_temp_dir() . '/fm-' . $name . '.cache'; if(!is_file($path) || (filemtime($path) + $lifetime) < time()) file_put_contents($path, serialize($callable())); return unserialize(file_get_contents($path)); } $reqMethod = (string)filter_input(INPUT_SERVER, 'REQUEST_METHOD'); $reqPath = '/' . trim(parse_url((string)filter_input(INPUT_SERVER, 'REQUEST_URI'), PHP_URL_PATH), '/'); $reqHead = false; if($reqMethod == 'HEAD') { $reqMethod = 'GET'; $reqHead = true; } $router = new Router; $router->get('/error/:code', function(string $code) use ($reqHead) { $errorInfo = FM_ERRS[$code ?? 404] ?? FM_ERRS[404]; http_response_code($errorInfo['code']); if(!$reqHead) { $body = fm_component('header', ['title' => $errorInfo['title']]); $body .= <<

{$errorInfo['title']}

{$errorInfo['image']}
{$errorInfo['desc']}
HTML; $body .= fm_component('footer'); return $body; } }); function mkiRedirect(string $to): callable { return function() use ($to) { header('Location: ' . $to); return 302; }; } require_once MKI_DIR_PAGES . '/contact.php'; require_once MKI_DIR_PAGES . '/index.php'; require_once MKI_DIR_PAGES . '/projects.php'; require_once MKI_DIR_PAGES . '/ssh.php'; header('X-Powered-By: Makai'); try { $handlers = $router->resolve($reqMethod, $reqPath); } catch(RoutePathNotFoundException $ex) { $handlers = $router->resolve('GET', '/error/404'); } catch(RouteMethodNotSupportedException $ex) { $handlers = $router->resolve('GET', '/error/405'); } $result = $handlers->run(); if(is_int($result) && $result >= 400 && $result < 600) $result = $router->resolve('GET', "/error/{$result}")->run(); if($result !== null && !is_bool($result)) { if(is_int($result)) { http_response_code($result); header('Content-Type: text/plain; charset=us-ascii'); echo $result; } elseif(is_array($result) || $result instanceof \stdClass || $result instanceof \JsonSerializable) { http_response_code(200); header('Content-Type: application/json; charset=utf-8'); echo json_encode($result); } else { $result = (string)$result; if(strtolower(substr($result, 0, 14)) === '