and just a heap of shit

This commit is contained in:
flash 2016-09-14 00:05:03 +02:00
parent 6a4d984189
commit 8b603d5e37
41 changed files with 405 additions and 606 deletions

View file

@ -259,7 +259,7 @@ class Settings
"{$cpfx}id",
"{$cpfx}session",
];
$this->avatarUrl = route('file.avatar', '{0}', true);
$this->avatarUrl = route('user.avatar', '{0}', true);
$this->profileUrl = route('user.profile', '{0}', true);
$this->development = config('dev.show_errors');
$this->languagePath = config('chat.language_path');

View file

@ -51,8 +51,7 @@ class AuthController extends Controller
CurrentSession::stop();
// Return true indicating a successful logout
header('Location: ' . route('auth.login'));
return;
redirect(route('auth.login'));
}
/**

View file

@ -36,7 +36,7 @@ class ChatController extends Controller
*/
public function redirect()
{
header('Location: ' . config('chat.webclient'));
redirect(config('chat.webclient'));
}
/**

View file

@ -6,8 +6,15 @@
namespace Sakura\Controllers;
use Phroute\Phroute\Exception\HttpMethodNotAllowedException;
use Phroute\Phroute\Exception\HttpRouteNotFoundException;
use Sakura\Config;
use Sakura\CurrentSession;
use Sakura\DB;
use Sakura\Exceptions\FileException;
use Sakura\File;
use Sakura\Perms;
use Sakura\Perms\Manage;
use Sakura\Perms\Site;
use Sakura\Template;
use Sakura\User;
@ -19,6 +26,15 @@ use Sakura\User;
*/
class FileController extends Controller
{
/**
* Possible modes.
*/
const MODES = [
'avatar',
'background',
'header',
];
/**
* The base for serving a file.
* @param string $data
@ -28,126 +44,171 @@ class FileController extends Controller
*/
private function serve($data, $mime, $name)
{
// Add original filename
header("Content-Disposition: inline; filename={$name}");
// Set content type
header("Content-Type: {$mime}");
// Return image data
return $data;
}
/**
* Attempt to get an avatar.
* @param int $id
* @return string
* Handles file uploads.
* @param string $mode
* @param array $file
* @return array
*/
public function avatar($id = 0)
private function upload($mode, $file, $user)
{
$noAvatar = ROOT . 'public/' . str_replace(
'%tplname%',
Template::$name,
config('user.avatar_none')
);
$none = [
'name' => basename($noAvatar),
'data' => file_get_contents($noAvatar),
'mime' => getimagesizefromstring($noAvatar)['mime'],
];
$error = null;
$bannedPath = ROOT . 'public/' . str_replace(
'%tplname%',
Template::$name,
config('user.avatar_ban')
);
$banned = [
'name' => basename($bannedPath),
'data' => file_get_contents($bannedPath),
'mime' => getimagesizefromstring($bannedPath)['mime'],
];
// Handle errors
switch ($file['error']) {
case UPLOAD_ERR_OK:
break;
$user = User::construct($id);
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
throw new FileException("Your file was too large!");
if ($user->permission(Site::RESTRICTED)) {
return $this->serve($banned['data'], $banned['mime'], $banned['name']);
case UPLOAD_ERR_PARTIAL:
throw new FileException("The upload failed!");
case UPLOAD_ERR_NO_TMP_DIR:
case UPLOAD_ERR_CANT_WRITE:
throw new FileException("Wasn't able to save the file, contact a staff member!");
case UPLOAD_ERR_EXTENSION:
default:
throw new FileException("Something prevented the file upload!");
}
if ($user->id < 1 || !$user->avatar || $user->permission(Site::DEACTIVATED)) {
return $this->serve($none['data'], $none['mime'], $none['name']);
// Get the temp filename
$tmpName = $file['tmp_name'];
// Get the image meta data
$meta = getimagesize($tmpName);
// Check if image
if (!$meta
|| (
$meta[2] !== IMAGETYPE_GIF
&& $meta[2] !== IMAGETYPE_JPEG
&& $meta[2] !== IMAGETYPE_PNG
)
) {
throw new FileException("Please upload a valid image!");
}
$serve = new File($user->avatar);
// Check dimensions
$maxWidth = config("file.{$mode}.max_width");
$maxHeight = config("file.{$mode}.max_height");
if (!$serve->id) {
return $this->serve($none['data'], $none['mime'], $none['name']);
if ($meta[0] > $maxWidth
|| $meta[1] > $maxHeight) {
throw new FileException("Your image can't be bigger than {$maxWidth}x{$maxHeight}" .
", yours was {$meta[0]}x{$meta[1]}!");
}
return $this->serve($serve->data, $serve->mime, $serve->name);
// Check file size
$maxFileSize = config("file.{$mode}.max_file_size");
if (filesize($tmpName) > $maxFileSize) {
$maxSizeFmt = byte_symbol($maxFileSize);
throw new FileException("Your image is not allowed to be larger than {$maxSizeFmt}!");
}
$userId = $user->id;
$ext = image_type_to_extension($meta[2]);
$filename = "{$mode}_{$userId}{$ext}";
// Create the file
$file = File::create(file_get_contents($tmpName), $filename, $user);
// Delete the old file
$this->delete($mode, $user);
$column = "user_{$mode}";
// Save new avatar
DB::table('users')
->where('user_id', $user->id)
->update([
$column => $file->id,
]);
}
/**
* Attempt to get a background.
* @param int $id
* @return string
* Deletes a file.
* @param string $mode
*/
public function background($id = 0)
public function delete($mode, $user)
{
$noBg = ROOT . "public/images/pixel.png";
$none = [
'name' => basename($noBg),
'data' => file_get_contents($noBg),
'mime' => getimagesizefromstring($noBg)['mime'],
];
$fileId = $user->{$mode};
if (!$id) {
return $this->serve($none['data'], $none['mime'], $none['name']);
if ($fileId) {
(new File($fileId))->delete();
}
$user = User::construct($id);
if ($user->permission(Site::DEACTIVATED)
|| $user->permission(Site::RESTRICTED)
|| !$user->background) {
return $this->serve($none['data'], $none['mime'], $none['name']);
}
$serve = new File($user->background);
if (!$serve->id) {
return $this->serve($none['data'], $none['mime'], $none['name']);
}
return $this->serve($serve->data, $serve->mime, $serve->name);
}
/**
* Attempt to get a profile header.
* @param int $id
* Catchall serve.
* @param string $method
* @param array $params
* @todo add a specific permission for mods to override uploads.
* @return string
*/
public function header($id = 0)
public function __call($method, $params)
{
$noHeader = ROOT . "public/images/pixel.png";
$none = [
'name' => basename($noHeader),
'data' => file_get_contents($noHeader),
'mime' => getimagesizefromstring($noHeader)['mime'],
];
if (!$id) {
return $this->serve($none['data'], $none['mime'], $none['name']);
if (!in_array($method, self::MODES)) {
throw new HttpRouteNotFoundException;
}
$user = User::construct($id);
$user = User::construct($params[0] ?? 0);
if (session_check()) {
if (!CurrentSession::$user->permission(Manage::USE_MANAGE, Perms::MANAGE)
&& ($user->id !== CurrentSession::$user->id
|| !$user->permission(constant("Sakura\Perms\Site::CHANGE_" . strtoupper($method)))
|| $user->permission(Site::DEACTIVATED)
|| $user->permission(Site::RESTRICTED))
) {
throw new HttpMethodNotAllowedException;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$error = null;
try {
$this->upload($method, $_FILES['file'] ?? null, $user);
} catch (FileException $e) {
$error = $e->getMessage();
}
return $this->json(compact('error'));
} elseif ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
$this->delete($method, $user);
return;
}
}
$noFile = ROOT . 'public/' . str_replace(
'%tplname%',
Template::$name,
config("user.{$method}_none")
);
$none = [
'name' => basename($noFile),
'data' => file_get_contents($noFile),
'mime' => getimagesizefromstring($noFile)['mime'],
];
if ($user->permission(Site::DEACTIVATED)
|| $user->permission(Site::RESTRICTED)
|| !$user->header) {
|| !$user->{$method}) {
return $this->serve($none['data'], $none['mime'], $none['name']);
}
$serve = new File($user->header);
$serve = new File($user->{$method});
if (!$serve->id) {
return $this->serve($none['data'], $none['mime'], $none['name']);

View file

@ -118,7 +118,7 @@ class ForumController extends Controller
// Redirect forum id 0 to the main page
if ($forum->id === 0) {
header("Location: " . route('forums.index'));
redirect(route('forums.index'));
return;
}
@ -130,7 +130,7 @@ class ForumController extends Controller
// Check if the forum isn't a link
if ($forum->type === 2) {
header("Location: {$forum->link}");
redirect($forum->link);
return;
}
@ -158,6 +158,6 @@ class ForumController extends Controller
$forum->trackUpdateAll(CurrentSession::$user->id);
header("Location: " . route('forums.forum', $forum->id));
redirect(route('forums.forum', $forum->id));
}
}

View file

@ -57,7 +57,7 @@ class PostController extends Controller
$topicLink .= "?page={$postAt}";
}
return header("Location: {$topicLink}#p{$post->id}");
redirect("{$topicLink}#p{$post->id}");
}
/**
@ -178,7 +178,7 @@ class PostController extends Controller
$postLink = route('forums.post', $post->id);
return header("Location: {$postLink}");
redirect($postLink);
}
/**
@ -211,8 +211,6 @@ class PostController extends Controller
throw new HttpMethodNotAllowedException();
}
if (session_check('sessionid')) {
if (isset($_POST['yes'])) {
// Check if the topic only has 1 post
if ($topic->replyCount() === 1) {
// Delete the entire topic
@ -220,21 +218,12 @@ class PostController extends Controller
$redirect = route('forums.forum', $forum->id);
} else {
// Just delete the post
$post->delete();
// Just delete the post (replace this with soft deleting)
$post->purge();
$redirect = route('forums.topic', $topic->id);
}
} else {
$redirect = route('forums.post', $post->id);
}
header("Location: {$redirect}");
return;
}
$message = "Are you sure?";
return view('global/confirm', compact('message'));
redirect($redirect);
}
}

View file

@ -6,6 +6,8 @@
namespace Sakura\Controllers\Forum;
use Phroute\Phroute\Exception\HttpMethodNotAllowedException;
use Phroute\Phroute\Exception\HttpRouteNotFoundException;
use Sakura\CurrentSession;
use Sakura\Forum\Forum;
use Sakura\Forum\Post;
@ -22,6 +24,7 @@ class TopicController extends Controller
/**
* Views a topic.
* @param int $id
* @throws HttpRouteNotFoundException
* @return string
*/
public function view($id = 0)
@ -32,10 +35,7 @@ class TopicController extends Controller
// Check if the forum exists
if ($topic->id === 0
|| !$forum->permission(ForumPerms::VIEW, CurrentSession::$user->id)) {
$message = "This topic doesn't exist or you don't have access to it!";
$redirect = route('forums.index');
return view('global/information', compact('message', 'redirect'));
throw new HttpRouteNotFoundException;
}
$topic->trackUpdate(CurrentSession::$user->id);
@ -47,6 +47,7 @@ class TopicController extends Controller
/**
* Checks if a user can moderate the topic.
* @param int $id
* @throws HttpRouteNotFoundException
* @return array
*/
private function modBase($id)
@ -60,194 +61,136 @@ class TopicController extends Controller
return compact('topic', 'forum');
}
return false;
throw new HttpRouteNotFoundException;
}
/**
* Sticky a topic.
* @param int $id
* @throws HttpMethodNotAllowedException
* @return string
*/
public function sticky($id)
{
$modBase = $this->modBase($id);
$redirect = route('forums.index');
$message = "This forum doesn't exist or you don't have access to it.";
extract($this->modBase($id));
if ($modBase !== false) {
extract($modBase);
$redirect = route('forums.topic', $topic->id);
if (!$forum->permission(ForumPerms::STICKY, CurrentSession::$user->id)) {
throw new HttpMethodNotAllowedException;
}
if ($forum->permission(ForumPerms::STICKY, CurrentSession::$user->id)) {
$topic->type = $topic->type !== 1 ? 1 : 0;
$topic->update();
$message = $topic->type
? 'Changed the topic to sticky!' : 'Reverted the topic back to normal!';
} else {
$message = "You aren't allowed to sticky topics!";
}
}
return view('global/information', compact('message', 'redirect'));
redirect(route('forums.topic', $topic->id));
}
/**
* Announce a topic.
* @param int $id
* @throws HttpMethodNotAllowedException
* @return string
*/
public function announce($id)
{
$modBase = $this->modBase($id);
$redirect = route('forums.index');
$message = "This forum doesn't exist or you don't have access to it.";
extract($this->modBase($id));
if ($modBase !== false) {
extract($modBase);
$redirect = route('forums.topic', $topic->id);
if (!$forum->permission(ForumPerms::ANNOUNCEMENT, CurrentSession::$user->id)) {
throw new HttpMethodNotAllowedException;
}
if ($forum->permission(ForumPerms::ANNOUNCEMENT, CurrentSession::$user->id)) {
$topic->type = $topic->type !== 2 ? 2 : 0;
$topic->update();
$message = $topic->type
? 'Changed the topic to an announcement!' : 'Reverted the topic back to normal!';
} else {
$message = "You aren't allowed to announce topics!";
}
}
return view('global/information', compact('message', 'redirect'));
redirect(route('forums.topic', $topic->id));
}
/**
* Lock a topic.
* @param int $id
* @throws HttpMethodNotAllowedException
* @return string
*/
public function lock($id)
{
$modBase = $this->modBase($id);
$redirect = route('forums.index');
$message = "This forum doesn't exist or you don't have access to it.";
extract($this->modBase($id));
if ($modBase !== false) {
extract($modBase);
$redirect = route('forums.topic', $topic->id);
if (!$forum->permission(ForumPerms::LOCK, CurrentSession::$user->id)) {
throw new HttpMethodNotAllowedException;
}
if ($forum->permission(ForumPerms::LOCK, CurrentSession::$user->id)) {
$topic->status = $topic->status !== 1 ? 1 : 0;
$topic->update();
$message = ($topic->status ? 'Locked' : 'Unlocked') . ' the topic!';
} else {
$message = "You aren't allowed to lock topics!";
}
}
return view('global/information', compact('message', 'redirect'));
redirect(route('forums.topic', $topic->id));
}
/**
* Delete an entire topic.
* @param int $id
* @throws HttpMethodNotAllowedException
* @return string
*/
public function delete($id)
{
$modBase = $this->modBase($id);
$redirect = route('forums.index');
$message = "This forum doesn't exist or you don't have access to it.";
extract($this->modBase($id));
if ($modBase !== false) {
extract($modBase);
$trash = config('forum.trash');
$trash = intval(config('forum.trash'));
// Check if we're operating from the trash
if ($topic->forum === $trash) {
if ($forum->permission(ForumPerms::DELETE_ANY, CurrentSession::$user->id)) {
$topic->delete();
$message = "Deleted the topic!";
if ($topic->forum === $trash
&& $forum->permission(ForumPerms::DELETE_ANY, CurrentSession::$user->id)) {
$redirect = route('forums.forum', $trash);
} else {
$message = "You aren't allowed to delete topics!";
}
} else {
$topic->delete();
} elseif ($forum->permission(ForumPerms::MOVE, CurrentSession::$user->id)) {
$redirect = route('forums.topic', $topic->id);
if ($forum->permission(ForumPerms::MOVE, CurrentSession::$user->id)) {
$topic->move($trash);
$message = "Moved the topic to the trash!";
} else {
$message = "You're not allowed to do this!";
}
}
throw new HttpMethodNotAllowedException;
}
return view('global/information', compact('message', 'redirect'));
redirect($redirect);
}
/**
* Restore a topic to its previous location.
* @param int $id
* @throws HttpMethodNotAllowedException
* @return string
*/
public function restore($id)
{
$modBase = $this->modBase($id);
$redirect = route('forums.index');
$message = "This forum doesn't exist or you don't have access to it.";
extract($this->modBase($id));
if ($modBase !== false) {
extract($modBase);
$redirect = route('forums.topic', $topic->id);
if (!$forum->permission(ForumPerms::MOVE, CurrentSession::$user->id)) {
throw new HttpMethodNotAllowedException;
}
if ($forum->permission(ForumPerms::MOVE, CurrentSession::$user->id)) {
if ($topic->oldForum) {
$topic->move($topic->oldForum, false);
$message = "Moved the topic back to it's old location!";
} else {
$message = "This topic has never been moved!";
}
} else {
$message = "You aren't allowed to move threads!";
}
}
return view('global/information', compact('message', 'redirect'));
redirect(route('forums.topic', $topic->id));
}
/**
* Move a topic.
* @param int $id
* @throws HttpMethodNotAllowedException
* @return string
*/
public function move($id)
{
$modBase = $this->modBase($id);
$redirect = route('forums.index');
$message = "This forum doesn't exist or you don't have access to it.";
if ($modBase !== false) {
extract($modBase);
$redirect = route('forums.topic', $topic->id);
if ($forum->permission(ForumPerms::MOVE, CurrentSession::$user->id)) {
extract($this->modBase($id));
$dest_forum = new Forum($_REQUEST['forum_id'] ?? 0);
if ($dest_forum->id === 0
if (!$forum->permission(ForumPerms::MOVE, CurrentSession::$user->id)
|| $dest_forum->id === 0
|| $dest_forum->permission(ForumPerms::VIEW, CurrentSession::$user->id)) {
throw new HttpMethodNotAllowedException;
}
$topic->move($dest_forum->id);
$message = "Moved to the topic to {$dest_forum->name}!";
} else {
$message = "The destination forum doesn't exist or you don't have access to it.";
}
} else {
$message = "You aren't allowed to move threads!";
}
}
return view('global/information', compact('message', 'redirect'));
redirect(route('forums.topic', $topic->id));
}
/**
@ -330,7 +273,7 @@ class TopicController extends Controller
$postLink = route('forums.post', $post->id);
// Head to the post
return header("Location: {$postLink}");
redirect($postLink);
}
/**
@ -418,7 +361,8 @@ class TopicController extends Controller
$postLink = route('forums.post', $post->id);
// Head to the post
return header("Location: {$postLink}");
redirect($postLink);
return;
}
return view('forum/topic', compact('forum'));

View file

@ -33,7 +33,7 @@ class FriendsController extends Controller
$alert->time = time();
$alert->title = $title;
$alert->text = $text;
$alert->image = route('file.avatar', $user->id);
$alert->image = route('user.avatar', $user->id);
$alert->timeout = 60000;
$alert->link = route('user.profile', $user->id);

View file

@ -67,7 +67,7 @@ class PremiumController extends Controller
// Check months
if ($months < 1
|| $months > $amountLimit) {
header("Location: " . route('premium.error'));
redirect(route('premium.error'));
return;
}
@ -97,14 +97,14 @@ class PremiumController extends Controller
// Attempt to create a transaction
if (!$transaction) {
header("Location: " . route('premium.error'));
redirect(route('premium.error'));
return;
}
// Store the amount of months in the global session array
$_SESSION['premiumMonths'] = (int) $months;
return header("Location: {$transaction}");
redirect($transaction);
}
/**
@ -125,7 +125,8 @@ class PremiumController extends Controller
|| !$payment
|| !$payer
|| !$months) {
return header("Location: {$failRoute}");
redirect($failRoute);
return;
}
// Attempt to complete the transaction
@ -136,12 +137,13 @@ class PremiumController extends Controller
}
if (!$finalise) {
return header("Location: {$failRoute}");
redirect($failRoute);
return;
}
CurrentSession::$user->addPremium(self::PERIOD_PER_PAYMENT * $months);
return header("Location: {$successRoute}");
redirect($successRoute);
}
/**

View file

@ -80,7 +80,7 @@ class AccountController extends Controller
]);
}
header("Location: {$redirect}");
redirect($redirect);
return;
}
@ -212,7 +212,7 @@ class AccountController extends Controller
$user->setPassword($password);
}
header("Location: {$redirect}");
redirect($redirect);
return;
}
@ -271,7 +271,7 @@ class AccountController extends Controller
CurrentSession::$user->setMainRank($rank);
header("Location: {$redirect}");
redirect($redirect);
return;
}

View file

@ -54,7 +54,7 @@ class AdvancedController extends Controller
// Delete it
$session->delete();
header("Location: {$redirect}");
redirect($redirect);
return;
}
@ -94,9 +94,7 @@ class AdvancedController extends Controller
// Destroy all active sessions
CurrentSession::$user->purgeSessions();
$redirect = route('main.index');
$message = "Farewell!";
return view('global/information', compact('message', 'redirect'));
return view('settings/advanced/deactivate_bye');
}
return view('settings/advanced/deactivate');

View file

@ -9,7 +9,6 @@ namespace Sakura\Controllers\Settings;
use Phroute\Phroute\Exception\HttpMethodNotAllowedException;
use Sakura\CurrentSession;
use Sakura\DB;
use Sakura\File;
use Sakura\Perms\Site;
/**
@ -19,196 +18,6 @@ use Sakura\Perms\Site;
*/
class AppearanceController extends Controller
{
/**
* Handles file uploads.
* @param string $mode
* @param array $file
* @return array
*/
private function handleUpload($mode, $file)
{
// Handle errors
switch ($file['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
return "Your file was too large!";
case UPLOAD_ERR_PARTIAL:
return "The upload failed!";
case UPLOAD_ERR_NO_TMP_DIR:
case UPLOAD_ERR_CANT_WRITE:
return "Wasn't able to save the file, contact a staff member!";
case UPLOAD_ERR_EXTENSION:
default:
return "Something prevented the file upload!";
}
// Get the temp filename
$tmpName = $_FILES[$mode]['tmp_name'];
// Get the image meta data
$meta = getimagesize($tmpName);
// Check if image
if (!$meta
|| (
$meta[2] !== IMAGETYPE_GIF
&& $meta[2] !== IMAGETYPE_JPEG
&& $meta[2] !== IMAGETYPE_PNG
)
) {
return "Please upload a valid image!";
}
$confp = $mode === 'header' ? 'cover' : $mode;
// Check dimensions
$maxWidth = config("file.{$confp}.max_width");
$maxHeight = config("file.{$confp}.max_height");
if ($meta[0] > $maxWidth
|| $meta[1] > $maxHeight) {
return "Your image has to be at least {$minWidth}x{$minHeight}"
. " and not bigger than {$maxWidth}x{$maxHeight}, yours was {$meta[0]}x{$meta[1]}!";
}
// Check file size
$maxFileSize = config("file.{$confp}.max_file_size");
if (filesize($tmpName) > $maxFileSize) {
$maxSizeFmt = byte_symbol($maxFileSize);
return "Your image is not allowed to be larger than {$maxSizeFmt}!";
}
$userId = CurrentSession::$user->id;
$ext = image_type_to_extension($meta[2]);
$filename = "{$mode}_{$userId}{$ext}";
// Create the file
$file = File::create(file_get_contents($tmpName), $filename, CurrentSession::$user);
// Delete the old file
$this->deleteFile($mode);
$column = "user_{$mode}";
// Save new avatar
DB::table('users')
->where('user_id', CurrentSession::$user->id)
->update([
$column => $file->id,
]);
return null;
}
/**
* Deletes a file.
* @param string $mode
*/
public function deleteFile($mode)
{
$fileId = CurrentSession::$user->{$mode};
if ($fileId) {
(new File($fileId))->delete();
}
}
/**
* Renders the avatar changing page
* @return string
*/
public function avatar()
{
// Check permission
if (!CurrentSession::$user->permission(Site::CHANGE_AVATAR)) {
throw new HttpMethodNotAllowedException();
}
if (session_check()) {
$avatar = $_FILES['avatar'] ?? null;
$redirect = route('settings.appearance.avatar');
if ($avatar && $avatar['error'] !== UPLOAD_ERR_NO_FILE) {
$upload = $this->handleUpload('avatar', $_FILES['avatar']);
$message = $upload !== null ? $upload : "Changed your avatar!";
} else {
$this->deleteFile('avatar');
$message = "Deleted your avatar!";
}
return view('global/information', compact('message', 'redirect'));
}
return view('settings/appearance/avatar');
}
/**
* Renders the background changing page.
* @return string
*/
public function background()
{
// Check permission
if (!CurrentSession::$user->permission(Site::CHANGE_BACKGROUND)) {
throw new HttpMethodNotAllowedException();
}
if (session_check()) {
$background = $_FILES['background'] ?? null;
$redirect = route('settings.appearance.background');
if ($background && $background['error'] !== UPLOAD_ERR_NO_FILE) {
$upload = $this->handleUpload('background', $_FILES['background']);
$message = $upload !== null ? $upload : "Changed your background!";
} else {
$this->deleteFile('background');
$message = "Deleted your background!";
}
return view('global/information', compact('message', 'redirect'));
}
return view('settings/appearance/background');
}
/**
* Renders the banner changing page.
* @return string
*/
public function header()
{
// Check permission
if (!CurrentSession::$user->permission(Site::CHANGE_HEADER)) {
throw new HttpMethodNotAllowedException();
}
if (session_check()) {
$header = $_FILES['header'] ?? null;
$redirect = route('settings.appearance.header');
if ($header && $header['error'] !== UPLOAD_ERR_NO_FILE) {
$upload = $this->handleUpload('header', $_FILES['header']);
$message = $upload !== null ? $upload : "Changed your header!";
} else {
$this->deleteFile('header');
$message = "Deleted your header!";
}
return view('global/information', compact('message', 'redirect'));
}
return view('settings/appearance/header');
}
/**
* Renders the userpage editing page.
*/

View file

@ -55,15 +55,6 @@ class Controller extends BaseController
}
// Appearance
if (CurrentSession::$user->permission(Site::CHANGE_AVATAR)) {
$nav["Appearance"]["Avatar"] = route('settings.appearance.avatar');
}
if (CurrentSession::$user->permission(Site::CHANGE_BACKGROUND)) {
$nav["Appearance"]["Background"] = route('settings.appearance.background');
}
if (CurrentSession::$user->permission(Site::CHANGE_HEADER)) {
$nav["Appearance"]["Header"] = route('settings.appearance.header');
}
if ((
CurrentSession::$user->page
&& CurrentSession::$user->permission(Site::CHANGE_USERPAGE)

View file

@ -6,6 +6,7 @@
namespace Sakura\Controllers;
use Phroute\Phroute\Exception\HttpMethodNotAllowedException;
use Sakura\Config;
use Sakura\CurrentSession;
use Sakura\DB;
@ -31,7 +32,7 @@ class UserController extends Controller
$profile = User::construct($id);
// If the user id is zero check if there was a namechange
if ($profile->id == 0) {
if ($profile->id === 0) {
// Fetch from username_history
$check = DB::table('username_history')
->where('username_old_clean', clean_string($id, true, true))
@ -40,9 +41,8 @@ class UserController extends Controller
// Redirect if so
if ($check) {
$message = "This user changed their username! Redirecting you to their new profile.";
$redirect = route('user.profile', $check->user_id);
return view('global/information', compact('message', 'redirect'));
redirect(route('user.profile', $check->user_id));
return;
}
}
@ -52,13 +52,14 @@ class UserController extends Controller
/**
* Display the memberlist.
* @param int $rank
* @throws HttpMethodNotAllowedException
* @return string
*/
public function members($rank = null)
{
// Check permission
if (!CurrentSession::$user->permission(Site::VIEW_MEMBERLIST)) {
return view('global/restricted');
throw new HttpMethodNotAllowedException;
}
// Get all ranks
@ -79,10 +80,7 @@ class UserController extends Controller
// Get the active rank
$rank = array_key_exists($rank, $ranks) ? $rank : ($rank ? 0 : intval(config("rank.regular")));
// Get members per page
$membersPerPage = 30;
return view('user/members', compact('ranks', 'rank', 'membersPerPage'));
return view('user/members', compact('ranks', 'rank'));
}
/**

View file

@ -0,0 +1,16 @@
<?php
/**
* Holds an exception class.
* @package Sakura
*/
namespace Sakura\Exceptions;
/**
* Thrown when the config file doesn't exist.
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class FileException extends BaseException
{
}

View file

@ -91,6 +91,12 @@ class Post
*/
public $editUser = null;
/**
* Post deleted?
* @var bool
*/
public $deleted = false;
/**
* Constructor.
* @param int $postId
@ -114,6 +120,7 @@ class Post
$this->editTime = intval($postRow->post_edit_time);
$this->editReason = $postRow->post_edit_reason;
$this->editUser = User::construct($postRow->post_edit_user);
$this->deleted = boolval($postRow->post_deleted);
// Temporary backwards compatible IP storage system
try {
@ -199,10 +206,34 @@ class Post
return new Post($this->id);
}
/**
* Undo deletion.
*/
public function restore()
{
DB::table('posts')
->where('post_id', $this->id)
->update([
'post_deleted' => 0,
]);
}
/**
* delete this.
*/
public function delete()
{
DB::table('posts')
->where('post_id', $this->id)
->update([
'post_deleted' => 1,
]);
}
/**
* DELETE THIS.
*/
public function purge()
{
DB::table('posts')
->where('post_id', $this->id)

View file

@ -124,17 +124,18 @@ max_file_size = 5242880
max_height = 1440
max_width = 2560
; Cover requirements
[file.cover]
; Header requirements
[file.header]
max_file_size = 2097152
max_height = 500
max_width = 2048
; User settings
[user]
; Avatars (relative to public/)
avatar_ban = images/%tplname%-ban.png
; Default avatar, background and header (relative to public/)
avatar_none = images/%tplname%-none.png
background_none = images/pixel.png
header_none = images/pixel.png
; Username constraints
name_min = 3

View file

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Sakura\DB;
class SoftDeleting extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
$schema = DB::getSchemaBuilder();
$schema->table('posts', function (Blueprint $table) {
$table->tinyInteger('post_deleted')
->nullable()
->default(0);
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
$schema = DB::getSchemaBuilder();
$schema->table('posts', function (Blueprint $table) {
$table->dropColumn('post_deleted');
});
}
}

View file

@ -36,7 +36,7 @@
{% if user.isActive %}
<a class="header__user" href="{{ route('user.profile', user.id) }}" style="color: {{ user.colour }}">
<div class="header__username">{{ user.username }}</div>
<div class="header__avatar" style="background-image: url('{{ route('file.avatar', user.id) }}')"></div>
<div class="header__avatar" style="background-image: url('{{ route('user.avatar', user.id) }}')"></div>
</a>
{% else %}
<a class="header__user" href="{{ route('auth.login') }}">

View file

@ -115,7 +115,7 @@
{% block content %}
<div class="profile__content">
<div class="profile__container profile__container--left">
<div class="profile__avatar" style="background-image: url('{{ route('file.avatar', profile.id) }}');"></div>
<div class="profile__avatar" style="background-image: url('{{ route('user.avatar', profile.id) }}');"></div>
<div class="platform profile__platform profile__hierarchies">{#
#}{% for id, data in hierarchies %}{#
#}{% if data.display %}

View file

@ -1,6 +1,6 @@
<li id="comment-{{ comment.id }}">
<div class="comment">
<a class="comment-avatar clean" href="{{ route('user.profile', comment.userData.id) }}" style="background-image: url('{{ route('file.avatar', comment.userData.id) }}');"><span style="color: {{ comment.userData.colour }};">{{ comment.userData.username }}</span></a>
<a class="comment-avatar clean" href="{{ route('user.profile', comment.userData.id) }}" style="background-image: url('{{ route('user.avatar', comment.userData.id) }}');"><span style="color: {{ comment.userData.colour }};">{{ comment.userData.username }}</span></a>
<div class="comment-pointer"></div>
<div class="comment-content">
<div class="comment-controls">
@ -10,7 +10,7 @@
{% else %}
<li><a href="{{ route('user.report', comment.userData.id) }}" class="clean fa fa-exclamation-circle" title="Report"></a></li>
{% endif %}
<li><a href="javascript:void(0);" onclick="commentReply({{ comment.id }}, '{{ session_id() }}', '{{ route('file.avatar', user.id) }}');" class="clean fa fa-reply" title="Reply" id="comment-action-reply-{{ comment.id }}"></a></li>
<li><a href="javascript:void(0);" onclick="commentReply({{ comment.id }}, '{{ session_id() }}', '{{ route('user.avatar', user.id) }}');" class="clean fa fa-reply" title="Reply" id="comment-action-reply-{{ comment.id }}"></a></li>
<li class="shown voting like"><a href="javascript:void(0);" onclick="commentVote({{ comment.id }}, 1);" class="clean"><span class="fa fa-thumbs-up"></span> <span id="comment-{{ comment.id }}-likes">{{ comment.upvotes }}</span></a></li>
<li class="shown voting dislike"><a href="javascript:void(0);" onclick="commentVote({{ comment.id }}, 0);" class="clean"><span class="fa fa-thumbs-down"></span> <span id="comment-{{ comment.id }}-dislikes">{{ comment.downvotes }}</span></a></li>
</ul>

View file

@ -2,7 +2,7 @@
<div class="comment-input-section">
{% if user.isActive %}
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ route('file.avatar', user.id) }}');"></div>
<div class="comment-avatar" style="background-image: url('{{ route('user.avatar', user.id) }}');"></div>
<div class="comment-pointer"></div>
<textarea class="comment-content" name="text" placeholder="Join the conversation..."></textarea>
<button class="comment-submit new" name="session" value="{{ session_id() }}" onclick="commentPost(this.parentNode, '{{ route('comments.category.post', commentsCategory) }}');">&#xf1d8;</button>
@ -65,7 +65,7 @@
var avatar = document.createElement('a');
avatar.className = 'comment-avatar clean';
avatar.href = "{{ route('user.profile', 1) }}".replace(1, obj.user);
avatar.style.backgroundImage = "url('{{ route('file.avatar', 1) }}')".replace(1, obj.user);
avatar.style.backgroundImage = "url('{{ route('user.avatar', 1) }}')".replace(1, obj.user);
inner.appendChild(avatar);
var pointer = document.createElement('div');
@ -104,7 +104,7 @@
controlsReply.href = 'javascript:void(0);';
controlsReply.title = 'Reply';
controlsReply.className = 'clean fa fa-reply';
controlsReply.setAttribute('onclick', 'commentReply(' + obj.id + ', "{{ session_id() }}", "{{ route("file.avatar", user.id) }}");');
controlsReply.setAttribute('onclick', 'commentReply(' + obj.id + ', "{{ session_id() }}", "{{ route("user.avatar", user.id) }}");');
controlsReplyContainer.appendChild(controlsReply);
controlsInner.appendChild(controlsReplyContainer);

View file

@ -1,7 +1,7 @@
<div id="indexPanel">
{% if user.isActive %}
<div class="user-container" style="background-image: url({{ route('user.header', user.id) }});">
<div class="default-avatar-setting user-container-avatar" style="background-image: url({{ route('file.avatar', user.id) }}); box-shadow: 0 0 5px {{ user.colour }};"><a href="{{ route('settings.appearance.avatar') }}" class="clean" style="display: block; height: 100%; width: 100%;"></a></div>
<div class="default-avatar-setting user-container-avatar" style="background-image: url({{ route('user.avatar', user.id) }}); box-shadow: 0 0 5px {{ user.colour }};"><a href="{{ route('user.profile', user.id) }}" class="clean" style="display: block; height: 100%; width: 100%;"></a></div>
<div class="user-container-info">
<a href="{{ route('user.profile', user.id) }}" class="clean"><h1 style="color: {{ user.colour }}; text-shadow: 0 0 7px {% if user.colour != 'inherit' %}{{ user.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;">{{ user.username }}</h1></a>
{% set friendRequests = user.friends(-1, true)|length %}

View file

@ -2,7 +2,7 @@
<div class="news-body">
<a class="no-underline" href="{{ route('user.profile', post.userData.id) }}">
<div class="news-poster">
<img src="{{ route('file.avatar', post.userData.id) }}" alt="{{ post.userData.username }}" class="default-avatar-setting">
<img src="{{ route('user.avatar', post.userData.id) }}" alt="{{ post.userData.username }}" class="default-avatar-setting">
<h1 style="color: {{ post.userData.colour }}; text-shadow: 0 0 7px {% if post.userData.colour != 'inherit' %}{{ post.userData.colour }}{% else %}#222{% endif %}; padding: 0 0 10px;">{{ post.userData.username }}</h1>
</div>
</a>

View file

@ -46,7 +46,7 @@
{% if activePoster.id %}
<a class="clean" href="{{ route('user.profile', activePoster.id) }}">
<div class="user-container" style="background-image: url({{ route('user.header', activePoster.id) }});">
<div class="default-avatar-setting user-container-avatar" style="background-image: url({{ route('file.avatar', activePoster.id) }}); box-shadow: 0 0 5px #{% if activePoster.isOnline %}484{% else %}844{% endif %};"></div>
<div class="default-avatar-setting user-container-avatar" style="background-image: url({{ route('user.avatar', activePoster.id) }}); box-shadow: 0 0 5px #{% if activePoster.isOnline %}484{% else %}844{% endif %};"></div>
<div class="user-container-info">
<h1 style="color: {{ activePoster.colour }}; text-shadow: 0 0 7px {% if activePoster.colour != 'inherit' %}{{ activePoster.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;" {% if activePoster.getUsernameHistory %} title="Known as {{ activePoster.getUsernameHistory[0].username_old }} before {{ activePoster.getUsernameHistory[0].change_time|date(config('general.date_format')) }}." {% endif %}>{{ activePoster.username }}</h1>
{% if activePoster.isPremium %}<img src="/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;"> {% endif %}<img src="/images/flags/{{ activePoster.country|lower }}.png" alt="{{ activePoster.country }}" style="vertical-align: middle;" title="{{ activePoster.country(true) }}"> <span style="font-size: .8em;">{{ activePoster.title }}</span>

View file

@ -80,7 +80,7 @@
<tr class="post" id="p{{ post.id }}">
<td class="userpanel">
{% if not post.poster.permission(constant('Sakura\\Perms\\Site::DEACTIVATED')) or post.poster.permission(constant('Sakura\\Perms\\Site::RESTRICTED')) %}<a href="{{ route('user.profile', post.poster.id) }}" class="default username" style="color: {{ post.poster.colour }}; text-shadow: 0 0 5px {% if post.poster.colour != 'inherit' %}{{ post.poster.colour }}{% else %}#222{% endif %};" title="Go to {{ post.poster.username }}'s profile">{{ post.poster.username }}</a>
<img src="{{ route('file.avatar', post.poster.id) }}" alt="{{ post.poster.username }}" class="avatar" style="box-shadow: 0 3px 7px #{% if post.poster.isOnline %}484{% else %}844{% endif %};">
<img src="{{ route('user.avatar', post.poster.id) }}" alt="{{ post.poster.username }}" class="avatar" style="box-shadow: 0 3px 7px #{% if post.poster.isOnline %}484{% else %}844{% endif %};">
{% else %}
<a class="username">[deleted user]</a>
{% endif %}
@ -136,7 +136,7 @@
<tr class="post" id="postingPreview" style="display: none;">
<td class="userpanel">
<a class="default username" href="{{ route('user.profile', user.id) }}" style="color: {{ user.colour }}; text-shadow: 0 0 5px {% if user.colour != 'inherit' %}{{ user.colour }}{% else %}#222{% endif %};" title="Go to {{ user.username }}'s profile">{{ user.username }}</a>
<img src="{{ route('file.avatar', user.id) }}" alt="{{ user.username }}" class="avatar" style="box-shadow: 0 3px 7px #484;">
<img src="{{ route('user.avatar', user.id) }}" alt="{{ user.username }}" class="avatar" style="box-shadow: 0 3px 7px #484;">
<div class="userdata">
<div class="usertitle">{{ user.title }}</div>
<img src="/images/tenshi.png" alt="Tenshi"{% if not user.isPremium %} style="opacity: 0;"{% endif %}> <img src="/images/flags/{{ user.country|lower }}.png" alt="{{ user.country(true) }}">{% if user.id == (topic.posts|first).poster.id %} <img src="/images/op.png" alt="OP" title="Original Poster">{% endif %}

View file

@ -1,22 +0,0 @@
{% extends 'master.twig' %}
{% set title = 'Confirmation' %}
{% block content %}
<div class="content standalone">
<div>
<h1>{% block header %}Confirmation{% endblock %}</h1>
<hr class="default">
{{ message }}
<form method="post" action="{{ server['REQUEST_URI'] }}" id="confirmationForm">
<input type="hidden" name="sessionid" value="{{ session_id() }}">
<input type="hidden" name="timestamp" value="{{ date().timestamp }}">
{% for key,value in conditions %}
<input type="hidden" name="{{ key }}" value="{{ value }}">
{% endfor %}
<input type="submit" class="inputStyling" name="yes" value="Yes">
<input type="submit" class="inputStyling" name="no" value="No">
</form>
</div>
</div>
{% endblock %}

View file

@ -1,12 +0,0 @@
{% extends 'master.twig' %}
{% set title = 'Restricted' %}
{% block content %}
<div class="content standalone">
<div>
<h1>You aren't allowed to view this page!</h1>
Please make sure that you're logged in and are supposed to be able to access this page. If you think this was a mistake please contact a staff member.
</div>
</div>
{% endblock %}

View file

@ -47,7 +47,7 @@
<div class="menu-ucp" id="navMenuUser">
<!-- User menu, displayed on right side of the bar. -->
{% if user.isActive %}
<a class="menu-item avatar" href="{{ route('user.profile', user.id) }}" title="Logged in as {{ user.username }}" style="background-image: url('{{ route('file.avatar', user.id) }}'); width: auto; color: {{ user.colour }}; border-color: {{ user.colour }}; font-weight: 700;"></a>
<a class="menu-item avatar" href="{{ route('user.profile', user.id) }}" title="Logged in as {{ user.username }}" style="background-image: url('{{ route('user.avatar', user.id) }}'); width: auto; color: {{ user.colour }}; border-color: {{ user.colour }}; font-weight: 700;"></a>
{#<a class="menu-item fa-envelope" href="#" title="Messages"></a>#}
{% if user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
<a class="menu-item fa-gavel" href="{{ route('manage.index') }}" title="Manage"></a>
@ -64,7 +64,7 @@
<div id="contentwrapper">
<div id="notifications"></div>
{% if profile is defined ? profile.background : (user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) and (user.backgroundSitewide or showBG) and user.background) %}
<div id="userBackground" style="background-image: url('{{ route('file.background', (profile is defined ? profile : user).id) }}');"></div>
<div id="userBackground" style="background-image: url('{{ route('user.background', (profile is defined ? profile : user).id) }}');"></div>
{% endif %}
{% if not user.isActive and server['REQUEST_URI'] != route('auth.login') %}
<div class="headerLoginContainer">

View file

@ -6,6 +6,27 @@
{% include 'elements/indexPanel.twig' %}
</div>
<div class="content-left content-column">
<div class="head">Temporary avatar upload test form!!</div>
<form enctype="multipart/form-data" method="post" action="{{ route('user.avatar', user.id) }}" style="margin: 1em">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ config('file.avatar.max_file_size') }}">
<input type="hidden" name="session" value="{{ session_id() }}">
<input type="file" name="file">
<button>upload</button>
</form>
<div class="head">Temporary <del>avatar</del> background upload test form!!</div>
<form enctype="multipart/form-data" method="post" action="{{ route('user.background', user.id) }}" style="margin: 1em">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ config('file.background.max_file_size') }}">
<input type="hidden" name="session" value="{{ session_id() }}">
<input type="file" name="file">
<button>upload</button>
</form>
<div class="head">Temporary <del>avatar background</del> header upload test form!!</div>
<form enctype="multipart/form-data" method="post" action="{{ route('user.header', user.id) }}" style="margin: 1em">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ config('file.header.max_file_size') }}">
<input type="hidden" name="session" value="{{ session_id() }}">
<input type="file" name="file">
<button>upload</button>
</form>
<div class="head">News</div>
{% for post in news %}
{% include 'elements/newsPost.twig' %}

View file

@ -10,7 +10,7 @@
{% for friend in friends[get.page|default(1) - 1] %}
<div class="friend-container" id="friendslist-friend-{{ friend.id }}">
<a class="friends-list-data clean" href="{{ route('user.profile', friend.id) }}">
<img src="{{ route('file.avatar', friend.id) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;">
<img src="{{ route('user.avatar', friend.id) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;">
<div class="friends-list-name" style="color: {{ friend.colour }};">{{ friend.username }}</div>
</a>
</div>

View file

@ -0,0 +1,11 @@
{% extends 'master.twig' %}
{% set title = 'Farewell!' %}
{% block content %}
<div class="content standalone" style="text-align: center;">
<h1 class="stylised" style="margin: 1em auto;">Farewell!</h1>
<h1 class="fa fa-frown-o stylised" style="font-size: 20em;"></h1>
<h3>Remember that you can reactivate your account anytime if you decide to come back!</h3>
</div>
{% endblock %}

View file

@ -1,27 +0,0 @@
{% extends 'settings/appearance/master.twig' %}
{% set mode = 'Avatar' %}
{% block description %}
<p>Maximum image size is {{ config('file.avatar.max_width') }}x{{ config('file.avatar.max_height') }} and can't be larger than {{ config('file.avatar.max_file_size')|byte_symbol }}.</p>
{% endblock %}
{% block settingsContent %}
<form enctype="multipart/form-data" method="post" action="{{ route('settings.appearance.avatar') }}">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ config('file.avatar.max_file_size') }}">
<div style="text-align: center;">
<div>
<img src="{{ route('file.avatar', user.id) }}" alt="Your Avatar" class="default-avatar-setting">
</div>
<div>
<input type="file" name="avatar">
<div style="font-size: .8em;">
(Leave upload box empty to remove avatar)
</div>
</div>
<div>
<button value="{{ session_id() }}" name="session" class="inputStyling">Upload</button>
</div>
</div>
</form>
{% endblock %}

