diff --git a/public_html/dispatch.php b/public_html/dispatch.php
index 65d46d08..448e19e2 100644
--- a/public_html/dispatch.php
+++ b/public_html/dispatch.php
@@ -132,40 +132,39 @@ $tagValidation =
 \Chibi\Router::register(['TagController', 'mergeView'], 'GET', '/tags-merge', $tagValidation);
 \Chibi\Router::register(['TagController', 'mergeAction'], 'POST', '/tags-merge', $tagValidation);
 
-$userValidations =
+$userValidation =
 [
 	'name' => '[^\/]+',
 	'page' => '\d*',
-	'tab' => 'favs|uploads',
+	'tab' => 'favs|uploads|settings|edit|delete',
 	'filter' => '[^\/]+',
 ];
 
-\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users', $userValidations);
-\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidations);
-\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidations);
-\Chibi\Router::register(['UserController', 'flagAction'], 'POST', '/user/{name}/flag', $userValidations);
-\Chibi\Router::register(['UserController', 'banAction'], 'POST', '/user/{name}/ban', $userValidations);
-\Chibi\Router::register(['UserController', 'unbanAction'], 'POST', '/user/{name}/unban', $userValidations);
-\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], 'POST', '/user/{name}/accept-registration', $userValidations);
-\Chibi\Router::register(['UserController', 'deleteView'], 'GET', '/user/{name}/delete', $userValidations);
-\Chibi\Router::register(['UserController', 'deleteAction'], 'POST', '/user/{name}/delete', $userValidations);
+\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users', $userValidation);
+\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{page}', $userValidation);
+\Chibi\Router::register(['UserController', 'listView'], 'GET', '/users/{filter}/{page}', $userValidation);
+\Chibi\Router::register(['UserController', 'flagAction'], 'POST', '/user/{name}/flag', $userValidation);
+\Chibi\Router::register(['UserController', 'banAction'], 'POST', '/user/{name}/ban', $userValidation);
+\Chibi\Router::register(['UserController', 'unbanAction'], 'POST', '/user/{name}/unban', $userValidation);
+\Chibi\Router::register(['UserController', 'acceptRegistrationAction'], 'POST', '/user/{name}/accept-registration', $userValidation);
+\Chibi\Router::register(['UserController', 'deleteAction'], 'POST', '/user/{name}/delete', $userValidation);
+\Chibi\Router::register(['UserController', 'settingsAction'], 'POST', '/user/{name}/settings', $userValidation);
+\Chibi\Router::register(['UserController', 'editAction'], 'POST', '/user/{name}/edit', $userValidation);
+\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}', $userValidation);
+\Chibi\Router::register(['UserController', 'genericView'], 'GET', '/user/{name}/{tab}/{page}', $userValidation);
 
 foreach (['GET', 'POST'] as $method)
 {
 	\Chibi\Router::register(['TagController', 'massTagRedirectAction'], $method, '/mass-tag-redirect', $tagValidation);
 
-	\Chibi\Router::register(['UserController', 'registrationAction'], $method, '/register', $userValidations);
-	\Chibi\Router::register(['UserController', 'viewAction'], $method, '/user/{name}/{tab}', $userValidations);
-	\Chibi\Router::register(['UserController', 'viewAction'], $method, '/user/{name}/{tab}/{page}', $userValidations);
-	\Chibi\Router::register(['UserController', 'settingsAction'], $method, '/user/{name}/settings', $userValidations);
-	\Chibi\Router::register(['UserController', 'editAction'], $method, '/user/{name}/edit', $userValidations);
-	\Chibi\Router::register(['UserController', 'activationAction'], $method, '/activation/{token}', $userValidations);
-	\Chibi\Router::register(['UserController', 'activationProxyAction'], $method, '/activation-proxy', $userValidations);
-	\Chibi\Router::register(['UserController', 'activationProxyAction'], $method, '/activation-proxy/{token}', $userValidations);
-	\Chibi\Router::register(['UserController', 'passwordResetAction'], $method, '/password-reset/{token}', $userValidations);
-	\Chibi\Router::register(['UserController', 'passwordResetProxyAction'], $method, '/password-reset-proxy', $userValidations);
-	\Chibi\Router::register(['UserController', 'passwordResetProxyAction'], $method, '/password-reset-proxy/{token}', $userValidations);
-	\Chibi\Router::register(['UserController', 'toggleSafetyAction'], $method, '/user/toggle-safety/{safety}', $userValidations);
+	\Chibi\Router::register(['UserController', 'registrationAction'], $method, '/register', $userValidation);
+	\Chibi\Router::register(['UserController', 'activationAction'], $method, '/activation/{token}', $userValidation);
+	\Chibi\Router::register(['UserController', 'activationProxyAction'], $method, '/activation-proxy', $userValidation);
+	\Chibi\Router::register(['UserController', 'activationProxyAction'], $method, '/activation-proxy/{token}', $userValidation);
+	\Chibi\Router::register(['UserController', 'passwordResetAction'], $method, '/password-reset/{token}', $userValidation);
+	\Chibi\Router::register(['UserController', 'passwordResetProxyAction'], $method, '/password-reset-proxy', $userValidation);
+	\Chibi\Router::register(['UserController', 'passwordResetProxyAction'], $method, '/password-reset-proxy/{token}', $userValidation);
+	\Chibi\Router::register(['UserController', 'toggleSafetyAction'], $method, '/user/toggle-safety/{safety}', $userValidation);
 }
 
 Assets::setTitle($config->main->title);
diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php
index df112665..0994017f 100644
--- a/src/Controllers/UserController.php
+++ b/src/Controllers/UserController.php
@@ -17,6 +17,189 @@ class UserController
 		$context->transport->paginator = $ret;
 	}
 
+	public function genericView($name, $tab = 'favs', $page = 1)
+	{
+		$user = UserModel::findByNameOrEmail($name);
+		$flagged = in_array(TextHelper::reprUser($user), SessionHelper::get('flagged', []));
+
+		$context = getContext();
+		$context->flagged = $flagged;
+		$context->transport->tab = $tab;
+		$context->transport->user = $user;
+		$context->handleExceptions = true;
+		$context->viewName = 'user-view';
+
+		if ($tab == 'uploads')
+			$query = 'submit:' . $user->name;
+		elseif ($tab == 'favs')
+			$query = 'fav:' . $user->name;
+
+		if (isset($query))
+		{
+			$ret = Api::run(
+				new ListPostsJob(),
+				[
+					ListPostsJob::PAGE_NUMBER => $page,
+					ListPostsJob::QUERY => $query
+				]);
+
+			$context->transport->posts = $ret->entities;
+			$context->transport->paginator = $ret;
+			$context->transport->lastSearchQuery = $query;
+		}
+
+		Access::assert(
+			Privilege::ViewUser,
+			Access::getIdentity($user));
+	}
+
+	public function settingsAction($name)
+	{
+		$this->genericView($name, 'settings');
+
+		$user = getContext()->transport->user;
+
+		Access::assert(
+			Privilege::ViewUser,
+			Access::getIdentity($user));
+		Access::assert(
+			Privilege::ChangeUserSettings,
+			Access::getIdentity($user));
+
+		$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 == Auth::getCurrentUser()->id)
+			Auth::setCurrentUser($user);
+
+		Messenger::message('Browsing settings updated!');
+	}
+
+	public function editAction($name)
+	{
+		$this->genericView($name, 'edit');
+		$this->requirePasswordConfirmation();
+
+		$user = getContext()->transport->user;
+
+		Access::assert(
+			Privilege::ViewUser,
+			Access::getIdentity($user));
+
+		$suppliedCurrentPassword = InputHelper::get('current-password');
+		$suppliedName = InputHelper::get('name');
+		$suppliedPassword1 = InputHelper::get('password1');
+		$suppliedPassword2 = InputHelper::get('password2');
+		$suppliedEmail = InputHelper::get('email');
+		$suppliedAccessRank = InputHelper::get('access-rank');
+
+		$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 (Auth::getCurrentUser()->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 ($confirmMail)
+			self::sendEmailChangeConfirmation($user);
+
+		UserModel::save($user);
+		if (Auth::getCurrentUser()->id == $user->id)
+			Auth::setCurrentUser($user);
+
+		LogHelper::flush();
+		$message = 'Account settings updated!';
+		if ($confirmMail)
+			$message .= ' You will be sent an e-mail address confirmation message soon.';
+
+		Messenger::message($message);
+	}
+
+	public function deleteAction($name)
+	{
+		$this->genericView($name, 'delete');
+		$this->requirePasswordConfirmation();
+
+		Api::run(new DeleteUserJob(), [
+			DeleteUserJob::USER_NAME => $name]);
+
+		$user = UserModel::findById(Auth::getCurrentUser()->id, false);
+		if (!$user)
+			Auth::logOut();
+
+		\Chibi\Util\Url::forward(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
+		exit;
+	}
+
 	public function flagAction($name)
 	{
 		Api::run(new FlagUserJob(), [FlagUserJob::USER_NAME => $name]);
@@ -42,231 +225,6 @@ class UserController
 			AcceptUserRegistrationJob::USER_NAME => $name]);
 	}
 
