diff options
| author | Freya Murphy <freya@freyacat.org> | 2026-02-23 22:57:27 -0500 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2026-02-23 22:57:27 -0500 |
| commit | f373ead95fb5beb962c376b5b7b46dfde8ac4e57 (patch) | |
| tree | c99df23521ff2a5e5e2e4627c525a5e99dc2e3ae /src | |
| parent | add 96x96 logo (diff) | |
| download | website-f373ead95fb5beb962c376b5b7b46dfde8ac4e57.tar.gz website-f373ead95fb5beb962c376b5b7b46dfde8ac4e57.tar.bz2 website-f373ead95fb5beb962c376b5b7b46dfde8ac4e57.zip | |
update website to work with crimson framework
Diffstat (limited to '')
35 files changed, 124 insertions, 1111 deletions
diff --git a/src/db/migrations/0003.sql b/src/db/migrations/0003.sql new file mode 100644 index 0000000..1e47e73 --- /dev/null +++ b/src/db/migrations/0003.sql @@ -0,0 +1,11 @@ +BEGIN TRANSACTION; +SET search_path = public; + +-- Migration Start +ALTER SCHEMA admin RENAME TO website; +-- Migration End; + +-- Set Current Revision +UPDATE sys.database_info SET curr_revision = 4 WHERE name = current_database(); + +COMMIT TRANSACTION; diff --git a/src/public/css/prism.css b/src/public/css/prism.css deleted file mode 100644 index 5137f0c..0000000 --- a/src/public/css/prism.css +++ /dev/null @@ -1,3 +0,0 @@ -/* PrismJS 1.29.0 -https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+awk+bash+c+csharp+cpp+elixir+erlang+go+java+javadoclike+kotlin+lua+markup-templating+php+plsql+racket+ruby+rust+sass+scss+scala+scheme+sql+typescript+zig */ -code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green} diff --git a/src/public/icons/favicon.ico b/src/public/favicon.ico Binary files differindex 1fae1b9..1fae1b9 100644 --- a/src/public/icons/favicon.ico +++ b/src/public/favicon.ico diff --git a/src/scss/main.scss b/src/scss/main.scss index 1148ba1..b9ef3ee 100644 --- a/src/scss/main.scss +++ b/src/scss/main.scss @@ -77,6 +77,9 @@ html { font-family: $font; font-size: 120%; background: #181818; +} + +body { background-image: url("../img/background.jpg?ref=2"); background-repeat: repeat; background-size: 512px; diff --git a/src/web/_controller/_comments.php b/src/web/_controller/_comments.php index 3b8fe35..c81ae9d 100644 --- a/src/web/_controller/_comments.php +++ b/src/web/_controller/_comments.php @@ -5,6 +5,7 @@ class _comments_controller extends Controller { function __construct() { $this->comments_model = $this->load_model('_comments'); + $this->load_lang('common'); } public function comments(string $page, string $ref): void { @@ -12,7 +13,8 @@ class _comments_controller extends Controller { $this->view('comments', array( 'comments' => $data, 'ref' => $ref, - 'page' => $page + 'page' => $page, + 'ip', $this->comments_model->get_ip(), )); } diff --git a/src/web/_controller/_meta.php b/src/web/_controller/_meta.php index 9ea3f47..ac9f682 100644 --- a/src/web/_controller/_meta.php +++ b/src/web/_controller/_meta.php @@ -1,6 +1,10 @@ <?php /* Copyright (c) 2024 Freya Murphy */ class _meta_controller extends Controller { + function __construct() { + $this->load_lang('common'); + } + public function robots(): void { header("Content-Type: text/plain"); diff --git a/src/web/_controller/blog.php b/src/web/_controller/blog.php index 2ea45df..9cb93e5 100644 --- a/src/web/_controller/blog.php +++ b/src/web/_controller/blog.php @@ -8,6 +8,7 @@ class Blog_controller extends Controller { { $this->blog_model = $this->load_model('blog'); $this->comments_controller = $this->load_controller('_comments'); + $this->load_lang('common', 'blog'); } public function index(): void diff --git a/src/web/_controller/bucket.php b/src/web/_controller/bucket.php index e14f9b6..460f862 100644 --- a/src/web/_controller/bucket.php +++ b/src/web/_controller/bucket.php @@ -6,6 +6,7 @@ class Bucket_controller extends Controller { function __construct() { $this->bucket_model = $this->load_model('bucket'); + $this->load_lang('common', 'bucket'); } public function index(): void diff --git a/src/web/_controller/error.php b/src/web/_controller/error.php index 9efbb7e..ed89a89 100644 --- a/src/web/_controller/error.php +++ b/src/web/_controller/error.php @@ -6,6 +6,7 @@ class Error_controller extends Controller { function __construct() { $this->error_model = $this->load_model('error'); + $this->load_lang('common', 'error'); } public function code(int $code): void @@ -18,7 +19,7 @@ class Error_controller extends Controller { parent::index(); $this->load_lang('error'); - $data = $this->error_model->get_data($code); + $data = $this->error_model->get_error_data($code); $this->view('header', $data); $this->view('error/main', $data); $this->view('footer', $data); diff --git a/src/web/_controller/home.php b/src/web/_controller/home.php index 89e67e8..28ccd1e 100644 --- a/src/web/_controller/home.php +++ b/src/web/_controller/home.php @@ -1,11 +1,19 @@ <?php /* Copyright (c) 2024 Freya Murphy */ class Home_controller extends Controller { + private $home_model; + + function __construct() + { + $this->home_model = $this->load_model('home'); + $this->load_lang('common', 'home'); + } + public function index(): void { parent::index(); - $data = Model::get_base_data(); + $data = $this->home_model->get_data(); $this->view('header', $data); $this->view('home/main', $data); $this->view('footer', $data); diff --git a/src/web/_controller/projects.php b/src/web/_controller/projects.php index fea4664..35274b5 100644 --- a/src/web/_controller/projects.php +++ b/src/web/_controller/projects.php @@ -6,6 +6,7 @@ class Projects_controller extends Controller { function __construct() { $this->projects_model = $this->load_model('projects'); + $this->load_lang('common', 'projects'); } public function index(): void diff --git a/src/web/_model/_comments.php b/src/web/_model/_comments.php index 3518508..765fda8 100644 --- a/src/web/_model/_comments.php +++ b/src/web/_model/_comments.php @@ -36,10 +36,10 @@ class _comments_model extends Model { public function get_comments($page) { - $ip = CONTEXT['ip']; + $ip = $this->get_ip(); $query = $this->db() ->select('*') - ->from('admin.comment c') + ->from('website.comment c') ->where('c.page') ->eq($page) ->query('AND ( @@ -53,12 +53,30 @@ class _comments_model extends Model { public function post_comment($author, $content, $page, $vulgar) { - $ip = CONTEXT['ip']; + $ip = $this->get_ip(); return $this->db() - ->insert_into('admin.comment', + ->insert_into('website.comment', 'author', 'content', 'page', 'ip', 'vulgar') ->values($author, $content, $page, $ip, $vulgar) ->execute(); } + public function get_ip(): ?string + { + $headers = array ( + 'HTTP_CLIENT_IP', + 'HTTP_X_FORWARDED_FOR', + 'HTTP_X_FORWARDED', + 'HTTP_FORWARDED_FOR', + 'HTTP_FORWARDED', + 'HTTP_X_REAL_IP', + 'REMOTE_ADDR' + ); + foreach ($headers as $header) { + if (isset($_SERVER[$header])) + return $_SERVER[$header]; + } + return NULL; + } + } diff --git a/src/web/_model/blog.php b/src/web/_model/blog.php index 94ca049..6446564 100644 --- a/src/web/_model/blog.php +++ b/src/web/_model/blog.php @@ -30,7 +30,7 @@ class Blog_model extends Model { } public function get_data(): array { - $data = parent::get_base_data('blog'); + $data = parent::get_data(); $this->load_blog($data); $data['title'] = lang('title'); $data['desc'] = lang('blog_short_desc'); @@ -68,7 +68,7 @@ class Blog_model extends Model { * @return bool|null|array */ public function get_post($name): ?array { - $data = parent::get_base_data(); + $data = parent::get_data(); $post = $this->render_post($name); if (!$post) { return NULL; @@ -97,7 +97,7 @@ class Blog_model extends Model { * @return bool|null|array */ public function get_writeup($name): ?array { - $data = parent::get_base_data(); + $data = parent::get_data(); $writeup = $this->render_writeup($name); if (!$writeup) { return NULL; @@ -108,4 +108,3 @@ class Blog_model extends Model { return $data; } } -?> diff --git a/src/web/_model/bucket.php b/src/web/_model/bucket.php index 374836e..7c426b7 100644 --- a/src/web/_model/bucket.php +++ b/src/web/_model/bucket.php @@ -3,7 +3,9 @@ class Bucket_model extends Model { public function get_data(): ?array { - $data = parent::get_base_data(); + $data = parent::get_data(); + $data['title'] = lang('first_name'); + $data['desc'] = lang('default_short_desc'); if (array_key_exists('name', $_GET)) $data['name'] = $_GET['name']; @@ -18,4 +20,3 @@ class Bucket_model extends Model { return $data; } } -?> diff --git a/src/web/_model/error.php b/src/web/_model/error.php index 08046f3..74bbd20 100644 --- a/src/web/_model/error.php +++ b/src/web/_model/error.php @@ -5,21 +5,22 @@ class Error_model extends Model { { http_response_code($code); $data['title'] = $code; - $msg = ucfirst(lang('error_' . $code, FALSE)); + $msg = status_code_msg($code); + if (!$msg && $code == 0) + $msg = lang('error_0'); if (!$msg) { $error_text = lang('error', NULL); $msg = $error_text[array_rand($error_text)]; $msg = sprintf($msg, $code); } $data['msg'] = $msg; - + $data['desc'] = $msg; } - public function get_data(int $code): array + public function get_error_data(int $code): array { - $data = parent::get_base_data('error'); + $data = parent::get_data(); $this->get_msg($data, $code); return $data; } } -?> diff --git a/src/web/_model/home.php b/src/web/_model/home.php new file mode 100644 index 0000000..d1041db --- /dev/null +++ b/src/web/_model/home.php @@ -0,0 +1,10 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ +class Home_model extends Model { + + public function get_data(): ?array { + $data = parent::get_data(); + $data['title'] = lang('first_name'); + $data['desc'] = lang('default_short_desc'); + return $data; + } +} diff --git a/src/web/_model/projects.php b/src/web/_model/projects.php index 537bce5..fbf37c8 100644 --- a/src/web/_model/projects.php +++ b/src/web/_model/projects.php @@ -31,11 +31,10 @@ class Projects_model extends Model { public function get_data(): ?array { - $data = parent::get_base_data(); + $data = parent::get_data(); $this->load_projects($data); $data['title'] = lang('title'); $data['desc'] = lang('short_desc'); return $data; } } -?> diff --git a/src/web/_views/head.php b/src/web/_views/head.php index ab7bb1b..1ca6954 100644 --- a/src/web/_views/head.php +++ b/src/web/_views/head.php @@ -23,7 +23,7 @@ <link rel="manifest" href="/manifest.json"> <?php /* Main CSS */ - if (CONTEXT['app'] != 'bucket') + if (ROUTER->req['app'] != 'bucket') echo $this->link_css('css/main.css'); /* IE 4-7 Styles */ diff --git a/src/web/_views/header.php b/src/web/_views/header.php index 90a31ea..f6b4740 100644 --- a/src/web/_views/header.php +++ b/src/web/_views/header.php @@ -17,15 +17,15 @@ <li class="ie-nav"> <?=ilang('action_home', href: $this->get_url('home'), - container: 'h2' + subtype: 'h2' )?></li> <li><?=ilang('action_projects', href: $this->get_url('projects'), - container: 'h2' + subtype: 'h2' )?></li> <li><?=ilang('action_blog', href: $this->get_url('blog'), - container: 'h2' + subtype: 'h2' )?></li> </ul> </div> diff --git a/src/web/config.php b/src/web/config.php index 8689b8e..4a4e830 100644 --- a/src/web/config.php +++ b/src/web/config.php @@ -1,26 +1,33 @@ <?php /* Copyright (c) 2024 Freya Murphy */ -// ENVIRONMENT +// CONFIG +// config values needed across the website // -// devlopment - do not cache any assets -// - use http host provided by user +// domain - the default domain for the website // -// production - use generated timestamps for each file -// - hard code http host to 'domain' lang string +// allowed_hosts - accepted domains to use for the website // -define('ENVIRONMENT', 'devlopment'); - -// CONFIG +// base_path - the base path the website is located at // -// config values needed across the website - -define('CONFIG', array( +// theme_color - html hex color used for browser metadata +// +// routes - array of regex keys that match the request path and +// - place it with the value if it matches +// - e.g. '' => 'home' sends / to /home +// +// style - single or list of css styles to load on specific routes +// +// js - single or list of js script to load on specific routes +// +// autoload - list of directories to autoload all PHP files in them +// +define('SITE_CONFIG', array( /* core config settings */ - 'domain' => 'freya.cat', - 'allowed_hosts' => ['freya.cat', 'www.freya.cat'], - 'base_path' => '/', + 'domain' => getenv("WEBSITE_HOST"), + 'allowed_hosts' => explode(" ", getenv("WEBSITE_ALLOWED_HOSTS")), + 'base_path' => getenv("WEBSITE_BASE_PATH"), 'theme_color' => '#181818', - 'git_url' => 'https://g.freya.cat/freya', + 'git_url' => 'https://g.freya.cat', /* route overides */ 'routes' => array( '' => 'home', @@ -39,4 +46,8 @@ define('CONFIG', array( 'js' => array( 'blog' => 'js/prism.js', ), + /* directories to autoload php code */ + 'autoload' => array('/third_party', '/lib'), )); + +define('ASSET_ROOT', PHP_ROOT . '/assets'); diff --git a/src/web/core/component.php b/src/web/core/component.php deleted file mode 100644 index 376e24d..0000000 --- a/src/web/core/component.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -/** - * Gives access to imporant - * needed utility functions for - * accessing everything else! - */ -abstract class Component extends Core { - - // keep track of what has been loaded - private static array $loaded = array(); - -// ============================= LOADABLE OBJECTS == - - /** - * Loads a $type of object from a $dir with a given $name - * @param string $name - the name of the object to load - * @param string $dir - the directory theese objects are stored in - * @param string $type - the type of the object - */ - private function load_type($name, $dir, $type): object|NULL - { - - $path = $dir . '/' . $name . '.php'; - - // dont reload an ohject - if (array_key_exists($path, Component::$loaded)) - return Component::$loaded[$path]; - - // only load a object if it exists - if (!file_exists($path)) - return NULL; - - - $parts = explode('/', $name); - $part = end($parts); - $class = ucfirst($part) . '_' . $type; - require($path); - - $ref = NULL; - try { - $ref = new ReflectionClass($class); - } catch (Exception $_e) {} - - if ($ref === NULL) - return NULL; - - $obj = $ref->newInstance(); - Component::$loaded[$path] = $obj; - - return $obj; - } - - /** - * Loads a model - * @param string $name - the name of the model to load - */ - protected function load_model($name): Model|NULL - { - $dir = WEB_ROOT . '/_model'; - return $this->load_type($name, $dir, 'model'); - } - - /** - * Loads a controller - * @param string $name - the name of the controller to load - */ - public function load_controller($name): Controller|NULL - { - $dir = WEB_ROOT . '/_controller'; - return $this->load_type($name, $dir, 'controller'); - } - -// ========================================= LANG == - - /** - * Loads a php lang file into the lang array - */ - private static function load_lang_file(string $file): void - { - $lang = $GLOBALS['__lang']; - require($file); - $GLOBALS['__lang'] = $lang; - } - - /** - * Loads each php file lang strings in a directory - */ - private static function load_lang_dir(string $dir): void - { - if ($handle = opendir($dir)) { - while (false !== ($entry = readdir($handle))) { - if ($entry === '.' || $entry === '..') - continue; - Component::load_lang_file($entry); - } - } - } - - /** - * Loads the given common lang - */ - protected static function load_lang(string ...$langs): void - { - $root = WEB_ROOT . '/lang'; - - foreach ($langs as $lang) { - $file = "{$root}/{$lang}.php"; - $dir = "{$root}/{$lang}"; - - if (file_exists($file)) - Component::load_lang_file($file); - else if (is_dir($dir)) - Component::load_lang_dir($dir); - - } - } - -} diff --git a/src/web/core/controller.php b/src/web/core/controller.php deleted file mode 100644 index ca892e2..0000000 --- a/src/web/core/controller.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -abstract class Controller extends Component { - - /** - * Default index for a app, empty - */ - public function index(): void {} - - /** - * Redirectes to a link - */ - public function redirect(string $link): void - { - header('Location: '. $link, true, 301); - die(); - } - - /** - * Lodas a view - */ - protected function view(string $__name, array $data = array()): void - { - $__path = WEB_ROOT . '/_views/' . $__name . '.php'; - if (is_file($__path)) { - extract($data); - require($__path); - } - } - - /** - * Loads a erorr page with a given - * error code - */ - protected function error(int $code): void - { - $error_controller = $this->load_controller('error'); - $error_controller->code($code); - die(); - } - - /** - * Returns HTTP POST information if POST request. - * Returns 405 Method Not Allowed if not. - * - * If $key is specified, returns only that key. otherwise - * returns HTTP 400 Bad Request; - */ - protected function post_data(?string $key = NULL): array|string - { - // only post requests allowed - if ($_SERVER['REQUEST_METHOD'] != 'POST') - $this->error(405); - - // return entire $_POST array - if (!$key) - return $_POST; - - if (!isset($_POST[$key])) - $this->error(400); - - return $_POST[$key]; - } - -} diff --git a/src/web/core/core.php b/src/web/core/core.php deleted file mode 100644 index 4c341c2..0000000 --- a/src/web/core/core.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -/** - * Core functions needed everywhere - */ -abstract class Core { - - private static ?DatabaseHelper $db = NULL; - - /** - * Loads the database - */ - public static function db(): DatabaseHelper - { - if (!Component::$db) - Component::$db = new DatabaseHelper(); - return Component::$db; - } - - /** - * Gets the stamp for a asset path - * @param string $path - */ - public static function asset_stamp(string $path): int - { - if (ENVIRONMENT == 'devlopment') - return time(); - if (isset(FILE_TIMES[$path])) - return FILE_TIMES[$path]; - return 0; - } - - /** - * Gets a full path url from a relative path - * @param string $path - * @param bool $timestamp - */ - public static function get_url(string $path, bool $timestamp = FALSE): string - { - $scheme = 'http'; - if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) - $scheme = $_SERVER['HTTP_X_FORWARDED_PROTO']; - - $host = $_SERVER['HTTP_HOST']; - - if (ENVIRONMENT == 'production') { - $default = CONFIG['domain']; - $allowed = CONFIG['allowed_hosts']; - if (!is_array($allowed)) - $allowed = [$allowed]; - if (!in_array($host, $allowed)) - $host = $default; - } - - $base = CONFIG['base_path']; - $url = "{$scheme}://{$host}{$base}{$path}"; - if ($timestamp) { - $time = Core::asset_stamp($path); - $url .= "?timestamp={$time}"; - } - return $url; - } - - /** - * Loads a js html link - * @param string $path - the path to the js file - */ - public static function link_js(string $path): string - { - $stamp = Core::asset_stamp("public/$path"); - $href = Core::get_url("public/{$path}?timestamp={$stamp}"); - return '<script src="'. $href .'"></script>'; - } - - /** - * Loads a css html link - * @param string $path - the path to the css file - */ - public static function link_css(string $path): string - { - $stamp = Core::asset_stamp("public/$path"); - $href = Core::get_url("public/{$path}?timestamp={$stamp}"); - return '<link rel="stylesheet" href="'. $href .'">'; - } - - /** - * Loads a css html link - * @param string $path - the path to the css file - */ - public static function embed_css(string $path): string - { - $file = PUBLIC_ROOT . '/' . $path; - if (file_exists($file)) { - $text = file_get_contents($file); - return "<style>{$text}</style>"; - } else { - return ""; - } - } - - /** - * Formats a ISO date - * @param $iso_date the ISO date - */ - public static function format_date(string $iso_date): string - { - return date("Y-m-d D H:i", strtotime($iso_date)) . ' EST'; - } -} diff --git a/src/web/core/model.php b/src/web/core/model.php deleted file mode 100644 index 6a42a98..0000000 --- a/src/web/core/model.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -abstract class Model extends Component { - - /** - * @return array<string,mixed> - */ - public static function get_base_data(?string $app = NULL): array - { - $data = array(); - $data['title'] = lang('first_name'); - $data['desc'] = lang('default_short_desc'); - $data['css'] = array(); - $data['js'] = array(); - - $style = CONFIG['style']; - $js = CONFIG['js']; - - if (!$app) - $app = CONTEXT['app']; - - if (isset($style[$app])) { - $css = $style[$app]; - if (!is_array($css)) - $css = array($css); - $data['css'] = $css; - } - - if (isset($js[$app])) { - $js = $js[$app]; - if (!is_array($js)) - $js = array($js); - $data['js'] = $js; - } - - return $data; - } - -} diff --git a/src/web/core/router.php b/src/web/core/router.php deleted file mode 100644 index 6a543aa..0000000 --- a/src/web/core/router.php +++ /dev/null @@ -1,208 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -class Router extends Component { - - private bool $db_ready; - private bool $recursed; - private array $req; - - /** - * Creates a router - * @param Loader $load - the main laoder object - */ - function __construct() - { - $this->db_ready = file_exists('/status/ready'); - $this->recursed = FALSE; - $this->req = $this->get_req(); - } - - /** - * @param string $path - the current request path - * Gets the current route - * @return array<string,mixed> - */ - private function get_req_route($path): array - { - // trim the path - $path = trim($path); - // remove first '/' - $path = substr($path, 1); - - // get modified route - $routes = CONFIG['routes']; - foreach ($routes as $key => $value) { - $key = "/^{$key}$/"; - if (!preg_match($key, $path, $matches)) - continue; - - $path = $value; - - for ($i = 1; $i < count($matches); $i++) { - $path = str_replace( - "\\{$i}", - $matches[$i], - $path); - } - - break; - } - - // get path parts - $parts = explode('/', $path); - // get the length - $len = count($parts); - // get route info - $route = array(); - $route['app'] = $len > 0 ? $parts[0] : 'index'; - $route['slug'] = $len > 1 ? $parts[1] : 'index'; - $route['args'] = array_slice($parts, 2); - - return $route; - } - - /** - * Gets the users ip - */ - private function get_ip(): ?string - { - $headers = array ( - 'HTTP_CLIENT_IP', - 'HTTP_X_FORWARDED_FOR', - 'HTTP_X_FORWARDED', - 'HTTP_FORWARDED_FOR', - 'HTTP_FORWARDED', - 'HTTP_X_REAL_IP', - 'REMOTE_ADDR' - ); - foreach ($headers as $header) { - if (isset($_SERVER[$header])) - return $_SERVER[$header]; - } - return NULL; - } - - /** - * Gets the curret request info - * @return array<string,mixed> - */ - private function get_req(): array - { - $method = $_SERVER['REQUEST_METHOD']; - $uri_str = $_SERVER['REQUEST_URI']; - $uri = parse_url($uri_str); - - if (!$uri) { - $uri = array('path' => '/error'); - } - - $path = ''; - if (array_key_exists('path', $uri)) { - $path = $uri['path']; - } - - return array_merge( - array( - 'uri' => $uri, - 'uri_str' => $uri_str, - 'method' => $method, - 'ip' => $this->get_ip() - ), - $this->get_req_route($path), - ); - } - - /** - * Handles a router error code - * @param int $code - the http error code - */ - private function handle_error(int $code): void - { - if ($this->recursed) - die($code . ' (recursed)'); - - $this->recursed = TRUE; - $this->req['app'] = 'error'; - $this->req['slug'] = 'code'; - $this->req['args'] = array($code); - $this->handle_req(); - } - - /** - * @param array<int,mixed> $req - */ - private function load_htc(array $req): void - { - $parts = explode('/', $req['uri_str']); - $file = end($parts); - $path = PUBLIC_ROOT . '/polyfills/' . $file; - - if (file_exists($path)) { - header('Content-type: text/x-component'); - include($path); - } else { - $this->handle_error(400); - } - } - - /** - * @param array $req - * @param array<int,mixed> $req - */ - public function handle_req(): void - { - if ($this->recursed === FALSE) { - // if we are in a recursing error handler - // we dont want to trigger a db 503 forever - // since its already active - if ($this->db_ready === FALSE) { - $this->handle_error(503); - return; - } - } - - // server error if we cannot parse url - if (!$this->req) { - $this->handle_error(500); - return; - } - - // load htc if someone is requesting it (hi IE6 :3) - if (str_ends_with($this->req['uri_str'], '.htc')) { - $this->load_htc($this->req); - return; - } - - // load the controller - $controller = $this->load_controller($this->req['app']); - if ($controller === NULL) { - $this->handle_error(404); - return; - } - - $ref = NULL; - try { - $cls = new ReflectionClass($controller); - $mds = $cls->getMethods(ReflectionMethod::IS_PUBLIC); - foreach ($mds as $md) { - if ($md->name !== $this->req['slug']) - continue; - if (count($md->getParameters()) != - count($this->req['args'])) - continue; - $ref = $md; - break; - } - } catch (Exception $_e) {} - - if ($ref === NULL) { - $this->handle_error(404); - return; - } - - define('CONTEXT', $this->req); - Component::load_lang('common', $this->req['app']); - $ref->invokeArgs($controller, $this->req['args']); - } - -} diff --git a/src/web/helpers/database.php b/src/web/helpers/database.php deleted file mode 100644 index 82c711d..0000000 --- a/src/web/helpers/database.php +++ /dev/null @@ -1,323 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -function __nullify(mixed $val): mixed -{ - if (!$val) { - return NULL; - } else { - return $val; - } -} - -class DatabaseQuery { - - private \PDO $conn; - private string $query; - - private bool $where; - private bool $set; - - private array $param; - - function __construct(\PDO $conn) - { - $this->conn = $conn; - $this->query = ''; - - $this->set = FALSE; - $this->where = FALSE; - $this->param = array(); - } - - /// - /// ARBITRARY QUERY - /// - - public function query(string $query): DatabaseQuery - { - $this->query .= $query; - return $this; - } - - /// - /// SELECT - /// - - public function select(string $select): DatabaseQuery - { - $this->query .= "SELECT $select\n"; - return $this; - } - - public function from(string $from): DatabaseQuery - { - $this->query .= "FROM $from\n"; - return $this; - } - - /// - /// INSERT - /// - - public function insert_into(string $insert, string ...$columns): DatabaseQuery - { - $this->query .= "INSERT INTO $insert\n ("; - foreach ($columns as $idx => $column) { - if ($idx !== 0) { - $this->query .= ","; - } - $this->query .= $column; - } - $this->query .= ")\n"; - return $this; - } - - public function values(mixed ...$values): DatabaseQuery - { - $this->query .= "VALUES ("; - foreach ($values as $idx => $value) { - if ($idx !== 0) { - $this->query .= ","; - } - $this->query .= "?"; - array_push($this->param, $value); - } - $this->query .= ")\n"; - return $this; - } - - /// - /// WHERE - /// - - public function where(string $cond): DatabaseQuery - { - if (!$this->where) { - $this->where = TRUE; - $this->query .= "WHERE "; - } else { - $this->query .= "AND "; - } - $this->query .= "$cond "; - return $this; - } - - /** - * @param array<mixed> $array - */ - public function where_in(string $column, array $array): DatabaseQuery - { - if (!$this->where) { - $this->where = TRUE; - $this->query .= "WHERE "; - } else { - $this->query .= "AND "; - } - if (empty($array)) { - $this->query .= "FALSE\n"; - return $this; - } - $in = $this->in($array); - $this->query .= "$column $in\n"; - return $this; - } - - /** - * @param array<mixed> $array - */ - private function in(array $array): DatabaseQuery - { - $in = 'IN ('; - foreach ($array as $idx => $item) { - if ($idx != 0) { - $in .= ","; - } - $in .= "?"; - array_push($this->param, $item); - } - $in .= ")"; - return $in; - } - - /// - /// OPERATORS - /// - - public function like(mixed $item): DatabaseQuery - { - $this->query .= "LIKE ?\n"; - array_push($this->param, $item); - return $this; - } - - public function eq(mixed $item): DatabaseQuery - { - $this->query .= "= ?\n"; - array_push($this->param, $item); - return $this; - } - - public function ne(mixed $item): DatabaseQuery - { - $this->query .= "<> ?\n"; - array_push($this->param, $item); - return $this; - } - - public function lt(mixed $item): DatabaseQuery - { - $this->query .= "< ?\n"; - array_push($this->param, $item); - return $this; - } - - public function le(mixed $item): DatabaseQuery - { - $this->query .= "<= ?\n"; - array_push($this->param, $item); - return $this; - } - - /// - /// JOINS - /// - - public function join(string $table, string $on, string $type = 'LEFT'): DatabaseQuery - { - $this->query .= "$type JOIN $table ON $on\n"; - return $this; - } - - /// - /// LIMIT, OFFSET, ORDER - /// - - public function limit(int $limit): DatabaseQuery - { - $this->query .= "LIMIT ?\n"; - array_push($this->param, $limit); - return $this; - } - - public function offset(int $offset): DatabaseQuery - { - $this->query .= "OFFSET ?\n"; - array_push($this->param, $offset); - return $this; - } - - public function order_by(string $column, string $order = 'ASC'): DatabaseQuery - { - $this->query .= "ORDER BY " . $column . ' ' . $order . ' '; - return $this; - } - - /// - /// COLLECT - /// - - public function rows(mixed ...$params): ?array - { - $args = $this->param; - foreach ($params as $param) { - array_push($args, $param); - } - $stmt = $this->conn->prepare($this->query); - try { - $stmt->execute($args); - } catch (Exception $ex) { - echo $ex; - echo '<br> >> caused by <<<br>'; - echo str_replace("\n", "<br>", $this->query); - } - return __nullify($stmt->fetchAll(PDO::FETCH_ASSOC)); - } - - public function row(mixed ...$params): ?array - { - $args = $this->param; - foreach ($params as $param) { - array_push($args, $param); - } - $stmt = $this->conn->prepare($this->query); - $stmt->execute($args); - return __nullify($stmt->fetch(PDO::FETCH_ASSOC)); - } - - public function execute(mixed ...$params): bool - { - $args = $this->param; - foreach ($params as $param) { - array_push($args, $param); - } - $stmt = $this->conn->prepare($this->query); - try { - $stmt->execute($args); - return TRUE; - } catch (Exception $_e) { - echo $_e; - echo '<br> >> caused by <<<br>'; - echo str_replace("\n", "<br>", $this->query); - return FALSE; - } - } -} - -/** - * DatabaseHelper - * allows queries on the - * postgres database - */ -class DatabaseHelper { - - private ?\PDO $conn; - - function __construct() - { - $this->conn = NULL; - } - - private function connect(): \PDO - { - if ($this->conn === NULL) { - $user = getenv("POSTGRES_USER"); - $pass = getenv("POSTGRES_PASSWORD"); - $db = getenv("POSTGRES_DB"); - $host = 'db'; - $port = '5432'; - - $conn_str = sprintf("pgsql:host=%s;port=%d;dbname=%s;user=%s;password=%s", - $host, - $port, - $db, - $user, - $pass - ); - $this->conn = new \PDO($conn_str); - $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - } - return $this->conn; - } - - public function select(string $select): DatabaseQuery - { - $conn = $this->connect(); - $query = new DatabaseQuery($conn); - return $query->select($select); - } - - public function insert_into(string $insert, string ...$columns): DatabaseQuery - { - $conn = $this->connect(); - $query = new DatabaseQuery($conn); - return $query->insert_into($insert, ...$columns); - } - - public function query(string $query_str): DatabaseQuery - { - $conn = $this->connect(); - $query = new DatabaseQuery($conn); - return $query->query($query_str); - } -} - diff --git a/src/web/helpers/lang.php b/src/web/helpers/lang.php deleted file mode 100644 index 72167fc..0000000 --- a/src/web/helpers/lang.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ -$__lang = array(); - -/** - * @param ?array<string,mixed> $sub - */ -function lang( - string $key, - ?string $default = NULL, - ?array $sub = NULL) { - $lang = $GLOBALS['__lang']; - if(array_key_exists($key, $lang)) { - if ($sub) { - return sprintf($lang[$key], ...$sub); - } else { - return $lang[$key]; - } - } else if ($default !== NULL) { - return $default; - } else { - trigger_error('Undefined lang string: ' . $key, E_USER_WARNING); - return $key; - } -} - -/** - * @param array<string,string> $attrs - * @param ?array<string,mixed> $sub - */ -function ilang( - string $key, - ?string $class = NULL, - ?string $id = NULL, - ?string $href = NULL, - ?string $click = NULL, - array $attrs = array(), - ?array $sub = NULL, - bool $button = FALSE, - string $container = 'span' -) { - $text = ucfirst(lang($key . "_text", FALSE, sub: $sub)); - $tip = lang($key . "_tip", FALSE, sub: $sub); - $icon = lang($key . "_icon", FALSE); - $content = lang($key . "_content", FALSE); - - if ($click || $button) { - echo '<button '; - } else { - echo '<a '; - } - if ($tip) { - echo 'title="' . $tip . '" '; - echo 'aria-label="' . $tip . '" '; - } - if ($class) { - echo 'class="' . $class . '" '; - } - if ($id) { - echo 'id="' . $id . '" '; - } - if ($click) { - echo 'onclick="' . $click . '" '; - } - if ($href) { - echo 'href="' . $href . '" '; - } - foreach ($attrs as $key => $attr) { - echo $key . '="' . $attr . '" '; - } - echo '> '; - if ($icon) { - echo '<i class="' . $icon . '">'; - if ($content) { - echo $content; - } - echo '</i>'; - } - if ($text) { - echo '<' . $container; - if ($icon) { - echo ' class="ml-sm"'; - } - echo '>' . $text . '</' . $container . '>'; - } - if ($click || $button) { - echo '</button>'; - } else { - echo '</a>'; - } -} diff --git a/src/web/helpers/sanitize.php b/src/web/helpers/sanitize.php deleted file mode 100644 index 495c249..0000000 --- a/src/web/helpers/sanitize.php +++ /dev/null @@ -1,8 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -function esc(string $data): string { - $data = str_replace('&', '&', $data); - $data = str_replace('<', '<', $data); - $data = str_replace('>', '>', $data); - return $data; -} diff --git a/src/web/index.php b/src/web/index.php deleted file mode 100644 index 9958b1b..0000000 --- a/src/web/index.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php /* Copyright (c) 2024 Freya Murphy */ - -// ========================= ENVIRONMENT == - -ini_set('html_errors', '1'); -ini_set('browscap', 'browscap.ini'); -date_default_timezone_set('America/New_York'); - -// FOLDER_ROOT -// -// define folder directiroy paths based on this file -define('PHP_ROOT', realpath(dirname(__FILE__) . '/..')); -define('WEB_ROOT', PHP_ROOT . '/web'); -define('ASSET_ROOT', PHP_ROOT . '/assets'); -define('PUBLIC_ROOT', PHP_ROOT . '/public'); - -// ========================== BOOTSTRAP == - -// load the config -require(WEB_ROOT . '/config.php'); - -// load all third party -require(WEB_ROOT . '/third_party/parsedown.php'); -require(WEB_ROOT . '/third_party/parsedown_extra.php'); - -// load all the helpers -require(WEB_ROOT . '/helpers/ie.php'); -require(WEB_ROOT . '/helpers/lang.php'); -require(WEB_ROOT . '/helpers/aria.php'); -require(WEB_ROOT . '/helpers/image.php'); -require(WEB_ROOT . '/helpers/markdown.php'); -require(WEB_ROOT . '/helpers/database.php'); -require(WEB_ROOT . '/helpers/sanitize.php'); - -// load all core files -require(WEB_ROOT . '/core/core.php'); -require(WEB_ROOT . '/core/component.php'); -require(WEB_ROOT . '/core/controller.php'); -require(WEB_ROOT . '/core/model.php'); -require(WEB_ROOT . '/core/router.php'); - - -// load file stamps -require(WEB_ROOT . '/stamp.php'); - -// ============================== START == - -(new Router())->handle_req(); diff --git a/src/web/lang/error.php b/src/web/lang/error.php index 549700d..449d18f 100644 --- a/src/web/lang/error.php +++ b/src/web/lang/error.php @@ -1,64 +1,6 @@ <?php /* Copyright (c) 2024 Freya Murphy */ $lang['error_0'] = 'Why the actual fuck is there an error zero??'; -$lang['error_100'] = "Continue"; -$lang['error_101'] = "Switching Protocols"; -$lang['error_200'] = "OK"; -$lang['error_201'] = "Created"; -$lang['error_202'] = "Accepted"; -$lang['error_203'] = "Non-Authoritative Information"; -$lang['error_204'] = "No Content"; -$lang['error_205'] = "Reset Content"; -$lang['error_206'] = "Partial Content"; -$lang['error_300'] = "Multiple Choices"; -$lang['error_301'] = "Moved Permanently"; -$lang['error_302'] = "Found"; -$lang['error_303'] = "See Other"; -$lang['error_304'] = "Not Modified"; -$lang['error_305'] = "Use Proxy"; -$lang['error_306'] = "unused"; -$lang['error_307'] = "Temporary Redirect"; -$lang['error_308'] = "Permanent Redirect"; -$lang['error_400'] = "Bad Request"; -$lang['error_401'] = "Unauthorized"; -$lang['error_402'] = "Payment Required"; -$lang['error_403'] = "Forbidden"; -$lang['error_404'] = "Not Found"; -$lang['error_405'] = "Method Not Allowed"; -$lang['error_406'] = "Not Acceptable"; -$lang['error_407'] = "Proxy Authentication Required"; -$lang['error_408'] = "Request Timeout"; -$lang['error_409'] = "Conflict"; -$lang['error_410'] = "Gone"; -$lang['error_411'] = "Length Required"; -$lang['error_412'] = "Precondition Failed"; -$lang['error_413'] = "Content Too Large"; -$lang['error_414'] = "URI Too Long"; -$lang['error_415'] = "Unsupported Media Type"; -$lang['error_416'] = "Range Not Satisfiable"; -$lang['error_417'] = "Expectation Failed"; -$lang['error_418'] = "I'm a teapot"; -$lang['error_421'] = "Misdirected Request"; -$lang['error_422'] = "Unprocessable Content"; -$lang['error_423'] = "Locked"; -$lang['error_424'] = "Failed Dependency"; -$lang['error_425'] = "Too Early"; -$lang['error_426'] = "Upgrade Required"; -$lang['error_428'] = "Precondition Required"; -$lang['error_429'] = "Too Many Requests"; -$lang['error_431'] = "Request Header Fields Too Large"; -$lang['error_451'] = "Unavailable For Legal Reasons"; -$lang['error_500'] = "Whoops! Server error :("; -$lang['error_501'] = "Not Implemented"; -$lang['error_502'] = "Bad Gateway"; -$lang['error_503'] = "Service Unavailable"; -$lang['error_504'] = "Gateway Timeout"; -$lang['error_505'] = "HTTP Version Not Supported"; -$lang['error_506'] = "Variant Also Negotiates"; -$lang['error_507'] = "Insufficient Storage"; -$lang['error_508'] = "Loop Detected"; -$lang['error_510'] = "Not Extended"; -$lang['error_511'] = "Network Authentication Required"; $lang['error'] = [ 'How the fuck did you get here.', 'A known error has occoured', diff --git a/src/web/helpers/aria.php b/src/web/lib/aria.php index 0e06b97..0e06b97 100644 --- a/src/web/helpers/aria.php +++ b/src/web/lib/aria.php diff --git a/src/web/lib/hooks.php b/src/web/lib/hooks.php new file mode 100644 index 0000000..70853e1 --- /dev/null +++ b/src/web/lib/hooks.php @@ -0,0 +1,10 @@ +<?php /* Copyright (c) 2024 Freya Murphy */ + +function CRIMSON_pre_route_hook(Router $router): void { +} + +function CRIMSON_error_hook(?array $req, int $code): never { + $error_controller = ROUTER->load_controller('error'); + $error_controller->code($code); + CRIMSON_DIE(); +} diff --git a/src/web/helpers/ie.php b/src/web/lib/ie.php index ead6c1a..ead6c1a 100644 --- a/src/web/helpers/ie.php +++ b/src/web/lib/ie.php diff --git a/src/web/helpers/image.php b/src/web/lib/image.php index d4683fe..7b6ec0e 100644 --- a/src/web/helpers/image.php +++ b/src/web/lib/image.php @@ -1,5 +1,7 @@ <?php /* Copyright (c) 2024 Freya Murphy */ + + function __get_mime($type) { switch ($type) { @@ -30,7 +32,7 @@ function __make_source( } else { $media = ''; } - $path = Core::get_url('public/' . $name . '.' . $format, TRUE); + $path = Base::get_url('public/' . $name . '.' . $format, TRUE); $mime = __get_mime($format); return sprintf('<source type="%s" srcset="%s" %s>', $mime, $path, $media); @@ -68,7 +70,7 @@ function image( } $format = end($formats); - $path = Core::get_url('public/' . $name . '.' . $format, TRUE); + $path = Base::get_url('public/' . $name . '.' . $format, TRUE); $out .= "<img src=\"$path\""; if ($alt) { $alt = lang($alt); diff --git a/src/web/helpers/markdown.php b/src/web/lib/markdown.php index 5279a1f..5279a1f 100644 --- a/src/web/helpers/markdown.php +++ b/src/web/lib/markdown.php |