From c52531e8fc53c4ed4694f954c09ae2a9879b52fc Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Wed, 30 Apr 2014 08:08:24 +0200 Subject: [PATCH] Increasing readability --- src/Controllers/AuthController.php | 24 +- src/Controllers/CommentController.php | 68 +- src/Controllers/PostController.php | 367 ++++----- src/Controllers/TagController.php | 82 +- src/Controllers/UserController.php | 1054 ++++++++++++------------- src/Helpers/TransferHelper.php | 94 +++ src/Models/Entities/PostEntity.php | 67 +- 7 files changed, 889 insertions(+), 867 deletions(-) create mode 100644 src/Helpers/TransferHelper.php diff --git a/src/Controllers/AuthController.php b/src/Controllers/AuthController.php index 7117fc44..4234547a 100644 --- a/src/Controllers/AuthController.php +++ b/src/Controllers/AuthController.php @@ -61,20 +61,20 @@ class AuthController return; } - if (InputHelper::get('submit')) - { - $suppliedName = InputHelper::get('name'); - $suppliedPassword = InputHelper::get('password'); - $dbUser = self::tryLogin($suppliedName, $suppliedPassword); + if (!InputHelper::get('submit')) + return; - if (InputHelper::get('remember')) - { - $token = implode('|', [base64_encode($suppliedName), base64_encode($suppliedPassword)]); - setcookie('auth', TextHelper::encrypt($token), time() + 365 * 24 * 3600, '/'); - } - StatusHelper::success(); - self::redirectAfterLog(); + $suppliedName = InputHelper::get('name'); + $suppliedPassword = InputHelper::get('password'); + $dbUser = self::tryLogin($suppliedName, $suppliedPassword); + + if (InputHelper::get('remember')) + { + $token = implode('|', [base64_encode($suppliedName), base64_encode($suppliedPassword)]); + setcookie('auth', TextHelper::encrypt($token), time() + 365 * 24 * 3600, '/'); } + StatusHelper::success(); + self::redirectAfterLog(); } public function logoutAction() diff --git a/src/Controllers/CommentController.php b/src/Controllers/CommentController.php index c09d22bf..20571ff7 100644 --- a/src/Controllers/CommentController.php +++ b/src/Controllers/CommentController.php @@ -40,28 +40,28 @@ class CommentController $post = PostModel::findById($postId); $context->transport->post = $post; - if (InputHelper::get('submit')) + if (!InputHelper::get('submit')) + return; + + $text = InputHelper::get('text'); + $text = CommentModel::validateText($text); + + $comment = CommentModel::spawn(); + $comment->setPost($post); + if ($context->loggedIn) + $comment->setCommenter($context->user); + else + $comment->setCommenter(null); + $comment->commentDate = time(); + $comment->text = $text; + + if (InputHelper::get('sender') != 'preview') { - $text = InputHelper::get('text'); - $text = CommentModel::validateText($text); - - $comment = CommentModel::spawn(); - $comment->setPost($post); - if ($context->loggedIn) - $comment->setCommenter($context->user); - else - $comment->setCommenter(null); - $comment->commentDate = time(); - $comment->text = $text; - - if (InputHelper::get('sender') != 'preview') - { - CommentModel::save($comment); - LogHelper::log('{user} commented on {post}', ['post' => TextHelper::reprPost($post->id)]); - } - $context->transport->textPreview = $comment->getText(); - StatusHelper::success(); + CommentModel::save($comment); + LogHelper::log('{user} commented on {post}', ['post' => TextHelper::reprPost($post->id)]); } + $context->transport->textPreview = $comment->getText(); + StatusHelper::success(); } public function editAction($id) @@ -74,22 +74,22 @@ class CommentController Privilege::EditComment, Access::getIdentity($comment->getCommenter())); - if (InputHelper::get('submit')) + if (!InputHelper::get('submit')) + return; + + $text = InputHelper::get('text'); + $text = CommentModel::validateText($text); + + $comment->text = $text; + + if (InputHelper::get('sender') != 'preview') { - $text = InputHelper::get('text'); - $text = CommentModel::validateText($text); - - $comment->text = $text; - - if (InputHelper::get('sender') != 'preview') - { - CommentModel::save($comment); - LogHelper::log('{user} edited comment in {post}', [ - 'post' => TextHelper::reprPost($comment->getPost())]); - } - $context->transport->textPreview = $comment->getText(); - StatusHelper::success(); + CommentModel::save($comment); + LogHelper::log('{user} edited comment in {post}', [ + 'post' => TextHelper::reprPost($comment->getPost())]); } + $context->transport->textPreview = $comment->getText(); + StatusHelper::success(); } public function deleteAction($id) diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php index 14a77d77..20a53103 100644 --- a/src/Controllers/PostController.php +++ b/src/Controllers/PostController.php @@ -1,41 +1,6 @@ transport->post = $post; - if (InputHelper::get('submit')) + if (!InputHelper::get('submit')) + return; + + Access::assert( + Privilege::MassTag, + Access::getIdentity($post->getUploader())); + + $tags = $post->getTags(); + + if (!$enable) { - Access::assert( - Privilege::MassTag, - Access::getIdentity($post->getUploader())); + foreach ($tags as $i => $tag) + if ($tag->name == $tagName) + unset($tags[$i]); - $tags = $post->getTags(); - - if (!$enable) - { - foreach ($tags as $i => $tag) - if ($tag->name == $tagName) - unset($tags[$i]); - - LogHelper::log('{user} untagged {post} with {tag}', [ - 'post' => TextHelper::reprPost($post), - 'tag' => TextHelper::reprTag($tag)]); - } - elseif ($enable) - { - $tag = TagModel::findByName($tagName, false); - if ($tag === null) - { - $tag = TagModel::spawn(); - $tag->name = $tagName; - TagModel::save($tag); - } - - $tags []= $tag; - LogHelper::log('{user} tagged {post} with {tag}', [ - 'post' => TextHelper::reprPost($post), - 'tag' => TextHelper::reprTag($tag)]); - } - - $post->setTags($tags); - - PostModel::save($post); - StatusHelper::success(); + LogHelper::log('{user} untagged {post} with {tag}', [ + 'post' => TextHelper::reprPost($post), + 'tag' => TextHelper::reprTag($tag)]); } + elseif ($enable) + { + $tag = TagModel::findByName($tagName, false); + if ($tag === null) + { + $tag = TagModel::spawn(); + $tag->name = $tagName; + TagModel::save($tag); + } + + $tags []= $tag; + LogHelper::log('{user} tagged {post} with {tag}', [ + 'post' => TextHelper::reprPost($post), + 'tag' => TextHelper::reprTag($tag)]); + } + + $post->setTags($tags); + + PostModel::save($post); + StatusHelper::success(); } public function favoritesAction($page = 1) @@ -161,49 +126,49 @@ class PostController if (getConfig()->registration->needEmailForUploading) Access::assertEmailConfirmation(); - if (InputHelper::get('submit')) + if (!InputHelper::get('submit')) + return; + + \Chibi\Database::transaction(function() use ($context) { - \Chibi\Database::transaction(function() use ($context) - { - $post = PostModel::spawn(); - LogHelper::bufferChanges(); + $post = PostModel::spawn(); + LogHelper::bufferChanges(); - //basic stuff - $anonymous = InputHelper::get('anonymous'); - if ($context->loggedIn and !$anonymous) - $post->setUploader($context->user); + //basic stuff + $anonymous = InputHelper::get('anonymous'); + if ($context->loggedIn and !$anonymous) + $post->setUploader($context->user); - //store the post to get the ID in the logs - PostModel::forgeId($post); + //store the post to get the ID in the logs + PostModel::forgeId($post); - //do the edits - $this->doEdit($post, true); + //do the edits + $this->doEdit($post, true); - //this basically means that user didn't specify file nor url - if (empty($post->type)) - throw new SimpleException('No post type detected; upload faled'); + //this basically means that user didn't specify file nor url + if (empty($post->type)) + throw new SimpleException('No post type detected; upload faled'); - //clean edit log - LogHelper::setBuffer([]); + //clean edit log + LogHelper::setBuffer([]); - //log - $fmt = ($anonymous and !getConfig()->misc->logAnonymousUploads) - ? '{anon}' - : '{user}'; - $fmt .= ' added {post} (tags: {tags}, safety: {safety}, source: {source})'; - LogHelper::log($fmt, [ - 'post' => TextHelper::reprPost($post), - 'tags' => TextHelper::reprTags($post->getTags()), - 'safety' => PostSafety::toString($post->safety), - 'source' => $post->source]); + //log + $fmt = ($anonymous and !getConfig()->misc->logAnonymousUploads) + ? '{anon}' + : '{user}'; + $fmt .= ' added {post} (tags: {tags}, safety: {safety}, source: {source})'; + LogHelper::log($fmt, [ + 'post' => TextHelper::reprPost($post), + 'tags' => TextHelper::reprTags($post->getTags()), + 'safety' => PostSafety::toString($post->safety), + 'source' => $post->source]); - //finish - LogHelper::flush(); - PostModel::save($post); - }); + //finish + LogHelper::flush(); + PostModel::save($post); + }); - StatusHelper::success(); - } + StatusHelper::success(); } public function editAction($id) @@ -212,21 +177,21 @@ class PostController $post = PostModel::findByIdOrName($id); $context->transport->post = $post; - if (InputHelper::get('submit')) - { - $editToken = InputHelper::get('edit-token'); - if ($editToken != $post->getEditToken()) - throw new SimpleException('This post was already edited by someone else in the meantime'); + if (!InputHelper::get('submit')) + return; - LogHelper::bufferChanges(); - $this->doEdit($post, false); - LogHelper::flush(); + $editToken = InputHelper::get('edit-token'); + if ($editToken != $post->getEditToken()) + throw new SimpleException('This post was already edited by someone else in the meantime'); - PostModel::save($post); - TagModel::removeUnused(); + LogHelper::bufferChanges(); + $this->doEdit($post, false); + LogHelper::flush(); - StatusHelper::success(); - } + PostModel::save($post); + TagModel::removeUnused(); + + StatusHelper::success(); } public function flagAction($id) @@ -234,19 +199,19 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::FlagPost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - $key = TextHelper::reprPost($post); + if (!InputHelper::get('submit')) + return; - $flagged = SessionHelper::get('flagged', []); - if (in_array($key, $flagged)) - throw new SimpleException('You already flagged this post'); - $flagged []= $key; - SessionHelper::set('flagged', $flagged); + $key = TextHelper::reprPost($post); - LogHelper::log('{user} flagged {post} for moderator attention', ['post' => TextHelper::reprPost($post)]); - StatusHelper::success(); - } + $flagged = SessionHelper::get('flagged', []); + if (in_array($key, $flagged)) + throw new SimpleException('You already flagged this post'); + $flagged []= $key; + SessionHelper::set('flagged', $flagged); + + LogHelper::log('{user} flagged {post} for moderator attention', ['post' => TextHelper::reprPost($post)]); + StatusHelper::success(); } public function hideAction($id) @@ -254,14 +219,14 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::HidePost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - $post->setHidden(true); - PostModel::save($post); + if (!InputHelper::get('submit')) + return; - LogHelper::log('{user} hidden {post}', ['post' => TextHelper::reprPost($post)]); - StatusHelper::success(); - } + $post->setHidden(true); + PostModel::save($post); + + LogHelper::log('{user} hidden {post}', ['post' => TextHelper::reprPost($post)]); + StatusHelper::success(); } public function unhideAction($id) @@ -269,14 +234,14 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::HidePost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - $post->setHidden(false); - PostModel::save($post); + if (!InputHelper::get('submit')) + return; - LogHelper::log('{user} unhidden {post}', ['post' => TextHelper::reprPost($post)]); - StatusHelper::success(); - } + $post->setHidden(false); + PostModel::save($post); + + LogHelper::log('{user} unhidden {post}', ['post' => TextHelper::reprPost($post)]); + StatusHelper::success(); } public function deleteAction($id) @@ -284,13 +249,13 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::DeletePost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - PostModel::remove($post); + if (!InputHelper::get('submit')) + return; - LogHelper::log('{user} deleted {post}', ['post' => TextHelper::reprPost($id)]); - StatusHelper::success(); - } + PostModel::remove($post); + + LogHelper::log('{user} deleted {post}', ['post' => TextHelper::reprPost($id)]); + StatusHelper::success(); } public function addFavoriteAction($id) @@ -299,15 +264,15 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::FavoritePost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - if (!$context->loggedIn) - throw new SimpleException('Not logged in'); + if (!InputHelper::get('submit')) + return; - UserModel::updateUserScore($context->user, $post, 1); - UserModel::addToUserFavorites($context->user, $post); - StatusHelper::success(); - } + if (!$context->loggedIn) + throw new SimpleException('Not logged in'); + + UserModel::updateUserScore($context->user, $post, 1); + UserModel::addToUserFavorites($context->user, $post); + StatusHelper::success(); } public function removeFavoriteAction($id) @@ -316,14 +281,14 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::FavoritePost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - if (!$context->loggedIn) - throw new SimpleException('Not logged in'); + if (!InputHelper::get('submit')) + return; - UserModel::removeFromUserFavorites($context->user, $post); - StatusHelper::success(); - } + if (!$context->loggedIn) + throw new SimpleException('Not logged in'); + + UserModel::removeFromUserFavorites($context->user, $post); + StatusHelper::success(); } public function scoreAction($id, $score) @@ -332,14 +297,14 @@ class PostController $post = PostModel::findByIdOrName($id); Access::assert(Privilege::ScorePost, Access::getIdentity($post->getUploader())); - if (InputHelper::get('submit')) - { - if (!$context->loggedIn) - throw new SimpleException('Not logged in'); + if (!InputHelper::get('submit')) + return; - UserModel::updateUserScore($context->user, $post, $score); - StatusHelper::success(); - } + if (!$context->loggedIn) + throw new SimpleException('Not logged in'); + + UserModel::updateUserScore($context->user, $post, $score); + StatusHelper::success(); } public function featureAction($id) @@ -457,39 +422,8 @@ class PostController $context->transport->filePath = $path; } - - private function doEdit($post, $isNew) { - /* file contents */ - if (!empty($_FILES['file']['name'])) - { - if (!$isNew) - Access::assert(Privilege::EditPostFile, Access::getIdentity($post->getUploader())); - - $suppliedFile = $_FILES['file']; - self::handleUploadErrors($suppliedFile); - - $srcPath = $suppliedFile['tmp_name']; - $post->setContentFromPath($srcPath); - $post->origName = $suppliedFile['name']; - - if (!$isNew) - LogHelper::log('{user} changed contents of {post}', ['post' => TextHelper::reprPost($post)]); - } - elseif (InputHelper::get('url')) - { - if (!$isNew) - Access::assert(Privilege::EditPostFile, Access::getIdentity($post->getUploader())); - - $url = InputHelper::get('url'); - $post->setContentFromUrl($url); - $post->origName = $url; - - if (!$isNew) - LogHelper::log('{user} changed contents of {post}', ['post' => TextHelper::reprPost($post)]); - } - /* safety */ $suppliedSafety = InputHelper::get('safety'); if ($suppliedSafety !== null) @@ -580,6 +514,32 @@ class PostController } } + /* file contents */ + if (!empty($_FILES['file']['name'])) + { + if (!$isNew) + Access::assert(Privilege::EditPostFile, Access::getIdentity($post->getUploader())); + + $suppliedFile = $_FILES['file']; + TransferHelper::handleUploadErrors($suppliedFile); + + $post->setContentFromPath($suppliedFile['tmp_name'], $suppliedFile['name']); + + if (!$isNew) + LogHelper::log('{user} changed contents of {post}', ['post' => TextHelper::reprPost($post)]); + } + elseif (InputHelper::get('url')) + { + if (!$isNew) + Access::assert(Privilege::EditPostFile, Access::getIdentity($post->getUploader())); + + $url = InputHelper::get('url'); + $post->setContentFromUrl($url); + + if (!$isNew) + LogHelper::log('{user} changed contents of {post}', ['post' => TextHelper::reprPost($post)]); + } + /* thumbnail */ if (!empty($_FILES['thumb']['name'])) { @@ -587,10 +547,9 @@ class PostController Access::assert(Privilege::EditPostThumb, Access::getIdentity($post->getUploader())); $suppliedFile = $_FILES['thumb']; - self::handleUploadErrors($suppliedFile); + TransferHelper::handleUploadErrors($suppliedFile); - $srcPath = $suppliedFile['tmp_name']; - $post->setCustomThumbnailFromPath($srcPath); + $post->setCustomThumbnailFromPath($srcPath = $suppliedFile['tmp_name']); LogHelper::log('{user} changed thumb of {post}', ['post' => TextHelper::reprPost($post)]); } diff --git a/src/Controllers/TagController.php b/src/Controllers/TagController.php index 3d2e2f87..ed140a84 100644 --- a/src/Controllers/TagController.php +++ b/src/Controllers/TagController.php @@ -86,24 +86,24 @@ class TagController $context->handleExceptions = true; Access::assert(Privilege::MergeTags); - if (InputHelper::get('submit')) - { - TagModel::removeUnused(); + if (!InputHelper::get('submit')) + return; - $suppliedSourceTag = InputHelper::get('source-tag'); - $suppliedSourceTag = TagModel::validateTag($suppliedSourceTag); + TagModel::removeUnused(); - $suppliedTargetTag = InputHelper::get('target-tag'); - $suppliedTargetTag = TagModel::validateTag($suppliedTargetTag); + $suppliedSourceTag = InputHelper::get('source-tag'); + $suppliedSourceTag = TagModel::validateTag($suppliedSourceTag); - TagModel::merge($suppliedSourceTag, $suppliedTargetTag); + $suppliedTargetTag = InputHelper::get('target-tag'); + $suppliedTargetTag = TagModel::validateTag($suppliedTargetTag); - LogHelper::log('{user} merged {source} with {target}', [ - 'source' => TextHelper::reprTag($suppliedSourceTag), - 'target' => TextHelper::reprTag($suppliedTargetTag)]); + TagModel::merge($suppliedSourceTag, $suppliedTargetTag); - StatusHelper::success('Tags merged successfully.'); - } + LogHelper::log('{user} merged {source} with {target}', [ + 'source' => TextHelper::reprTag($suppliedSourceTag), + 'target' => TextHelper::reprTag($suppliedTargetTag)]); + + StatusHelper::success('Tags merged successfully.'); } public function renameAction() @@ -113,24 +113,24 @@ class TagController $context->handleExceptions = true; Access::assert(Privilege::MergeTags); - if (InputHelper::get('submit')) - { - TagModel::removeUnused(); + if (!InputHelper::get('submit')) + return; - $suppliedSourceTag = InputHelper::get('source-tag'); - $suppliedSourceTag = TagModel::validateTag($suppliedSourceTag); + TagModel::removeUnused(); - $suppliedTargetTag = InputHelper::get('target-tag'); - $suppliedTargetTag = TagModel::validateTag($suppliedTargetTag); + $suppliedSourceTag = InputHelper::get('source-tag'); + $suppliedSourceTag = TagModel::validateTag($suppliedSourceTag); - TagModel::rename($suppliedSourceTag, $suppliedTargetTag); + $suppliedTargetTag = InputHelper::get('target-tag'); + $suppliedTargetTag = TagModel::validateTag($suppliedTargetTag); - LogHelper::log('{user} renamed {source} to {target}', [ - 'source' => TextHelper::reprTag($suppliedSourceTag), - 'target' => TextHelper::reprTag($suppliedTargetTag)]); + TagModel::rename($suppliedSourceTag, $suppliedTargetTag); - StatusHelper::success('Tag renamed successfully.'); - } + LogHelper::log('{user} renamed {source} to {target}', [ + 'source' => TextHelper::reprTag($suppliedSourceTag), + 'target' => TextHelper::reprTag($suppliedTargetTag)]); + + StatusHelper::success('Tag renamed successfully.'); } public function massTagRedirectAction() @@ -139,21 +139,21 @@ class TagController $context->viewName = 'tag-list-wrapper'; Access::assert(Privilege::MassTag); - if (InputHelper::get('submit')) - { - $suppliedOldPage = intval(InputHelper::get('old-page')); - $suppliedOldQuery = InputHelper::get('old-query'); - $suppliedQuery = InputHelper::get('query'); - $suppliedTag = InputHelper::get('tag'); + if (!InputHelper::get('submit')) + return; - $params = [ - 'source' => 'mass-tag', - 'query' => $suppliedQuery ?: ' ', - 'additionalInfo' => $suppliedTag ? TagModel::validateTag($suppliedTag) : '', - ]; - if ($suppliedOldPage != 0 and $suppliedOldQuery == $suppliedQuery) - $params['page'] = $suppliedOldPage; - \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['PostController', 'listAction'], $params)); - } + $suppliedOldPage = intval(InputHelper::get('old-page')); + $suppliedOldQuery = InputHelper::get('old-query'); + $suppliedQuery = InputHelper::get('query'); + $suppliedTag = InputHelper::get('tag'); + + $params = [ + 'source' => 'mass-tag', + 'query' => $suppliedQuery ?: ' ', + 'additionalInfo' => $suppliedTag ? TagModel::validateTag($suppliedTag) : '', + ]; + if ($suppliedOldPage != 0 and $suppliedOldQuery == $suppliedQuery) + $params['page'] = $suppliedOldPage; + \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['PostController', 'listAction'], $params)); } } diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php index 843e7557..6d2e8629 100644 --- a/src/Controllers/UserController.php +++ b/src/Controllers/UserController.php @@ -1,6 +1,533 @@ browsing->usersPerPage); + + $users = UserSearchService::getEntities($suppliedFilter, $usersPerPage, $page); + $userCount = UserSearchService::getEntityCount($suppliedFilter); + $pageCount = ceil($userCount / $usersPerPage); + $page = min($pageCount, $page); + + $context->filter = $suppliedFilter; + $context->transport->users = $users; + $context->transport->paginator = new StdClass; + $context->transport->paginator->page = $page; + $context->transport->paginator->pageCount = $pageCount; + $context->transport->paginator->entityCount = $userCount; + $context->transport->paginator->entities = $users; + $context->transport->paginator->params = func_get_args(); + } + + public function flagAction($name) + { + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::FlagUser, + Access::getIdentity($user)); + + if (!InputHelper::get('submit')) + return; + + $key = TextHelper::reprUser($user); + + $flagged = SessionHelper::get('flagged', []); + if (in_array($key, $flagged)) + throw new SimpleException('You already flagged this user'); + $flagged []= $key; + SessionHelper::set('flagged', $flagged); + + LogHelper::log('{user} flagged {subject} for moderator attention', [ + 'subject' => TextHelper::reprUser($user)]); + + StatusHelper::success(); + } + + public function banAction($name) + { + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::BanUser, + Access::getIdentity($user)); + + if (!InputHelper::get('submit')) + return; + + $user->banned = true; + UserModel::save($user); + + LogHelper::log('{user} banned {subject}', ['subject' => TextHelper::reprUser($user)]); + StatusHelper::success(); + } + + public function unbanAction($name) + { + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::BanUser, + Access::getIdentity($user)); + + if (!InputHelper::get('submit')) + return; + + $user->banned = false; + UserModel::save($user); + + LogHelper::log('{user} unbanned {subject}', ['subject' => TextHelper::reprUser($user)]); + StatusHelper::success(); + } + + public function acceptRegistrationAction($name) + { + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::AcceptUserRegistration); + + if (!InputHelper::get('submit')) + return; + + $user->staffConfirmed = true; + UserModel::save($user); + LogHelper::log('{user} confirmed {subject}\'s account', ['subject' => TextHelper::reprUser($user)]); + StatusHelper::success(); + } + + public function deleteAction($name) + { + $context = getContext(); + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::ViewUser, + Access::getIdentity($user)); + Access::assert( + Privilege::DeleteUser, + Access::getIdentity($user)); + + $this->loadUserView($user); + $context->transport->tab = 'delete'; + + $context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password'); + + if (!InputHelper::get('submit')) + return; + + $name = $user->name; + if ($context->user->id == $user->id) + { + $suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt); + if ($suppliedPasswordHash != $user->passHash) + throw new SimpleException('Must supply valid password'); + } + + $oldId = $user->id; + UserModel::remove($user); + if ($oldId == $context->user->id) + AuthController::doLogOut(); + + \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['IndexController', 'indexAction'])); + LogHelper::log('{user} removed {subject}\'s account', ['subject' => TextHelper::reprUser($name)]); + StatusHelper::success(); + } + + public function settingsAction($name) + { + $context = getContext(); + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::ViewUser, + Access::getIdentity($user)); + Access::assert( + Privilege::ChangeUserSettings, + Access::getIdentity($user)); + + $this->loadUserView($user); + $context->transport->tab = 'settings'; + + if (!InputHelper::get('submit')) + return; + + $suppliedSafety = InputHelper::get('safety'); + if (!is_array($suppliedSafety)) + $suppliedSafety = []; + foreach (PostSafety::getAll() as $safety) + $user->enableSafety($safety, in_array($safety, $suppliedSafety)); + + $user->enableEndlessScrolling(InputHelper::get('endless-scrolling')); + $user->enablePostTagTitles(InputHelper::get('post-tag-titles')); + $user->enableHidingDislikedPosts(InputHelper::get('hide-disliked-posts')); + + if ($user->accessRank != AccessRank::Anonymous) + UserModel::save($user); + if ($user->id == $context->user->id) + $context->user = $user; + AuthController::doReLog(); + StatusHelper::success('Browsing settings updated!'); + } + + public function editAction($name) + { + $context = getContext(); + try + { + $user = UserModel::findByNameOrEmail($name); + Access::assert( + Privilege::ViewUser, + Access::getIdentity($user)); + + $this->loadUserView($user); + $context->transport->tab = 'edit'; + + $context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password'); + $context->suppliedName = $suppliedName = InputHelper::get('name'); + $context->suppliedPassword1 = $suppliedPassword1 = InputHelper::get('password1'); + $context->suppliedPassword2 = $suppliedPassword2 = InputHelper::get('password2'); + $context->suppliedEmail = $suppliedEmail = InputHelper::get('email'); + $context->suppliedAccessRank = $suppliedAccessRank = InputHelper::get('access-rank'); + $currentPasswordHash = $user->passHash; + + if (!InputHelper::get('submit')) + return; + + $confirmMail = false; + LogHelper::bufferChanges(); + + if ($suppliedName != '' and $suppliedName != $user->name) + { + Access::assert( + Privilege::ChangeUserName, + Access::getIdentity($user)); + + $suppliedName = UserModel::validateUserName($suppliedName); + $oldName = $user->name; + $user->name = $suppliedName; + LogHelper::log('{user} renamed {old} to {new}', [ + 'old' => TextHelper::reprUser($oldName), + 'new' => TextHelper::reprUser($suppliedName)]); + } + + if ($suppliedPassword1 != '') + { + Access::assert( + Privilege::ChangeUserPassword, + Access::getIdentity($user)); + + if ($suppliedPassword1 != $suppliedPassword2) + throw new SimpleException('Specified passwords must be the same'); + $suppliedPassword = UserModel::validatePassword($suppliedPassword1); + $user->passHash = UserModel::hashPassword($suppliedPassword, $user->passSalt); + LogHelper::log('{user} changed {subject}\'s password', ['subject' => TextHelper::reprUser($user)]); + } + + if ($suppliedEmail != '' and $suppliedEmail != $user->emailConfirmed) + { + Access::assert( + Privilege::ChangeUserEmail, + Access::getIdentity($user)); + + $suppliedEmail = UserModel::validateEmail($suppliedEmail); + if ($context->user->id == $user->id) + { + $user->emailUnconfirmed = $suppliedEmail; + if (!empty($user->emailUnconfirmed)) + $confirmMail = true; + LogHelper::log('{user} changed e-mail to {mail}', ['mail' => $suppliedEmail]); + } + else + { + $user->emailUnconfirmed = null; + $user->emailConfirmed = $suppliedEmail; + LogHelper::log('{user} changed {subject}\'s e-mail to {mail}', [ + 'subject' => TextHelper::reprUser($user), + 'mail' => $suppliedEmail]); + } + } + + if ($suppliedAccessRank != '' and $suppliedAccessRank != $user->accessRank) + { + Access::assert( + Privilege::ChangeUserAccessRank, + Access::getIdentity($user)); + + $suppliedAccessRank = UserModel::validateAccessRank($suppliedAccessRank); + $user->accessRank = $suppliedAccessRank; + LogHelper::log('{user} changed {subject}\'s access rank to {rank}', [ + 'subject' => TextHelper::reprUser($user), + 'rank' => AccessRank::toString($suppliedAccessRank)]); + } + + if ($context->user->id == $user->id) + { + $suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt); + if ($suppliedPasswordHash != $currentPasswordHash) + throw new SimpleException('Must supply valid current password'); + } + UserModel::save($user); + if ($context->user->id == $user->id) + AuthController::doReLog(); + + if ($confirmMail) + self::sendEmailChangeConfirmation($user); + + LogHelper::flush(); + $message = 'Account settings updated!'; + if ($confirmMail) + $message .= ' You will be sent an e-mail address confirmation message soon.'; + StatusHelper::success($message); + } + catch (Exception $e) + { + $context->transport->user = UserModel::findByNameOrEmail($name); + throw $e; + } + } + + public function viewAction($name, $tab = 'favs', $page) + { + $context = getContext(); + $postsPerPage = intval(getConfig()->browsing->postsPerPage); + $user = UserModel::findByNameOrEmail($name); + if ($tab === null) + $tab = 'favs'; + if ($page === null) + $page = 1; + + Access::assert( + Privilege::ViewUser, + Access::getIdentity($user)); + + $this->loadUserView($user); + + $query = ''; + if ($tab == 'uploads') + $query = 'submit:' . $user->name; + elseif ($tab == 'favs') + $query = 'fav:' . $user->name; + else + throw new SimpleException('Wrong tab'); + + $page = max(1, $page); + $posts = PostSearchService::getEntities($query, $postsPerPage, $page); + $postCount = PostSearchService::getEntityCount($query, $postsPerPage, $page); + $pageCount = ceil($postCount / $postsPerPage); + PostModel::preloadTags($posts); + + $context->transport->tab = $tab; + $context->transport->lastSearchQuery = $query; + $context->transport->paginator = new StdClass; + $context->transport->paginator->page = $page; + $context->transport->paginator->pageCount = $pageCount; + $context->transport->paginator->entityCount = $postCount; + $context->transport->paginator->entities = $posts; + $context->transport->posts = $posts; + } + + public function toggleSafetyAction($safety) + { + $context = getContext(); + Access::assert( + Privilege::ChangeUserSettings, + Access::getIdentity($context->user)); + + if (!in_array($safety, PostSafety::getAll())) + throw new SimpleExcetpion('Invalid safety'); + + $context->user->enableSafety($safety, + !$context->user->hasEnabledSafety($safety)); + + if ($context->user->accessRank != AccessRank::Anonymous) + UserModel::save($context->user); + AuthController::doReLog(); + + StatusHelper::success(); + } + + public function registrationAction() + { + $context = getContext(); + $context->handleExceptions = true; + + //check if already logged in + if ($context->loggedIn) + { + \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['IndexController', 'indexAction'])); + return; + } + + $suppliedName = InputHelper::get('name'); + $suppliedPassword1 = InputHelper::get('password1'); + $suppliedPassword2 = InputHelper::get('password2'); + $suppliedEmail = InputHelper::get('email'); + $context->suppliedName = $suppliedName; + $context->suppliedPassword1 = $suppliedPassword1; + $context->suppliedPassword2 = $suppliedPassword2; + $context->suppliedEmail = $suppliedEmail; + + if (!InputHelper::get('submit')) + return; + + $suppliedName = UserModel::validateUserName($suppliedName); + + if ($suppliedPassword1 != $suppliedPassword2) + throw new SimpleException('Specified passwords must be the same'); + $suppliedPassword = UserModel::validatePassword($suppliedPassword1); + + $suppliedEmail = UserModel::validateEmail($suppliedEmail); + if (empty($suppliedEmail) and getConfig()->registration->needEmailForRegistering) + throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.'); + + //register the user + $dbUser = UserModel::spawn(); + $dbUser->name = $suppliedName; + $dbUser->passHash = UserModel::hashPassword($suppliedPassword, $dbUser->passSalt); + $dbUser->emailUnconfirmed = $suppliedEmail; + + $dbUser->joinDate = time(); + if (UserModel::getCount() == 0) + { + //very first user + $dbUser->accessRank = AccessRank::Admin; + $dbUser->staffConfirmed = true; + $dbUser->emailUnconfirmed = null; + $dbUser->emailConfirmed = $suppliedEmail; + } + else + { + $dbUser->accessRank = AccessRank::Registered; + $dbUser->staffConfirmed = false; + $dbUser->staffConfirmed = null; + } + + //save the user to db if everything went okay + UserModel::save($dbUser); + + if (!empty($dbUser->emailUnconfirmed)) + self::sendEmailChangeConfirmation($dbUser); + + $message = 'Congratulations, your account was created.'; + if (!empty($context->mailSent)) + { + $message .= ' Please wait for activation e-mail.'; + if (getConfig()->registration->staffActivation) + $message .= ' After this, your registration must be confirmed by staff.'; + } + elseif (getConfig()->registration->staffActivation) + $message .= ' Your registration must be now confirmed by staff.'; + + LogHelper::log('{subject} just signed up', ['subject' => TextHelper::reprUser($dbUser)]); + StatusHelper::success($message); + + if (!getConfig()->registration->needEmailForRegistering and !getConfig()->registration->staffActivation) + { + $context->user = $dbUser; + AuthController::doReLog(); + } + } + + public function activationAction($token) + { + $context = getContext(); + $context->viewName = 'message'; + Assets::setSubTitle('account activation'); + + $dbToken = TokenModel::findByToken($token); + TokenModel::checkValidity($dbToken); + + $dbUser = $dbToken->getUser(); + $dbUser->emailConfirmed = $dbUser->emailUnconfirmed; + $dbUser->emailUnconfirmed = null; + $dbToken->used = true; + TokenModel::save($dbToken); + UserModel::save($dbUser); + + LogHelper::log('{subject} just activated account', ['subject' => TextHelper::reprUser($dbUser)]); + $message = 'Activation completed successfully.'; + if (getConfig()->registration->staffActivation) + $message .= ' However, your account still must be confirmed by staff.'; + StatusHelper::success($message); + + if (!getConfig()->registration->staffActivation) + { + $context->user = $dbUser; + AuthController::doReLog(); + } + } + + public function passwordResetAction($token) + { + $context = getContext(); + $context->viewName = 'message'; + Assets::setSubTitle('password reset'); + + $dbToken = TokenModel::findByToken($token); + TokenModel::checkValidity($dbToken); + + $alphabet = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9')); + $randomPassword = join('', array_map(function($x) use ($alphabet) + { + return $alphabet[$x]; + }, array_rand($alphabet, 8))); + + $dbUser = $dbToken->getUser(); + $dbUser->passHash = UserModel::hashPassword($randomPassword, $dbUser->passSalt); + $dbToken->used = true; + TokenModel::save($dbToken); + UserModel::save($dbUser); + + LogHelper::log('{subject} just reset password', ['subject' => TextHelper::reprUser($dbUser)]); + $message = 'Password reset successful. Your new password is **' . $randomPassword . '**.'; + StatusHelper::success($message); + + $context->user = $dbUser; + AuthController::doReLog(); + } + + public function passwordResetProxyAction() + { + $context = getContext(); + $context->viewName = 'user-select'; + Assets::setSubTitle('password reset'); + + if (!InputHelper::get('submit')) + return; + + $name = InputHelper::get('name'); + $user = UserModel::findByNameOrEmail($name); + if (empty($user->emailConfirmed)) + throw new SimpleException('This user has no e-mail confirmed; password reset cannot proceed'); + + self::sendPasswordResetConfirmation($user); + StatusHelper::success('E-mail sent. Follow instructions to reset password.'); + } + + public function activationProxyAction() + { + $context = getContext(); + $context->viewName = 'user-select'; + Assets::setSubTitle('account activation'); + + if (!InputHelper::get('submit')) + return; + + $name = InputHelper::get('name'); + $user = UserModel::findByNameOrEmail($name); + if (empty($user->emailUnconfirmed)) + { + if (!empty($user->emailConfirmed)) + throw new SimpleException('E-mail was already confirmed; activation skipped'); + else + throw new SimpleException('This user has no e-mail specified; activation cannot proceed'); + } + self::sendEmailChangeConfirmation($user); + StatusHelper::success('Activation e-mail resent.'); + } + private function loadUserView($user) { $context = getContext(); @@ -99,531 +626,4 @@ class UserController $user->emailConfirmed, 'passwordResetAction'); } - - public function listAction($filter, $page) - { - $context = getContext(); - Access::assert( - Privilege::ListUsers); - - $suppliedFilter = $filter ?: InputHelper::get('filter') ?: 'order:alpha,asc'; - $page = max(1, intval($page)); - $usersPerPage = intval(getConfig()->browsing->usersPerPage); - - $users = UserSearchService::getEntities($suppliedFilter, $usersPerPage, $page); - $userCount = UserSearchService::getEntityCount($suppliedFilter); - $pageCount = ceil($userCount / $usersPerPage); - $page = min($pageCount, $page); - - $context->filter = $suppliedFilter; - $context->transport->users = $users; - $context->transport->paginator = new StdClass; - $context->transport->paginator->page = $page; - $context->transport->paginator->pageCount = $pageCount; - $context->transport->paginator->entityCount = $userCount; - $context->transport->paginator->entities = $users; - $context->transport->paginator->params = func_get_args(); - } - - public function flagAction($name) - { - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::FlagUser, - Access::getIdentity($user)); - - if (InputHelper::get('submit')) - { - $key = TextHelper::reprUser($user); - - $flagged = SessionHelper::get('flagged', []); - if (in_array($key, $flagged)) - throw new SimpleException('You already flagged this user'); - $flagged []= $key; - SessionHelper::set('flagged', $flagged); - - LogHelper::log('{user} flagged {subject} for moderator attention', [ - 'subject' => TextHelper::reprUser($user)]); - - StatusHelper::success(); - } - } - - public function banAction($name) - { - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::BanUser, - Access::getIdentity($user)); - - if (InputHelper::get('submit')) - { - $user->banned = true; - UserModel::save($user); - - LogHelper::log('{user} banned {subject}', ['subject' => TextHelper::reprUser($user)]); - StatusHelper::success(); - } - } - - public function unbanAction($name) - { - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::BanUser, - Access::getIdentity($user)); - - if (InputHelper::get('submit')) - { - $user->banned = false; - UserModel::save($user); - - LogHelper::log('{user} unbanned {subject}', ['subject' => TextHelper::reprUser($user)]); - StatusHelper::success(); - } - } - - public function acceptRegistrationAction($name) - { - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::AcceptUserRegistration); - - if (InputHelper::get('submit')) - { - $user->staffConfirmed = true; - UserModel::save($user); - LogHelper::log('{user} confirmed {subject}\'s account', ['subject' => TextHelper::reprUser($user)]); - StatusHelper::success(); - } - } - - public function deleteAction($name) - { - $context = getContext(); - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::ViewUser, - Access::getIdentity($user)); - Access::assert( - Privilege::DeleteUser, - Access::getIdentity($user)); - - $this->loadUserView($user); - $context->transport->tab = 'delete'; - - $context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password'); - - if (InputHelper::get('submit')) - { - $name = $user->name; - if ($context->user->id == $user->id) - { - $suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt); - if ($suppliedPasswordHash != $user->passHash) - throw new SimpleException('Must supply valid password'); - } - - $oldId = $user->id; - UserModel::remove($user); - if ($oldId == $context->user->id) - AuthController::doLogOut(); - - \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['IndexController', 'indexAction'])); - LogHelper::log('{user} removed {subject}\'s account', ['subject' => TextHelper::reprUser($name)]); - StatusHelper::success(); - } - } - - public function settingsAction($name) - { - $context = getContext(); - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::ViewUser, - Access::getIdentity($user)); - Access::assert( - Privilege::ChangeUserSettings, - Access::getIdentity($user)); - - $this->loadUserView($user); - $context->transport->tab = 'settings'; - - if (InputHelper::get('submit')) - { - $suppliedSafety = InputHelper::get('safety'); - if (!is_array($suppliedSafety)) - $suppliedSafety = []; - foreach (PostSafety::getAll() as $safety) - $user->enableSafety($safety, in_array($safety, $suppliedSafety)); - - $user->enableEndlessScrolling(InputHelper::get('endless-scrolling')); - $user->enablePostTagTitles(InputHelper::get('post-tag-titles')); - $user->enableHidingDislikedPosts(InputHelper::get('hide-disliked-posts')); - - if ($user->accessRank != AccessRank::Anonymous) - UserModel::save($user); - if ($user->id == $context->user->id) - $context->user = $user; - AuthController::doReLog(); - StatusHelper::success('Browsing settings updated!'); - } - } - - public function editAction($name) - { - $context = getContext(); - try - { - $user = UserModel::findByNameOrEmail($name); - Access::assert( - Privilege::ViewUser, - Access::getIdentity($user)); - - $this->loadUserView($user); - $context->transport->tab = 'edit'; - - $context->suppliedCurrentPassword = $suppliedCurrentPassword = InputHelper::get('current-password'); - $context->suppliedName = $suppliedName = InputHelper::get('name'); - $context->suppliedPassword1 = $suppliedPassword1 = InputHelper::get('password1'); - $context->suppliedPassword2 = $suppliedPassword2 = InputHelper::get('password2'); - $context->suppliedEmail = $suppliedEmail = InputHelper::get('email'); - $context->suppliedAccessRank = $suppliedAccessRank = InputHelper::get('access-rank'); - $currentPasswordHash = $user->passHash; - - if (InputHelper::get('submit')) - { - $confirmMail = false; - LogHelper::bufferChanges(); - - if ($suppliedName != '' and $suppliedName != $user->name) - { - Access::assert( - Privilege::ChangeUserName, - Access::getIdentity($user)); - - $suppliedName = UserModel::validateUserName($suppliedName); - $oldName = $user->name; - $user->name = $suppliedName; - LogHelper::log('{user} renamed {old} to {new}', [ - 'old' => TextHelper::reprUser($oldName), - 'new' => TextHelper::reprUser($suppliedName)]); - } - - if ($suppliedPassword1 != '') - { - Access::assert( - Privilege::ChangeUserPassword, - Access::getIdentity($user)); - - if ($suppliedPassword1 != $suppliedPassword2) - throw new SimpleException('Specified passwords must be the same'); - $suppliedPassword = UserModel::validatePassword($suppliedPassword1); - $user->passHash = UserModel::hashPassword($suppliedPassword, $user->passSalt); - LogHelper::log('{user} changed {subject}\'s password', ['subject' => TextHelper::reprUser($user)]); - } - - if ($suppliedEmail != '' and $suppliedEmail != $user->emailConfirmed) - { - Access::assert( - Privilege::ChangeUserEmail, - Access::getIdentity($user)); - - $suppliedEmail = UserModel::validateEmail($suppliedEmail); - if ($context->user->id == $user->id) - { - $user->emailUnconfirmed = $suppliedEmail; - if (!empty($user->emailUnconfirmed)) - $confirmMail = true; - LogHelper::log('{user} changed e-mail to {mail}', ['mail' => $suppliedEmail]); - } - else - { - $user->emailUnconfirmed = null; - $user->emailConfirmed = $suppliedEmail; - LogHelper::log('{user} changed {subject}\'s e-mail to {mail}', [ - 'subject' => TextHelper::reprUser($user), - 'mail' => $suppliedEmail]); - } - } - - if ($suppliedAccessRank != '' and $suppliedAccessRank != $user->accessRank) - { - Access::assert( - Privilege::ChangeUserAccessRank, - Access::getIdentity($user)); - - $suppliedAccessRank = UserModel::validateAccessRank($suppliedAccessRank); - $user->accessRank = $suppliedAccessRank; - LogHelper::log('{user} changed {subject}\'s access rank to {rank}', [ - 'subject' => TextHelper::reprUser($user), - 'rank' => AccessRank::toString($suppliedAccessRank)]); - } - - if ($context->user->id == $user->id) - { - $suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt); - if ($suppliedPasswordHash != $currentPasswordHash) - throw new SimpleException('Must supply valid current password'); - } - UserModel::save($user); - if ($context->user->id == $user->id) - AuthController::doReLog(); - - if ($confirmMail) - self::sendEmailChangeConfirmation($user); - - LogHelper::flush(); - $message = 'Account settings updated!'; - if ($confirmMail) - $message .= ' You will be sent an e-mail address confirmation message soon.'; - StatusHelper::success($message); - } - } - catch (Exception $e) - { - $context->transport->user = UserModel::findByNameOrEmail($name); - throw $e; - } - } - - public function viewAction($name, $tab = 'favs', $page) - { - $context = getContext(); - $postsPerPage = intval(getConfig()->browsing->postsPerPage); - $user = UserModel::findByNameOrEmail($name); - if ($tab === null) - $tab = 'favs'; - if ($page === null) - $page = 1; - - Access::assert( - Privilege::ViewUser, - Access::getIdentity($user)); - - $this->loadUserView($user); - - $query = ''; - if ($tab == 'uploads') - $query = 'submit:' . $user->name; - elseif ($tab == 'favs') - $query = 'fav:' . $user->name; - else - throw new SimpleException('Wrong tab'); - - $page = max(1, $page); - $posts = PostSearchService::getEntities($query, $postsPerPage, $page); - $postCount = PostSearchService::getEntityCount($query, $postsPerPage, $page); - $pageCount = ceil($postCount / $postsPerPage); - PostModel::preloadTags($posts); - - $context->transport->tab = $tab; - $context->transport->lastSearchQuery = $query; - $context->transport->paginator = new StdClass; - $context->transport->paginator->page = $page; - $context->transport->paginator->pageCount = $pageCount; - $context->transport->paginator->entityCount = $postCount; - $context->transport->paginator->entities = $posts; - $context->transport->posts = $posts; - } - - public function toggleSafetyAction($safety) - { - $context = getContext(); - Access::assert( - Privilege::ChangeUserSettings, - Access::getIdentity($context->user)); - - if (!in_array($safety, PostSafety::getAll())) - throw new SimpleExcetpion('Invalid safety'); - - $context->user->enableSafety($safety, - !$context->user->hasEnabledSafety($safety)); - - if ($context->user->accessRank != AccessRank::Anonymous) - UserModel::save($context->user); - AuthController::doReLog(); - - StatusHelper::success(); - } - - public function registrationAction() - { - $context = getContext(); - $context->handleExceptions = true; - - //check if already logged in - if ($context->loggedIn) - { - \Chibi\Util\Url::forward(\Chibi\Router::linkTo(['IndexController', 'indexAction'])); - return; - } - - $suppliedName = InputHelper::get('name'); - $suppliedPassword1 = InputHelper::get('password1'); - $suppliedPassword2 = InputHelper::get('password2'); - $suppliedEmail = InputHelper::get('email'); - $context->suppliedName = $suppliedName; - $context->suppliedPassword1 = $suppliedPassword1; - $context->suppliedPassword2 = $suppliedPassword2; - $context->suppliedEmail = $suppliedEmail; - - if (InputHelper::get('submit')) - { - $suppliedName = UserModel::validateUserName($suppliedName); - - if ($suppliedPassword1 != $suppliedPassword2) - throw new SimpleException('Specified passwords must be the same'); - $suppliedPassword = UserModel::validatePassword($suppliedPassword1); - - $suppliedEmail = UserModel::validateEmail($suppliedEmail); - if (empty($suppliedEmail) and getConfig()->registration->needEmailForRegistering) - throw new SimpleException('E-mail address is required - you will be sent confirmation e-mail.'); - - //register the user - $dbUser = UserModel::spawn(); - $dbUser->name = $suppliedName; - $dbUser->passHash = UserModel::hashPassword($suppliedPassword, $dbUser->passSalt); - $dbUser->emailUnconfirmed = $suppliedEmail; - - $dbUser->joinDate = time(); - if (UserModel::getCount() == 0) - { - //very first user - $dbUser->accessRank = AccessRank::Admin; - $dbUser->staffConfirmed = true; - $dbUser->emailUnconfirmed = null; - $dbUser->emailConfirmed = $suppliedEmail; - } - else - { - $dbUser->accessRank = AccessRank::Registered; - $dbUser->staffConfirmed = false; - $dbUser->staffConfirmed = null; - } - - //save the user to db if everything went okay - UserModel::save($dbUser); - - if (!empty($dbUser->emailUnconfirmed)) - self::sendEmailChangeConfirmation($dbUser); - - $message = 'Congratulations, your account was created.'; - if (!empty($context->mailSent)) - { - $message .= ' Please wait for activation e-mail.'; - if (getConfig()->registration->staffActivation) - $message .= ' After this, your registration must be confirmed by staff.'; - } - elseif (getConfig()->registration->staffActivation) - $message .= ' Your registration must be now confirmed by staff.'; - - LogHelper::log('{subject} just signed up', ['subject' => TextHelper::reprUser($dbUser)]); - StatusHelper::success($message); - - if (!getConfig()->registration->needEmailForRegistering and !getConfig()->registration->staffActivation) - { - $context->user = $dbUser; - AuthController::doReLog(); - } - } - } - - public function activationAction($token) - { - $context = getContext(); - $context->viewName = 'message'; - Assets::setSubTitle('account activation'); - - $dbToken = TokenModel::findByToken($token); - TokenModel::checkValidity($dbToken); - - $dbUser = $dbToken->getUser(); - $dbUser->emailConfirmed = $dbUser->emailUnconfirmed; - $dbUser->emailUnconfirmed = null; - $dbToken->used = true; - TokenModel::save($dbToken); - UserModel::save($dbUser); - - LogHelper::log('{subject} just activated account', ['subject' => TextHelper::reprUser($dbUser)]); - $message = 'Activation completed successfully.'; - if (getConfig()->registration->staffActivation) - $message .= ' However, your account still must be confirmed by staff.'; - StatusHelper::success($message); - - if (!getConfig()->registration->staffActivation) - { - $context->user = $dbUser; - AuthController::doReLog(); - } - } - - public function passwordResetAction($token) - { - $context = getContext(); - $context->viewName = 'message'; - Assets::setSubTitle('password reset'); - - $dbToken = TokenModel::findByToken($token); - TokenModel::checkValidity($dbToken); - - $alphabet = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9')); - $randomPassword = join('', array_map(function($x) use ($alphabet) - { - return $alphabet[$x]; - }, array_rand($alphabet, 8))); - - $dbUser = $dbToken->getUser(); - $dbUser->passHash = UserModel::hashPassword($randomPassword, $dbUser->passSalt); - $dbToken->used = true; - TokenModel::save($dbToken); - UserModel::save($dbUser); - - LogHelper::log('{subject} just reset password', ['subject' => TextHelper::reprUser($dbUser)]); - $message = 'Password reset successful. Your new password is **' . $randomPassword . '**.'; - StatusHelper::success($message); - - $context->user = $dbUser; - AuthController::doReLog(); - } - - public function passwordResetProxyAction() - { - $context = getContext(); - $context->viewName = 'user-select'; - Assets::setSubTitle('password reset'); - - if (InputHelper::get('submit')) - { - $name = InputHelper::get('name'); - $user = UserModel::findByNameOrEmail($name); - if (empty($user->emailConfirmed)) - throw new SimpleException('This user has no e-mail confirmed; password reset cannot proceed'); - - self::sendPasswordResetConfirmation($user); - StatusHelper::success('E-mail sent. Follow instructions to reset password.'); - } - } - - public function activationProxyAction() - { - $context = getContext(); - $context->viewName = 'user-select'; - Assets::setSubTitle('account activation'); - - if (InputHelper::get('submit')) - { - $name = InputHelper::get('name'); - $user = UserModel::findByNameOrEmail($name); - if (empty($user->emailUnconfirmed)) - { - if (!empty($user->emailConfirmed)) - throw new SimpleException('E-mail was already confirmed; activation skipped'); - else - throw new SimpleException('This user has no e-mail specified; activation cannot proceed'); - } - self::sendEmailChangeConfirmation($user); - StatusHelper::success('Activation e-mail resent.'); - } - } } diff --git a/src/Helpers/TransferHelper.php b/src/Helpers/TransferHelper.php new file mode 100644 index 00000000..f07f405c --- /dev/null +++ b/src/Helpers/TransferHelper.php @@ -0,0 +1,94 @@ + $maxBytes) + { + fclose($srcHandle); + fclose($dstHandle); + throw new SimpleException( + 'File is too big (maximum size: %s)', + TextHelper::useBytesUnits($maxBytes)); + } + } + } + finally + { + fclose($srcHandle); + fclose($dstHandle); + + chmod($dstPath, 0644); + } + } + + public static function moveUpload($srcPath, $dstPath) + { + if (is_uploaded_file($srcPath)) + { + move_uploaded_file($srcPath, $dstPath); + } + else + { + //problems with permissions on some systems? + #rename($srcPath, $dstPath); + copy($srcPath, $dstPath); + unlink($srcPath); + } + } + + public static function handleUploadErrors($file) + { + switch ($file['error']) + { + case UPLOAD_ERR_OK: + break; + + case UPLOAD_ERR_INI_SIZE: + throw new SimpleException('File is too big (maximum size: %s)', ini_get('upload_max_filesize')); + + case UPLOAD_ERR_FORM_SIZE: + throw new SimpleException('File is too big than it was allowed in HTML form'); + + case UPLOAD_ERR_PARTIAL: + throw new SimpleException('File transfer was interrupted'); + + case UPLOAD_ERR_NO_FILE: + throw new SimpleException('No file was uploaded'); + + case UPLOAD_ERR_NO_TMP_DIR: + throw new SimpleException('Server misconfiguration error: missing temporary folder'); + + case UPLOAD_ERR_CANT_WRITE: + throw new SimpleException('Server misconfiguration error: cannot write to disk'); + + case UPLOAD_ERR_EXTENSION: + throw new SimpleException('Server misconfiguration error: upload was canceled by an extension'); + + default: + throw new SimpleException('Generic file upload error (id: ' . $file['error'] . ')'); + } + if (!is_uploaded_file($file['tmp_name'])) + throw new SimpleException('Generic file upload error'); + } +} diff --git a/src/Models/Entities/PostEntity.php b/src/Models/Entities/PostEntity.php index cf5b7b1c..7932f557 100644 --- a/src/Models/Entities/PostEntity.php +++ b/src/Models/Entities/PostEntity.php @@ -213,17 +213,18 @@ class PostEntity extends AbstractEntity throw new SimpleException('Invalid thumbnail type "%s"', $mimeType); list ($imageWidth, $imageHeight) = getimagesize($srcPath); - if ($imageWidth != $config->browsing->thumbWidth) - throw new SimpleException('Invalid thumbnail width (should be %d)', $config->browsing->thumbWidth); - if ($imageHeight != $config->browsing->thumbHeight) - throw new SimpleException('Invalid thumbnail height (should be %d)', $config->browsing->thumbHeight); + if ($imageWidth != $config->browsing->thumbWidth + or $imageHeight != $config->browsing->thumbHeight) + { + throw new SimpleException( + 'Invalid thumbnail size (should be %dx%d)', + $config->browsing->thumbWidth, + $config->browsing->thumbHeight); + } $dstPath = $this->getThumbCustomPath(); - if (is_uploaded_file($srcPath)) - move_uploaded_file($srcPath, $dstPath); - else - rename($srcPath, $dstPath); + TransferHelper::moveUpload($srcPath, $dstPath); } public function makeThumb($width = null, $height = null) @@ -334,10 +335,11 @@ class PostEntity extends AbstractEntity return true; } - public function setContentFromPath($srcPath) + public function setContentFromPath($srcPath, $origName) { $this->fileSize = filesize($srcPath); $this->fileHash = md5_file($srcPath); + $this->origName = $origName; if ($this->fileSize == 0) throw new SimpleException('Specified file is empty'); @@ -384,10 +386,7 @@ class PostEntity extends AbstractEntity $dstPath = $this->getFullPath(); - if (is_uploaded_file($srcPath)) - move_uploaded_file($srcPath, $dstPath); - else - rename($srcPath, $dstPath); + TransferHelper::moveUpload($srcPath, $dstPath); $thumbPath = $this->getThumbDefaultPath(); if (file_exists($thumbPath)) @@ -399,6 +398,8 @@ class PostEntity extends AbstractEntity if (!preg_match('/^https?:\/\//', $srcUrl)) throw new SimpleException('Invalid URL "%s"', $srcUrl); + $this->origName = $srcUrl; + if (preg_match('/youtube.com\/watch.*?=([a-zA-Z0-9_-]+)/', $srcUrl, $matches)) { $youtubeId = $matches[1]; @@ -425,45 +426,13 @@ class PostEntity extends AbstractEntity $srcPath = tempnam(sys_get_temp_dir(), 'upload') . '.dat'; - //warning: low level sh*t ahead - //download the URL $srcUrl into $srcPath - $maxBytes = TextHelper::stripBytesUnits(ini_get('upload_max_filesize')); - set_time_limit(0); - $urlFP = fopen($srcUrl, 'rb'); - if (!$urlFP) - throw new SimpleException('Cannot open URL for reading'); - $srcFP = fopen($srcPath, 'w+b'); - if (!$srcFP) - { - fclose($urlFP); - throw new SimpleException('Cannot open file for writing'); - } - try { - while (!feof($urlFP)) - { - $buffer = fread($urlFP, 4 * 1024); - if (fwrite($srcFP, $buffer) === false) - throw new SimpleException('Cannot write into file'); - fflush($srcFP); - if (ftell($srcFP) > $maxBytes) - { - throw new SimpleException( - 'File is too big (maximum size: %s)', - TextHelper::useBytesUnits($maxBytes)); - } - } - } - finally - { - fclose($urlFP); - fclose($srcFP); - } + $maxBytes = TextHelper::stripBytesUnits(ini_get('upload_max_filesize')); - try - { - $this->setContentFromPath($srcPath); + TransferHelper::download($srcUrl, $srcPath, $maxBytes); + + $this->setContentFromPath($srcPath, basename($srcUrl)); } finally {