summaryrefslogtreecommitdiff
path: root/src/web
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-12-23 11:13:27 -0500
committerFreya Murphy <freya@freyacat.org>2024-12-23 11:13:27 -0500
commit5a2ba9c2e7605bb788bc406184547d22c6436867 (patch)
treecbd988d534e8a8593a31d70571222443f80da0b3 /src/web
parentfix about modal (diff)
downloadxssbook2-5a2ba9c2e7605bb788bc406184547d22c6436867.tar.gz
xssbook2-5a2ba9c2e7605bb788bc406184547d22c6436867.tar.bz2
xssbook2-5a2ba9c2e7605bb788bc406184547d22c6436867.zip
v2.1.0, refactor w/ crimson
Diffstat (limited to 'src/web')
-rw-r--r--src/web/_controller/_index.php23
-rw-r--r--src/web/_controller/_meta.php12
-rw-r--r--src/web/_controller/_modal.php28
-rw-r--r--src/web/_controller/_post.php (renamed from src/web/_controller/_util/post.php)113
-rw-r--r--src/web/_controller/_template.php21
-rw-r--r--src/web/_controller/apps/auth.php56
-rw-r--r--src/web/_controller/apps/error.php21
-rw-r--r--src/web/_controller/apps/home.php26
-rw-r--r--src/web/_controller/apps/people.php48
-rw-r--r--src/web/_controller/apps/profile.php44
-rw-r--r--src/web/_controller/apps/settings.php41
-rw-r--r--src/web/_controller/auth.php45
-rw-r--r--src/web/_controller/error.php36
-rw-r--r--src/web/_controller/home.php27
-rw-r--r--src/web/_controller/index.php16
-rw-r--r--src/web/_controller/modal.php38
-rw-r--r--src/web/_controller/people.php45
-rw-r--r--src/web/_controller/profile.php44
-rw-r--r--src/web/_controller/settings.php34
-rw-r--r--src/web/_controller/template.php23
-rw-r--r--src/web/_model/apps/auth.php13
-rw-r--r--src/web/_model/apps/error.php31
-rw-r--r--src/web/_model/apps/home.php22
-rw-r--r--src/web/_model/apps/people.php90
-rw-r--r--src/web/_model/apps/profile.php65
-rw-r--r--src/web/_model/apps/settings.php16
-rw-r--r--src/web/_model/auth.php42
-rw-r--r--src/web/_model/cache.php37
-rw-r--r--src/web/_model/error.php3
-rw-r--r--src/web/_model/format.php36
-rw-r--r--src/web/_model/home.php17
-rw-r--r--src/web/_model/main.php119
-rw-r--r--src/web/_model/people.php72
-rw-r--r--src/web/_model/profile.php70
-rw-r--r--src/web/_model/request.php40
-rw-r--r--src/web/_model/settings.php3
-rw-r--r--src/web/_views/_modal/about.php (renamed from src/web/_views/modal/about.php)0
-rw-r--r--src/web/_views/_modal/new_post.php (renamed from src/web/_views/modal/new_post.php)25
-rw-r--r--src/web/_views/_modal/register.php (renamed from src/web/_views/modal/register.php)2
-rw-r--r--src/web/_views/_template/comment.php (renamed from src/web/_views/template/comment.php)7
-rw-r--r--src/web/_views/_template/error.php (renamed from src/web/_views/template/error.php)0
-rw-r--r--src/web/_views/_template/modal.php (renamed from src/web/_views/template/modal.php)2
-rw-r--r--src/web/_views/_template/post.php (renamed from src/web/_views/template/post.php)13
-rw-r--r--src/web/_views/_template/posts.php (renamed from src/web/_views/template/posts.php)11
-rw-r--r--src/web/_views/_template/toast.php (renamed from src/web/_views/template/toast.php)18
-rw-r--r--src/web/_views/apps/people/people.php7
-rw-r--r--src/web/_views/auth/main.php (renamed from src/web/_views/apps/auth/login.php)6
-rw-r--r--src/web/_views/error/main.php (renamed from src/web/_views/apps/error/main.php)0
-rw-r--r--src/web/_views/head.php15
-rw-r--r--src/web/_views/header.php38
-rw-r--r--src/web/_views/home/main.php (renamed from src/web/_views/apps/home/main.php)8
-rw-r--r--src/web/_views/people/card.php (renamed from src/web/_views/apps/people/card.php)2
-rw-r--r--src/web/_views/people/footer.php (renamed from src/web/_views/apps/people/footer.php)0
-rw-r--r--src/web/_views/people/header.php (renamed from src/web/_views/apps/people/header.php)0
-rw-r--r--src/web/_views/people/main.php (renamed from src/web/_views/apps/people/main.php)12
-rw-r--r--src/web/_views/people/people.php5
-rw-r--r--src/web/_views/profile/main.php (renamed from src/web/_views/apps/profile/main.php)28
-rw-r--r--src/web/_views/settings/main.php (renamed from src/web/_views/apps/settings/main.php)7
-rw-r--r--src/web/config.php56
-rw-r--r--src/web/config/aesthetic.php83
-rw-r--r--src/web/config/routes.php12
-rw-r--r--src/web/core/_controller.php69
-rw-r--r--src/web/core/_model.php44
-rw-r--r--src/web/core/database.php282
-rw-r--r--src/web/core/loader.php101
-rw-r--r--src/web/core/router.php159
-rw-r--r--src/web/helper/error.php9
-rw-r--r--src/web/helper/lang.php81
-rw-r--r--src/web/index.php46
-rw-r--r--src/web/lang/api.php (renamed from src/web/lang/en_US/api_lang.php)2
-rw-r--r--src/web/lang/auth.php (renamed from src/web/lang/en_US/apps/auth.php)4
-rw-r--r--src/web/lang/common.php (renamed from src/web/lang/en_US/common_lang.php)45
-rw-r--r--src/web/lang/en_US/error_lang.php8
-rw-r--r--src/web/lang/home.php (renamed from src/web/lang/en_US/apps/home.php)4
-rw-r--r--src/web/lang/people.php (renamed from src/web/lang/en_US/apps/people.php)4
-rw-r--r--src/web/lang/post.php35
-rw-r--r--src/web/lang/profile.php (renamed from src/web/lang/en_US/apps/profile.php)7
-rw-r--r--src/web/lang/settings.php (renamed from src/web/lang/en_US/apps/settings.php)2
-rw-r--r--src/web/lib/_base.php61
-rw-r--r--src/web/lib/_controller.php49
-rw-r--r--src/web/lib/_model.php61
-rw-r--r--src/web/lib/hooks.php31
-rw-r--r--src/web/lib/image.php (renamed from src/web/helper/image.php)0
-rw-r--r--src/web/lib/utils.php6
-rw-r--r--src/web/stamp.php46
85 files changed, 1017 insertions, 1913 deletions
diff --git a/src/web/_controller/_index.php b/src/web/_controller/_index.php
deleted file mode 100644
index 2fd7db2..0000000
--- a/src/web/_controller/_index.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class _index_controller extends Controller {
-
- // the home model
- private $home_model;
-
- // the request model
- private $request_model;
-
- // the caceh model
- private $cache_model;
-
- public function index(): void {
- if ($this->main->session) {
- $this->redirect('/home');
- } else {
- $this->redirect('/auth/login');
- }
- }
-
-}
-
-?>
diff --git a/src/web/_controller/_meta.php b/src/web/_controller/_meta.php
index bec3c65..06c7c0a 100644
--- a/src/web/_controller/_meta.php
+++ b/src/web/_controller/_meta.php
@@ -1,21 +1,21 @@
<?php /* Copyright (c) 2024 Freya Murphy */
-class _meta_controller extends Controller {
+class _meta_controller extends XSS_Controller {
public function manifest(): void {
$json = array(
- 'short_name' => 'xssbook.com',
- 'name' => 'xssbook.com',
+ 'short_name' => CONFIG['domain'],
+ 'name' => CONFIG['domain'],
'icons' => [
array(
- 'src' => 'https://xssbook.com/public/icons/logo512.png',
+ 'src' => $this->get_url('public/icons/logo512.png'),
'type' => 'image/png',
'sizes' => '512x512',
'purpose' => 'any maskable'
)
],
- 'id' => 'https://xssbook.com/home',
- 'start_url' => 'https://xssbook.com/home',
+ 'id' => $this->get_url('home'),
+ 'start_url' => $this->get_url('home'),
'background_color' => '#181818',
'display' => 'standalone',
'scope' => '/',
diff --git a/src/web/_controller/_modal.php b/src/web/_controller/_modal.php
new file mode 100644
index 0000000..0447ca8
--- /dev/null
+++ b/src/web/_controller/_modal.php
@@ -0,0 +1,28 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class _modal_controller extends XSS_Controller {
+
+ /**
+ * @param string $name
+ * @param array $data
+ */
+ private function modal($name): void {
+ $data = $this->model->get_data();
+ $data['title'] = ucwords(lang($name . '_modal_title'));
+ $data['content'] = $name;
+ $this->view('_template/modal', $data);
+ }
+
+ public function new_post(): void {
+ $this->load_lang('post');
+ $this->modal('new_post');
+ }
+
+ public function about(): void {
+ $this->modal('about');
+ }
+
+ public function register(): void {
+ $this->load_lang('auth');
+ $this->modal('register');
+ }
+}
diff --git a/src/web/_controller/_util/post.php b/src/web/_controller/_post.php
index 5346497..56c997f 100644
--- a/src/web/_controller/_util/post.php
+++ b/src/web/_controller/_post.php
@@ -1,30 +1,22 @@
<?php /* Copyright (c) 2024 Freya Murphy */
-class Post_controller extends Controller {
+class _post_controller extends XSS_Controller {
- // the request model
- private $request_model;
+ private $auth_model;
- // the caceh model
- private $cache_model;
-
- // page size
- private $page_size;
-
- function __construct($load) {
- parent::__construct($load);
- $this->request_model = $this->load->model('request');
- $this->cache_model = $this->load->model('cache');
- $this->page_size = 10;
+ function __construct() {
+ parent::__construct();
+ $this->auth_model = $this->load_model('auth');
+ $this->load_lang('post');
}
public function index(): void {
- $this->view('template/posts');
+ $this->view('_template/posts');
}
public function post(): void {
- $pid = $this->request_model->get_int('id', 0);
+ $pid = $this->get_int('id', 0);
- $post = $this->db
+ $post = $this->db()
->select('p.*, l.id as like_id')
->from('api.post p')
->join('api.like l', 'p.id = l.post_id AND l.user_id')
@@ -33,42 +25,37 @@ class Post_controller extends Controller {
->eq($pid)
->row();
- if (!$post) {
+ if (!$post)
return;
- }
- $users = $this->cache_model->get_users([$post]);
+ $users = $this->model->get_users([$post]);
$uid = $post['user_id'];
- if (!array_key_exists($uid, $users)) {
+ if (!isset($users[$uid]))
return;
- }
$user = $users[$uid];
- $data = array(
- 'user' => $user,
- 'page_size' => $this->page_size,
- 'post' => $post
- );
- $this->view('template/post', $data);
+ $data = $this->model->get_data();
+ $data['user'] = $user;
+ $data['page_size'] = POST_PAGE_SIZE;
+ $data['post'] = $post;
+ $this->view('_template/post', $data);
}
/**
* @return array<string,mixed>
*/
public function posts(): array {
- $page = $this->request_model->get_int('page', 0);
- $max = $this->request_model->get_int('max');
- $offset = $page * $this->page_size;
- $filter_uid = $this->request_model->get_int('user_id', FALSE);
+ $page = $this->get_int('page', 0);
+ $max = $this->get_int('max');
+ $offset = $page * POST_PAGE_SIZE;
+ $filter_uid = $this->get_int('user_id', FALSE);
- $user = $this->main->user();
+ $user = $this->auth_model->session();
$uid = isset($user) ? $user['id'] : NULL;
- $query = $this->db;
-
- $query = $this->db
+ $query = $this->db()
->select('p.*, l.id as like_id')
->from('api.post p')
->join('api.like l', 'p.id = l.post_id AND l.user_id')
@@ -86,23 +73,23 @@ class Post_controller extends Controller {
$posts = $query
->order_by('p.id', 'DESC')
- ->limit($this->page_size)
+ ->limit(POST_PAGE_SIZE)
->offset($offset)
->rows();
- $users = $this->cache_model->get_users($posts);
+ $users = $this->model->get_users($posts);
$max = 0;
foreach ($posts as $post) {
$max = max($max, $post['id']);
- $data = array();
- $data['page_size'] = $this->page_size;
+ $data = $this->model->get_data();
+ $data['page_size'] = POST_PAGE_SIZE;
$data['user'] = $users[$post['user_id']];
$data['post'] = $post;
- $this->view('template/post', $data);
+ $this->view('_template/post', $data);
}
- $query = $this->db
+ $query = $this->db()
->select('COUNT(p.id) as pc')
->from('api.post p');
@@ -117,16 +104,17 @@ class Post_controller extends Controller {
return array(
'loaded' => count($posts),
'total' => $pc,
- 'page_size' => $this->page_size,
+ 'page_size' => POST_PAGE_SIZE,
+
'max' => $max,
'filter_uid' => $filter_uid
);
}
public function comment(): void {
- $cid = $this->request_model->get_int('id', 0);
+ $cid = $this->get_int('id', 0);
- $comment = $this->db
+ $comment = $this->db()
->select('*')
->from('api.comment')
->where('id')
@@ -137,7 +125,7 @@ class Post_controller extends Controller {
return;
}
- $users = $this->cache_model->get_users([$comment]);
+ $users = $this->model->get_users([$comment]);
$uid = $comment['user_id'];
if (!array_key_exists($uid, $users)) {
@@ -146,23 +134,24 @@ class Post_controller extends Controller {
$user = $users[$uid];
- $data = array(
- 'user' => $user,
- 'comment' => $comment
- );
- $this->view('template/comment', $data);
+ $data = $this->model->get_data();
+ $data['user'] = $user;
+ $data['comment'] = $comment;
+ $this->view('_template/comment', $data);
}
/**
* @return array<string,mixed>
*/
public function comments(): array {
- $page = $this->request_model->get_int('page', 0);
- $max = $this->request_model->get_int('max');
- $id = $this->request_model->get_int('id', 0);
- $offset = $page * $this->page_size;
+ $page = $this->get_int('page', 0);
+ $max = $this->get_int('max');
+ $id = $this->get_int('id', 0);
+ $offset = $page * COMMENT_PAGE_SIZE;
+
+ $user = $this->auth_model->session();
- $query = $this->db
+ $query = $this->db()
->select('*')
->from('api.comment')
->where('post_id')
@@ -177,11 +166,11 @@ class Post_controller extends Controller {
$comments = $query
->order_by('id', 'ASC')
- ->limit($this->page_size)
+ ->limit(COMMENT_PAGE_SIZE)
->offset($offset)
->rows();
- $users = $this->cache_model->get_users($comments);
+ $users = $this->model->get_users($comments);
$max = 0;
// only add this hr when not logged in
@@ -190,22 +179,22 @@ class Post_controller extends Controller {
if (
count($comments) &&
$page == 0 &&
- $this->main->session === NULL
+ $user === NULL
) {
echo '<hr>';
}
foreach ($comments as $comment) {
$max = max($max, $comment['id']);
- $data = array();
+ $data = $this->model->get_data();
$data['user'] = $users[$comment['user_id']];
$data['comment'] = $comment;
- $this->view('template/comment', $data);
+ $this->view('_template/comment', $data);
}
return array(
'loaded' => count($comments),
- 'page_size' => $this->page_size,
+ 'page_size' => COMMENT_PAGE_SIZE,
'max' => $max,
);
}
diff --git a/src/web/_controller/_template.php b/src/web/_controller/_template.php
new file mode 100644
index 0000000..9c82956
--- /dev/null
+++ b/src/web/_controller/_template.php
@@ -0,0 +1,21 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class _template_controller extends XSS_Controller {
+
+ public function toast(): void {
+ $msg = $this->get_string('msg') ?? '';
+ $detail = $this->get_string('detail');
+ $hint = $this->get_string('hint');
+ $type = $this->get_string('type', 'error');
+
+ $data = array(
+ 'msg' => $msg,
+ 'detail' => $detail,
+ 'hint' => $hint,
+ 'type' => $type,
+ );
+
+ $this->view('_template/toast', $data);
+ }
+
+}
+
diff --git a/src/web/_controller/apps/auth.php b/src/web/_controller/apps/auth.php
deleted file mode 100644
index 1df74da..0000000
--- a/src/web/_controller/apps/auth.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Auth_controller extends Controller {
-
- // the home model
- private $auth_model;
-
- // the post controller
- protected $post_controller;
-
- function __construct($load) {
- parent::__construct($load);
- $this->auth_model = $this->load->model('apps/auth');
- }
-
- public function index(): void {
- if ($this->main->session) {
- $this->redirect('/home');
- } else {
- $this->redirect('/auth/login');
- }
- }
-
- public function login(): void {
- if ($this->main->session) {
- $this->redirect('/home');
- }
-
- parent::index();
- $data = $this->auth_model->get_data();
- $this->view('head', $data);
- $this->view('apps/auth/login', $data);
- $this->view('footer', $data);
- }
-
- public function logout(): void {
- if ($this->main->session) {
- $_SESSION['jwt'] = NULL;
- }
- $this->redirect('/auth/login');
- }
-
- public function update(): void {
- if (!$this->is_ajax()) {
- $this->error(400);
- }
- if (!isset($_POST['key']) || !isset($_POST['value'])) {
- $this->error(400);
- }
- $key = $_POST['key'];
- $value = $_POST['value'];
- $_SESSION[$key] = $value;
- }
-
-}
-
-?>
diff --git a/src/web/_controller/apps/error.php b/src/web/_controller/apps/error.php
deleted file mode 100644
index 03bbd8d..0000000
--- a/src/web/_controller/apps/error.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Error_controller extends Controller {
-
- private $error_model;
-
- function __construct($load) {
- parent::__construct($load);
- $this->error_model = $this->load->model('apps/error');
- }
-
- public function index(): void {
- parent::index();
- $data = $this->error_model->get_data();
- $this->view('header', $data);
- $this->view('apps/error/main', $data);
- $this->view('footer', $data);
- }
-
-}
-
-?>
diff --git a/src/web/_controller/apps/home.php b/src/web/_controller/apps/home.php
deleted file mode 100644
index c9a116d..0000000
--- a/src/web/_controller/apps/home.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Home_controller extends Controller {
-
- // the home model
- private $home_model;
-
- // the post controller
- protected $post_controller;
-
- function __construct($load) {
- parent::__construct($load);
- $this->home_model = $this->load->model('apps/home');
- $this->post_controller = $this->load->controller('_util/post');
- }
-
- public function index(): void {
- parent::index();
- $data = $this->home_model->get_data();
- $this->view('header', $data);
- $this->view('apps/home/main', $data);
- $this->view('footer', $data);
- }
-
-}
-
-?>
diff --git a/src/web/_controller/apps/people.php b/src/web/_controller/apps/people.php
deleted file mode 100644
index 86da3b3..0000000
--- a/src/web/_controller/apps/people.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class People_controller extends Controller {
-
- // the people model
- private $people_model;
-
- // format model
- protected $format_model;
-
- function __construct($load) {
- parent::__construct($load);
- $this->people_model = $this->load->model('apps/people');
- $this->format_model = $this->load->model('format');
- }
-
- public function index(): void {
- parent::index();
- $data = $this->people_model->get_data();
- $this->view('header', $data);
- $this->view('apps/people/header', $data);
- $this->view('apps/people/main', $data);
- $this->view('apps/people/footer', $data);
- $this->view('footer', $data);
- }
-
- public function content(): void {
- $data = $this->people_model->get_data();
- $this->view('apps/people/main', $data);
- }
-
- /**
- * @return array<string,mixed>
- */
- public function people(): array {
- $data = $this->people_model->get_users();
-
- $this->view('apps/people/people', $data);
-
- $max = 0;
- foreach ($data['users'] as $user) {
- $max = max($max, $user['id']);
- }
-
- return $data;
- }
-}
-
-?>
diff --git a/src/web/_controller/apps/profile.php b/src/web/_controller/apps/profile.php
deleted file mode 100644
index 9e9fca6..0000000
--- a/src/web/_controller/apps/profile.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Profile_controller extends Controller {
-
- // the home model
- private $profile_model;
-
- // the format model
- protected $format_model;
-
- // the post controller
- protected $post_controller;
-
- // the people controller
- protected $people_controller;
-
- function __construct($load) {
- parent::__construct($load);
- $this->profile_model = $this->load->model('apps/profile');
- $this->people_controller = $this->load->controller('apps/people');
- $this->format_model = $this->load->model('format');
- $this->post_controller = $this->load->controller('_util/post');
- }
-
- public function index(): void {
-
- if ($this->main->user() && !isset($_GET['id'])) {
- $this->redirect('/profile?id=' . $this->main->user()['id']);
- }
-
- parent::index();
- $data = $this->profile_model->get_data();
-
- if (!$data) {
- $this->error(404);
- }
-
- $this->view('header', $data);
- $this->view('apps/profile/main', $data);
- $this->view('footer', $data);
- }
-
-}
-
-?>
diff --git a/src/web/_controller/apps/settings.php b/src/web/_controller/apps/settings.php
deleted file mode 100644
index 8a409cc..0000000
--- a/src/web/_controller/apps/settings.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Settings_controller extends Controller {
-
- // the home model
- private $settings_model;
-
- // the format model
- protected $format_model;
-
- // the post controller
- protected $post_controller;
-
- // the people controller
- protected $people_controller;
-
- function __construct($load) {
- parent::__construct($load);
- $this->settings_model = $this->load->model('apps/settings');
- }
-
- public function index(): void {
- if (!$this->main->session) {
- $this->redirect('/auth/login');
- }
-
- parent::index();
- $data = $this->settings_model->get_data();
-
- if (!$data) {
- $this->error(404);
- }
-
- $this->load->app_lang($this->main->info['lang'], 'auth');
- $this->view('header', $data);
- $this->view('apps/settings/main', $data);
- $this->view('footer', $data);
- }
-
-}
-
-?>
diff --git a/src/web/_controller/auth.php b/src/web/_controller/auth.php
new file mode 100644
index 0000000..fd1931c
--- /dev/null
+++ b/src/web/_controller/auth.php
@@ -0,0 +1,45 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Auth_controller extends XSS_Controller {
+
+ private $auth_model;
+
+ function __construct() {
+ parent::__construct();
+ $this->auth_model = $this->load_model('auth');
+ $this->load_lang('auth');
+ }
+
+ public function index(): void {
+ $this->load_controller('index')->index();
+ }
+
+ public function login(): void {
+ if ($this->auth_model->session())
+ $this->redirect('/home');
+
+ parent::index();
+ $data = $this->auth_model->get_data();
+ $this->view('head', $data);
+ $this->view('auth/main', $data);
+ $this->view('footer', $data);
+ }
+
+ public function logout(): void {
+ if ($this->auth_model->session())
+ $_SESSION['jwt'] = NULL;
+ $this->redirect('/auth/login');
+ }
+
+ public function update(): void {
+ $key = $this->post_data('key');
+ $value = $this->post_data('value');
+
+ if (!$key || !$value)
+ $this->error(400);
+
+ $_SESSION[$key] = $value;
+ }
+
+}
+
+?>
diff --git a/src/web/_controller/error.php b/src/web/_controller/error.php
new file mode 100644
index 0000000..55034ba
--- /dev/null
+++ b/src/web/_controller/error.php
@@ -0,0 +1,36 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Error_controller extends XSS_Controller {
+
+ private $error_model;
+
+ function __construct() {
+ parent::__construct();
+ $this->error_model = $this->load_model('error');
+ }
+
+ public function index(): void {
+ $this->code(404);
+ }
+
+ public function code($code): void {
+ parent::index();
+
+ $code = intval($code);
+ if ($code == 404 && rand(0, 100) > 95)
+ $code = 451;
+ if (!is_valid_status_code($code))
+ $code = 404;
+ $msg = status_code_msg($code);
+
+ $data = $this->error_model->get_data();
+ $data['title'] = $code;
+ $data['msg'] = $msg;
+
+ $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
new file mode 100644
index 0000000..dc9da4d
--- /dev/null
+++ b/src/web/_controller/home.php
@@ -0,0 +1,27 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Home_controller extends XSS_Controller {
+
+ // the home model
+ protected $home_model;
+
+ // the post controller
+ protected $post_controller;
+
+ function __construct() {
+ parent::__construct();
+ $this->home_model = $this->load_model('home');
+ $this->post_controller = $this->load_controller('_post');
+ $this->load_lang('post', 'home');
+ }
+
+ public function index(): void {
+ parent::index();
+ $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/index.php b/src/web/_controller/index.php
new file mode 100644
index 0000000..0822a22
--- /dev/null
+++ b/src/web/_controller/index.php
@@ -0,0 +1,16 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Index_controller extends XSS_Controller {
+
+ public function index(): void {
+ $auth_model = $this->load_model('auth');
+ $session = $auth_model->session();
+
+ $home = $this->get_url('home');
+ $login = $this->get_url('auth/login');
+
+ $this->redirect($session ? $home : $login);
+ }
+
+}
+
+?>
diff --git a/src/web/_controller/modal.php b/src/web/_controller/modal.php
deleted file mode 100644
index da17cca..0000000
--- a/src/web/_controller/modal.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Modal_controller extends Controller {
-
-
- function __construct($load) {
- parent::__construct($load);
- }
-
- /**
- * @param string $name
- * @param array $data
- */
- private function modal($name, $data = array()): void {
- $title = ucwords(lang($name . '_modal_title'));
- $data['title'] = $title;
- $data['content'] = $name;
- $this->view('template/modal', $data);
- }
-
- public function new_post(): void {
- $this->modal('new_post');
- }
-
- public function about(): void {
- $this->modal('about');
- }
-
- public function register(): void {
- $this->load->app_lang(
- $this->main->info['lang'],
- 'auth'
- );
- $this->modal('register');
- }
-}
-
-?>
-
diff --git a/src/web/_controller/people.php b/src/web/_controller/people.php
new file mode 100644
index 0000000..bb2db2c
--- /dev/null
+++ b/src/web/_controller/people.php
@@ -0,0 +1,45 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class People_controller extends XSS_Controller {
+
+ // the people model
+ private $people_model;
+
+ function __construct() {
+ parent::__construct();
+ $this->people_model = $this->load_model('people');
+ $this->load_lang('people');
+ }
+
+ public function index(): void {
+ parent::index();
+ $data = $this->people_model->get_data();
+ $this->view('header', $data);
+ $this->view('people/header', $data);
+ $this->view('people/main', $data);
+ $this->view('people/footer', $data);
+ $this->view('footer', $data);
+ }
+
+ public function content(): void {
+ $data = $this->people_model->get_data();
+ $this->view('people/main', $data);
+ }
+
+ /**
+ * @return array<string,mixed>
+ */
+ public function people(): array {
+ $data = $this->people_model->get_people();
+
+ $this->view('people/people', $data);
+
+ $max = 0;
+ foreach ($data['users'] as $user) {
+ $max = max($max, $user['id']);
+ }
+
+ return $data;
+ }
+}
+
+?>
diff --git a/src/web/_controller/profile.php b/src/web/_controller/profile.php
new file mode 100644
index 0000000..dd02ed2
--- /dev/null
+++ b/src/web/_controller/profile.php
@@ -0,0 +1,44 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Profile_controller extends XSS_Controller {
+
+ // the profile model
+ private $profile_model;
+
+ // the post controller
+ protected $post_controller;
+
+ // the people controller
+ protected $people_controller;
+
+ function __construct() {
+ parent::__construct();
+ $this->profile_model = $this->load_model('profile');
+ $this->people_controller = $this->load_controller('people');
+ $this->post_controller = $this->load_controller('_post');
+ $this->load_lang('profile');
+ }
+
+ public function index(): void {
+ $id = $this->get_int('id');
+
+ parent::index();
+ $data = $this->profile_model->get_data();
+
+ // profile does not exist
+ if (!$data) {
+ // not logged in and trying to access own profile
+ if (!$id)
+ $this->redirect('/auth/login');
+ // directly accessing unknown user id => 404
+ else
+ $this->error(404);
+ }
+
+ $this->view('header', $data);
+ $this->view('profile/main', $data);
+ $this->view('footer', $data);
+ }
+
+}
+
+?>
diff --git a/src/web/_controller/settings.php b/src/web/_controller/settings.php
new file mode 100644
index 0000000..e42389f
--- /dev/null
+++ b/src/web/_controller/settings.php
@@ -0,0 +1,34 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Settings_controller extends XSS_Controller {
+
+ // the settings model
+ private $settings_model;
+
+ // the auth model
+ private $auth_model;
+
+ function __construct() {
+ parent::__construct();
+ $this->settings_model = $this->load_model('settings');
+ $this->auth_model = $this->load_model('auth');
+ $this->load_lang('auth', 'settings');
+ }
+
+ public function index(): void {
+ if (!$this->auth_model->session())
+ $this->redirect('/auth/login');
+
+ parent::index();
+ $data = $this->settings_model->get_data();
+
+ if (!$data)
+ $this->error(404);
+
+ $this->view('header', $data);
+ $this->view('settings/main', $data);
+ $this->view('footer', $data);
+ }
+
+}
+
+?>
diff --git a/src/web/_controller/template.php b/src/web/_controller/template.php
deleted file mode 100644
index 879eadc..0000000
--- a/src/web/_controller/template.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Template_controller extends Controller {
-
- // the request model
- private $request_model;
-
- function __construct($load) {
- parent::__construct($load);
- $this->request_model = $this->load->model('request');
- }
-
- public function toast(): void {
- $data = array(
- 'msg' => $this->request_model->get_str('msg', FALSE),
- 'detail' => $this->request_model->get_str('detail', FALSE),
- 'hint' => $this->request_model->get_str('hint', FALSE),
- 'type' => $this->request_model->get_str('type', 'error')
- );
- $this->view('template/toast', $data);
- }
-
-}
-
diff --git a/src/web/_model/apps/auth.php b/src/web/_model/apps/auth.php
deleted file mode 100644
index c528601..0000000
--- a/src/web/_model/apps/auth.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Auth_model extends Model {
-
- function __construct($load) {
- parent::__construct($load);
- }
-
- public function get_data(): ?array {
- $data = parent::get_data();
- $data['title'] = ucfirst(lang('login'));
- return $data;
- }
-}
diff --git a/src/web/_model/apps/error.php b/src/web/_model/apps/error.php
deleted file mode 100644
index 0a08fdd..0000000
--- a/src/web/_model/apps/error.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Error_model extends Model {
-
- function __construct($load) {
- parent::__construct($load);
- }
-
- private function get_msg(&$data) {
- if (!array_key_exists('code', $_GET)) {
- http_response_code(500);
- $data['msg'] = ucfirst(lang('error'));
- $data['title'] = '500';
- } else {
- $code = $_GET['code'];
- http_response_code($code);
- $data['title'] = $code;
- $msg = ucfirst(lang('error_' . $code, FALSE));
- if (!$msg) {
- $msg = ucfirst(lang('error'));
- }
- $data['msg'] = $msg;
- }
- }
-
- public function get_data(): ?array {
- $data = parent::get_data();
- $this->get_msg($data);
- return $data;
- }
-}
-?>
diff --git a/src/web/_model/apps/home.php b/src/web/_model/apps/home.php
deleted file mode 100644
index 634bc67..0000000
--- a/src/web/_model/apps/home.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Home_model extends Model {
-
- function __construct($load) {
- parent::__construct($load);
- }
-
- private function get_posts(): array {
- return $this->db
- ->select('*')
- ->from('xssbook.post')
- ->limit(20)
- ->rows();
- }
-
- public function get_data(): ?array {
- $data = parent::get_data();
- $data['title'] = ucfirst(lang('title'));
- $data['posts'] = $this->get_posts();
- return $data;
- }
-}
diff --git a/src/web/_model/apps/people.php b/src/web/_model/apps/people.php
deleted file mode 100644
index 08366a7..0000000
--- a/src/web/_model/apps/people.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class People_model extends Model {
-
- private $request_model;
-
- function __construct($load) {
- parent::__construct($load);
- $this->request_model = $this->load->model('request');
- }
- /**
- * @param mixed $select
- */
- private function get_filted_query($select): DatabaseQuery {
- $filter_type = $this->request_model->get_str('filter', FALSE);
- $filter_uid = $this->request_model->get_int('uid', FALSE);
- $max = $this->request_model->get_int('max', FALSE);
-
- $query = $this->db
- ->select($select)
- ->from('api.user u');
-
- if ($filter_type && $filter_uid) {
- switch ($filter_type) {
- case 'follower': {
- $query = $query
- ->join('xssbook.follow f', 'f.follower_id = u.id AND f.followee_id', 'INNER')
- ->eq($filter_uid)
- ->where('f.value = TRUE');
- } break;
-
- case 'followee': {
- $query = $query
- ->join('xssbook.follow f', 'f.followee_id = u.id AND f.follower_id', 'INNER')
- ->eq($filter_uid)
- ->where('f.value = TRUE');
- } break;
- }
- }
-
- if ($max) {
- $query = $query
- ->where('u.id')
- ->le($max);
- }
-
- return $query;
- }
-
- /**
- * @return array<string,mixed>
- */
- public function get_users(): array {
- $page = $this->request_model->get_int('page', 0);
- $page_size = 24;
- $offset = $page_size * $page;
-
- $users = $this->get_filted_query('u.*')
- ->order_by('u.id', 'DESC')
- ->offset($offset)
- ->limit($page_size)
- ->rows();
-
- $count = $this->get_filted_query('COUNT(u.id) AS count')
- ->row()['count'];
-
- $max = 0;
-
- foreach ($users as $user) {
- $max = max($max, $user['id']);
- }
-
- $filter_type = $this->request_model->get_str('filter', FALSE);
- $filter_uid = $this->request_model->get_int('uid', FALSE);
-
- return array(
- 'users' => $users,
- 'count' => $count,
- 'page_size' => $page_size,
- 'max_id' => $max,
- 'filter_type' => $filter_type || '',
- 'filter_uid' => $filter_uid || ''
- );
- }
-
- public function get_data(): ?array {
- $data = parent::get_data();
- $data['title'] = ucfirst(lang('title'));
- return $data;
- }
-}
diff --git a/src/web/_model/apps/profile.php b/src/web/_model/apps/profile.php
deleted file mode 100644
index acec9c0..0000000
--- a/src/web/_model/apps/profile.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Profile_model extends Model {
-
- private $request_model;
-
- function __construct($load) {
- parent::__construct($load);
- $this->request_model = $this->load->model('request');
- }
-
- public function get_data(): ?array {
- $uid = $this->request_model->get_int('id', FALSE);
- if ($uid === FALSE) {
- if ($this->main->session) {
- $uid = $this->main->user()['id'];
- } else {
- return NULL;
- }
- }
-
- $user = $this->db
- ->select('*')
- ->from('api.user u')
- ->where('u.id')
- ->eq($uid)
- ->row();
-
- if (!$user) {
- return NULL;
- }
-
- $following = FALSE;
- $followed = FALSE;
- $follow_id = NULL;
-
- if ($this->main->session) {
- $sid = $this->main->user()['id'];
- $res = $this->db->select('f.value, f.id')
- ->from('xssbook.follow f')
- ->where('f.follower_id')
- ->eq($sid)
- ->where('f.followee_id')
- ->eq($uid)
- ->row();
- $following = $res ? $res['value'] : FALSE;
- $follow_id = $res ? $res['id'] : NULL;
- $res = $this->db->select('f.value')
- ->from('xssbook.follow f')
- ->where('f.follower_id')
- ->eq($uid)
- ->where('f.followee_id')
- ->eq($sid)
- ->row();
- $followed = $res ? $res['value'] : FALSE;
- }
-
- $data = parent::get_data();
- $data['user'] = $user;
- $data['following'] = $following;
- $data['followed'] = $followed;
- $data['follow_id'] = $follow_id;
- $data['title'] = ucfirst(lang('title', sub: [$user['first_name']]));
- return $data;
- }
-}
diff --git a/src/web/_model/apps/settings.php b/src/web/_model/apps/settings.php
deleted file mode 100644
index 1f1e3f9..0000000
--- a/src/web/_model/apps/settings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Settings_model extends Model {
-
- private $request_model;
-
- function __construct($load) {
- parent::__construct($load);
- $this->request_model = $this->load->model('request');
- }
-
- public function get_data(): ?array {
- $data = parent::get_data();
- $data['title'] = ucfirst(lang('title'));
- return $data;
- }
-}
diff --git a/src/web/_model/auth.php b/src/web/_model/auth.php
new file mode 100644
index 0000000..50cb367
--- /dev/null
+++ b/src/web/_model/auth.php
@@ -0,0 +1,42 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Auth_model extends XSS_Model {
+
+ private static ?array $session = NULL;
+
+ /**
+ * Loads current session
+ * @param string $jwt - the user provided JWT
+ */
+ public function session(): ?array {
+ // check
+ if (self::$session)
+ return self::$session;
+ // get jwt
+ $jwt = $_SESSION['jwt'] ?? '';
+ if (!$jwt)
+ return NULL;
+ // get session
+ $result = $this->db()
+ ->select("_api.verify_jwt(?) AS user_id;")
+ ->row($jwt);
+ // invalid JWT
+ if (!$result)
+ return NULL;
+ // load user inside session
+ $user_id = $result['user_id'];
+ $user = $this->db()
+ ->select('*')
+ ->from('api.user')
+ ->where('id')
+ ->eq($user_id)
+ ->row();
+ // valid JWT, but invalid user
+ if (!$result)
+ return NULL;
+ // return session
+ self::$session = array_merge(
+ $user,
+ array('jwt' => $jwt));
+ return self::$session;
+ }
+}
diff --git a/src/web/_model/cache.php b/src/web/_model/cache.php
deleted file mode 100644
index 6cf9924..0000000
--- a/src/web/_model/cache.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Cache_model extends Model {
-
- // the user cache
- private $users;
-
- function __construct($load) {
- parent::__construct($load);
- $this->users = array();
- }
-
- /**
- * Gets a array of users
- */
- public function get_users($objs) {
- $ids = array();
- foreach ($objs as $obj) {
- $id = $obj['user_id'];
- if (!array_key_exists($id, $this->users)) {
- array_push($ids, intval($id));
- }
- }
- if (!empty($ids)) {
- $result = $this->main->db
- ->select('*')
- ->from('api.user')
- ->where_in('id', $ids)
- ->rows();
- foreach ($result as $user) {
- $id = $user['id'];
- $this->users[$id] = $user;
- }
- }
- return $this->users;
- }
-
-}
diff --git a/src/web/_model/error.php b/src/web/_model/error.php
new file mode 100644
index 0000000..ec376c7
--- /dev/null
+++ b/src/web/_model/error.php
@@ -0,0 +1,3 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Error_model extends XSS_Model {
+}
diff --git a/src/web/_model/format.php b/src/web/_model/format.php
deleted file mode 100644
index d2b7316..0000000
--- a/src/web/_model/format.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Format_model extends Model {
-
- function __construct($load) {
- parent::__construct($load);
- }
-
- /**
- * Formats a users's name
- * @param array $user - the $user
- * @returns the user's formatted display name
- */
- public function name($user) {
- $name = '';
- if ($user['first_name']) {
- $name .= $user['first_name'];
- }
- if ($user['middle_name']) {
- if ($name != '') {
- $name .= ' ';
- }
- $name .= $user['middle_name'];
- }
- if ($user['last_name']) {
- if ($name != '') {
- $name .= ' ';
- }
- $name .= $user['last_name'];
- }
- if ($name == '') {
- $name = '@' . $user['username'];
- }
- return $name;
- }
-
-}
diff --git a/src/web/_model/home.php b/src/web/_model/home.php
new file mode 100644
index 0000000..f4a33e0
--- /dev/null
+++ b/src/web/_model/home.php
@@ -0,0 +1,17 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Home_model extends XSS_Model {
+
+ private function get_posts(): ?array {
+ return $this->db()
+ ->select('*')
+ ->from('api.post')
+ ->limit(POST_PAGE_SIZE)
+ ->rows();
+ }
+
+ public function get_data(): ?array {
+ $data = parent::get_data();
+ $data['posts'] = $this->get_posts();
+ return $data;
+ }
+}
diff --git a/src/web/_model/main.php b/src/web/_model/main.php
deleted file mode 100644
index cd34740..0000000
--- a/src/web/_model/main.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Main_model {
-
- // the website database
- public $db;
-
- // the current user session (can be NULL)
- public $session;
-
- // current loaded users
- private $users;
-
- // stores the current request info
- public $info;
-
- // tthe logged in user
- private $user;
-
- /**
- * Loads the main model
- * @param Loader $load - the main loader object
- */
- function __construct($load) {
- /// load the database helper
- $this->db = new DatabaseHelper();
- /// load the current session
- if (array_key_exists('jwt', $_SESSION)) {
- $this->get_session($_SESSION['jwt']);
- } else {
- $this->session = NULL;
- };
- /// init other vars
- $this->users = array();
- $this->user = NULL;
- }
-
- /**
- * Loads current session
- * @param string $jwt - the user provided JWT
- */
- private function get_session($jwt) {
- $query = $this->db
- ->select("_api.verify_jwt(?) AS user_id;");
- $result = $query->row($jwt);
- $user_id = $result['user_id'];
- if ($user_id) {
- $this->session = array(
- 'id' => $user_id,
- 'jwt' => $jwt
- );
- $user = $this->user();
- if ($user === FALSE) {
- /// valid jwt for invalid user!!!
- $this->session = NULL;
- $this->user = NULL;
- }
- }
- }
-
- /**
- * Gets the stamp for a asset path
- * @param string $path
- */
- private function asset_stamp($path): int {
- $root = $GLOBALS['webroot'];
- $path = $root . '/../public/' . $path;
- return filemtime($path);
- }
-
- /**
- * Loads a css html link
- * @param string $path - the path to the css file
- */
- public function link_css($path) {
- $stamp = $this->asset_stamp($path);
- return '<link rel="stylesheet" href="/public/' . $path . '?stamp=' . $stamp . '">';
- }
-
- /**
- * Loads a js html link
- * @param string $path - the path to the js file
- */
- public function link_js($path) {
- $stamp = $this->asset_stamp($path);
- return '<script src="/public/'. $path . '?stamp=' . $stamp . '"></script>';
- }
-
- /**
- * Gets the current user
- */
- public function user() {
- if ($this->user) {
- return $this->user;
- }
- if ($this->session) {
- $this->user = $this->db
- ->select('*')
- ->from('api.user')
- ->where('id')
- ->eq($this->session['id'])
- ->row();
- return $this->user;
- }
- return NULL;
- }
-
- /**
- * Formats a date
- * @param string $date - the data in RFC3999 format
- * @returns the formatted date
- */
- public function date($date) {
- $date=date_create($date);
- return date_format($date, "Y-m-d D H:m");
- }
-
-}
-
-?>
diff --git a/src/web/_model/people.php b/src/web/_model/people.php
new file mode 100644
index 0000000..bf540cf
--- /dev/null
+++ b/src/web/_model/people.php
@@ -0,0 +1,72 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+class People_model extends XSS_Model {
+
+ private function get_filted_query($select): DatabaseQuery {
+ $filter_type = $this->get_string('filter');
+ $filter_uid = $this->get_int('uid');
+ $max = $this->get_int('max');
+ $query = $this->db()
+ ->select($select)
+ ->from('api.user u');
+
+ if ($filter_type && $filter_uid) {
+ switch ($filter_type) {
+ // only show followers
+ case 'follower':
+ $query = $query
+ ->join('xssbook.follow f', 'f.follower_id = u.id AND f.followee_id', 'INNER')
+ ->eq($filter_uid)
+ ->where('f.value = TRUE');
+ break;
+ // only show followees
+ case 'followee':
+ $query = $query
+ ->join('xssbook.follow f', 'f.followee_id = u.id AND f.follower_id', 'INNER')
+ ->eq($filter_uid)
+ ->where('f.value = TRUE');
+ break;
+ }
+ }
+
+ if ($max) {
+ $query = $query
+ ->where('u.id')
+ ->le($max);
+ }
+
+ return $query;
+ }
+
+ public function get_people(): array {
+ $filter_type = $this->get_string('filter');
+ $filter_uid = $this->get_int('uid');
+ $page = $this->get_int('page', 0);
+
+ $page_size = PEOPLE_PAGE_SIZE;
+ $offset = $page_size * $page;
+
+ $users = $this->get_filted_query('u.*')
+ ->order_by('u.id', 'DESC')
+ ->offset($offset)
+ ->limit($page_size)
+ ->rows();
+
+ $count = $this->get_filted_query('COUNT(u.id) AS count')
+ ->row()['count'];
+
+ $max = 0;
+
+ foreach ($users as $user)
+ $max = max($max, $user['id']);
+
+ return array(
+ 'users' => $users,
+ 'count' => $count,
+ 'page_size' => $page_size,
+ 'max_id' => $max,
+ 'filter_type' => $filter_type,
+ 'filter_uid' => $filter_uid,
+ );
+ }
+}
diff --git a/src/web/_model/profile.php b/src/web/_model/profile.php
new file mode 100644
index 0000000..d35cc46
--- /dev/null
+++ b/src/web/_model/profile.php
@@ -0,0 +1,70 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Profile_model extends XSS_Model {
+
+ private $auth_model;
+
+ function __construct() {
+ $this->auth_model = $this->load_model('auth');
+ }
+
+ public function get_data(): ?array {
+ $uid = $this->get_int('id');
+ $session = $this->auth_model->session();
+
+ if (!$uid && $session)
+ $uid = $session['id'];
+ if (!$uid)
+ return NULL;
+
+ $user = $this->db()
+ ->select('*')
+ ->from('api.user u')
+ ->where('u.id')
+ ->eq($uid)
+ ->row();
+
+ if (!$user)
+ return NULL;
+
+ // am i following $uid?
+ $following = FALSE;
+ $following_id = NULL;
+ // is $uid following me?
+ $followed = FALSE;
+
+ if ($session) {
+ $sid = $session['id'];
+ // am i following $uid?
+ $res = $this->db()
+ ->select('f.value, f.id')
+ ->from('xssbook.follow f')
+ ->where('f.follower_id')
+ ->eq($sid)
+ ->where('f.followee_id')
+ ->eq($uid)
+ ->row();
+ $following = $res ? $res['value'] : FALSE;
+ $following_id = $res ? $res['id'] : NULL;
+ // is $uid following me?
+ $res = $this->db()
+ ->select('f.value')
+ ->from('xssbook.follow f')
+ ->where('f.follower_id')
+ ->eq($uid)
+ ->where('f.followee_id')
+ ->eq($sid)
+ ->row();
+ $followed = $res ? $res['value'] : FALSE;
+ }
+
+ $data = parent::get_data();
+ $data['user'] = $user;
+ $data['following'] = $following;
+ $data['following_id'] = $following_id;
+ $data['followed'] = $followed;
+
+ $name = $this->format_name($user);
+ $data['title'] .= " - $name";
+ return $data;
+ }
+}
diff --git a/src/web/_model/request.php b/src/web/_model/request.php
deleted file mode 100644
index 4cce07a..0000000
--- a/src/web/_model/request.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Request_model extends Model {
-
- function __construct($load) {
- parent::__construct($load);
- }
-
- /**
- * Loads a string from the GET request
- * @param string $key - the name for the query param
- * @param string $default - the default value if not exists
- */
- public function get_str($key, $default = NULL): string | NULL {
- if (!array_key_exists($key, $_GET)) {
- return $default;
- } else {
- return $_GET[$key];
- }
- }
-
- /**
- * Loads a number from the GET request
- * @param string $key - the name for the query param
- * @param int $default - the default value if not exists
- */
- public function get_int($key, $default = NULL): int | NULL {
- if (!array_key_exists($key, $_GET)) {
- return $default;
- } else {
- $val = $_GET[$key];
- $val = intval($val);
- if ($val < 0) {
- return 0;
- } else {
- return $val;
- }
- }
- }
-
-}
diff --git a/src/web/_model/settings.php b/src/web/_model/settings.php
new file mode 100644
index 0000000..9748f26
--- /dev/null
+++ b/src/web/_model/settings.php
@@ -0,0 +1,3 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Settings_model extends XSS_Model {
+}
diff --git a/src/web/_views/modal/about.php b/src/web/_views/_modal/about.php
index 4bc7a4f..4bc7a4f 100644
--- a/src/web/_views/modal/about.php
+++ b/src/web/_views/_modal/about.php
diff --git a/src/web/_views/modal/new_post.php b/src/web/_views/_modal/new_post.php
index 66e6561..aff19a5 100644
--- a/src/web/_views/modal/new_post.php
+++ b/src/web/_views/_modal/new_post.php
@@ -1,31 +1,28 @@
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
<?php /* vi: syntax=php */ ?>
-<?php
- $user = $this->main->user();
-?>
<form id="new-post-form">
<div class="modal-content new-post-modal">
<div class="row">
- <?=pfp($user)?>
+ <?=pfp($session)?>
<div class="col ml">
- <strong><?=$user['first_name'] . ' ' . $user['last_name']?></strong>
- <span class="subtext"><?=ucfirst(lang('now'))?></span>
+ <strong><?=$session['first_name'] . ' ' . $session['last_name']?></strong>
+ <span class="subtext"><?=ucfirst(lang('now'))?></span>
</div>
</div>
<textarea
type="text"
name="content"
id="new-post-content"
- placeholder="<?=ucfirst(lang('action_new_post_text', sub: [$user['first_name']]))?>"
+ placeholder="<?=ucfirst(lang('action_new_post_text', sub: [$session['first_name']]))?>"
></textarea>
</div>
<div class="modal-footer">
- <?=ilang('action_submit',
- id: 'new-post-submit',
- class: 'btn btn-submit btn-alt grow',
- attrs: array('type' => 'submit'),
- button: TRUE
- )?>
+ <?=ilang('action_submit',
+ id: 'new-post-submit',
+ class: 'btn btn-submit btn-alt grow',
+ attrs: array('type' => 'submit'),
+ type: 'button',
+ )?>
</div>
</form>
<script>
@@ -44,7 +41,7 @@
const onPost = function(data) {
let id = data[0].id;
$.get({
- url: '/_util/post/post?id=' + id,
+ url: '/_post/post?id=' + id,
success: getPost
});
}
diff --git a/src/web/_views/modal/register.php b/src/web/_views/_modal/register.php
index 5c76fe9..2126d0d 100644
--- a/src/web/_views/modal/register.php
+++ b/src/web/_views/_modal/register.php
@@ -125,7 +125,7 @@
id: 'register-submit',
class: 'btn btn-submit btn-alt grow',
attrs: array('type' => 'submit'),
- button: TRUE
+ type: 'button',
)?>
</div>
</form>
diff --git a/src/web/_views/template/comment.php b/src/web/_views/_template/comment.php
index ceac588..b947ff6 100644
--- a/src/web/_views/template/comment.php
+++ b/src/web/_views/_template/comment.php
@@ -1,14 +1,11 @@
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
<?php /* vi: syntax=php */ ?>
-<?php
- $format_model = $this->load->model('format');
-?>
<div class="comment row mt">
<?=pfp($user)?>
<div class="ml col sub-card">
<div class="row">
- <strong><?=$format_model->name($user)?></strong>
- <span class="subtext ml"><?=$this->main->date($comment['created'])?></span>
+ <strong><?=$this->format_name($user)?></strong>
+ <span class="subtext ml"><?=$this->format_date($comment['created'])?></span>
</div>
<?=$comment['content']?>
</div>
diff --git a/src/web/_views/template/error.php b/src/web/_views/_template/error.php
index 2e02cb1..2e02cb1 100644
--- a/src/web/_views/template/error.php
+++ b/src/web/_views/_template/error.php
diff --git a/src/web/_views/template/modal.php b/src/web/_views/_template/modal.php
index 2a041a7..8e4545d 100644
--- a/src/web/_views/template/modal.php
+++ b/src/web/_views/_template/modal.php
@@ -9,6 +9,6 @@
class: 'btn btn-action modal-close',
)?>
</div>
- <?php $this->view('modal/' . $content) ?>
+ <?php $this->view('_modal/' . $content, $data) ?>
</div>
</div>
diff --git a/src/web/_views/template/post.php b/src/web/_views/_template/post.php
index 48f8bb6..f7f5de2 100644
--- a/src/web/_views/template/post.php
+++ b/src/web/_views/_template/post.php
@@ -5,14 +5,13 @@
<?=pfp($user)?>
<div class="col ml">
<strong><?=$user['first_name'] . ' ' . $user['last_name']?></strong>
- <span class="subtext"><?=$this->main->date($post['created'])?></span>
+ <span class="subtext"><?=$this->format_date($post['created'])?></span>
</div>
</div>
<p>
<?=$post['content']?>
</p>
<?php
- $self = $this->main->user();
$liked = $post['like_id'] ? 'btn-primary' : '';
$post_attrs = array(
'postId' => $post['id']
@@ -22,7 +21,7 @@
}
?>
<span class="likes subtext"><span class="count"><?=$post['like_count']?></span><?=' ' . ucfirst(lang('likes'))?></span>
-<?php if ($self): ?>
+<?php if ($session): ?>
<hr>
<div class="row">
<?=ilang('action_like',
@@ -30,7 +29,7 @@
attrs: $post_attrs
)?>
<?=ilang('action_comment', class: 'btn grow action-comment',
- click: '$(\'#action-new-comment-' . $post['id'] . '\').focus()'
+ onclick: '$(\'#action-new-comment-' . $post['id'] . '\').focus()'
)?>
</div>
<hr>
@@ -46,7 +45,7 @@
$total = $post['comment_count'];
if ($loaded >= $page_size && $page_size < $total) {
- ilang('action_load_comments',
+ echo ilang('action_load_comments',
class: 'action-load-comments btn btn-blend mt',
attrs: array(
'postId' => $post['id'],
@@ -60,9 +59,9 @@
?>
</div>
-<?php if ($self): ?>
+<?php if ($session): ?>
<div class="row pb">
- <?=pfp($self)?>
+ <?=pfp($session)?>
<form class="ml action-new-comment-form row">
<input
type="hidden"
diff --git a/src/web/_views/template/posts.php b/src/web/_views/_template/posts.php
index ed79688..4202e67 100644
--- a/src/web/_views/template/posts.php
+++ b/src/web/_views/_template/posts.php
@@ -7,9 +7,16 @@
$total = $pdata['total'];
$max = $pdata['max'];
$filterUid = $pdata['filter_uid'];
-
+?>
+<?php if ($loaded == 0): ?>
+ <div id="no-posts" class="card">
+ <span class="no-posts-title mb"><?=lang('no_posts_found')?></span>
+ <span><?=random_value(explode("\n", lang('no_posts_found_ext')))?></span>
+ </div>
+<?php endif; ?>
+<?php
if ($loaded >= $page_size && $page_size < $total) {
- ilang('action_load_posts',
+ echo ilang('action_load_posts',
id: 'action-load-posts',
class: 'btn btn-blend grow mb mt',
attrs: array(
diff --git a/src/web/_views/template/toast.php b/src/web/_views/_template/toast.php
index 0a6a82f..902955c 100644
--- a/src/web/_views/template/toast.php
+++ b/src/web/_views/_template/toast.php
@@ -3,21 +3,17 @@
<?php
$params = array();
- if ($detail) {
- array_push($params, lang('api_column_' . $detail));
- }
+ if ($detail)
+ $params[] = lang('api_column_' . $detail);
- if ($hint) {
- array_push($params, $hint);
- }
+ if ($hint)
+ $params[] = $hint;
- $lang_msg = lang($msg, FALSE, sub: $params);
-
- if(!$lang_msg) {
+ $lang_msg = lang($msg, '', sub: $params);
+ if(!$lang_msg)
$lang_msg = $msg;
- } else {
+ else
$lang_msg = ucfirst($lang_msg);
- }
?>
<div class="toast <?=$type?>">
diff --git a/src/web/_views/apps/people/people.php b/src/web/_views/apps/people/people.php
deleted file mode 100644
index 5fc0d17..0000000
--- a/src/web/_views/apps/people/people.php
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */ ?>
-<?php /* vi: syntax=php */ ?>
-<?php
- foreach($users as $user) {
- $this->view('apps/people/card', array('user' => $user));
- }
-?>
diff --git a/src/web/_views/apps/auth/login.php b/src/web/_views/auth/main.php
index ac4cd02..9604770 100644
--- a/src/web/_views/apps/auth/login.php
+++ b/src/web/_views/auth/main.php
@@ -32,7 +32,7 @@
</div>
<?=ilang('action_login',
class: 'btn btn-primary btn-alt grow',
- button: TRUE,
+ type: 'button',
attrs: array('type' => 'submit')
)?>
<?/*=ilang('action_forgot_passwd',
@@ -43,7 +43,7 @@
<?=ilang('action_create_account',
id: 'action-register',
class: 'btn btn-success btn-alt grow',
- button: TRUE,
+ type: 'button',
attrs: array('type' => 'submit')
)?>
</div>
@@ -79,7 +79,7 @@
});
$('#action-register').on('click', function() {
- $.get( "/modal/register", function (data) {
+ $.get( "/_modal/register", function (data) {
$(document.body).append(data);
});
})
diff --git a/src/web/_views/apps/error/main.php b/src/web/_views/error/main.php
index bcc6f90..bcc6f90 100644
--- a/src/web/_views/apps/error/main.php
+++ b/src/web/_views/error/main.php
diff --git a/src/web/_views/head.php b/src/web/_views/head.php
index cca43a1..809ab36 100644
--- a/src/web/_views/head.php
+++ b/src/web/_views/head.php
@@ -4,23 +4,14 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
- <?php if ($this->main->session): ?>
- var jwtStr = <?=json_encode($this->main->session['jwt'])?>;
+ <?php if ($session): ?>
+ var jwtStr = <?=json_encode($session['jwt'])?>;
<?php else: ?>
var jwtStr = null;
<?php endif; ?>
</script>
- <?php
- foreach ($js_files as $js) {
- echo $this->main->link_js($js);
- }
- foreach ($css_files as $css) {
- echo $this->main->link_css($css);
- }
- ?>
+ <?=CRIMSON_META($this)?>
<title><?=$title?></title>
- <!-- haa haa hee hee hoo hoo -->
- <script src="https://unpkg.com/@ruffle-rs/ruffle"></script>
</head>
<body>
<div id="toast-container">
diff --git a/src/web/_views/header.php b/src/web/_views/header.php
index 7315afb..4ba15ed 100644
--- a/src/web/_views/header.php
+++ b/src/web/_views/header.php
@@ -1,7 +1,6 @@
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
<?php /* vim: syntax=php */ ?>
<?php
- $self = $this->main->user();
$this->view('head', $data);
?>
<header id="header">
@@ -11,41 +10,29 @@
<div class="center" :class="{hidden: !visible}">
<a
id="action-home"
- class="btn <?=$this->main->info['app'] == 'home' ? 'btn-primary btn-border' : ''?>"
+ class="btn <?=ROUTER->req['app'] == 'home' ? 'btn-primary btn-border' : ''?>"
href="/home"
- title="<?=ucfirst(lang('action_home_tip'))?>"
- >
+ title="<?=ucfirst(lang('action_home_tip'))?>">
<i class="mi mi-lg">home</i>
<span><?=ucfirst(lang('action_home_text'))?></span>
</a>
<a
id="action-people"
- class="btn <?=$this->main->info['app'] == 'people' ? 'btn-primary btn-border' : ''?>"
+ class="btn <?=ROUTER->req['app'] == 'people' ? 'btn-primary btn-border' : ''?>"
href="/people"
- title="<?=ucfirst(lang('action_people_tip'))?>"
- >
+ title="<?=ucfirst(lang('action_people_tip'))?>">
<i class="mi mi-lg">people</i>
<span><?=ucfirst(lang('action_people_text'))?></span>
</a>
- <!--a
- id="action-chat"
- class="btn <?=$this->main->info['app'] == 'chat' ? 'btn-primary btn-border' : ''?>"
- href="/chat"
- title="<?=lang('action_chat_tip')?>"
- >
- <i class="mi mi-lg">chat</i>
- <span><?=lang('action_chat_text')?></span>
- </a-->
</div>
<div class="right">
<button
id="action-hamburger"
title="<?=ucfirst(lang('action_hamburger_tip'))?>"
- class="btn mr"
- >
+ class="btn mr">
<i class="mi mi-lg">menu</i>
</button>
- <?php if($self): ?>
+ <?php if($session): ?>
<script>
var userMenu = null;
@@ -53,13 +40,13 @@
userMenu.toggleClass('hidden');
}
</script>
- <?=pfp($self, FALSE, 'toggleUserMenu()')?>
+ <?=pfp($session, FALSE, 'toggleUserMenu()')?>
<div class="card col hidden" id="user-menu">
<span class="user-menu-header row mr">
- <?=pfp($self, FALSE)?>
+ <?=pfp($session, FALSE)?>
<span class="col">
- <strong><?=$this->format_model->name($self)?></strong>
- <span class="subtext"><?=$self['username']?></span>
+ <strong><?=$this->format_name($session)?></strong>
+ <span class="subtext"><?=$session['username']?></span>
</span>
</span>
<hr>
@@ -67,13 +54,12 @@
'action_profile',
id: 'action-profile',
class: 'btn',
- href: '/profile?id=' . $self['id']
+ href: '/profile?id=' . $session['id']
)?>
<?=ilang(
'action_xssbook_about',
id: 'action-xssbook-about',
class: 'btn',
- click: 'viewAbout'
)?>
<?=ilang(
'action_settings',
@@ -94,7 +80,7 @@
</div>
<script>
$('#action-xssbook-about').on('click', function() {
- $.get( "/modal/about", function (data) {
+ $.get( "/_modal/about", function (data) {
$(document.body).append(data);
});
})
diff --git a/src/web/_views/apps/home/main.php b/src/web/_views/home/main.php
index 864034a..c9373d2 100644
--- a/src/web/_views/apps/home/main.php
+++ b/src/web/_views/home/main.php
@@ -1,22 +1,22 @@
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
<?php /* vi: syntax=php */ ?>
<main id="main">
-<?php if ($self): ?>
+<?php if ($session): ?>
<div id="new-post" class="card">
<div class="row grow">
- <?=pfp($self)?>
+ <?=pfp($session)?>
<a
id="action-new-post"
class="btn btn-alt grow ml"
autocomplete="off"
aria-label="<?=ucfirst(lang('action_new_post_tip'))?>"
>
- <?=ucfirst(lang('action_new_post_text', sub: [$self['first_name']]))?>
+ <?=ucfirst(lang('action_new_post_text', sub: [$session['first_name']]))?>
</a>
</div>
<script>
$('#action-new-post').on('click', function() {
- $.get( "/modal/new_post", function (data) {
+ $.get( "/_modal/new_post", function (data) {
$(document.body).append(data);
});
})
diff --git a/src/web/_views/apps/people/card.php b/src/web/_views/people/card.php
index 93b1350..7e040ba 100644
--- a/src/web/_views/apps/people/card.php
+++ b/src/web/_views/people/card.php
@@ -7,7 +7,7 @@
<div class="col">
<?=pfp($user, FALSE)?>
<div class="col ml">
- <span class="name"><?=$this->format_model->name($user)?></span>
+ <span class="name"><?=$this->format_name($user)?></span>
<span class="subtext"><?=$user['username']?></span>
</div>
</div>
diff --git a/src/web/_views/apps/people/footer.php b/src/web/_views/people/footer.php
index f18e031..f18e031 100644
--- a/src/web/_views/apps/people/footer.php
+++ b/src/web/_views/people/footer.php
diff --git a/src/web/_views/apps/people/header.php b/src/web/_views/people/header.php
index b1099ec..b1099ec 100644
--- a/src/web/_views/apps/people/header.php
+++ b/src/web/_views/people/header.php
diff --git a/src/web/_views/apps/people/main.php b/src/web/_views/people/main.php
index ec84ab9..c602b2c 100644
--- a/src/web/_views/apps/people/main.php
+++ b/src/web/_views/people/main.php
@@ -1,18 +1,22 @@
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
-<?php /* vi: syntax=php */ ?>
<div id="people-container" class="col">
-<?php
- $pdata = $this->people();
-?>
+ <?php $pdata = $this->people(); ?>
</div>
<?php
+
$loaded = count($pdata['users']);
$page_size = $pdata['page_size'];
$total = $pdata['count'];
$max = $pdata['max_id'];
$filter_uid = $pdata['filter_uid'];
$filer_type = $pdata['filter_type'];
+
?>
+<?php if ($loaded == 0): ?>
+ <div id="no-people" class="card">
+ <?=lang('no_people_found')?>
+ </div>
+<?php endif; ?>
<?php if ($loaded >= $page_size && $page_size < $total): ?>
<?=ilang('action_load_users',
id: 'action-load-users',
diff --git a/src/web/_views/people/people.php b/src/web/_views/people/people.php
new file mode 100644
index 0000000..8726f1d
--- /dev/null
+++ b/src/web/_views/people/people.php
@@ -0,0 +1,5 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+foreach($users as $user) {
+ $this->view('people/card', array('user' => $user));
+}
+?>
diff --git a/src/web/_views/apps/profile/main.php b/src/web/_views/profile/main.php
index b2ad496..3e7129c 100644
--- a/src/web/_views/apps/profile/main.php
+++ b/src/web/_views/profile/main.php
@@ -11,47 +11,47 @@
<div class="col content grow">
<div class="row grow">
<div class="col mb">
- <strong class="name"><?=$this->format_model->name($user)?></strong>
+ <strong class="name"><?=$this->format_name($user)?></strong>
<span class="subtext"><?=$user['follower_count'] . ' ' . ucfirst(lang('followers'))?></span>
</div>
<?php if (
- $this->main->session &&
- (!isset($self) || $self['id'] != $user['id'])
+ $session &&
+ ($session['id'] != $user['id'])
): ?>
<div class="follow">
<?=ilang(
'action_follow',
id: 'action-follow-follow',
class: 'btn btn-alt',
+ sub: [$user['first_name']],
style: (!$following && !$followed) ? '' : 'display: none',
- sub: [$user['first_name']]
)?>
<?=ilang(
'action_follow_back',
id: 'action-follow-follow-back',
class: 'btn btn-alt',
+ sub: [$user['first_name']],
style: (!$following && $followed) ? '' : 'display: none',
- sub: [$user['first_name']]
)?>
<?=ilang(
'action_following',
id: 'action-follow-following',
class: 'btn btn-alt btn-primary',
+ sub: [$user['first_name']],
style: ($following && !$followed) ? '' : 'display: none',
- sub: [$user['first_name']]
)?>
<?=ilang(
'action_friends',
id: 'action-follow-friends',
class: 'btn btn-alt btn-primary',
+ sub: [$user['first_name']],
style: ($following && $followed) ? '' : 'display: none',
- sub: [$user['first_name']]
)?>
</div>
<script>
let following = <?=json_encode($following)?>;
+ let followingId = <?=json_encode($following_id)?>;
let followed = <?=json_encode($followed)?>;
- let followId = <?=json_encode($follow_id)?>;
let followee_id = <?=json_encode($user['id'])?>;
let btns = {};
@@ -84,15 +84,15 @@
}
const onPostFollow = (data) => {
- followId = data[0].id;
+ followingId = data[0].id;
following = true;
updateFollow();
}
const onClickFollow = () => {
- if (followId) {
+ if (followingId) {
$.ajax({
- url: '/api/follow?id=eq.' + followId,
+ url: '/api/follow?id=eq.' + followingId,
method: 'PATCH',
data: JSON.stringify({ followee_id, value: !following }),
success: onPatchFollow
@@ -181,7 +181,7 @@
</tr>
<tr>
<td><strong><?=ucfirst(lang('about_general_birth_date'))?></strong></td>
- <td><?=$this->main->date($user['birth_date'])?></td>
+ <td><?=$this->format_date($user['birth_date'])?></td>
</tr>
</table>
<h1><?=ucfirst(lang('about_stats'))?></h1>
@@ -204,11 +204,11 @@
</tr>
<tr>
<td><strong><?=ucfirst(lang('about_stats_joined'))?></strong></td>
- <td><?=$this->main->date($user['created'])?></td>
+ <td><?=$this->format_date($user['created'])?></td>
</tr>
<tr>
<td><strong><?=ucfirst(lang('about_stats_seen'))?></strong></td>
- <td><?=$this->main->date($user['seen'])?></td>
+ <td><?=$this->format_date($user['seen'])?></td>
</tr>
</table>
</div>
diff --git a/src/web/_views/apps/settings/main.php b/src/web/_views/settings/main.php
index 2033acc..4401fe1 100644
--- a/src/web/_views/apps/settings/main.php
+++ b/src/web/_views/settings/main.php
@@ -1,9 +1,6 @@
-<?php /* Copyright (c) 2024 Freya Murphy */ ?>
-<?php /* vi: syntax=php */ ?>
+<?php /* Copyright (c) 2024 Freya Murphy */
-<?php
-
-$user = $this->main->user();
+$user = $session;
function __create_form($user, $col) {
$ph = ucfirst(lang('ph_' . $col));
diff --git a/src/web/config.php b/src/web/config.php
new file mode 100644
index 0000000..3ca2bbd
--- /dev/null
+++ b/src/web/config.php
@@ -0,0 +1,56 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+// CONFIG
+// config values needed across the website
+//
+// domain - the default domain for the website
+//
+// allowed_hosts - accepted domains to use for the website
+//
+// base_path - the base path the website is located at
+//
+// 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 settings */
+ 'domain' => 'xssbook.com',
+ 'allowed_hosts' => ['xssbook.com'],
+ 'base_path' => '/',
+ 'theme_color' => '#1778f2',
+ /* route overides */
+ 'routes' => array(
+ 'manifest.json' => '_meta/manifest',
+ ),
+ /* css to load on each route */
+ 'style' => array(
+ '' => 'css/common.css',
+ 'home' => ['css/home.css', 'css/post.css'],
+ 'auth' => 'css/auth.css',
+ 'people' => 'css/people.css',
+ 'profile' => ['css/profile.css', 'css/people.css', 'css/post.css'],
+ 'settings' => 'css/settings.css',
+ 'error' => 'css/error.css',
+ ),
+ /* js to load on each route */
+ 'js' => array(
+ '' => ['js/thirdparty/jquery.min.js', 'js/lib.js', 'js/modal.js'],
+ 'home' => 'js/post.js',
+ 'profile' => 'js/post.js',
+ ),
+ /* directories to autoload php code */
+ 'autoload' => array('/lib'),
+));
+
+define('POST_PAGE_SIZE', 10);
+define('COMMENT_PAGE_SIZE', 5);
+define('PEOPLE_PAGE_SIZE', 24);
diff --git a/src/web/config/aesthetic.php b/src/web/config/aesthetic.php
deleted file mode 100644
index 5a66660..0000000
--- a/src/web/config/aesthetic.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Aesthetic {
-
- private $config;
-
- function __construct() {
- $this->config = array(
- '_common' => array(
- 'js' => [
- 'js/thirdparty/jquery.min.js',
- 'js/lib.js',
- 'js/modal.js',
- ],
- 'css' => [
- 'css/common.css'
- ],
- ),
- 'error' => array(
- 'css' => [
- 'css/error.css'
- ],
- ),
- 'home' => array(
- 'js' => [
- 'js/post.js',
- ],
- 'css' => [
- 'css/home.css',
- 'css/post.css'
- ],
- ),
- 'auth' => array(
- 'css' => [
- 'css/auth.css'
- ],
- ),
- 'people' => array(
- 'css' => [
- 'css/people.css'
- ],
- ),
- 'profile' => array(
- 'js' => [
- 'js/post.js',
- ],
- 'css' => [
- 'css/profile.css',
- 'css/people.css',
- 'css/post.css'
- ],
- ),
- 'settings' => array(
- 'css' => [
- 'css/settings.css'
- ]
- ),
- );
- }
- /**
- * @param mixed $route
- * @return array<string,>
- */
- function get_files($route): array {
- $js_files = $this->config['_common']['js'];
- $css_files = $this->config['_common']['css'];
-
- if (array_key_exists($route, $this->config)) {
- $config = $this->config[$route];
- if (array_key_exists('js', $config)) {
- $js_files = array_merge($js_files, $config['js']);
- }
- if (array_key_exists('css', $config)) {
- $css_files = array_merge($css_files, $config['css']);
- }
- }
-
- return array(
- 'js_files' => $js_files,
- 'css_files' => $css_files,
- );
- }
-
-}
diff --git a/src/web/config/routes.php b/src/web/config/routes.php
deleted file mode 100644
index 20b499a..0000000
--- a/src/web/config/routes.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-$routes = array();
-$routes['home'] = 'apps/home';
-$routes['error'] = 'apps/error';
-$routes['auth'] = 'apps/auth';
-$routes['people'] = 'apps/people';
-$routes['profile'] = 'apps/profile';
-$routes['settings'] = 'apps/settings';
-
-$routes[''] = '_index';
-$routes['manifest.json'] = '_meta/manifest';
diff --git a/src/web/core/_controller.php b/src/web/core/_controller.php
deleted file mode 100644
index 3502ea5..0000000
--- a/src/web/core/_controller.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-abstract class Controller {
-
- // the main model
- public $main;
-
- // the loader
- public $load;
-
- // the database
- public $db;
-
- // the format model
- protected $format_model;
-
- /**
- * Creates a constructor
- * @param Loader $load - the website loaded object
- */
- function __construct($load) {
- $this->load = $load;
- $this->main = $this->load->model('main');
- $this->db = $this->main->db;
-
- $info = $this->main->info;
- $lang = $info['lang'];
- $this->load->lang($lang);
- $app = $info['app'];
- if ($app) {
- $this->load->app_lang($lang, $app);
- }
-
- $this->format_model = $this->load->model('format');
- }
-
- public function index() {}
-
- public function redirect($link) {
- header('Location: '. $link, true, 301);
- die();
- }
-
- protected function view($__name, $data = array()) {
- $__root = $GLOBALS['webroot'];
- $__path = $__root . '/_views/' . $__name . '.php';
- if (is_file($__path)) {
- extract($data);
- require($__path);
- return;
- }
- }
-
- protected function is_ajax(): bool {
- $_POST = json_decode(
- file_get_contents("php://input"), true
- );
- return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
- }
-
- protected function error($code): void {
- $_GET['code'] = $code;
- $this->main->info['app'] = 'error';
- $error_controller = $this->load->controller('apps/error');
- $error_controller->index();
- die();
- }
-
-}
-?>
diff --git a/src/web/core/_model.php b/src/web/core/_model.php
deleted file mode 100644
index dfc7163..0000000
--- a/src/web/core/_model.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-abstract class Model {
- // the main model
- // shared by all controllers and models
- public $main;
- public $load;
-
- // the database
- public $db;
-
- private $config;
-
- /**
- * Creates a model
- * @param Loader $load - the main loader object
- */
- function __construct($load) {
- $this->load = $load;
- $this->main = $this->load->model('main');
- $this->db = $this->main->db;
- $this->config = new Aesthetic();
- }
-
- /**
- * @returns the base model data
- */
- public function get_data(): ?array {
- $data = array();
- $data['self'] = $this->main->user();
-
- $info = $this->main->info;
- $app = $info['app'];
-
- if ($app) {
- $files = $this->config->get_files($app);
- $data = array_merge($data, $files);
- } else {
- $files = $this->config->get_files();
- $data = array_merge($data, $files);
- }
-
- return $data;
- }
-}
diff --git a/src/web/core/database.php b/src/web/core/database.php
deleted file mode 100644
index 25cb5ba..0000000
--- a/src/web/core/database.php
+++ /dev/null
@@ -1,282 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-class DatabaseQuery {
-
- private $conn;
- private $query;
-
- private $where;
- private $set;
-
- private $param;
-
- function __construct($conn) {
- $this->conn = $conn;
- $this->query = '';
-
- $this->set = FALSE;
- $this->where = FALSE;
- $this->param = array();
- }
-
- ///
- /// ARBITRARY QUERY
- ///
-
- public function query($query) {
- $this->query .= $query;
- return $this;
- }
-
- ///
- /// SELECT
- ///
-
- public function select($select) {
- $this->query .= "SELECT $select\n";
- return $this;
- }
-
- public function from($from) {
- $this->query .= "FROM $from\n";
- return $this;
- }
-
- ///
- /// INSERT
- ///
-
- public function insert_into($insert, ...$columns) {
- $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(...$values) {
- $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($cond) {
- if (!$this->where) {
- $this->where = TRUE;
- $this->query .= "WHERE ";
- } else {
- $this->query .= "AND ";
- }
- $this->query .= "$cond ";
- return $this;
- }
-
- public function where_in($column, $array) {
- 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;
- }
-
- private function in($array) {
- $in = 'IN (';
- foreach ($array as $idx => $item) {
- if ($idx != 0) {
- $in .= ",";
- }
- $in .= "?";
- array_push($this->param, $item);
- }
- $in .= ")";
- return $in;
- }
-
- ///
- /// OPERATORS
- ///
-
- public function like($item) {
- $this->query .= "LIKE ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function eq($item) {
- $this->query .= "= ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function ne($item) {
- $this->query .= "<> ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function lt($item) {
- $this->query .= "< ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function le($item) {
- $this->query .= "<= ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- ///
- /// JOINS
- ///
-
- public function join($table, $on, $type = 'LEFT') {
- $this->query .= "$type JOIN $table ON $on\n";
- return $this;
- }
-
- ///
- /// LIMIT, OFFSET, ORDER
- ///
-
- public function limit($limit) {
- $this->query .= "LIMIT ?\n";
- array_push($this->param, $limit);
- return $this;
- }
-
- public function offset($offset) {
- $this->query .= "OFFSET ?\n";
- array_push($this->param, $offset);
- return $this;
- }
-
- public function order_by($column, $order = 'ASC') {
- $this->query .= "ORDER BY " . $column . ' ' . $order . ' ';
- return $this;
- }
-
- ///
- /// COLLECT
- ///
-
- public function rows(...$params) {
- $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 $stmt->fetchAll(PDO::FETCH_ASSOC);
- }
-
- public function row(...$params) {
- $args = $this->param;
- foreach ($params as $param) {
- array_push($args, $param);
- }
- $stmt = $this->conn->prepare($this->query);
- $stmt->execute($args);
- return $stmt->fetch(PDO::FETCH_ASSOC);
- }
-
- public function execute(...$params) {
- $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 $conn;
-
- function __construct() {
- $this->conn = NULL;
- }
-
- private function connect() {
- 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($select) {
- $conn = $this->connect();
- $query = new DatabaseQuery($conn);
- return $query->select($select);
- }
-
- public function insert_into($insert, ...$columns) {
- $conn = $this->connect();
- $query = new DatabaseQuery($conn);
- return $query->insert_into($insert, ...$columns);
- }
-
- public function query($query_str) {
- $conn = $this->connect();
- $query = new DatabaseQuery($conn);
- return $query->query($query_str);
- }
-}
-
diff --git a/src/web/core/loader.php b/src/web/core/loader.php
deleted file mode 100644
index 2091533..0000000
--- a/src/web/core/loader.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Loader {
-
- // keep track of what has been loaded
- private $loaded;
-
- function __construct() {
- $this->loaded = array();
- }
-
- /**
- * 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';
- if (array_key_exists($path, $this->loaded)) {
- return $this->loaded[$path];
- }
-
- 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($this);
- $this->loaded[$path] = $obj;
-
- return $obj;
- }
-
- /**
- * Loads a model
- * @param string $name - the name of the model to load
- */
- public function model($name): object|NULL {
- $root = $GLOBALS['webroot'];
- $dir = $root . '/_model';
- return $this->load_type($name, $dir, 'model');
- }
-
- /**
- * Loads a controller
- * @param string $name - the name of the controller to load
- */
- public function controller($name): Controller|NULL {
- $root = $GLOBALS['webroot'];
- $dir = $root . '/_controller';
- return $this->load_type($name, $dir, 'controller');
- }
-
- /**
- * Loads the given common lang
- * @param string $lang_code 0 the language code
- */
- public function lang($lang_code): void {
- $dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/';
- $lang = $GLOBALS['lang'];
- if ($handle = opendir($dir)) {
- while (false !== ($entry = readdir($handle))) {
- if ($entry === '.' || $entry === '..' || $entry === 'apps') {
- continue;
- }
- $path = $dir . $entry;
- require($path);
- }
- }
- $GLOBALS['lang'] = $lang;
- }
-
- /**
- * Loads a given app specific lang
- * @param string $lang_code - the language code
- * @param string $name - the name of the app
- */
- public function app_lang($lang_code, $name): void {
- $dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/apps/';
- $file = $dir . $name . '.php';
- if (file_exists($file)) {
- $lang = $GLOBALS['lang'];
- require($dir . $name . '.php');
- $GLOBALS['lang'] = $lang;
- }
- }
-
-}
diff --git a/src/web/core/router.php b/src/web/core/router.php
deleted file mode 100644
index 557665b..0000000
--- a/src/web/core/router.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-class Router {
-
- // the loader
- private $load;
-
- // the main model
- private $main;
-
- /**
- * Creates a router
- * @param Loader $load - the main laoder object
- */
- function __construct($load) {
- $this->load = $load;
- $this->main = $this->load->model('main');
- }
-
- /**
- * @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 path parts
- $parts = explode('/', $path);
-
- $len = count($parts);
-
- // get route info
- $route = array();
- // e.g. /
- if ($path === '') {
- $route = array(
- 'route' => '',
- 'slug' => 'index',
- );
- // e.g. /home /login
- } else if ($len === 1) {
- $route = array(
- 'route' => $parts[0],
- 'slug' => 'index',
- );
- // e.g. /home/posts
- } else {
- $route = array (
- 'route' => implode('/', array_slice($parts, 0, -1)),
- 'slug' => end($parts)
- );
- };
-
- $route['app'] = $route['route'];
- $routes = $GLOBALS['routes'];
- if (array_key_exists($route['route'], $routes)) {
- $route['route'] = $routes[$route['route']];
- }
-
- return $route;
- }
-
- /**
- * Gets the curret request info
- * @return array<string,mixed>
- */
- private function get_req(): array|bool {
- $method = $_SERVER['REQUEST_METHOD'];
-
- $uri = parse_url($_SERVER['REQUEST_URI']);
- if (!$uri) {
- return FALSE;
- }
-
- $path = $uri['path'];
-
- return array_merge(
- array(
- 'uri' => $uri,
- 'method' => $method,
- 'lang' => $this->get_lang(),
- ),
- $this->get_req_route($path),
- );
- }
-
- /**
- * Gets the current language
- * @return string
- */
- private function get_lang(): string {
- return 'en_US';
- }
-
- /**
- * Handles a router error code
- * @param int $code - the http error code
- * @param bool $recursed
- */
- private function handle_error($code, $recursed): void {
- if ($recursed) {
- die($code . ' (recursed)');
- }
-
- $this->main->info = array();
- $this->main->info['slug'] = 'index';
- $this->main->info['app'] = 'error';
- $this->main->info['route'] = 'apps/error';
- $this->main->info['lang'] = $this->get_lang();
- $req = $this->main->info;
- $_GET['code'] = $code;
-
- $this->handle_req($req, TRUE);
- }
-
- /**
- * @param array $req
- * @param bool $recursed
- */
- private function handle_req($req, $recursed = FALSE): void {
-
- if ($req === FALSE) {
- $this->handle_error(500, $recursed);
- return;
- }
-
- $controller = $this->load->controller($req['route']);
-
- if ($controller === NULL) {
- $this->handle_error(404, $recursed);
- return;
- }
-
- $ref = NULL;
- try {
- $ref = new ReflectionMethod($controller, $req['slug']);
- } catch (Exception $_e) {}
-
- if ($ref === NULL || !$ref->isPublic()) {
- $this->handle_error(404, $recursed);
- return;
-
- }
-
- $ref->invoke($controller);
- }
-
- /**
- * Handels the incomming reuqest
- */
- public function handle_request(): void {
- $req = $this->get_req();
- $this->main->info = $req;
- $this->handle_req($req);
- }
-
-}
diff --git a/src/web/helper/error.php b/src/web/helper/error.php
deleted file mode 100644
index 2b6959e..0000000
--- a/src/web/helper/error.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-function error_page($code, $msg) {
- $root = $GLOBALS['webroot'];
- error_reporting(E_ERROR | E_PARSE);
- http_response_code($code);
- require($root . '/_views/template/error.php');
- die();
-}
diff --git a/src/web/helper/lang.php b/src/web/helper/lang.php
deleted file mode 100644
index 3397d63..0000000
--- a/src/web/helper/lang.php
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-$lang = array();
-
-function lang($key, $default = NULL, $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 {
- return $key;
- }
-}
-
-function ilang($key,
- $class = NULL,
- $style = NULL,
- $id = NULL,
- $href = NULL,
- $click = NULL,
- $attrs = array(),
- $sub = NULL,
- $button = FALSE,
-) {
- $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 ($style) {
- echo 'style="' . $style . '" ';
- }
- 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 '<span';
- if ($icon) {
- echo ' style="margin-left: .5em;"';
- }
- echo '>' . $text . '</span>';
- }
- if ($click || $button) {
- echo '</button>';
- } else {
- echo '</a>';
- }
-}
diff --git a/src/web/index.php b/src/web/index.php
deleted file mode 100644
index 75c1b62..0000000
--- a/src/web/index.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-$webroot = dirname(__FILE__);
-
-// load all the helper files
-require($webroot . '/helper/image.php');
-require($webroot . '/helper/error.php');
-require($webroot . '/helper/lang.php');
-
-// load all the config files
-require($webroot . '/config/aesthetic.php');
-require($webroot . '/config/routes.php');
-
-// load all core files
-require($webroot . '/core/_controller.php');
-require($webroot . '/core/_model.php');
-require($webroot . '/core/database.php');
-require($webroot . '/core/loader.php');
-require($webroot . '/core/router.php');
-
-session_save_path('/var/lib/php/session');
-session_start();
-setcookie(
- session_name(),
- session_id(),
- array(
- 'expires' => time() + 60*60*24*7,
- 'path' => '/',
- 'domain' => NULL,
- 'secure' => FALSE,
- 'httponly' => FALSE,
- 'samesite' => 'Lax'
- )
-);
-
-function __init() {
- $load = new Loader();
- $router = new Router($load);
- $router->handle_request();
-};
-
-if (!file_exists('/status/ready')) {
- error_page(503, 'Service Unavailable');
-}
-
-__init();
diff --git a/src/web/lang/en_US/api_lang.php b/src/web/lang/api.php
index bc118dd..123052e 100644
--- a/src/web/lang/en_US/api_lang.php
+++ b/src/web/lang/api.php
@@ -29,5 +29,3 @@ $lang['api_unknown'] = 'An unknown error as occurred';
// toast messages
$lang['toast_date_empty'] = 'Birthday cannot be empty';
-
-?>
diff --git a/src/web/lang/en_US/apps/auth.php b/src/web/lang/auth.php
index fb9d758..b87ddd7 100644
--- a/src/web/lang/en_US/apps/auth.php
+++ b/src/web/lang/auth.php
@@ -1,4 +1,4 @@
-<?php
+<?php /* Copyright (c) 2024 Freya Murphy */
$lang['login'] = 'Login';
$lang['login_branding'] = 'Connect with javascript and the world around you on XSSBook.';
@@ -30,5 +30,3 @@ $lang['action_forgot_passwd_text'] = 'Forgot password?';
$lang['register_modal_title'] = 'Create New Account';
$lang['action_register_text'] = 'Register';
$lang['action_register_tip'] = 'Register';
-
-?>
diff --git a/src/web/lang/en_US/common_lang.php b/src/web/lang/common.php
index 073229f..8ed1df7 100644
--- a/src/web/lang/en_US/common_lang.php
+++ b/src/web/lang/common.php
@@ -1,9 +1,21 @@
<?php /* Copyright (c) 2024 Freya Murphy */
-$lang['version'] = 'Version 2.0.8';
+$lang['version'] = 'Version 2.1.0';
$lang['copyright'] = 'Freya Murphy © 2024';
-// Navigation Bar Lang
+// Defaults
+$lang['title'] = '';
+
+// General
+$lang['xssbook'] = 'XSSBook';
+$lang['action_submit_text'] = 'Submit';
+$lang['action_submit_tip'] = 'Submit';
+$lang['action_close_text'] = '';
+$lang['action_close_tip'] = 'Close';
+$lang['action_close_icon'] = 'mi mi-sm';
+$lang['action_close_content'] = 'close';
+
+// Header
$lang['action_home_text'] = 'Home';
$lang['action_home_tip'] = 'Goto your home page.';
$lang['action_people_text'] = 'People';
@@ -15,38 +27,13 @@ $lang['action_hamburger_tip'] = 'View header dropdown.';
$lang['action_login_text'] = 'Login';
$lang['action_login_tip'] = 'Login or signup';
-// Post lang
-$lang['action_like_text'] = 'Like';
-$lang['action_like_tip'] = 'Like this post.';
-$lang['action_like_icon'] = 'mi mi-sm';
-$lang['action_like_content'] = 'thumb_up';
-$lang['action_comment_text'] = 'Comment';
-$lang['action_comment_tip'] = 'Focus the comment box.';
-$lang['action_comment_icon'] = 'mi mi-sm';
-$lang['action_comment_content'] = 'comment';
-$lang['action_new_comment_text'] = 'Write a comment';
-$lang['action_new_comment_tip'] = 'Write a comment, then press enter to submit.';
-$lang['action_load_comments_text'] = 'Load more comments';
-$lang['action_load_comments_tip'] = 'Load more comments';
-
-// General
-$lang['action_submit_text'] = 'Submit';
-$lang['action_submit_tip'] = 'Submit';
-$lang['action_close_text'] = '';
-$lang['action_close_tip'] = 'Close';
-$lang['action_close_icon'] = 'mi mi-sm';
-$lang['action_close_content'] = 'close';
-
-// Modals
+// Modal
$lang['action_modal_close_text'] = '';
$lang['action_modal_close_tip'] = 'Close modal.';
$lang['action_modal_close_icon'] = 'mi mi-sm';
$lang['action_modal_close_content'] = 'close';
-$lang['new_post_modal_title'] = 'Author New Post';
-$lang['action_new_post_text'] = 'What\'s on your mind, %s';
-$lang['action_new_post_tip'] = 'Author a new post.';
-
+// About Modal
$lang['about_modal_title'] = 'XSSBook';
// User Menu
diff --git a/src/web/lang/en_US/error_lang.php b/src/web/lang/en_US/error_lang.php
deleted file mode 100644
index afecaa1..0000000
--- a/src/web/lang/en_US/error_lang.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-$lang['error_400'] = 'Bad request';
-$lang['error_404'] = 'Resource not found';
-$lang['error_500'] = 'Whoops! Server error :(';
-$lang['error'] = 'An unknown error has occoured';
-
-?>
diff --git a/src/web/lang/en_US/apps/home.php b/src/web/lang/home.php
index a30eb88..a8bf849 100644
--- a/src/web/lang/en_US/apps/home.php
+++ b/src/web/lang/home.php
@@ -1,9 +1,7 @@
-<?php
+<?php /* Copyright (c) 2024 Freya Murphy */
$lang['title'] = 'Home';
// actions
$lang['action_load_posts_text'] = 'Load more posts';
$lang['action_load_posts_tip'] = 'Load more posts';
-
-?>
diff --git a/src/web/lang/en_US/apps/people.php b/src/web/lang/people.php
index 2bfc240..55204aa 100644
--- a/src/web/lang/en_US/apps/people.php
+++ b/src/web/lang/people.php
@@ -1,4 +1,4 @@
-<?php
+<?php /* Copyright (c) 2024 Freya Murphy */
$lang['title'] = 'Directory';
$lang['desc'] = 'Explore other people on xssbook!';
@@ -14,4 +14,4 @@ $lang['tbl_gender'] = 'Gender ';
$lang['action_load_users_text'] = 'Load more users';
$lang['action_load_users_tip'] = 'Load more users';
-?>
+$lang['no_people_found'] = 'No one is here... :(';
diff --git a/src/web/lang/post.php b/src/web/lang/post.php
new file mode 100644
index 0000000..39cb24d
--- /dev/null
+++ b/src/web/lang/post.php
@@ -0,0 +1,35 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+// Posts
+$lang['action_like_text'] = 'Like';
+$lang['action_like_tip'] = 'Like this post.';
+$lang['action_like_icon'] = 'mi mi-sm';
+$lang['action_like_content'] = 'thumb_up';
+
+$lang['no_posts_found'] = 'No posts here...';
+$lang['no_posts_found_ext'] =
+"We ate them all.
+They got lost in transit.
+All stuck in line at the DMV.
+Death has taken them.
+[REDACTED]
+They were non-RFC complient.
+Submit a formal complaint at your local IRS office.
+They are in jail for killing child processes.
+They didn't deem you worthy.
+Meta stole them for AI training.";
+
+// Comments
+$lang['action_comment_text'] = 'Comment';
+$lang['action_comment_tip'] = 'Focus the comment box.';
+$lang['action_comment_icon'] = 'mi mi-sm';
+$lang['action_comment_content'] = 'comment';
+$lang['action_new_comment_text'] = 'Write a comment';
+$lang['action_new_comment_tip'] = 'Write a comment, then press enter to submit.';
+$lang['action_load_comments_text'] = 'Load more comments';
+$lang['action_load_comments_tip'] = 'Load more comments';
+
+// New Post Modal
+$lang['new_post_modal_title'] = 'Author New Post';
+$lang['action_new_post_text'] = 'What\'s on your mind, %s';
+$lang['action_new_post_tip'] = 'Author a new post.';
diff --git a/src/web/lang/en_US/apps/profile.php b/src/web/lang/profile.php
index bb91e02..d7bbf2b 100644
--- a/src/web/lang/en_US/apps/profile.php
+++ b/src/web/lang/profile.php
@@ -1,6 +1,5 @@
-<?php
-
-$lang['title'] = '%s\'s profile';
+<?php /* Copyright (c) 2024 Freya Murphy */
+$lang['title'] = '';
$lang['joined'] = 'Joined: ';
$lang['seen'] = 'Seen: ';
@@ -42,5 +41,3 @@ $lang['about_stats_comments'] = 'Comments Created';
$lang['about_stats_following'] = 'Accounts Followed';
$lang['about_stats_joined'] = 'Date Joined';
$lang['about_stats_seen'] = 'Last Seen';
-
-?>
diff --git a/src/web/lang/en_US/apps/settings.php b/src/web/lang/settings.php
index 81ba0ec..537cdca 100644
--- a/src/web/lang/en_US/apps/settings.php
+++ b/src/web/lang/settings.php
@@ -1,4 +1,4 @@
-<?php
+<?php /* Copyright (c) 2024 Freya Murphy */
$lang['title'] = 'Settings';
diff --git a/src/web/lib/_base.php b/src/web/lib/_base.php
new file mode 100644
index 0000000..790bac9
--- /dev/null
+++ b/src/web/lib/_base.php
@@ -0,0 +1,61 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+trait XSS_Base {
+
+ /**
+ * Formats a users's name
+ * @param array $user - the $user
+ * @returns the user's formatted display name
+ */
+ public function format_name(array $user): string {
+ $name = '';
+ // first_name
+ if ($user['first_name'])
+ $name .= $user['first_name'];
+ // middle_name
+ if ($user['middle_name']) {
+ if ($name != '')
+ $name .= ' ';
+ $name .= $user['middle_name'];
+ }
+ // last_name
+ if ($user['last_name']) {
+ if ($name != '')
+ $name .= ' ';
+ $name .= $user['last_name'];
+ }
+ if ($name == '') {
+ $name = '@' . $user['username'];
+ }
+ return $name;
+ }
+
+ /**
+ * Formats a ISO date
+ * @param $iso_date the ISO date
+ */
+ public function format_date(string $iso_date): string
+ {
+ return date("Y-m-d D H:i", strtotime($iso_date));
+ }
+
+ /**
+ * Loads a STRING from $_GET, or returns $default on failure
+ */
+ public function get_string(string $key, ?string $default = NULL): ?string {
+ if (isset($_GET[$key]))
+ return $_GET[$key];
+ return $default;
+ }
+
+ /**
+ * Loads a INT from $_GET, or returns $default on failure
+ */
+ public function get_int(string $key, ?int $default = NULL): ?int {
+ $value = $this->get_string($key);
+ if ($value)
+ return intval($value);
+ return $default;
+ }
+
+}
diff --git a/src/web/lib/_controller.php b/src/web/lib/_controller.php
new file mode 100644
index 0000000..122a7a7
--- /dev/null
+++ b/src/web/lib/_controller.php
@@ -0,0 +1,49 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+class XSS_Controller extends Controller {
+ use XSS_Base;
+
+ protected $model;
+
+ public function __construct() {
+ $this->model = new XSS_model();
+ $this->load_lang('common', 'api');
+ }
+
+ /**
+ * Formats a users's name
+ * @param array $user - the $user
+ * @returns the user's formatted display name
+ */
+ public function format_name(array $user): string {
+ $name = '';
+ // first_name
+ if ($user['first_name'])
+ $name .= $user['first_name'];
+ // middle_name
+ if ($user['middle_name']) {
+ if ($name != '')
+ $name .= ' ';
+ $name .= $user['middle_name'];
+ }
+ // last_name
+ if ($user['last_name']) {
+ if ($name != '')
+ $name .= ' ';
+ $name .= $user['last_name'];
+ }
+ if ($name == '') {
+ $name = '@' . $user['username'];
+ }
+ return $name;
+ }
+
+ /**
+ * Formats a ISO date
+ * @param $iso_date the ISO date
+ */
+ public function format_date(string $iso_date): string
+ {
+ return date("Y-m-d D H:i", strtotime($iso_date));
+ }
+}
diff --git a/src/web/lib/_model.php b/src/web/lib/_model.php
new file mode 100644
index 0000000..c29e015
--- /dev/null
+++ b/src/web/lib/_model.php
@@ -0,0 +1,61 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+class XSS_Model extends Model {
+ use XSS_Base;
+
+ private static array $loaded_users = array();
+
+ /**
+ * Gets an array of users with IDs specified by 'user_id' in $objs
+ */
+ public function get_users($objs) {
+ // null check
+ if (!$objs)
+ return self::$loaded_users;
+
+ $ids = array();
+ // get all user_id's to load (not in loaded_users)
+ foreach ($objs as $obj) {
+ $id = $obj['user_id'];
+ if (!isset(self::$loaded_users[$id]))
+ $ids[] = intval($id);
+ }
+ // if there are users to load
+ if (count($ids)) {
+ $result = $this->db()
+ ->select('*')
+ ->from('api.user')
+ ->where_in('id', $ids)
+ ->rows();
+ foreach ($result as $user)
+ self::$loaded_users[$user['id']] = $user;
+ }
+ // return result
+ return self::$loaded_users;
+ }
+
+ /**
+ * Gets the page's title
+ */
+ public function get_title(): string {
+ $xssbook = lang('xssbook');
+ $title = lang('title');
+ if ($title)
+ return "$xssbook - $title";
+ return $xssbook;
+ }
+
+ /**
+ * Adds title to base data
+ */
+ #[\Override]
+ public function get_data(): ?array {
+ $data = parent::get_data();
+ // title
+ $data['title'] = $this->get_title();
+ // session
+ $auth_model = $this->load_model('auth');
+ $data['session'] = $auth_model->session();;
+ return $data;
+ }
+}
diff --git a/src/web/lib/hooks.php b/src/web/lib/hooks.php
new file mode 100644
index 0000000..45316ec
--- /dev/null
+++ b/src/web/lib/hooks.php
@@ -0,0 +1,31 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+function XSSBOOK_begin_session(): void {
+ session_start();
+ setcookie(
+ session_name(),
+ session_id(),
+ array(
+ 'expires' => time() + 60*60*24*7,
+ 'path' => '/',
+ 'domain' => NULL,
+ 'secure' => FALSE,
+ 'httponly' => FALSE,
+ 'samesite' => 'Lax'
+ )
+ );
+}
+
+function CRIMSON_init_hook(): void {
+ //date_default_timezone_set('America/New_York');
+ XSSBOOK_begin_session();
+}
+
+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/helper/image.php b/src/web/lib/image.php
index 6d42678..6d42678 100644
--- a/src/web/helper/image.php
+++ b/src/web/lib/image.php
diff --git a/src/web/lib/utils.php b/src/web/lib/utils.php
new file mode 100644
index 0000000..254f9ea
--- /dev/null
+++ b/src/web/lib/utils.php
@@ -0,0 +1,6 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+function random_value(array $array): mixed {
+ shuffle($array);
+ return end($array);
+}
diff --git a/src/web/stamp.php b/src/web/stamp.php
new file mode 100644
index 0000000..7a1956b
--- /dev/null
+++ b/src/web/stamp.php
@@ -0,0 +1,46 @@
+<?php
+$__stamps = array();
+$__stamps['public/css/home.css'] = 1734805900;
+$__stamps['public/css/error.css'] = 1734805900;
+$__stamps['public/css/post.css'] = 1734805900;
+$__stamps['public/css/people.css'] = 1734805900;
+$__stamps['public/css/profile.css'] = 1734805900;
+$__stamps['public/css/auth.css'] = 1734805900;
+$__stamps['public/css/common.css'] = 1734805900;
+$__stamps['public/css/settings.css'] = 1734805900;
+$__stamps['public/favicon.ico'] = 1721008734;
+$__stamps['public/font/Facebook.otf'] = 1721008734;
+$__stamps['public/font/Facebook.ttf'] = 1734674363;
+$__stamps['public/font/Facebook.woff'] = 1734674376;
+$__stamps['public/font/Facebook.woff2'] = 1734674377;
+$__stamps['public/font/Helvetica'] = ;
+$__stamps['public/Neue.otf'] = ;
+$__stamps['public/font/Helvetica'] = ;
+$__stamps['public/Neue.ttf'] = ;
+$__stamps['public/font/Helvetica'] = ;
+$__stamps['public/Neue.woff'] = ;
+$__stamps['public/font/Helvetica'] = ;
+$__stamps['public/Neue.woff2'] = ;
+$__stamps['public/font/Material'] = ;
+$__stamps['public/Icons.ttf'] = ;
+$__stamps['public/font/SF'] = ;
+$__stamps['public/Pro.otf'] = ;
+$__stamps['public/font/SF'] = ;
+$__stamps['public/Pro.ttf'] = ;
+$__stamps['public/font/SF'] = ;
+$__stamps['public/Pro.woff'] = ;
+$__stamps['public/font/SF'] = ;
+$__stamps['public/Pro.woff2'] = ;
+$__stamps['public/font/Material'] = ;
+$__stamps['public/Icons.otf'] = ;
+$__stamps['public/font/Material'] = ;
+$__stamps['public/Icons.woff'] = ;
+$__stamps['public/font/Material'] = ;
+$__stamps['public/Icons.woff2'] = ;
+$__stamps['public/js/lib.js'] = 1734680679;
+$__stamps['public/js/modal.js'] = 1721008734;
+$__stamps['public/js/post.js'] = 1734678976;
+$__stamps['public/js/thirdparty/jquery.min.js'] = 1721008734;
+$__stamps['public/icons/logo512.png'] = 1731184206;
+define('FILE_TIMES', $__stamps);
+unset($__stamps);