fully routered!

This commit is contained in:
flash 2016-04-25 01:26:36 +02:00
parent 391ecbda59
commit 86072cf18d
9 changed files with 148 additions and 692 deletions

View file

@ -8,7 +8,9 @@
namespace Sakura\Controllers\Settings;
use Sakura\ActiveUser;
use Sakura\Config;
use Sakura\DB;
use Sakura\File;
use Sakura\Perms\Site;
use Sakura\Router;
use Sakura\Template;
@ -21,6 +23,97 @@ use Sakura\Template;
*/
class AppearanceController extends Controller
{
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!";
}
// Check dimensions
$minWidth = Config::get("{$mode}_min_width");
$minHeight = Config::get("{$mode}_min_height");
$maxWidth = Config::get("{$mode}_max_width");
$maxHeight = Config::get("{$mode}_max_height");
if ($meta[0] < $minWidth
|| $meta[1] < $minHeight
|| $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::get("{$mode}_max_fsize");
if (filesize($tmpName) > $maxFileSize) {
$maxSizeFmt = byte_symbol($maxFileSize);
return "Your image is not allowed to be larger than {$maxSizeFmt}!";
}
$userId = ActiveUser::$user->id;
$ext = image_type_to_extension($meta[2]);
$filename = "{$mode}_{$userId}.{$ext}";
// Create the file
$file = File::create(file_get_contents($tmpName), $filename, ActiveUser::$user);
// Delete the old file
$this->deleteFile($mode);
$column = "user_{$mode}";
// Save new avatar
DB::table('users')
->where('user_id', ActiveUser::$user->id)
->update([
$column => $file->id,
]);
return null;
}
public function deleteFile($mode)
{
(new File(ActiveUser::$user->{$mode}))->delete();
}
public function avatar()
{
// Check permission
@ -33,6 +126,25 @@ class AppearanceController extends Controller
return Template::render('global/information');
}
$session = $_POST['session'] ?? null;
if ($session) {
$avatar = $_FILES['avatar'] ?? null;
$redirect = Router::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!";
}
Template::vars(compact('message', 'redirect'));
return Template::render('global/information');
}
return Template::render('settings/appearance/avatar');
}
@ -48,6 +160,25 @@ class AppearanceController extends Controller
return Template::render('global/information');
}
$session = $_POST['session'] ?? null;
if ($session) {
$background = $_FILES['background'] ?? null;
$redirect = Router::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!";
}
Template::vars(compact('message', 'redirect'));
return Template::render('global/information');
}
return Template::render('settings/appearance/background');
}
@ -64,7 +195,23 @@ class AppearanceController extends Controller
}
$session = $_POST['session'] ?? null;
$header = $_POST['header'] ?? null;
if ($session) {
$header = $_FILES['header'] ?? null;
$redirect = Router::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!";
}
Template::vars(compact('message', 'redirect'));
return Template::render('global/information');
}
return Template::render('settings/appearance/header');
}

View file