-	public function deleteView($name)
-	{
-		$user = UserModel::findByNameOrEmail($name);
-
-		$this->loadUserView($user);
-		$context = getContext();
-		$context->transport->tab = 'delete';
-	}
-
-	public function deleteAction($name)
-	{
-		$this->deleteView($name);
-		$user = UserModel::findByNameOrEmail($name);
-
-		if (Auth::getCurrentUser()->id == $user->id)
-		{
-			$suppliedPassword = InputHelper::get('current-password');
-			$suppliedPasswordHash = UserModel::hashPassword($suppliedPassword, $user->passSalt);
-			if ($suppliedPasswordHash != $user->passHash)
-				throw new SimpleException('Must supply valid password');
-		}
-
-		$oldId = $user->id;
-
-		Api::run(new DeleteUserJob(), [
-			DeleteUserJob::USER_NAME => $name]);
-
-		if ($oldId == Auth::getCurrentUser()->id)
-			Auth::logOut();
-
-		\Chibi\Util\Url::forward(\Chibi\Router::linkTo(['StaticPagesController', 'mainPageView']));
-		exit;
-	}
-
-	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 == Auth::getCurrentUser()->id)
-			Auth::setCurrentUser($user);
-		Messenger::message('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 (Auth::getCurrentUser()->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 (Auth::getCurrentUser()->id == $user->id)
-			{
-				$suppliedPasswordHash = UserModel::hashPassword($suppliedCurrentPassword, $user->passSalt);
-				if ($suppliedPasswordHash != $currentPasswordHash)
-					throw new SimpleException('Must supply valid current password');
-			}
-			UserModel::save($user);
-			if (Auth::getCurrentUser()->id == $user->id)
-				Auth::setCurrentUser($user);
-
-			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.';
-			Messenger::message($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)
 	{
 		$user = Auth::getCurrentUser();
@@ -462,16 +420,6 @@ class UserController
 		Messenger::message('Activation e-mail resent.');
 	}
 
-	private function loadUserView($user)
-	{
-		$context = getContext();
-		$flagged = in_array(TextHelper::reprUser($user), SessionHelper::get('flagged', []));
-		$context->flagged = $flagged;
-		$context->transport->user = $user;
-		$context->handleExceptions = true;
-		$context->viewName = 'user-view';
-	}
-
 	private static function sendTokenizedEmail(
 		$user,
 		$body,
@@ -560,4 +508,16 @@ class UserController
 			$user->emailConfirmed,
 			'passwordResetAction');
 	}
