2020-07-30 00:55:37 +00:00
|
|
|
<?php
|
2022-02-04 20:30:52 +00:00
|
|
|
namespace Makai;
|
|
|
|
|
|
|
|
use Index\DateTime;
|
2022-02-05 03:35:42 +00:00
|
|
|
use Index\Routing\Router;
|
|
|
|
use Index\Routing\RoutePathNotFoundException;
|
|
|
|
use Index\Routing\RouteMethodNotSupportedException;
|
2022-02-04 20:30:52 +00:00
|
|
|
|
|
|
|
require_once __DIR__ . '/../makai.php';
|
|
|
|
|
2020-07-30 00:55:37 +00:00
|
|
|
define('FM_NAV', [
|
|
|
|
['title' => 'Home', 'link' => '/'],
|
|
|
|
['title' => 'Projects', 'link' => '/projects'],
|
|
|
|
['title' => 'Contact', 'link' => '/contact'],
|
|
|
|
]);
|
|
|
|
|
|
|
|
define('FM_BGS', [
|
2020-08-19 02:48:31 +00:00
|
|
|
'/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',
|
2020-07-30 00:55:37 +00:00
|
|
|
]);
|
|
|
|
|
|
|
|
define('FM_FEET', [
|
|
|
|
'if it ain\'t broke, i\'ll break it',
|
|
|
|
]);
|
|
|
|
|
|
|
|
define('FM_ERRS' , [
|
2020-08-19 14:33:55 +00:00
|
|
|
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?',
|
|
|
|
],
|
2020-07-30 00:55:37 +00:00
|
|
|
]);
|
|
|
|
|
2020-10-30 13:43:48 +00:00
|
|
|
define('FM_DYNLOAD', filter_input(INPUT_SERVER, 'HTTP_ACCEPT') === 'application/x-fdynload+json');
|
|
|
|
|
2022-02-05 03:35:42 +00:00
|
|
|
function fm_component(string $_component_name, array $vars = []): string {
|
2020-10-30 13:43:48 +00:00
|
|
|
if(FM_DYNLOAD) {
|
|
|
|
global $fmComponentVars;
|
|
|
|
if(!isset($fmComponentVars))
|
|
|
|
$fmComponentVars = [];
|
|
|
|
$fmComponentVars[$_component_name] = $vars;
|
2022-02-05 03:35:42 +00:00
|
|
|
return '';
|
2020-10-30 13:43:48 +00:00
|
|
|
}
|
|
|
|
|
2020-07-30 00:55:37 +00:00
|
|
|
extract($vars);
|
2022-02-05 03:35:42 +00:00
|
|
|
|
|
|
|
ob_start();
|
2020-09-08 21:09:02 +00:00
|
|
|
require __DIR__ . '/../components/' . $_component_name . '.php';
|
2022-02-05 03:35:42 +00:00
|
|
|
$meow = ob_get_contents();
|
|
|
|
ob_clean();
|
|
|
|
|
|
|
|
return $meow;
|
2020-07-30 00:55:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2022-02-04 20:30:52 +00:00
|
|
|
$reqMethod = (string)filter_input(INPUT_SERVER, 'REQUEST_METHOD');
|
|
|
|
$reqPath = '/' . trim(parse_url((string)filter_input(INPUT_SERVER, 'REQUEST_URI'), PHP_URL_PATH), '/');
|
2020-08-31 15:43:18 +00:00
|
|
|
$reqHead = false;
|
|
|
|
|
|
|
|
if($reqMethod == 'HEAD') {
|
|
|
|
$reqMethod = 'GET';
|
|
|
|
$reqHead = true;
|
|
|
|
}
|
2020-07-30 00:55:37 +00:00
|
|
|
|
2022-02-05 03:35:42 +00:00
|
|
|
$router = new Router;
|
2020-10-30 13:43:48 +00:00
|
|
|
|
2022-02-05 03:35:42 +00:00
|
|
|
$router->get('/error/:code', function(string $code) use ($reqHead) {
|
|
|
|
$errorInfo = FM_ERRS[$code ?? 404] ?? FM_ERRS[404];
|
2020-10-30 13:43:48 +00:00
|
|
|
http_response_code($errorInfo['code']);
|
2020-08-19 14:33:55 +00:00
|
|
|
|
2020-10-30 13:43:48 +00:00
|
|
|
if(!$reqHead) {
|
2022-02-05 03:35:42 +00:00
|
|
|
$body = fm_component('header', ['title' => $errorInfo['title']]);
|
|
|
|
|
|
|
|
$body .= <<<HTML
|
2020-10-30 13:43:48 +00:00
|
|
|
<div class="http-error">
|
2022-02-05 03:35:42 +00:00
|
|
|
<h2 class="http-error-head">{$errorInfo['title']}</h2>
|
|
|
|
<img src="{$errorInfo['image']}" alt="{$errorInfo['image']}" class="http-error-image"/>
|
|
|
|
<div class="http-error-desc">{$errorInfo['desc']}</div>
|
2020-10-30 13:43:48 +00:00
|
|
|
</div>
|
2022-02-05 03:35:42 +00:00
|
|
|
HTML;
|
|
|
|
|
|
|
|
$body .= fm_component('footer');
|
|
|
|
|
|
|
|
return $body;
|
2020-10-30 13:43:48 +00:00
|
|
|
}
|
2022-02-05 03:35:42 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
function mkiRedirect(string $to): callable {
|
|
|
|
return function() use ($to) {
|
|
|
|
header('Location: ' . $to);
|
|
|
|
return 302;
|
|
|
|
};
|
2020-10-30 13:43:48 +00:00
|
|
|
}
|
|
|
|
|
2022-02-05 03:35:42 +00:00
|
|
|
require_once MKI_DIR_PAGES . '/blog.php';
|
|
|
|
require_once MKI_DIR_PAGES . '/contact.php';
|
|
|
|
require_once MKI_DIR_PAGES . '/index.php';
|
|
|
|
require_once MKI_DIR_PAGES . '/projects.php';
|
2022-02-06 01:36:05 +00:00
|
|
|
require_once MKI_DIR_PAGES . '/ssh.php';
|
2022-02-05 03:35:42 +00:00
|
|
|
|
|
|
|
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');
|
|
|
|
}
|
2020-10-30 13:43:48 +00:00
|
|
|
|
2022-02-05 03:35:42 +00:00
|
|
|
$result = $handlers->run();
|
|
|
|
|
2022-02-05 03:39:56 +00:00
|
|
|
if(is_int($result) && $result >= 400 && $result < 600)
|
2022-02-05 03:35:42 +00:00
|
|
|
$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)) === '<!doctype html') {
|
|
|
|
header('Content-Type: text/html; charset=utf-8');
|
|
|
|
echo $result;
|
|
|
|
} else {
|
|
|
|
if(FM_DYNLOAD) {
|
|
|
|
header('Content-Type: application/x-fdynload+json');
|
|
|
|
echo json_encode([
|
|
|
|
'components' => $fmComponentVars ?? [],
|
|
|
|
'raw_html' => $result,
|
|
|
|
]);
|
|
|
|
} else {
|
|
|
|
echo $result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-08-31 15:43:18 +00:00
|
|
|
}
|