@ -12,7 +12,6 @@ use Sakura\Controllers\Controller as BaseController;
use Sakura\Perms\Site;
use Sakura\Router;
use Sakura\Template;
use Sakura\Urls;
/**
* Base controller (which other controllers should extend on).
@ -22,26 +21,13 @@ use Sakura\Urls;
*/
class Controller extends BaseController
{
private $urls;
public function __construct()
{
$this->urls = new Urls();
$navigation = $this->navigation();
Template::vars(compact('navigation'));
}
public function go($location)
{
$location = explode('.', $location);
$url = $this->urls->format('SETTING_MODE', $location, null, false);
return header("Location: {$url}");
}
public function navigation()
{
$nav = [];

View file

@ -1,42 +0,0 @@
<?php
/**
* Holds the url generation class.
*
* @package Sakura
*/
namespace Sakura;
/**
* URL generator.
*
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class Urls
{
/**
* Format a URL.
*
* @param string $lid doesn't do anything
* @param array $args [category, mode]
* @param bool $rewrite doesn't do anything either
* @param bool $b hackjob for the settings panel
*
* @return null|string url
*/
public function format($lid, $args = [], $rewrite = null, $b = true)
{
if ($b) {
$a = implode('.', $args);
$a = str_replace("usertitle", "title", $a);
return Router::route("settings.{$a}");
}
// Format urls
$formatted = vsprintf('/settings.php?cat=%s&mode=%s', $args);
// Return the formatted url
return $formatted;
}
}

View file

@ -1,550 +0,0 @@
<?php
/*
* Sakura User Settings
*/
// Declare Namespace
namespace Sakura;
use Sakura\Perms\Site;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php';
// Legacy support!!!!!!!!!
$renderData = [];
$currentUser = ActiveUser::$user;
if (isset($_POST['submit']) && isset($_POST['submit'])) {
$continue = true;
// Set redirector
$redirect = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('SETTINGS_INDEX');
// Check if the user is logged in
if (!ActiveUser::$user->id || !$continue) {
$renderData['page'] = [
'redirect' => '/login',
'message' => 'You must be logged in to edit your settings.',
'success' => 0,
];
$continue = false;
}
// Check session variables
if (!isset($_POST['timestamp'])
|| !isset($_POST['mode'])
|| $_POST['timestamp'] < time() - 1000
|| !isset($_POST['sessid'])
|| $_POST['sessid'] != session_id()
|| !$continue) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Your session has expired, please refresh the page and try again.',
'success' => 0,
];
$continue = false;
}
// Change settings
if ($continue) {
// Switch to the correct mode
switch ($_POST['mode']) {
// Avatar & Background
case 'avatar':
case 'background':
case 'header':
// Assign $_POST['mode'] to a $mode variable because I ain't typin that more than once
$mode = $_POST['mode'];
// Assign the correct column and title to a variable
switch ($mode) {
case 'background':
$column = 'user_background';
$msgTitle = 'Background';
$current = $currentUser->background;
$permission = $currentUser->permission(Site::CHANGE_BACKGROUND);
break;
case 'header':
$column = 'user_header';
$msgTitle = 'Header';
$current = $currentUser->header;
$permission = $currentUser->permission(Site::CHANGE_HEADER);
break;
case 'avatar':
default:
$column = 'user_avatar';
$msgTitle = 'Avatar';
$current = $currentUser->avatar;
$permission = $currentUser->permission(Site::CHANGE_AVATAR);
}
// Check if the user has the permissions to go ahead
if (!$permission) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You are not allowed to alter your ' . strtolower($msgTitle) . '.',
'success' => 0,
];
break;
}
// Set path variables
$filename = strtolower($msgTitle) . '_' . $currentUser->id;
// Check if $_FILES is set
if (!isset($_FILES[$mode]) && empty($_FILES[$mode])) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'No file was uploaded.',
'success' => 0,
];
break;
}
// Check if the upload went properly
if ($_FILES[$mode]['error'] !== UPLOAD_ERR_OK && $_FILES[$mode]['error'] !== UPLOAD_ERR_NO_FILE) {
// Get the error in text
switch ($_FILES[$mode]['error']) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$msg = 'The uploaded file exceeds the maximum filesize!';
break;
case UPLOAD_ERR_PARTIAL:
$msg = 'The upload was interrupted!';
break;
case UPLOAD_ERR_NO_TMP_DIR:
case UPLOAD_ERR_CANT_WRITE:
$msg = 'Unable to save file to temporary location, contact the administrator!';
break;
case UPLOAD_ERR_EXTENSION:
default:
$msg = 'An unknown exception occurred!';
break;
}
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => $msg,
'success' => 0,
];
break;
}
// Check if we're not in removal mode
if ($_FILES[$mode]['error'] != UPLOAD_ERR_NO_FILE) {
// Get the meta data
$metadata = getimagesize($_FILES[$mode]['tmp_name']);
// Check if the image is actually an image
if (!$metadata) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Uploaded file is not an image.',
'success' => 0,
];
break;
}
// Check if the image is an allowed filetype
if ((($metadata[2] !== IMAGETYPE_GIF)
&& ($metadata[2] !== IMAGETYPE_JPEG)
&& ($metadata[2] !== IMAGETYPE_PNG))) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'This filetype is not allowed.',
'success' => 0,
];
break;
}
// Check if the image is too large
if (($metadata[0] > Config::get($mode . '_max_width')
|| $metadata[1] > Config::get($mode . '_max_height'))) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'The resolution of this picture is too big.',
'success' => 0,
];
break;
}
// Check if the image is too small
if (($metadata[0] < Config::get($mode . '_min_width')
|| $metadata[1] < Config::get($mode . '_min_height'))) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'The resolution of this picture is too small.',
'success' => 0,
];
break;
}
// Check if the file is too large
if ((filesize($_FILES[$mode]['tmp_name']) > Config::get($mode . '_max_fsize'))) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'The filesize of this file is too large.',
'success' => 0,
];
break;
}
}
// Open the old file and remove it
$oldFile = new File($current);
$oldFile->delete();
unset($oldFile);
$fileId = 0;
if ($_FILES[$mode]['error'] != UPLOAD_ERR_NO_FILE) {
// Append extension to filename
$filename .= image_type_to_extension($metadata[2]);
// Store the file
$file = File::create(file_get_contents($_FILES[$mode]['tmp_name']), $filename, $currentUser);
// Assign the file id to a variable
$fileId = $file->id;
}
// Update table
DB::table('users')
->where('user_id', $currentUser->id)
->update([
$column => $fileId,
]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Updated your ' . strtolower($msgTitle) . '!',
'success' => 1,
];
break;
// Fallback
default:
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'The requested method does not exist.',
'success' => 0,
];
break;
}
}
// Print page contents or if the AJAX request is set only display the render data
if (isset($_REQUEST['ajax'])) {
echo $renderData['page']['message'] . '|' .
$renderData['page']['success'] . '|' .
$renderData['page']['redirect'];
} else {
// If not allowed print the restricted page
Template::vars($renderData);
// Print page contents
echo Template::render('global/information');
}
exit;
}
if (ActiveUser::$user->id) {
// Settings page list
$pages = [
'general' => [
'title' => 'General',
'modes' => [
'home' => [
'title' => 'Home',
'description' => [
'Welcome to the Settings Panel.
From here you can monitor, view and update your profile and preferences.',
],
'access' => !$currentUser->permission(Site::DEACTIVATED),
'menu' => true,
],
'profile' => [
'title' => 'Profile',
'description' => [
'These are the external account links etc.
on your profile, shouldn\'t need any additional explanation for this one.',
],
'access' => $currentUser->permission(Site::ALTER_PROFILE),
'menu' => true,
],
'options' => [
'title' => 'Options',
'description' => [
'These are a few personalisation options for the site while you\'re logged in.',
],
'access' => !$currentUser->permission(Site::DEACTIVATED),
'menu' => true,
],
],
],
'friends' => [
'title' => 'Friends',
'modes' => [
'listing' => [
'title' => 'Listing',
'description' => [
'Manage your friends.',
],
'access' => $currentUser->permission(Site::MANAGE_FRIENDS),
'menu' => true,
],
'requests' => [
'title' => 'Requests',
'description' => [
'Handle friend requests.',
],
'access' => $currentUser->permission(Site::MANAGE_FRIENDS),
'menu' => true,
],
],
],
'notifications' => [
'title' => 'Notifications',
'modes' => [
'history' => [
'title' => 'History',
'description' => [
'The history of notifications that have been sent to you in the last month.',
],
'access' => !$currentUser->permission(Site::DEACTIVATED),
'menu' => true,
],
],
],
'appearance' => [
'title' => 'Appearance',
'modes' => [
'avatar' => [
'title' => 'Avatar',
'description' => [
'Your avatar which is displayed all over the site and on your profile.',
'Maximum image size is {{ avatar.max_width }}x{{ avatar.max_height }},
minimum image size is {{ avatar.min_width }}x{{ avatar.min_height }},
maximum file size is {{ avatar.max_size_view }}.',
],
'access' => $currentUser->permission(Site::CHANGE_AVATAR),
'menu' => true,
],
'background' => [
'title' => 'Background',
'description' => [
'The background that is displayed on your profile.',
'Maximum image size is {{ background.max_width }}x{{ background.max_height }},
minimum image size is {{ background.min_width }}x{{ background.min_height }},
maximum file size is {{ background.max_size_view }}.',
],
'access' => $currentUser->permission(Site::CHANGE_BACKGROUND),
'menu' => true,
],
'header' => [
'title' => 'Header',
'description' => [
'The header that is displayed on your profile.',
'Maximum image size is {{ header.max_width }}x{{ header.max_height }},
minimum image size is {{ header.min_width }}x{{ header.min_height }},
maximum file size is {{ header.max_size_view }}.',
],
'access' => $currentUser->permission(Site::CHANGE_HEADER),
'menu' => true,
],
'userpage' => [
'title' => 'Userpage',
'description' => [
'The custom text that is displayed on your profile.',
],
'access' => (
$currentUser->page
&& $currentUser->permission(Site::CHANGE_USERPAGE)
) || $currentUser->permission(Site::CREATE_USERPAGE),
'menu' => true,
],
'signature' => [
'title' => 'Signature',
'description' => [
'This signature is displayed at the end of all your posts (unless you choose not to show it).',
],
'access' => $currentUser->permission(Site::CHANGE_SIGNATURE),
'menu' => true,
],
],
],
'account' => [
'title' => 'Account',
'modes' => [
'email' => [
'title' => 'E-mail address',
'description' => [
'You e-mail address is used for password recovery and stuff like that, we won\'t spam you ;).',
],
'access' => $currentUser->permission(Site::CHANGE_EMAIL),
'menu' => true,
],
'username' => [
'title' => 'Username',
'description' => [
'Probably the biggest part of your identity on a site.',
'<b>You can only change this once every 30 days so choose wisely.</b>',
],
'access' => $currentUser->permission(Site::CHANGE_USERNAME),
'menu' => true,
],
'usertitle' => [
'title' => 'Title',
'description' => [
'That little piece of text displayed under your username on your profile.',
],
'access' => $currentUser->permission(Site::CHANGE_USERTITLE),
'menu' => true,
],
'password' => [
'title' => 'Password',
'description' => [
'Used to authenticate with the site and certain related services.',
],
'access' => $currentUser->permission(Site::CHANGE_PASSWORD),
'menu' => true,
],
'ranks' => [
'title' => 'Ranks',
'description' => [
'Manage what ranks you\'re in and what is set as your main rank.
Your main rank is highlighted.
You get the permissions of all of the ranks you\'re in combined.',
],
'access' => $currentUser->permission(Site::ALTER_RANKS),
'menu' => true,
],
],
],
'advanced' => [
'title' => 'Advanced',
'modes' => [
'sessions' => [
'title' => 'Sessions',
'description' => [
'Session keys are a way of identifying yourself with the system without keeping
your password in memory.',
'If someone finds one of your session keys they could possibly compromise your account,
if you see any sessions here that shouldn\'t be here hit the Kill button to kill the
selected session.',
'If you get logged out after clicking one you\'ve most likely killed your current session,
to make it easier to avoid this from happening your current session is highlighted.',
],
'access' => $currentUser->permission(Site::MANAGE_SESSIONS),
'menu' => true,
],
'deactivate' => [
'title' => 'Deactivate',
'description' => [
'You can deactivate your account here if you want to leave :(.',
],
'access' => $currentUser->permission(Site::DEACTIVATE_ACCOUNT),
'menu' => true,
],
],
],
];
// Current settings page
$category = isset($_GET['cat']) ? (
array_key_exists($_GET['cat'], $pages) ? $_GET['cat'] : false
) : array_keys($pages)[0];
$mode = false;
// Only continue setting mode if $category is true
if ($category) {
$mode = isset($_GET['mode']) && $category ? (
array_key_exists($_GET['mode'], $pages[$category]['modes']) ? $_GET['mode'] : false
) : array_keys($pages[$category]['modes'])[0];
}
// Not found
if (!$category
|| empty($category)
|| !$mode
|| empty($mode)
|| !$pages[$category]['modes'][$mode]['access']) {
header('HTTP/1.0 404 Not Found');
// Set parse variables
Template::vars($renderData);
// Print page contents
echo Template::render('global/notfound');
exit;
}
// Set templates directory
$renderData['templates'] = 'old-settings';
// Render data
$renderData['current'] = $category . '.' . $mode;
// Settings pages
$renderData['pages'] = $pages;
// Page data
$renderData['page'] = [
'category' => $pages[$category]['title'],
'mode' => $pages[$category]['modes'][$mode]['title'],
'description' => $pages[$category]['modes'][$mode]['description'],
];
// Section specific
switch ($category . '.' . $mode) {
// Avatar and background sizes
case 'appearance.avatar':
case 'appearance.background':
case 'appearance.header':
$renderData[$mode] = [
'max_width' => Config::get($mode . '_max_width'),
'max_height' => Config::get($mode . '_max_height'),
'min_width' => Config::get($mode . '_min_width'),
'min_height' => Config::get($mode . '_min_height'),
'max_size' => Config::get($mode . '_max_fsize'),
'max_size_view' => byte_symbol(Config::get($mode . '_max_fsize')),
];
break;
}
// Set parse variables
Template::vars($renderData);
// Print page contents
echo Template::render('meta/settings');
} else {
// If not allowed print the restricted page
Template::vars($renderData);
// Print page contents
echo Template::render('global/restricted');
}