+
+	private function requirePasswordConfirmation()
+	{
+		$user = getContext()->transport->user;
+		if (Auth::getCurrentUser()->id == $user->id)
+		{
+			$suppliedPassword = InputHelper::get('current-password');
+			$suppliedPasswordHash = UserModel::hashPassword($suppliedPassword, $user->passSalt);
+			if ($suppliedPasswordHash != $user->passHash)
+				throw new SimpleException('Must supply valid password');
+		}
+	}
 }
diff --git a/src/CustomMarkdown.php b/src/CustomMarkdown.php
index 4c83d451..4acd7023 100644
--- a/src/CustomMarkdown.php
+++ b/src/CustomMarkdown.php
@@ -145,7 +145,7 @@ class CustomMarkdown extends \Michelf\MarkdownExtra
 
 	protected function doUsers($text)
 	{
-		$link = \Chibi\Router::linkTo(['UserController', 'viewAction'], ['name' => '_name_']);
+		$link = \Chibi\Router::linkTo(['UserController', 'genericView'], ['name' => '_name_']);
 		return preg_replace_callback('/(?:(?<![^\s\(\)\[\]]))\+([a-zA-Z0-9_-]+)/', function($x) use ($link)
 		{
 			return $this->hashPart('<a href="' . str_replace('_name_', $x[1], $link) . '">' . $x[0] . '</a>');
diff --git a/src/Views/comment-small.phtml b/src/Views/comment-small.phtml
index 46092298..19071ce2 100644
--- a/src/Views/comment-small.phtml
+++ b/src/Views/comment-small.phtml
@@ -8,7 +8,7 @@ Assets::addScript('comment-edit.js');
 	<div class="avatar">
 		<?php $commenter = $this->context->comment->getCommenter() ?>
 		<?php if ($commenter): ?>
-			<a href="<?= \Chibi\Router::linkTo(['UserController', 'viewAction'], ['name' => $commenter->name]) ?>">
+			<a href="<?= \Chibi\Router::linkTo(['UserController', 'genericView'], ['name' => $commenter->name]) ?>">
 				<img src="<?= htmlspecialchars($commenter->getAvatarUrl(40)) ?>" alt="<?= $commenter->name ?>"/>
 			</a>
 		<?php else: ?>
@@ -23,7 +23,7 @@ Assets::addScript('comment-edit.js');
 			<span class="nickname">
 				<?php if ($commenter): ?>
 					<a href="<?= \Chibi\Router::linkTo(
-						['UserController', 'viewAction'],
+						['UserController', 'genericView'],
 						['name' => $commenter->name]) ?>">
 						<?= $commenter->name ?>
 					</a>
diff --git a/src/Views/post-view.phtml b/src/Views/post-view.phtml
index 52e6bceb..d21da84e 100644
--- a/src/Views/post-view.phtml
+++ b/src/Views/post-view.phtml
@@ -94,7 +94,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
 			<?php if ($uploader): ?>
 				<span class="value" title="<?= $val = $uploader->name ?>">
 					<a href="<?= \Chibi\Router::linkTo(
-						['UserController', 'viewAction'],
+						['UserController', 'genericView'],
 						['name' => $uploader->name]) ?>">
 						<img src="<?= htmlentities($uploader->getAvatarUrl(24)) ?>" alt="<?= $uploader->name ?>"/>
 						<?= $val ?>
@@ -243,7 +243,7 @@ $canEditAnything = count(array_filter($editPostPrivileges)) > 0;
 				<?php foreach ($this->context->transport->post->getFavorites() as $user): ?>
 					<li>
 						<a title="<?= $user->name ?>" href="<?= \Chibi\Router::linkTo(
-							['UserController', 'viewAction'],
+							['UserController', 'genericView'],
 							['name' => $user->name]) ?>">
 							<img src="<?= htmlspecialchars($user->getAvatarUrl()) ?>" alt="<?= $user->name ?>">
 						</a>