View file

@ -1,25 +0,0 @@
{% extends 'settings/appearance/master.twig' %}
{% set mode = 'Background' %}
{% set showBG = true %}
{% block description %}
<p>Maximum image size is {{ config('file.background.max_width') }}x{{ config('file.background.max_height') }} and can't be larger than {{ config('file.background.max_file_size')|byte_symbol }}.</p>
{% endblock %}
{% block settingsContent %}
<form enctype="multipart/form-data" method="post" action="{{ route('settings.appearance.background') }}">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ config('file.background.max_file_size') }}">
<div style="text-align: center;">
<div>
<input type="file" name="background">
<div style="font-size: .8em;">
(Leave upload box empty to remove background)
</div>
</div>
<div>
<button value="{{ session_id() }}" name="session" class="inputStyling">Upload</button>
</div>
</div>
</form>
{% endblock %}

View file

@ -1,27 +0,0 @@
{% extends 'settings/appearance/master.twig' %}
{% set mode = 'Header' %}
{% block description %}
<p>Maximum image size is {{ config('file.cover.max_width') }}x{{ config('file.cover.max_height') }} and can't be larger than {{ config('file.cover.max_file_size')|byte_symbol }}.</p>
{% endblock %}
{% block settingsContent %}
<form enctype="multipart/form-data" method="post" action="{{ route('settings.appearance.header') }}">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ config('file.cover.max_file_size') }}">
<div style="text-align: center;">
<div>
<img src="{{ route('user.header', user.id) }}" alt="Your Header" class="default-avatar-setting" style="max-width: 90%; max-height: 90%;">
</div>
<div>
<input type="file" name="header">
<div style="font-size: .8em;">
(Leave upload box empty to remove header)
</div>
</div>
<div>
<button value="{{ session_id() }}" name="session" class="inputStyling">Upload</button>
</div>
</div>
</form>
{% endblock %}