View file

@ -92,9 +92,6 @@ ActiveUser::init(
$_COOKIE[Config::get('cookie_prefix') . 'session'] ?? ''
);
// Create the Urls object
$urls = new Urls();
if (!defined('SAKURA_NO_TPL')) {
// Start templating engine
Template::set(Config::get('site_style'));
@ -111,7 +108,6 @@ if (!defined('SAKURA_NO_TPL')) {
], $_SESSION),
'user' => ActiveUser::$user,
'urls' => $urls,
'get' => $_GET,
'post' => $_POST,

View file

@ -1,13 +0,0 @@
<div class="head">
Navigation
</div>
<div class="right-menu-nav">
{% for catname,category in pages %}
<div>{{ category.title }}</div>
{% for mname,mode in category.modes %}
{% if mode.access and mode.menu %}
<a href="{{ urls.format('SETTING_MODE', [catname, mname]) }}">{{ mode.title }}</a>
{% endif %}
{% endfor %}
{% endfor %}
</div>

View file

@ -1,20 +0,0 @@
<form enctype="multipart/form-data" method="post" action="{{ setting.action }}">
<input type="hidden" name="sessid" value="{{ session_id() }}" />
<input type="hidden" name="timestamp" value="{{ date().timestamp }}" />
<input type="hidden" name="mode" value="avatar" />
<input type="hidden" name="MAX_FILE_SIZE" value="{{ avatar.max_size }}" />
<div style="text-align: center;">
<div>
<img src="/a/{{ 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>
<input type="submit" value="Submit" name="submit" class="inputStyling" />
</div>
</div>
</form>