diff --git a/src/Views/static-main.phtml b/src/Views/static-main.phtml
index 8bcd22a8..f1bd4726 100644
--- a/src/Views/static-main.phtml
+++ b/src/Views/static-main.phtml
@@ -42,7 +42,7 @@ Assets::addStylesheet('static-main.css');
 			<?php if ($this->context->featuredPostUser): ?>
 				by
 				<a href="<?= \Chibi\Router::linkTo(
-					['UserController', 'viewAction'],
+					['UserController', 'genericView'],
 					['name' => $this->context->featuredPostUser->name]) ?>">
 					<?= $this->context->featuredPostUser->name ?>
 				</a>,
diff --git a/src/Views/top-navigation.phtml b/src/Views/top-navigation.phtml
index 7ac7b55d..ad330ba1 100644
--- a/src/Views/top-navigation.phtml
+++ b/src/Views/top-navigation.phtml
@@ -76,7 +76,7 @@
 	{
 		$registerNavItem(
 			'My account',
-			\Chibi\Router::linkTo(['UserController', 'viewAction'], ['name' => Auth::getCurrentUser()->name]),
+			\Chibi\Router::linkTo(['UserController', 'genericView'], ['name' => Auth::getCurrentUser()->name]),
 			$activeController == 'user' and isset($this->context->route->arguments['name']) and
 				$this->context->route->arguments['name'] == Auth::getCurrentUser()->name);
 
diff --git a/src/Views/user-edit.phtml b/src/Views/user-edit.phtml
index d337c979..c5f3ab26 100644
--- a/src/Views/user-edit.phtml
+++ b/src/Views/user-edit.phtml
@@ -32,7 +32,7 @@
 					name="name"
 					id="name"
 					placeholder="New name&hellip;"
-					value="<?= htmlspecialchars($this->context->suppliedName) ?>"/>
+					value="<?= htmlspecialchars(InputHelper::get('name')) ?>">
 			</div>
 		</div>
 	<?php endif ?>
@@ -49,7 +49,7 @@
 					name="email"
 					id="email"
 					placeholder="New e-mail&hellip;"
-					value="<?= htmlspecialchars($this->context->suppliedEmail) ?>"/>
+					value="<?= htmlspecialchars(InputHelper::get('email')) ?>"/>
 			</div>
 		</div>
 	<?php endif ?>
@@ -66,7 +66,7 @@
 					name="password1"
 					id="password1"
 					placeholder="New password&hellip;"
-					value="<?= htmlspecialchars($this->context->suppliedPassword1) ?>"/>
+					value="<?= htmlspecialchars(InputHelper::get('password1')) ?>"/>
 			</div>
 		</div>
 		<div class="form-row password2">
@@ -77,7 +77,7 @@
 					name="password2"
 					id="password2"
 					placeholder="New password&hellip; (repeat)"
-					value="<?= htmlspecialchars($this->context->suppliedPassword2) ?>"/>
+					value="<?= htmlspecialchars(InputHelper::get('password2')) ?>"/>
 			</div>
 		</div>
 	<?php endif ?>
@@ -92,8 +92,8 @@
 				<select name="access-rank" id="access-rank">
 					<?php foreach (AccessRank::getAll() as $rank): ?>
 						<?php if ($rank == AccessRank::Nobody) continue ?>
-						<?php if (($this->context->suppliedAccessRank != '' and $rank == $this->context->suppliedAccessRank)
-							or ($this->context->suppliedAccessRank == '' and $rank == $this->context->transport->user->accessRank)): ?>
+						<?php if ($rank == InputHelper::get('access-rank') or (!InputHelper::get('access-rank')
+							and $rank == $this->context->transport->user->accessRank)): ?>
 							<option value="<?= $rank ?>" selected="selected">
 						<?php else: ?>
 							<option value="<?= $rank ?>">
diff --git a/src/Views/user-list.phtml b/src/Views/user-list.phtml
index 38759bd2..78340eb9 100644
--- a/src/Views/user-list.phtml
+++ b/src/Views/user-list.phtml
@@ -43,14 +43,14 @@ if (Auth::getCurrentUser()->hasEnabledEndlessScrolling())
 			<?php foreach ($this->context->transport->users as $user): ?>
 				<div class="user">
 					<a class="avatar" href="<?= \Chibi\Router::linkTo(
-						['UserController', 'viewAction'],
+						['UserController', 'genericView'],
 						['name' => $user->name]) ?>">
 						<img src="<?= htmlspecialchars($user->getAvatarUrl(100)) ?>" alt="<?= $user->name ?>"/>
 					</a>
 					<div class="details">
 						<h1>
 							<a href="<?= \Chibi\Router::linkTo(
