diff options
Diffstat (limited to 'handler')
-rw-r--r-- | handler/Auto.php | 106 | ||||
-rw-r--r-- | handler/Contacts.php | 16 | ||||
-rw-r--r-- | handler/Index.php | 20 | ||||
-rw-r--r-- | handler/PostId.php | 20 | ||||
-rw-r--r-- | handler/ProjectsHtml.php | 11 | ||||
-rw-r--r-- | handler/RSS.php | 32 | ||||
-rw-r--r-- | handler/admin/AdminRequestHandler.php | 20 | ||||
-rw-r--r-- | handler/admin/AutoAddOrEdit.php | 97 | ||||
-rw-r--r-- | handler/admin/AutoDelete.php | 34 | ||||
-rw-r--r-- | handler/admin/AutoEdit.php | 127 | ||||
-rw-r--r-- | handler/admin/Index.php | 13 | ||||
-rw-r--r-- | handler/admin/Login.php | 31 | ||||
-rw-r--r-- | handler/admin/Logout.php | 17 | ||||
-rw-r--r-- | handler/admin/MarkdownPreview.php | 22 | ||||
-rw-r--r-- | handler/admin/PageAdd.php | 66 | ||||
-rw-r--r-- | handler/admin/PostAdd.php | 68 | ||||
-rw-r--r-- | handler/admin/UploadDelete.php | 25 | ||||
-rw-r--r-- | handler/admin/UploadEditNote.php | 25 | ||||
-rw-r--r-- | handler/admin/Uploads.php | 73 |
19 files changed, 823 insertions, 0 deletions
diff --git a/handler/Auto.php b/handler/Auto.php new file mode 100644 index 0000000..c0d4c13 --- /dev/null +++ b/handler/Auto.php @@ -0,0 +1,106 @@ +<?php + +namespace handler; + +use admin; +use NotFoundException; +use pages; +use Post; +use posts; +use RedirectResponse; +use RequestHandler; +use Response; +use Tag; + +class Auto extends RequestHandler { + + public function get(): Response { + list($name) = $this->input('name'); + if ($name == 'coreboot-mba51-flashing') + return new RedirectResponse('/coreboot-mba52-flashing/'); + + if (is_numeric($name)) { + $post = posts::get((int)$name); + } else { + $post = posts::getPostByName($name); + } + if ($post) + return $this->getPost($post); + + $tag = posts::getTag($name); + if ($tag) + return $this->getTag($tag); + + $page = pages::getPageByName($name); + if ($page) + return $this->getPage($page); + + if (admin::isAdmin()) { + $this->skin->title = $name; + return $this->skin->renderPage('admin/pageNew', + short_name: $name); + } + + throw new NotFoundException(); + } + + public function getPost(Post $post): Response { + global $config; + + if (!$post->visible && !admin::isAdmin()) + throw new NotFoundException(); + + $tags = $post->getTags(); + + $s = $this->skin; + $s->meta[] = ['property' => 'og:title', 'content' => $post->title]; + $s->meta[] = ['property' => 'og:url', 'content' => fullURL($post->getUrl())]; + if (($img = $post->getFirstImage()) !== null) + $s->meta[] = ['property' => 'og:image', 'content' => $img->getDirectUrl()]; + $s->meta[] = [ + 'name' => 'description', + 'property' => 'og:description', + 'content' => $post->getDescriptionPreview(155) + ]; + + $s->title = $post->title; + + return $s->renderPage('main/post', + title: $post->title, + id: $post->id, + unsafe_html: $post->getHtml($this->isRetina()), + date: $post->getFullDate(), + tags: $tags, + visible: $post->visible, + url: $post->getUrl(), + email: $config['admin_email'], + urlencoded_reply_subject: 'Re: '.$post->title); + } + + public function getTag(Tag $tag): Response { + $tag = posts::getTag($tag); + if (!admin::isAdmin() && !$tag->visiblePostsCount) + throw new NotFoundException(); + + $count = posts::getPostsCountByTagId($tag->id, admin::isAdmin()); + $posts = $count ? posts::getPostsByTagId($tag->id, admin::isAdmin()) : []; + + $this->skin->title = '#'.$tag->tag; + return $this->skin->renderPage('main/tag', + count: $count, + posts: $posts, + tag: $tag->tag); + } + + public function getPage(\Page $page): Response { + if (!admin::isAdmin() && !$page->visible) + throw new NotFoundException(); + + $this->skin->title = $page ? $page->title : '???'; + return $this->skin->renderPage('main/page', + unsafe_html: $page->getHtml($this->isRetina()), + page_url: $page->getUrl(), + short_name: $page->shortName); + } + +}
\ No newline at end of file diff --git a/handler/Contacts.php b/handler/Contacts.php new file mode 100644 index 0000000..c60479d --- /dev/null +++ b/handler/Contacts.php @@ -0,0 +1,16 @@ +<?php + +namespace handler; + +use Response; + +class Contacts extends \RequestHandler { + + public function get(): Response { + global $config; + $this->skin->title = $this->lang['contacts']; + return $this->skin->renderPage('main/contacts', + email: $config['admin_email']); + } + +}
\ No newline at end of file diff --git a/handler/Index.php b/handler/Index.php new file mode 100644 index 0000000..c852511 --- /dev/null +++ b/handler/Index.php @@ -0,0 +1,20 @@ +<?php + +namespace handler; + +use admin; +use posts; + +class Index extends \RequestHandler { + + public function get(): \Response { + $posts = posts::getPosts(include_hidden: admin::isAdmin()); + $tags = posts::getAllTags(include_hidden: admin::isAdmin()); + + $this->skin->title = "ch1p's Blog"; + $this->skin->setOptions(['dynlogo_enabled' => false]); + return $this->skin->renderPage('main/index', + posts: $posts, + tags: $tags); + } +}
\ No newline at end of file diff --git a/handler/PostId.php b/handler/PostId.php new file mode 100644 index 0000000..ec9f750 --- /dev/null +++ b/handler/PostId.php @@ -0,0 +1,20 @@ +<?php + +namespace handler; + +class PostId extends \RequestHandler { + + public function get(): \Response { + list($post_id) = $this->input('i:id'); + + $post = posts_getPost($post_id); + if (!$post || (!$post->visible && !\admin::isAdmin())) + throw new \NotFoundException(); + + if ($post->shortName != '') + return new \RedirectResponse($post->getUrl()); + + throw new \NotFoundException(); + } + +}
\ No newline at end of file diff --git a/handler/ProjectsHtml.php b/handler/ProjectsHtml.php new file mode 100644 index 0000000..beada44 --- /dev/null +++ b/handler/ProjectsHtml.php @@ -0,0 +1,11 @@ +<?php + +namespace handler\main; + +class ProjectsHtml extends \RequestHandler { + + public function get(): \Response { + return new \RedirectResponse('/projects/'); + } + +}
\ No newline at end of file diff --git a/handler/RSS.php b/handler/RSS.php new file mode 100644 index 0000000..08a2136 --- /dev/null +++ b/handler/RSS.php @@ -0,0 +1,32 @@ +<?php + +namespace handler; +use posts; +use Response; +use SkinContext; + +class RSS extends \RequestHandler { + + public function get(): Response { + global $config; + + $items = array_map(fn(\Post $post) => [ + 'title' => $post->title, + 'link' => $post->getUrl(), + 'pub_date' => date(DATE_RSS, $post->ts), + 'description' => $post->getDescriptionPreview(500), + ], posts::getPosts(0, 20)); + + $ctx = new SkinContext('\\skin\\rss'); + $body = $ctx->atom( + title: ($this->lang)('site_title'), + link: 'https://'.$config['domain'], + rss_link: 'https://'.$config['domain'].'/feed.rss', + items: $items); + + $response = new Response(200, $body); + $response->addHeader('Content-Type: application/rss+xml; charset=utf-8'); + return $response; + } + +}
\ No newline at end of file diff --git a/handler/admin/AdminRequestHandler.php b/handler/admin/AdminRequestHandler.php new file mode 100644 index 0000000..04b7cde --- /dev/null +++ b/handler/admin/AdminRequestHandler.php @@ -0,0 +1,20 @@ +<?php + +namespace handler\admin; + +use admin; +use Response; + +class AdminRequestHandler extends \RequestHandler { + + public function beforeDispatch(): ?Response { + $this->skin->static[] = '/css/admin.css'; + $this->skin->static[] = '/js/admin.js'; + + if (!($this instanceof Login) && !admin::isAdmin()) + throw new \ForbiddenException('looks like you are not admin'); + + return null; + } + +}
\ No newline at end of file diff --git a/handler/admin/AutoAddOrEdit.php b/handler/admin/AutoAddOrEdit.php new file mode 100644 index 0000000..027c827 --- /dev/null +++ b/handler/admin/AutoAddOrEdit.php @@ -0,0 +1,97 @@ +<?php + +namespace handler\admin; + +use Page; +use Post; +use Response; + +abstract class AutoAddOrEdit extends AdminRequestHandler { + + public function beforeDispatch(): ?Response { + $this->skin->setOptions([ + 'full_width' => true, + 'no_footer' => true + ]); + return parent::beforeDispatch(); + } + + protected function _get_postAdd( + string $title = '', + string $text = '', + ?array $tags = null, + string $short_name = '', + ?string $error_code = null + ): Response { + $this->skin->addLangKeys($this->lang->search('/^(err_)?blog_/')); + $this->skin->title = $this->lang['blog_write']; + return $this->skin->renderPage('admin/postForm', + title: $title, + text: $text, + tags: $tags ? implode(', ', $tags) : '', + short_name: $short_name, + error_code: $error_code); + } + + protected function _get_postEdit( + Post $post, + string $title = '', + string $text = '', + ?array $tags = null, + bool $visible = false, + string $short_name = '', + ?string $error_code = null, + bool $saved = false, + ): Response { + $this->skin->addLangKeys($this->lang->search('/^(err_)?blog_/')); + $this->skin->title = ($this->lang)('blog_post_edit_title', $post->title); + return $this->skin->renderPage('admin/postForm', + is_edit: true, + post_id: $post->id, + post_url: $post->getUrl(), + title: $title, + text: $text, + tags: $tags ? implode(', ', $tags) : '', + visible: $visible, + saved: $saved, + short_name: $short_name, + error_code: $error_code + ); + } + + protected function _get_pageAdd( + string $name, + string $title = '', + string $text = '', + ?string $error_code = null + ): Response { + $this->skin->addLangKeys($this->lang->search('/^(err_)?pages_/')); + $this->skin->title = ($this->lang)('pages_create_title', $name); + return $this->skin->renderPage('admin/pageForm', + short_name: $name, + title: $title, + text: $text, + error_code: $error_code); + } + + protected function _get_pageEdit( + Page $page, + string $title = '', + string $text = '', + bool $saved = false, + bool $visible = false, + ?string $error_code = null + ): Response { + $this->skin->addLangKeys($this->lang->search('/^(err_)?pages_/')); + $this->skin->title = ($this->lang)('pages_page_edit_title', $page->shortName.'.html'); + return $this->skin->renderPage('admin/pageForm', + is_edit: true, + short_name: $page->shortName, + title: $title, + text: $text, + visible: $visible, + saved: $saved, + error_code: $error_code); + } + +}
\ No newline at end of file diff --git a/handler/admin/AutoDelete.php b/handler/admin/AutoDelete.php new file mode 100644 index 0000000..80c8eef --- /dev/null +++ b/handler/admin/AutoDelete.php @@ -0,0 +1,34 @@ +<?php + +namespace handler\admin; + +use csrf; +use NotFoundException; +use pages; +use posts; +use RedirectResponse; +use Response; + +class AutoDelete extends AdminRequestHandler { + + public function get(): Response { + list($name) = $this->input('short_name'); + + $post = posts::getPostByName($name); + if ($post) { + csrf::check('delpost'.$post->id); + posts::delete($post); + return new RedirectResponse('/'); + } + + $page = pages::getPageByName($name); + if ($page) { + csrf::check('delpage'.$page->shortName); + pages::delete($page); + return new RedirectResponse('/'); + } + + throw new NotFoundException(); + } + +}
\ No newline at end of file diff --git a/handler/admin/AutoEdit.php b/handler/admin/AutoEdit.php new file mode 100644 index 0000000..9d70c5b --- /dev/null +++ b/handler/admin/AutoEdit.php @@ -0,0 +1,127 @@ +<?php + +namespace handler\admin; + +use csrf; +use pages; +use posts; +use Response; + +class AutoEdit extends AutoAddOrEdit { + + public function get(): Response { + list($short_name, $saved) = $this->input('short_name, b:saved'); + + $post = posts::getPostByName($short_name); + if ($post) { + $tags = $post->getTags(); + return $this->_get_postEdit($post, + tags: $post->getTags(), + saved: $saved, + title: $post->title, + text: $post->md, + visible: $post->visible, + short_name: $post->shortName, + ); + } + + $page = pages::getPageByName($short_name); + if ($page) { + return $this->_get_pageEdit($page, + title: $page->title, + text: $page->md, + visible: $page->visible, + saved: $saved, + ); + } + + throw new \NotFoundException(); + } + + public function post(): Response { + list($short_name) = $this->input('short_name'); + + $post = posts::getPostByName($short_name); + if ($post) { + csrf::check('editpost'.$post->id); + + list($text, $title, $tags, $visible, $short_name) + = $this->input('text, title, tags, b:visible, new_short_name'); + + $tags = posts::splitStringToTags($tags); + $error_code = null; + + if (!$title) { + $error_code = 'no_title'; + } else if (!$text) { + $error_code = 'no_text'; + } else if (empty($tags)) { + $error_code = 'no_tags'; + } else if (empty($short_name)) { + $error_code = 'no_short_name'; + } + + if ($error_code) + $this->_get_postEdit($post, + text: $text, + title: $title, + tags: $tags, + visible: $visible, + short_name: $short_name, + error_code: $error_code + ); + + $post->edit([ + 'title' => $title, + 'md' => $text, + 'visible' => (int)$visible, + 'short_name' => $short_name + ]); + $tag_ids = posts::getTagIds($tags); + $post->setTagIds($tag_ids); + + return new \RedirectResponse($post->getUrl().'edit/?saved=1'); + } + + $page = pages::getPageByName($short_name); + if ($page) { + csrf::check('editpage'.$page->shortName); + + list($text, $title, $visible, $short_name) + = $this->input('text, title, b:visible, new_short_name'); + + $text = trim($text); + $title = trim($title); + $error_code = null; + + if (!$title) { + $error_code = 'no_title'; + } else if (!$text) { + $error_code = 'no_text'; + } else if (!$short_name) { + $error_code = 'no_short_name'; + } + + if ($error_code) { + return $this->_get_pageEdit($page, + title: $title, + text: $text, + visible: $visible, + error_code: $error_code + ); + } + + $page->edit([ + 'title' => $title, + 'md' => $text, + 'visible' => (int)$visible, + 'short_name' => $short_name, + ]); + + return new \RedirectResponse($page->getUrl().'edit/?saved=1'); + } + + throw new \NotFoundException(); + } + +}
\ No newline at end of file diff --git a/handler/admin/Index.php b/handler/admin/Index.php new file mode 100644 index 0000000..e829913 --- /dev/null +++ b/handler/admin/Index.php @@ -0,0 +1,13 @@ +<?php + +namespace handler\admin; + +use Response; + +class Index extends AdminRequestHandler { + + public function get(): Response { + return $this->skin->renderPage('admin/index'); + } + +}
\ No newline at end of file diff --git a/handler/admin/Login.php b/handler/admin/Login.php new file mode 100644 index 0000000..cade137 --- /dev/null +++ b/handler/admin/Login.php @@ -0,0 +1,31 @@ +<?php + +namespace handler\admin; + +use admin; +use csrf; +use RedirectResponse; +use Response; +use UnauthorizedException; + +class Login extends AdminRequestHandler { + + public function get(): Response { + if (admin::isAdmin()) + return new RedirectResponse('/admin/'); + return $this->skin->renderPage('admin/login'); + } + + public function post(): Response { + csrf::check('adminlogin'); + $password = $_POST['password'] ?? ''; + $valid = admin::checkPassword($password); + if ($valid) { + admin::logAuth(); + admin::setCookie(); + return new RedirectResponse('/admin/'); + } + throw new UnauthorizedException('nice try'); + } + +}
\ No newline at end of file diff --git a/handler/admin/Logout.php b/handler/admin/Logout.php new file mode 100644 index 0000000..bb11e43 --- /dev/null +++ b/handler/admin/Logout.php @@ -0,0 +1,17 @@ +<?php + +namespace handler\admin; + +use admin; +use csrf; +use Response; + +class Logout extends AdminRequestHandler { + + public function get(): Response { + csrf::check('logout'); + admin::unsetCookie(); + return new \RedirectResponse('/admin/login/'); + } + +}
\ No newline at end of file diff --git a/handler/admin/MarkdownPreview.php b/handler/admin/MarkdownPreview.php new file mode 100644 index 0000000..e513709 --- /dev/null +++ b/handler/admin/MarkdownPreview.php @@ -0,0 +1,22 @@ +<?php + +namespace handler\admin; + +use Response; + +class MarkdownPreview extends AdminRequestHandler { + + public function post(): Response { + list($md, $title, $use_image_previews) = $this->input('md, title, b:use_image_previews'); + + $html = \markup::markdownToHtml($md, $use_image_previews); + + $ctx = new \SkinContext('\\skin\\admin'); + $html = $ctx->markdownPreview( + unsafe_html: $html, + title: $title + ); + return new \AjaxOkResponse(['html' => $html]); + } + +}
\ No newline at end of file diff --git a/handler/admin/PageAdd.php b/handler/admin/PageAdd.php new file mode 100644 index 0000000..8754f0f --- /dev/null +++ b/handler/admin/PageAdd.php @@ -0,0 +1,66 @@ +<?php + +namespace handler\admin; + +use csrf; +use NotFoundException; +use pages; +use RedirectResponse; +use Response; + +class PageAdd extends AutoAddOrEdit { + + public function get(): Response { + list($name) = $this->input('short_name'); + $page = pages::getPageByName($name); + if ($page) + throw new NotFoundException(); + + return $this->_get_pageAdd($name); + } + + public function post(): Response { + csrf::check('addpage'); + + list($name) = $this->input('short_name'); + $page = pages::getPageByName($name); + if ($page) + throw new NotFoundException(); + + $text = trim($_POST['text'] ?? ''); + $title = trim($_POST['title'] ?? ''); + $error_code = null; + + if (!$title) { + $error_code = 'no_title'; + } else if (!$text) { + $error_code = 'no_text'; + } + + if ($error_code) { + return $this->_get_pageAdd( + name: $name, + text: $text, + title: $title, + error_code: $error_code + ); + } + + if (!pages::add([ + 'short_name' => $name, + 'title' => $title, + 'md' => $text + ])) { + return $this->_get_pageAdd( + name: $name, + text: $text, + title: $title, + error_code: 'db_err' + ); + } + + $page = pages::getPageByName($name); + return new RedirectResponse($page->getUrl()); + } + +}
\ No newline at end of file diff --git a/handler/admin/PostAdd.php b/handler/admin/PostAdd.php new file mode 100644 index 0000000..c21a239 --- /dev/null +++ b/handler/admin/PostAdd.php @@ -0,0 +1,68 @@ +<?php + +namespace handler\admin; + +use csrf; +use posts; +use RedirectResponse; +use Response; + +class PostAdd extends AutoAddOrEdit { + + public function get(): Response { + return $this->_get_postAdd(); + } + + public function post(): Response { + csrf::check('addpost'); + + list($text, $title, $tags, $visible, $short_name) + = $this->input('text, title, tags, b:visible, short_name'); + $tags = posts::splitStringToTags($tags); + + $error_code = null; + + if (!$title) { + $error_code = 'no_title'; + } else if (!$text) { + $error_code = 'no_text'; + } else if (empty($tags)) { + $error_code = 'no_tags'; + } else if (empty($short_name)) { + $error_code = 'no_short_name'; + } + + if ($error_code) + return $this->_get_postAdd( + text: $text, + title: $title, + tags: $tags, + short_name: $short_name, + error_code: $error_code + ); + + $id = posts::add([ + 'title' => $title, + 'md' => $text, + 'visible' => (int)$visible, + 'short_name' => $short_name, + ]); + + if (!$id) + $this->_get_postAdd( + text: $text, + title: $title, + tags: $tags, + short_name: $short_name, + error_code: 'db_err' + ); + + // set tags + $post = posts::get($id); + $tag_ids = posts::getTagIds($tags); + $post->setTagIds($tag_ids); + + return new RedirectResponse($post->getUrl()); + } + +}
\ No newline at end of file diff --git a/handler/admin/UploadDelete.php b/handler/admin/UploadDelete.php new file mode 100644 index 0000000..26b58b7 --- /dev/null +++ b/handler/admin/UploadDelete.php @@ -0,0 +1,25 @@ +<?php + +namespace handler\admin; + +use csrf; +use RedirectResponse; +use Response; + +class UploadDelete extends AdminRequestHandler { + + public function get(): Response { + list($id) = $this->input('i:id'); + + $upload = \uploads::get($id); + if (!$upload) + return new RedirectResponse('/uploads/?error='.urlencode('upload not found')); + + csrf::check('delupl'.$id); + + \uploads::delete($id); + + return new RedirectResponse('/uploads/'); + } + +}
\ No newline at end of file diff --git a/handler/admin/UploadEditNote.php b/handler/admin/UploadEditNote.php new file mode 100644 index 0000000..e7cdbb2 --- /dev/null +++ b/handler/admin/UploadEditNote.php @@ -0,0 +1,25 @@ +<?php + +namespace handler\admin; + +use csrf; +use Response; + +class UploadEditNote extends AdminRequestHandler { + + public function post(): Response { + list($id) = $this->input('i:id'); + + $upload = \uploads::get($id); + if (!$upload) + return new \RedirectResponse('/uploads/?error='.urlencode('upload not found')); + + csrf::check('editupl'.$id); + + $note = $_POST['note'] ?? ''; + $upload->setNote($note); + + return new \RedirectResponse('/uploads/'); + } + +}
\ No newline at end of file diff --git a/handler/admin/Uploads.php b/handler/admin/Uploads.php new file mode 100644 index 0000000..0cbb2f6 --- /dev/null +++ b/handler/admin/Uploads.php @@ -0,0 +1,73 @@ +<?php + +namespace handler\admin; + +use csrf; +use RedirectResponse; +use Response; + +// So it's 2022 outside, and it's PHP 8.1 already, which is actually so cool comparing to 5.x and even 7.4, but... +// ...class names are still case-insensitive?!! And I can't import \uploads because it's the same as Uploads?!! +// +// PHP, what the fuck is wrong with you?! + +class Uploads extends AdminRequestHandler { + + public function get(): Response { + list($error) = $this->input('error'); + $uploads = \uploads::getAll(); + + $this->skin->title = ($this->lang)('blog_upload'); + return $this->skin->renderPage('admin/uploads', + error: $error, + uploads: $uploads); + } + + public function post(): Response { + csrf::check('addupl'); + + list($custom_name, $note) = $this->input('name, note'); + + if (!isset($_FILES['files'])) + return new RedirectResponse('/uploads/?error='.urlencode('no file')); + + $files = []; + for ($i = 0; $i < count($_FILES['files']['name']); $i++) { + $files[] = [ + 'name' => $_FILES['files']['name'][$i], + 'type' => $_FILES['files']['type'][$i], + 'tmp_name' => $_FILES['files']['tmp_name'][$i], + 'error' => $_FILES['files']['error'][$i], + 'size' => $_FILES['files']['size'][$i], + ]; + } + + if (count($files) > 1) { + $note = ''; + $custom_name = ''; + } + + foreach ($files as $f) { + if ($f['error']) + return new RedirectResponse('/uploads/?error='.urlencode('error code '.$f['error'])); + + if (!$f['size']) + return new RedirectResponse('/uploads/?error='.urlencode('received empty file')); + + $ext = extension($f['name']); + if (!\uploads::isExtensionAllowed($ext)) + return new RedirectResponse('/uploads/?error='.urlencode('extension not allowed')); + + $upload_id = \uploads::add( + $f['tmp_name'], + $custom_name ?: $f['name'], + $note); + + if (!$upload_id) + return new RedirectResponse('/uploads/?error='.urlencode('failed to create upload')); + } + + return new RedirectResponse('/uploads/'); + } + +}
\ No newline at end of file |