diff options
Diffstat (limited to 'handler/AdminHandler.php')
-rw-r--r-- | handler/AdminHandler.php | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/handler/AdminHandler.php b/handler/AdminHandler.php new file mode 100644 index 0000000..f90fc42 --- /dev/null +++ b/handler/AdminHandler.php @@ -0,0 +1,470 @@ +<?php + +class AdminHandler extends request_handler { + + function __construct() { + parent::__construct(); + add_static('css/admin.css', 'js/admin.js'); + } + + function before_dispatch(string $http_method, string $action) { + if ($action != 'login' && !is_admin()) + forbidden(); + } + + function GET_index() { + set_title('$admin_title'); + render('admin/index'); + } + + function GET_login() { + if (is_admin()) + redirect('/admin/'); + set_title('$admin_title'); + render('admin/login'); + } + + function POST_login() { + csrf_check('adminlogin'); + $password = $_POST['password'] ?? ''; + $valid = admin_check_password($password); + if ($valid) { + admin_log_auth(); + admin_set_cookie(); + redirect('/admin/'); + } + forbidden(); + } + + function GET_logout() { + csrf_check('logout'); + admin_unset_cookie(); + redirect('/admin/login/', HTTPCode::Found); + } + + function GET_uploads() { + list($error) = input('error'); + $uploads = uploads::getAllUploads(); + + set_title('$blog_upload'); + render('admin/uploads', + error: $error, + uploads: $uploads); + } + + function POST_uploads() { + csrf_check('addupl'); + + list($custom_name, $note) = input('name, note'); + + if (!isset($_FILES['files'])) + redirect('/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']) + redirect('/uploads/?error='.urlencode('error code '.$f['error'])); + + if (!$f['size']) + redirect('/uploads/?error='.urlencode('received empty file')); + + $ext = extension($f['name']); + if (!uploads::isExtensionAllowed($ext)) + redirect('/uploads/?error='.urlencode('extension not allowed')); + + $upload_id = uploads::add( + $f['tmp_name'], + $custom_name ?: $f['name'], + $note); + + if (!$upload_id) + redirect('/uploads/?error='.urlencode('failed to create upload')); + } + + redirect('/uploads/'); + } + + function GET_upload_delete() { + list($id) = input('i:id'); + $upload = uploads::get($id); + if (!$upload) + redirect('/uploads/?error='.urlencode('upload not found')); + csrf_check('delupl'.$id); + uploads::delete($id); + redirect('/uploads/'); + } + + function POST_upload_edit_note() { + list($id, $note) = input('i:id, note'); + + $upload = uploads::get($id); + if (!$upload) + redirect('/uploads/?error='.urlencode('upload not found')); + + csrf_check('editupl'.$id); + + $upload->setNote($note); + redirect('/uploads/'); + } + + function POST_ajax_md_preview() { + list($md, $title, $use_image_previews) = 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 + ); + ajax_ok(['html' => $html]); + } + + function GET_page_add() { + list($name) = input('short_name'); + $page = pages::getByName($name); + if ($page) + not_found(); + return $this->_get_pageAdd($name); + } + + function POST_page_add() { + csrf_check('addpage'); + + list($name, $text, $title) = input('short_name, text, title'); + $page = pages::getByName($name); + if ($page) + not_found(); + + $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, + title: $title, + text: $text, + error_code: $error_code + ); + } + + if (!pages::add([ + 'short_name' => $name, + 'title' => $title, + 'md' => $text + ])) { + return $this->_get_pageAdd( + name: $name, + title: $title, + text: $text, + error_code: 'db_err' + ); + } + + $page = pages::getByName($name); + redirect($page->getUrl()); + } + + function GET_post_add() { + return $this->_get_postAdd(); + } + + function POST_post_add() { + csrf_check('addpost'); + + list($text, $title, $tags, $visible, $short_name) + = input('text, title, tags, b:visible, short_name'); + $tags = tags::splitString($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( + title: $title, + text: $text, + 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( + title: $title, + text: $text, + tags: $tags, + short_name: $short_name, + error_code: 'db_err' + ); + + // set tags + $post = posts::get($id); + $tag_ids = array_values(tags::getTags($tags)); + $post->setTagIds($tag_ids); + + redirect($post->getUrl()); + } + + function GET_auto_delete() { + list($name) = input('short_name'); + + $post = posts::getByName($name); + if ($post) { + csrf_check('delpost'.$post->id); + posts::delete($post); + redirect('/'); + } + + $page = pages::getByName($name); + if ($page) { + csrf_check('delpage'.$page->shortName); + pages::delete($page); + redirect('/'); + } + + not_found(); + } + + function GET_auto_edit() { + list($short_name, $saved) = input('short_name, b:saved'); + + $post = posts::getByName($short_name); + if ($post) { + $tags = $post->getTags(); + return $this->_get_postEdit($post, + title: $post->title, + text: $post->md, + tags: $post->getTags(), + visible: $post->visible, + toc: $post->toc, + short_name: $post->shortName, + saved: $saved, + ); + } + + $page = pages::getByName($short_name); + if ($page) { + return $this->_get_pageEdit($page, + title: $page->title, + text: $page->md, + saved: $saved, + visible: $page->visible, + ); + } + + not_found(); + } + + function POST_auto_edit() { + list($short_name) = input('short_name'); + + $post = posts::getByName($short_name); + if ($post) { + csrf_check('editpost'.$post->id); + + list($text, $title, $tags, $visible, $toc, $short_name) + = input('text, title, tags, b:visible, b:toc, new_short_name'); + + $tags = tags::splitString($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, + title: $title, + text: $text, + tags: $tags, + visible: $visible, + toc: $toc, + short_name: $short_name, + error_code: $error_code + ); + + $post->edit([ + 'title' => $title, + 'md' => $text, + 'visible' => (int)$visible, + 'toc' => (int)$toc, + 'short_name' => $short_name + ]); + $tag_ids = array_values(tags::getTags($tags)); + $post->setTagIds($tag_ids); + + redirect($post->getUrl().'edit/?saved=1'); + } + + $page = pages::getByName($short_name); + if ($page) { + csrf_check('editpage'.$page->shortName); + + list($text, $title, $visible, $short_name) + = 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, + ]); + + redirect($page->getUrl().'edit/?saved=1'); + } + + not_found(); + } + + protected static function setWidePage() { + set_skin_opts([ + 'full_width' => true, + 'no_footer' => true + ]); + } + + protected function _get_pageAdd( + string $name, + string $title = '', + string $text = '', + ?string $error_code = null + ) { + add_skin_strings_re('/^(err_)?pages_/'); + set_title(lang('pages_create_title', $name)); + static::setWidePage(); + render('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 + ) { + add_skin_strings_re('/^(err_)?pages_/'); + set_title(lang('pages_page_edit_title', $page->shortName.'.html')); + static::setWidePage(); + render('admin/pageForm', + is_edit: true, + short_name: $page->shortName, + title: $title, + text: $text, + visible: $visible, + saved: $saved, + error_code: $error_code); + } + + protected function _get_postEdit( + Post $post, + string $title = '', + string $text = '', + ?array $tags = null, + bool $visible = false, + bool $toc = false, + string $short_name = '', + ?string $error_code = null, + bool $saved = false, + ) { + add_skin_strings_re('/^(err_)?blog_/'); + set_title(lang('blog_post_edit_title', $post->title)); + static::setWidePage(); + render('admin/postForm', + is_edit: true, + post_id: $post->id, + post_url: $post->getUrl(), + title: $title, + text: $text, + tags: $tags ? implode(', ', $tags) : '', + visible: $visible, + toc: $toc, + saved: $saved, + short_name: $short_name, + error_code: $error_code + ); + } + + protected function _get_postAdd( + string $title = '', + string $text = '', + ?array $tags = null, + string $short_name = '', + ?string $error_code = null + ) { + add_skin_strings_re('/^(err_)?blog_/'); + set_title('$blog_write'); + static::setWidePage(); + render('admin/postForm', + title: $title, + text: $text, + tags: $tags ? implode(', ', $tags) : '', + short_name: $short_name, + error_code: $error_code); + } + +}
\ No newline at end of file |