-								['UserController', 'viewAction'],
+								['UserController', 'genericView'],
 								['name' => $user->name]) ?>">
 								<?= $user->name ?>
 							</a>
diff --git a/src/Views/user-view.phtml b/src/Views/user-view.phtml
index 1cdb6f9c..4d7fe073 100644
--- a/src/Views/user-view.phtml
+++ b/src/Views/user-view.phtml
@@ -6,7 +6,7 @@ Assets::addStylesheet('user-view.css');
 <div id="sidebar">
 	<div class="avatar-wrapper">
 		<a href="<?= \Chibi\Router::linkTo(
-			['UserController', 'viewAction'],
+			['UserController', 'genericView'],
 			['name' => $this->context->transport->user->name]) ?>">
 
 			<img
@@ -201,7 +201,7 @@ Assets::addStylesheet('user-view.css');
 				<li class="favs">
 			<?php endif ?>
 				<a href="<?= \Chibi\Router::linkTo(
-					['UserController', 'viewAction'],
+					['UserController', 'genericView'],
 					['name' => $this->context->transport->user->name,
 					'tab' => 'favs',
 					'page' => 1]) ?>">
@@ -215,7 +215,7 @@ Assets::addStylesheet('user-view.css');
 				<li class="uploads">
 			<?php endif ?>
 				<a href="<?= \Chibi\Router::linkTo(
-					['UserController', 'viewAction'],
+					['UserController', 'genericView'],
 					['name' => $this->context->transport->user->name,
 					'tab' => 'uploads',
 					'page' => 1]) ?>">
@@ -233,8 +233,9 @@ Assets::addStylesheet('user-view.css');
 					<li class="settings">
 				<?php endif ?>
 					<a href="<?= \Chibi\Router::linkTo(
-						['UserController', 'settingsAction'],
-						['name' => $this->context->transport->user->name]) ?>">
+						['UserController', 'genericView'],
+						['name' => $this->context->transport->user->name,
+						'tab' => 'settings']) ?>">
 						Browsing settings
 					</a>
 				</li>
@@ -247,8 +248,9 @@ Assets::addStylesheet('user-view.css');
 					<li class="edit">
 				<?php endif ?>
 					<a href="<?= \Chibi\Router::linkTo(
-						['UserController', 'editAction'],
-						['name' => $this->context->transport->user->name]) ?>">
+						['UserController', 'genericView'],
+						['name' => $this->context->transport->user->name,
+						'tab' => 'edit']) ?>">
 						Account settings
 					</a>
 				</li>
@@ -263,8 +265,9 @@ Assets::addStylesheet('user-view.css');
 					<li class="delete">
 				<?php endif ?>
 					<a href="<?= \Chibi\Router::linkTo(
-						['UserController', 'deleteAction'],
-						['name' => $this->context->transport->user->name]) ?>">
+						['UserController', 'genericView'],
+						['name' => $this->context->transport->user->name,
+						'tab' => 'delete']) ?>">
 						Delete account
 					</a>
 				</li>