View file

@ -17,7 +17,7 @@
{% for friend in friends[get.page|default(1) - 1] %}
<div class="friend-container" id="friendslist-friend-{{ friend.id }}">
<a class="friends-list-data clean" href="{{ route('user.profile', friend.id) }}">
<img src="{{ route('file.avatar', friend.id) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;">
<img src="{{ route('user.avatar', friend.id) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;">
<div class="friends-list-name" style="color: {{ friend.colour }};">{{ friend.username }}</div>
</a>
<div class="friends-list-actions">

View file

@ -17,7 +17,7 @@
{% for friend in friends[get.page|default(1) - 1] %}
<div class="friend-container" id="friend-{{ friend.id }}">
<a class="friends-list-data clean" href="{{ route('user.profile', friend.id) }}">
<img src="{{ route('file.avatar', friend.id) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;">
<img src="{{ route('user.avatar', friend.id) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;">
<div class="friends-list-name" style="color: {{ friend.colour }};">{{ friend.username }}</div>
</a>
<div class="friends-list-actions">

View file

@ -13,7 +13,7 @@
{% if notfound %}The requested rank could not be found!{% else %}{{ ranks[rank].description }}{% endif %}
{% endset %}
{% set users = ranks[rank].users|batch(membersPerPage) %}
{% set users = ranks[rank].users|batch(30) %}
{% set currPage = get.page|default(1) - 1 %}
@ -99,7 +99,7 @@
{% for user in users[currPage] %}
<a href="{{ route('user.profile', user.id) }}">{# These comment tags are here to prevent the link extending too far
#}<div class="userBox" id="u{{ user.id }}">{#
#}<img src="/images/pixel.png" alt="{{ user.username }}" style="background: url('{{ route('file.avatar', user.id) }}') no-repeat center / contain;">{#
#}<img src="/images/pixel.png" alt="{{ user.username }}" style="background: url('{{ route('user.avatar', user.id) }}') no-repeat center / contain;">{#
#}<span class="userBoxUserName" style="color: {{ user.colour }};">{#
#}{{ user.username }}{#
#}</span>{#

View file

@ -142,7 +142,7 @@
<div class="new-profile-container">
<div class="new-profile-header" style="background-image: url({{ route('user.header', profile.id) }});">
<div class="new-profile-info">
<div class="default-avatar-setting new-profile-avatar" style="background-image: url({{ route('file.avatar', profile.id) }}); box-shadow: 0 0 5px #{% if profile.isOnline %}484{% else %}844{% endif %};"></div>
<div class="default-avatar-setting new-profile-avatar" style="background-image: url({{ route('user.avatar', profile.id) }}); box-shadow: 0 0 5px #{% if profile.isOnline %}484{% else %}844{% endif %};"></div>
<div class="new-profile-username">
<h1 style="color: {{ profile.colour }}; text-shadow: 0 0 7px {% if profile.colour != 'inherit' %}{{ profile.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;" {% if profile.getUsernameHistory %} title="Known as {{ profile.getUsernameHistory[0].username_old }} before {{ profile.getUsernameHistory[0].change_time|date(config('general.date_format')) }}." {% endif %}>{{ profile.username }}</h1>
{% if profile.isPremium %}<img src="/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;"> {% endif %}<img src="/images/flags/{{ profile.country|lower }}.png" alt="{{ profile.country }}" style="vertical-align: middle;" title="{{ profile.country(true) }}"> <span style="font-size: .8em;">{{ profile.title }}</span>

View file

@ -163,7 +163,18 @@ Routerv1::group(['before' => 'maintenance'], function () {
Routerv1::group(['prefix' => 'u'], function () {
Routerv1::get('/{id}', 'UserController@profile', 'user.profile');
Routerv1::get('/{id}/report', 'UserController@report', 'user.report');
Routerv1::get('/{id}/avatar', 'FileController@avatar', 'user.avatar');
Routerv1::post('/{id}/avatar', 'FileController@avatar', 'user.avatar');
Routerv1::delete('/{id}/avatar', 'FileController@avatar', 'user.avatar');
Routerv1::get('/{id}/background', 'FileController@background', 'user.background');
Routerv1::post('/{id}/background', 'FileController@background', 'user.background');
Routerv1::delete('/{id}/background', 'FileController@background', 'user.background');
Routerv1::get('/{id}/header', 'FileController@header', 'user.header');
Routerv1::post('/{id}/header', 'FileController@header', 'user.header');
Routerv1::delete('/{id}/header', 'FileController@header', 'user.header');
});
// Notifications
@ -185,10 +196,6 @@ Routerv1::group(['before' => 'maintenance'], function () {
Routerv1::post('/{id:i}/remove', 'FriendsController@remove', 'friends.remove');
});
// Files
Routerv1::get('/a/{id}', 'FileController@avatar', 'file.avatar');
Routerv1::get('/bg/{id}', 'FileController@background', 'file.background');
// Premium
Routerv1::group(['prefix' => 'support', 'before' => 'loginCheck'], function () {
Routerv1::get('/', 'PremiumController@index', 'premium.index');
@ -256,12 +263,6 @@ Routerv1::group(['before' => 'maintenance'], function () {
return header("Location: {$route}");
});
Routerv1::get('/avatar', 'Settings.AppearanceController@avatar', 'settings.appearance.avatar');
Routerv1::post('/avatar', 'Settings.AppearanceController@avatar', 'settings.appearance.avatar');
Routerv1::get('/background', 'Settings.AppearanceController@background', 'settings.appearance.background');
Routerv1::post('/background', 'Settings.AppearanceController@background', 'settings.appearance.background');
Routerv1::get('/header', 'Settings.AppearanceController@header', 'settings.appearance.header');
Routerv1::post('/header', 'Settings.AppearanceController@header', 'settings.appearance.header');
Routerv1::get('/userpage', 'Settings.AppearanceController@userpage', 'settings.appearance.userpage');
Routerv1::post('/userpage', 'Settings.AppearanceController@userpage', 'settings.appearance.userpage');
Routerv1::get('/signature', 'Settings.AppearanceController@signature', 'settings.appearance.signature');

View file

@ -73,6 +73,13 @@ function clean_string($string, $lower = false, $noSpecial = false, $replaceSpeci
return $string;
}
// Redirect with turbolinks header
function redirect($url)
{
header("Turbolinks-Location: {$url}");
header("Location: {$url}");
}
function check_mx_record($email)
{
// Get the domain from the e-mail address
@ -126,12 +133,10 @@ function get_country_name($code)
}
}
// Count the amount of unique characters in the password string and calculate the entropy
function password_entropy($password)
{
$password = utf8_decode($password);
// Count the amount of unique characters in the password string and calculate the entropy
return count(count_chars($password, 1)) * log(256, 2);
return count(count_chars(utf8_decode($password), 1)) * log(256, 2);
}
function byte_symbol($bytes)