View file

@ -1,24 +0,0 @@
{% if user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) %}
<form enctype="multipart/form-data" method="post" action="{{ setting.action }}">
<input type="hidden" name="sessid" value="{{ session_id() }}" />
<input type="hidden" name="timestamp" value="{{ date().timestamp }}" />
<input type="hidden" name="mode" value="background" />
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}" />
<div style="text-align: center;">
<div>
<img src="/bg/{{ user.id }}" alt="Your Background" class="default-avatar-setting" style="max-width: 90%; max-height: 90%;" />
</div>
<div>
<input type="file" name="background" />
<div style="font-size: .8em;">
(Leave upload box empty to remove background)
</div>
</div>
<div>
<input type="submit" value="Submit" name="submit" class="inputStyling" />
</div>
</div>
</form>
{% else %}
<h1 class="stylised" style="margin: 2em auto; text-align: center;">You do not have the permission to change your background.</h1>
{% endif %}

View file

@ -1,24 +0,0 @@
{% if user.permission(constant('Sakura\\Perms\\Site::CHANGE_HEADER')) %}
<form enctype="multipart/form-data" method="post" action="{{ setting.action }}">
<input type="hidden" name="sessid" value="{{ session_id() }}" />
<input type="hidden" name="timestamp" value="{{ date().timestamp }}" />
<input type="hidden" name="mode" value="header" />
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}" />
<div style="text-align: center;">
<div>
<img src="/u/{{ user.id }}/header" 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>
{% else %}
<h1 class="stylised" style="margin: 2em auto; text-align: center;">You do not have the permission to change your header.</h1>
{% endif %}