r20160227

This commit is contained in:
Pachira 2016-02-27 17:46:16 +01:00
parent bca6c5be99
commit d55ae7e936
30 changed files with 358 additions and 551 deletions

View file

@ -1,24 +0,0 @@
<?php
/**
* Holds the auth controllers.
*
* @package Sakura
*/
namespace Sakura\Controllers;
use Sakura\Template;
/**
* Authentication controllers.
*
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class Auth extends Controller
{
public function login()
{
return Template::render('main/login');
}
}

View file

@ -0,0 +1,178 @@
<?php
/**
* Holds the auth controllers.
*
* @package Sakura
*/
namespace Sakura\Controllers;
use Sakura\Config;
use Sakura\DB;
use Sakura\Hashing;
use Sakura\Net;
use Sakura\Perms\Site;
use Sakura\Router;
use Sakura\Session;
use Sakura\Template;
use Sakura\User;
use Sakura\Users;
use Sakura\Utils;
/**
* Authentication controllers.
*
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class AuthController extends Controller
{
protected function touchRateLimit($user, $mode = 0)
{
DB::table('login_attempts')
->insert([
'attempt_success' => $mode,
'attempt_timestamp' => time(),
'attempt_ip' => Net::pton(Net::IP()),
'user_id' => $user,
]);
}
public function logout()
{
// Check if user is logged in
$check = Users::checkLogin();
if (!$check || !isset($_REQUEST['s']) || $_REQUEST['s'] != session_id()) {
$message = 'Something happened! This probably happened because you went here without being logged in.';
$redirect = (isset($_REQUEST['redirect']) ? $_REQUEST['redirect'] : Router::route('main.index'));
Template::vars(['page' => ['success' => 0, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
// Destroy the active session
(new Session($check[0], $check[1]))->destroy();
// Return true indicating a successful logout
$message = 'Goodbye!';
$redirect = Router::route('auth.login');
Template::vars(['page' => ['success' => 1, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
public function loginGet()
{
return Template::render('main/login');
}
public function loginPost()
{
// Preliminarily set login to failed
$success = 0;
$redirect = Router::route('auth.login');
// Check if authentication is disallowed
if (Config::get('lock_authentication')) {
$message = 'Logging in is disabled for security checkups! Try again later.';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
// Get request variables
$username = isset($_REQUEST['username']) ? $_REQUEST['username'] : null;
$password = isset($_REQUEST['password']) ? $_REQUEST['password'] : null;
$remember = isset($_REQUEST['remember']);
// Check if we haven't hit the rate limit
$rates = DB::table('login_attempts')
->where('attempt_ip', Net::pton(Net::IP()))
->where('attempt_timestamp', '>', time() - 1800)
->where('attempt_success', '0')
->count();
if ($rates > 4) {
$message = 'Your have hit the login rate limit, try again later.';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
// Get account data
$user = User::construct(Utils::cleanString($username, true, true));
// Check if the user that's trying to log in actually exists
if ($user->id === 0) {
$this->touchRateLimit($user->id);
$message = 'The user you tried to log into does not exist.';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
// Validate password
switch ($user->passwordAlgo) {
// Disabled
case 'disabled':
$this->touchRateLimit($user->id);
$message = 'Logging into this account is disabled.';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
// Default hashing method
default:
if (!Hashing::validatePassword($password, [
$user->passwordAlgo,
$user->passwordIter,
$user->passwordSalt,
$user->passwordHash,
])) {
$this->touchRateLimit($user->id);
$message = 'The password you entered was invalid.';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
}
// Check if the user has the required privs to log in
if ($user->permission(Site::DEACTIVATED)) {
$this->touchRateLimit($user->id);
$message = 'Your account does not have the required permissions to log in.';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
// Create a new session
$session = new Session($user->id);
// Generate a session key
$sessionKey = $session->create($remember);
// User ID cookie
setcookie(
Config::get('cookie_prefix') . 'id',
$user->id,
time() + 604800,
Config::get('cookie_path')
);
// Session ID cookie
setcookie(
Config::get('cookie_prefix') . 'session',
$sessionKey,
time() + 604800,
Config::get('cookie_path')
);
$this->touchRateLimit($user->id, 1);
$success = 1;
$redirect = $user->lastOnline ? (isset($_REQUEST['redirect']) ? $_REQUEST['redirect'] : Router::route('main.index')) : Router::route('main.infopage', 'welcome');
$message = 'Welcome' . ($user->lastOnline ? ' back' : '') . '!';
Template::vars(['page' => ['success' => $success, 'redirect' => $redirect, 'message' => $message]]);
return Template::render('global/information');
}
}

View file

@ -18,7 +18,7 @@ use Sakura\Perms\Site;
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class Files extends Controller
class FileController extends Controller
{
private function serveImage($data, $mime, $name)
{

View file

@ -23,7 +23,7 @@ use Sakura\Utils;
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class Forums extends Controller
class ForumController extends Controller
{
/**
* Serves the forum index.

View file

@ -22,7 +22,7 @@ use Sakura\Utils;
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class Meta extends Controller
class MetaController extends Controller
{
/**
* Serves the site index.

View file

@ -22,7 +22,7 @@ use Sakura\Perms\Site;
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class Premium extends Controller
class PremiumController extends Controller
{
public function index()
{

View file

@ -21,7 +21,7 @@ use Sakura\Utils;
* @package Sakura
* @author Julian van de Groep <me@flash.moe>
*/
class User extends Controller
class UserController extends Controller
{
/**
* Display the profile of a user.
@ -99,7 +99,7 @@ class User extends Controller
*
* @return bool|string The memberlist.
*/
public function members($rank = 0)
public function members($rank = null)
{
global $currentUser;
@ -108,14 +108,31 @@ class User extends Controller
return Template::render('global/restricted');
}
// Get all ranks
// Execute query
$getRanks = DB::table('ranks')
->get(['rank_id']);
// Define variable
$ranks = [];
// Add the empty rank
$ranks[0] = Rank::construct(0);
// Reorder shit
foreach ($getRanks as $sortRank) {
$ranks[$sortRank->rank_id] = Rank::construct($sortRank->rank_id);
}
// Get the active rank
$rank = array_key_exists($rank, $ranks) ? $rank : ($rank ? 0 : 2);
// Set parse variables
Template::vars([
'memberlist' => [
'ranks' => ($_MEMBERLIST_RANKS = \Sakura\Users::getAllRanks()),
'active' => ($_MEMBERLIST_ACTIVE = (array_key_exists($rank, $_MEMBERLIST_RANKS) ? $rank : 2)),
'users' => Rank::construct($_MEMBERLIST_ACTIVE)->users(),
'membersPerPage' => Config::get('members_per_page'),
]
'ranks' => $ranks,
'rank' => $rank,
'membersPerPage' => Config::get('members_per_page'),
]);
// Render the template

View file

@ -118,9 +118,16 @@ class Router
*
* @return string The generated URI.
*/
public static function url($name, $args = null)
public static function route($name, $args = null)
{
return self::$router->route($name, $args);
// Array-ify the arguments
if ($args !== null && !is_array($args)) {
$temp = $args;
$args = [];
$args[] = $temp;
}
return self::$basePath . self::$router->route($name, $args);
}
/**

View file

@ -10,6 +10,7 @@ namespace Sakura;
use Twig_Environment;
use Twig_Extension_StringLoader;
use Twig_Loader_Filesystem;
use Twig_SimpleFunction;
/**
* Sakura wrapper for Twig.
@ -98,6 +99,11 @@ class Template
// Load String template loader
self::$template->addExtension(new Twig_Extension_StringLoader());
// Add route function
self::$template->addFunction(new Twig_SimpleFunction('route', function ($name, $args = null) {
return Router::route($name, $args);
}));
}
/**

View file

@ -98,130 +98,6 @@ class Users
return [$uid, $sid];
}
/**
* Log in to an account.
*
* @param string $username The username.
* @param string $password The password.
* @param bool $remember Stay logged in "forever"?
* @param bool $cookies Set cookies?
*
* @return array Return the status.
*/
public static function login($username, $password, $remember = false, $cookies = true)
{
// Check if authentication is disallowed
if (Config::get('lock_authentication')) {
return [0, 'AUTH_LOCKED'];
}
// Check if we haven't hit the rate limit
$rates = DBv2::prepare('SELECT * FROM `{prefix}login_attempts` WHERE `attempt_ip` = :ip AND `attempt_timestamp` > :time AND `attempt_success` = 0');
$rates->execute([
'ip' => Net::pton(Net::IP()),
'time' => time() - 1800,
]);
$rates = $rates->fetchAll(\PDO::FETCH_ASSOC);
if (count($rates) > 4) {
return [0, 'RATE_LIMIT'];
}
// Check if the user that's trying to log in actually exists
if (!$uid = self::userExists($username, false)) {
return [0, 'USER_NOT_EXIST'];
}
// Get account data
$user = User::construct($uid);
// Validate password
switch ($user->passwordAlgo) {
// Disabled
case 'disabled':
return [0, 'NO_LOGIN'];
// Default hashing method
default:
if (!Hashing::validatePassword($password, [
$user->passwordAlgo,
$user->passwordIter,
$user->passwordSalt,
$user->passwordHash,
])) {
return [0, 'INCORRECT_PASSWORD', $user->id, $user->passwordChan];
}
}
// Check if the user has the required privs to log in
if ($user->permission(Site::DEACTIVATED)) {
return [0, 'NOT_ALLOWED', $user->id];
}
// Create a new session
$session = new Session($user->id);
// Generate a session key
$sessionKey = $session->create($remember);
// Set cookies
if ($cookies) {
// User ID cookie
setcookie(
Config::get('cookie_prefix') . 'id',
$user->id,
time() + 604800,
Config::get('cookie_path')
);
// Session ID cookie
setcookie(
Config::get('cookie_prefix') . 'session',
$sessionKey,
time() + 604800,
Config::get('cookie_path')
);
}
// Successful login! (also has a thing for the legacy password system)
return [1, 'LOGIN_SUCCESS', $user->id];
}
/**
* Logout
*
* @return bool Was the logout successful?
*/
public static function logout()
{
// Check if user is logged in
if (!$check = self::checkLogin()) {
return false;
}
// Destroy the active session
(new Session($check[0], $check[1]))->destroy();
// Unset User ID
setcookie(
Config::get('cookie_prefix') . 'id',
0,
time() - 60,
Config::get('cookie_path')
);
// Unset Session ID
setcookie(
Config::get('cookie_prefix') . 'session',
'',
time() - 60,
Config::get('cookie_path')
);
// Return true indicating a successful logout
return true;
}
/**
* Register a new account.
*

View file

@ -65,16 +65,11 @@ if (isset($_REQUEST['mode'])) {
if ($continue) {
switch ($_REQUEST['mode']) {
case 'logout':
// Attempt logout
$logout = Users::logout();
// Add page specific data
// Add page specific things
$renderData['page'] = [
'redirect' => ($logout ? $_REQUEST['redirect'] : $urls->format('SITE_LOGIN')),
'message' => $logout ? 'You are now logged out.' : 'An unknown error occurred.',
'success' => $logout ? 1 : 0,
'redirect' => Router::route('main.index'),
'message' => 'Wrong logout page.',
'success' => 0,
];
break;
@ -165,41 +160,11 @@ if (isset($_REQUEST['mode'])) {
// Login processing
case 'login':
// Attempt login
$login = Users::login($_REQUEST['username'], $_REQUEST['password'], isset($_REQUEST['remember']));
// Array containing "human understandable" messages
$messages = [
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The user you tried to log into does not exist.',
'INCORRECT_PASSWORD' => 'The password you entered was invalid.',
'NOT_ALLOWED' => 'Your account does not have the required permissions to log in.',
'NO_LOGIN' => 'Logging into this account is disabled.',
'RATE_LIMIT' => 'Your IP has hit the login rate limit, try again later.',
'LOGIN_SUCCESS' => 'Login successful!',
];
// Check if we're not RATE_LIMIT
if ($login[1] != 'RATE_LIMIT') {
// Add to database
DBv2::prepare('INSERT INTO `{prefix}login_attempts` (`attempt_success`, `attempt_timestamp`, `attempt_ip`, `user_id`) VALUES (:succ, :time, :ip, :user)')
->execute([
'succ' => $login[0],
'time' => time(),
'ip' => Net::pton(Net::IP()),
'user' => isset($login[2]) ? $login[2] : 0,
]);
}
// Add page specific things
$renderData['page'] = [
'redirect' => $login[0] ? (User::construct($login[2])->lastOnline ? $_REQUEST['redirect'] : $urls->format('INFO_PAGE', ['welcome'])) : $urls->format('SITE_LOGIN'),
'message' => $messages[$login[1]],
'success' => $login[0],
'redirect' => Router::route('auth.login'),
'message' => 'Wrong login page.',
'success' => 0,
];
break;

2
public/robots.txt Normal file
View file

@ -0,0 +1,2 @@
User-agent: *
Disallow: /api/

View file

@ -7,38 +7,40 @@
namespace Sakura;
// Meta pages
Router::get('/', 'Meta@index', 'main.index');
Router::get('/faq', 'Meta@faq', 'main.faq');
Router::get('/search', 'Meta@search', 'main.search');
Router::get('/p/{id}', 'Meta@infoPage', 'main.infopage');
Router::get('/', 'MetaController@index', 'main.index');
Router::get('/faq', 'MetaController@faq', 'main.faq');
Router::get('/search', 'MetaController@search', 'main.search');
Router::get('/p/{id}', 'MetaController@infoPage', 'main.infopage');
// Auth
Router::get('/login', 'Auth@login', 'auth.login');
Router::get('/login', 'AuthController@loginGet', 'auth.login');
Router::post('/login', 'AuthController@loginPost', 'auth.login');
Router::get('/logout', 'AuthController@logout', 'auth.logout');
// News
Router::get('/news', 'Meta@news', 'news.index');
Router::get('/news/{category}', 'Meta@news', 'news.category');
Router::get('/news/{category}/{id}', 'Meta@news', 'news.post');
Router::get('/news', 'MetaController@news', 'news.index');
Router::get('/news/{category}', 'MetaController@news', 'news.category');
Router::get('/news/{category}/{id}', 'MetaController@news', 'news.post');
// Forum
Router::get('/forum', 'Forums@index', 'forums.index');
Router::get('/forum/{id}', 'Forums@forum', 'forums.forum');
Router::get('/forum', 'ForumController@index', 'forums.index');
Router::get('/forum/{id}', 'ForumController@forum', 'forums.forum');
// Members
Router::get('/members', 'User@members', 'members.index');
Router::get('/members/{rank}', 'User@members', 'members.rank');
Router::get('/members', 'UserController@members', 'members.index');
Router::get('/members/{rank}', 'UserController@members', 'members.rank');
// User
Router::get('/u/{id}', 'User@profile', 'user.profile');
Router::get('/u/{id}/header', 'Files@header', 'user.header');
Router::get('/u/{id}', 'UserController@profile', 'user.profile');
Router::get('/u/{id}/header', 'FileController@header', 'user.header');
// Files
Router::get('/a/{id}', 'Files@avatar', 'file.avatar');
Router::get('/bg/{id}', 'Files@background', 'file.background');
Router::get('/a/{id}', 'FileController@avatar', 'file.avatar');
Router::get('/bg/{id}', 'FileController@background', 'file.background');
// Premium
Router::get('/support', 'Premium@index', 'premium.index');
Router::get('/support/tracker', 'Premium@tracker', 'premium.tracker');
Router::get('/support', 'PremiumController@index', 'premium.index');
Router::get('/support/tracker', 'PremiumController@tracker', 'premium.tracker');
// Management
/*
@ -71,125 +73,3 @@ Router::get('/support/tracker', 'Premium@tracker', 'premium.tracker');
* - Management
* - Errors
*/
// Redirections
Router::any('/index.php', function () {
// Info pages
if (isset($_REQUEST['p'])) {
header('Location: /p/' . $_REQUEST['p']);
return;
}
// Forum index
if (isset($_REQUEST['forum']) && $_REQUEST['forum']) {
header('Location: /forum');
return;
}
// Site index
header('Location: /');
});
Router::any('/news.php', function () {
// Category + post
if (isset($_REQUEST['cat']) && isset($_REQUEST['id'])) {
header('Location: /news/' . $_REQUEST['cat'] . '/'. $_REQUEST['id']);
return;
}
// Category
if (isset($_REQUEST['cat'])) {
header('Location: /news/' . $_REQUEST['cat']);
return;
}
// Post in the main category
if (isset($_REQUEST['id'])) {
header('Location: /news/' . $_REQUEST['id']);
return;
}
// All posts in main category
header('Location: /news');
});
Router::any('/profile.php', function () {
// Redirect to the profile
if (isset($_REQUEST['u'])) {
header('Location: /u/' . $_REQUEST['u']);
return;
}
// Redirect to index
header('Location: /');
});
Router::any('/members.php', function () {
// Append sort
$append = isset($_REQUEST['sort']) ? '?sort=' . $_REQUEST['sort'] : '';
// Redirect to the profile
if (isset($_REQUEST['rank'])) {
header('Location: /members/' . $_REQUEST['rank'] . $append);
return;
}
// Redirect to index
header('Location: /members/' . $append);
});
Router::any('/viewforum.php', function () {
// Redirect to the profile
if (isset($_REQUEST['f'])) {
$req = [];
foreach ($_REQUEST as $k => $v) {
if ($k == 'f') {
continue;
}
$req[] = $k . '=' . $v;
}
header('Location: /forum/' . $_REQUEST['f'] . ($req ? '?' . implode('&', $req) : ''));
return;
}
// Redirect to index
header('Location: /forum/');
});
Router::any('/support.php', function () {
if (isset($_GET['tracker'])) {
header('Location: /support/tracker');
return;
}
header('Location: /support');
});
Router::any('/imageserve.php', function () {
// Category + post
if (isset($_REQUEST['u']) && isset($_REQUEST['m'])) {
switch ($_REQUEST['m']) {
case 'avatar':
header('Location: /a/' . $_REQUEST['u']);
return;
case 'background':
header('Location: /bg/' . $_REQUEST['u']);
return;
case 'header':
header('Location: /u/' . $_REQUEST['u'] . '/header');
return;
}
}
header('Location: /bg/0');
});
Router::any('/faq.php', function () {
header('Location: /faq');
});
Router::any('/search.php', function () {
header('Location: /search');
});

View file

@ -8,9 +8,7 @@
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20160219');
define('SAKURA_VLABEL', 'Amethyst');
define('SAKURA_COLOUR', '#9966CC');
define('SAKURA_VERSION', '20160227');
// Define Sakura Path
define('ROOT', __DIR__ . '/');
@ -27,14 +25,17 @@ mb_internal_encoding('utf-8');
// Stop the execution if the PHP Version is older than 5.5.0
if (version_compare(phpversion(), '5.5.0', '<')) {
die('Sakura requires at least PHP 5.5.0, please upgrade to a newer PHP version.');
throw new \Exception('Sakura requires at least PHP 5.5.0, please upgrade to a newer PHP version.');
}
// Include third-party libraries
if (!@include_once ROOT . 'vendor/autoload.php') {
die('Autoloader not found, did you run composer?');
// Check if the composer autoloader exists
if (!file_exists(ROOT . 'vendor/autoload.php')) {
throw new \Exception('Autoloader not found, did you run composer?');
}
// Require composer libraries
require_once ROOT . 'vendor/autoload.php';
// Setup the autoloader
spl_autoload_register(function ($className) {
// Replace \ with /
@ -187,6 +188,7 @@ if (!defined('SAKURA_NO_TPL')) {
'get' => $_GET,
'post' => $_POST,
'server' => $_SERVER,
]);
// Add the default render data

View file

@ -1,6 +1,6 @@
<li id="comment-{{ comment.comment_id }}">
<div class="comment">
<a class="comment-avatar clean" href="{{ urls.format('USER_PROFILE', [comment.comment_poster.id]) }}" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [comment.comment_poster.id]) }}');"><span style="color: {{ comment.comment_poster.colour }};">{{ comment.comment_poster.username }}</span></a>
<a class="comment-avatar clean" href="{{ route('user.profile', comment.comment_poster.id) }}" style="background-image: url('{{ route('file.avatar', comment.comment_poster.id) }}');"><span style="color: {{ comment.comment_poster.colour }};">{{ comment.comment_poster.username }}</span></a>
<div class="comment-pointer"></div>
<div class="comment-content">
<div class="comment-controls">

View file

@ -7,7 +7,7 @@
<input type="hidden" name="replyto" value="0" />
<input type="hidden" name="mode" value="comment" />
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [user.id]) }}');"></div>
<div class="comment-avatar" style="background-image: url('{{ route('file.avatar', user.id) }}');"></div>
<div class="comment-pointer"></div>
<textarea class="comment-content" name="comment" placeholder="Join the conversation..."></textarea>
<input class="comment-submit new" name="submit" type="submit" value="&#xf1d8;" />

View file

@ -1,7 +1,7 @@
<div id="indexPanel">
{% if session.checkLogin %}
<div class="head">Hi, {{ user.username }}!</div>
<a href="{{ urls.format('SETTING_MODE', ['appearance', 'avatar']) }}"><img src="{{ urls.format('IMAGE_AVATAR', [user.id]) }}" alt="{{ user.username }}" class="default-avatar-setting homepage-menu-avatar" /></a>
<a href="{{ urls.format('SETTING_MODE', ['appearance', 'avatar']) }}"><img src="{{ route('file.avatar', user.id) }}" alt="{{ user.username }}" class="default-avatar-setting homepage-menu-avatar" /></a>
<ul class="panelQuickLinks">
<li><a href="{{ urls.format('SETTING_MODE', ['friends', 'requests']) }}" title="Pending friend requests"><span class="fa fa-user-plus"></span><span class="count">{{ user.friends(-1, true)|length }}</span></a></li>
<li><a href="{{ urls.format('MESSAGES_INDEX') }}" title="View private messages"><span class="fa fa-envelope"></span><span class="count">0</span></a></li>
@ -19,32 +19,23 @@
Welcome to Flashii! This is a site for a bunch of friends to hang out, nothing special. Anyone is pretty much welcome to register so why not have a go?
<div class="indexSidePanelLinks">
<a class="fa fa-magic" href="{{ urls.format('SITE_REGISTER') }}" title="Register" id="indexSidePanelRegister"></a>
<a class="fa fa-sign-in" href="{{ urls.format('SITE_LOGIN') }}" title="Login" id="indexSidePanelLogin"></a>
<a class="fa fa-sign-in" href="{{ route('auth.login') }}" title="Login" id="indexSidePanelLogin"></a>
</div>
{% endif %}
{% endif %}
<div class="head">Stats</div>
We have <b>{{ stats.userCount }} user{% if stats.userCount != 1 %}s{% endif %}</b>,
<b><a href="{{ urls.format('USER_PROFILE', [stats.newestUser.id]) }}" style="color: {{ stats.newestUser.colour }};" class="default">{{ stats.newestUser.username }}</a></b> is the newest user,
<b><a href="{{ route('user.profile', stats.newestUser.id) }}" style="color: {{ stats.newestUser.colour }};" class="default">{{ stats.newestUser.username }}</a></b> is the newest user,
it has been <b>{{ stats.lastRegDate }} day{{ stats.lastRegDate == 1 ? '' : 's' }}</b> since the last user registered and the forum has <b>{{ stats.topicCount }} thread{% if stats.topicCount != 1 %}s{% endif %}</b> and <b>{{ stats.postCount }} post{% if stats.postCount != 1 %}s{% endif %}</b>.
<div class="head">Online Users</div>
{% if stats.onlineUsers %}
All active users in the past {{ sakura.onlineTimeout / 60 }} minute{% if sakura.onlineTimeout != 60 %}s{% endif %}
<table class="panelTable">
{% for amount,onlineUser in stats.onlineUsers %}
<tr><td style="text-align: left;"><a href="{{ urls.format('USER_PROFILE', [onlineUser.id]) }}" style="font-weight: bold; color: {{ onlineUser.colour }};" class="default">{{ onlineUser.username }}</a></td><td style="text-align: right;"><time>{{ onlineUser.lastOnline|date(sakura.dateFormat) }}</time></td></tr>
<tr><td style="text-align: left;"><a href="{{ route('user.profile', onlineUser.id) }}" style="font-weight: bold; color: {{ onlineUser.colour }};" class="default">{{ onlineUser.username }}</a></td><td style="text-align: right;"><time>{{ onlineUser.lastOnline|date(sakura.dateFormat) }}</time></td></tr>
{% endfor %}
</table>
{% else %}
There were no online users in the past {{ sakura.onlineTimeout / 60 }} minute{% if sakura.onlineTimeout != 60 %}s{% endif %}.
{% endif %}
{% if not user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) or user.mainRankId == 4 %}
<div class="ad-container ad-sidebar" id="sideAd">
<div class="ad-box">
<a href="http://jbox.com/r.php??&acc=269&___store=jlist&bannerid=28" target="_blank">
<img src="https://jlist.com/js/magestore/affiliateplus/banner.php?id=28&account_id=269&store_id=2" alt="250x250 PG senpai shirt" title="250x250 PG senpai shirt" width="250" height="250" />
</a>
</div>
</div>
{% endif %}
</div>

View file

@ -1,8 +1,8 @@
{% if not (viewPost and postExists) %}<a href="{{ urls.format('SITE_NEWS_CAT_POST', [post.news_category, post.news_id]) }}" class="news-head" id="{{ post.news_category }}_{{ post.news_id }}">{{ post.news_title }}</a>{% endif %}
{% if not (viewPost and postExists) %}<a href="{{ route('news.post', [post.news_category, post.news_id]) }}" class="news-head" id="{{ post.news_category }}_{{ post.news_id }}">{{ post.news_title }}</a>{% endif %}
<div class="news-body">
<a class="no-underline" href="{{ urls.format('USER_PROFILE', [post.news_poster.id]) }}">
<a class="no-underline" href="{{ route('user.profile', post.news_poster.id) }}">
<div class="news-poster">
<img src="{{ urls.format('IMAGE_AVATAR', [post.news_poster.id]) }}" alt="{{ post.news_poster.username }}" class="default-avatar-setting" />
<img src="{{ route('file.avatar', post.news_poster.id) }}" alt="{{ post.news_poster.username }}" class="default-avatar-setting" />
<h1 style="color: {{ post.news_poster.colour }}; text-shadow: 0 0 7px {% if post.news_poster.colour != 'inherit' %}{{ post.news_poster.colour }}{% else %}#222{% endif %}; padding: 0 0 10px;">{{ post.news_poster.username }}</h1>
</div>
</a>
@ -12,5 +12,5 @@
</div>
<div class="clear"></div>
<div class="news-post-time">
Posted <time>{{ post.news_timestamp|date(sakura.dateFormat) }}</time>{% if not (viewPost and postExists) %} <a class="default" href="{{ urls.format('SITE_NEWS_CAT_POST', [post.news_category, post.news_id]) }}#comments">{{ post.news_comments.count }} comment{% if post.news_comments.count != 1 %}s{% endif %}</a>{% endif %}
Posted <time>{{ post.news_timestamp|date(sakura.dateFormat) }}</time>{% if not (viewPost and postExists) %} <a class="default" href="{{ route('news.post', [post.news_category, post.news_id]) }}#comments">{{ post.news_comments.count }} comment{% if post.news_comments.count != 1 %}s{% endif %}</a>{% endif %}
</div>

View file

@ -4,7 +4,7 @@
{% if forum.type == 1 %}
{% if forum.forums|length and forum.permission(constant('Sakura\\Perms\\Forum::VIEW'), user.id) %}
<div class="forumCategory">
{% if forum.type != 1 %}Subforums{% else %}<a href="{{ urls.format('FORUM_SUB', [forum.id]) }}" class="clean">{{ forum.name }}</a>{% endif %}
{% if forum.type != 1 %}Subforums{% else %}<a href="{{ route('forums.forum', forum.id) }}" class="clean">{{ forum.name }}</a>{% endif %}
</div>
{% for forum in forum.forums %}
{% include 'forum/forumEntry.twig' %}
@ -19,7 +19,7 @@
{% set threads = forum.threads|batch(25) %}
{% set paginationPages = threads %}
{% set paginationUrl %}{{ urls.format('FORUM_SUB', [forum.id]) }}{% endset %}
{% set paginationUrl %}{{ route('forums.forum', forum.id) }}{% endset %}
{% include 'forum/forumBtns.twig' %}
{% if forum.threads %}

View file

@ -2,7 +2,7 @@
<div class="forumForum">
<div class="forumIcon {% if forum.unread(user.id) %}unread {% endif %}fa fa-3x {% if forum.icon %}{{ forum.icon }}{% else %}{% if forum.type == 2 %}fa-chevron-circle-right{% elseif forum.type == 1 %}fa-folder{% else %}fa-comments{% endif %}{% endif %}"></div>
<div class="forumTitle">
<div class="name"><a href="{% if forum.type == 2 %}{{ forum.link }}{% else %}{{ urls.format('FORUM_SUB', [forum.id]) }}{% endif %}" class="default">{{ forum.name }}</a></div>
<div class="name"><a href="{% if forum.type == 2 %}{{ forum.link }}{% else %}{{ route('forums.forum', forum.id) }}{% endif %}" class="default">{{ forum.name }}</a></div>
<div class="desc">
{{ forum.description }}
{% if forum.forums|length %}

View file

@ -73,36 +73,36 @@
<div id="container">
<span id="top"></span>
<div class="header" id="header">
<a class="logo" href="{{ urls.format('SITE_HOME') }}">{% if sakura.siteLogo %}<img src="{{ sakura.siteLogo }}" alt="{{ sakura.siteName }}" />{% else %}{{ sakura.siteName }}{% endif %}</a>
<a class="logo" href="{{ route('main.index') }}">{% if sakura.siteLogo %}<img src="{{ sakura.siteLogo }}" alt="{{ sakura.siteName }}" />{% else %}{{ sakura.siteName }}{% endif %}</a>
<div class="menu fa">
<div class="menu-nav" id="navMenuSite">
<!-- Navigation menu, displayed on left side of the bar. -->
<a class="menu-item fa-home" href="{{ urls.format('SITE_HOME') }}" title="Home"></a>
<a class="menu-item fa-newspaper-o" href="{{ urls.format('SITE_NEWS') }}" title="News"></a>
<a class="menu-item fa-commenting" href="{{ urls.format('INFO_PAGE', ['chat']) }}" title="Chat"></a>
<a class="menu-item fa-list" href="{{ urls.format('FORUM_INDEX') }}" title="Forums"></a>
<a class="menu-item fa-search" href="{{ urls.format('SITE_SEARCH') }}" title="Search"></a>
<a class="menu-item fa-home" href="{{ route('main.index') }}" title="Home"></a>
<a class="menu-item fa-newspaper-o" href="{{ route('news.index') }}" title="News"></a>
<a class="menu-item fa-commenting" href="{{ route('main.infopage', 'chat') }}" title="Chat"></a>
<a class="menu-item fa-list" href="{{ route('forums.index') }}" title="Forums"></a>
<a class="menu-item fa-search" href="{{ route('main.search') }}" title="Search"></a>
{% if session.checkLogin %}
<a class="menu-item fa-users" href="{{ urls.format('MEMBERLIST_INDEX') }}" title="Members"></a>
<a class="menu-item fa-heart" href="{{ urls.format('SITE_PREMIUM') }}" title="Support us"></a>
<a class="menu-item fa-users" href="{{ route('members.index') }}" title="Members"></a>
<a class="menu-item fa-heart" href="{{ route('premium.index') }}" title="Support us"></a>
{% endif %}
</div>
<div class="menu-ucp" id="navMenuUser">
<!-- User menu, displayed on right side of the bar. -->
{% if session.checkLogin %}
<a class="menu-item avatar" href="{{ urls.format('USER_PROFILE', [user.id]) }}" title="Logged in as {{ user.username }}" style="background-image: url('{{ urls.format('IMAGE_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('file.avatar', user.id) }}'); width: auto; color: {{ user.colour }}; border-color: {{ user.colour }}; font-weight: 700;"></a>
{#<a class="menu-item fa-envelope" href="{{ urls.format('SETTING_CAT', ['messages']) }}" title="Messages"></a>#}
{% if user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
<a class="menu-item fa-gavel" href="{{ urls.format('MANAGE_INDEX') }}" title="Manage"></a>
{% endif %}
<a class="menu-item fa-cogs" href="{{ urls.format('SETTINGS_INDEX') }}" title="Settings"></a>
<a class="menu-item fa-sign-out" href="{{ urls.format('USER_LOGOUT', [php.time, php.sessionid, sakura.currentPage]) }}" title="Logout" id="headerLogoutLink"></a>
<a class="menu-item fa-sign-out" href="{{ route('auth.logout') }}?s={{ php.sessionid }}" title="Logout" id="headerLogoutLink"></a>
{% else %}
{% if sakura.lockAuth %}
<div class="menu-item fa-lock" style="padding-left: 10px; padding-right: 10px;" title="Authentication is locked"></div>
{% else %}
<a class="menu-item fa-magic" href="{{ urls.format('SITE_REGISTER') }}" title="Login"></a>
<a class="menu-item fa-sign-in" href="{{ urls.format('SITE_LOGIN') }}" title="Login"></a>
<a class="menu-item fa-sign-in" href="{{ route('auth.login') }}" title="Login"></a>
{% endif %}
{% endif %}
</div>
@ -113,8 +113,8 @@
{% if php.self == '/profile.php' ? profile.background : (user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.background) %}
<div id="userBackground" style="background-image: url('{{ urls.format('IMAGE_BACKGROUND', [(php.self == '/profile.php' ? profile : user).id]) }}');"></div>
{% endif %}
{% if not session.checkLogin and php.self != '/authenticate.php' %}
<form method="post" action="{{ urls.format('AUTH_ACTION') }}" id="headerLoginForm">
{% if not session.checkLogin and sakura.currentPage != route('auth.login') %}
<form method="post" action="{{ route('auth.login') }}" id="headerLoginForm">
<input type="hidden" name="redirect" value="{{ sakura.currentPage }}" />
<input type="hidden" name="session" value="{{ php.sessionid }}" />
<input type="hidden" name="time" value="{{ php.time }}" />
@ -161,32 +161,22 @@
{% block content %}
<h1 class="stylised" style="text-align: center; margin: 2em auto;">{{ php.self }} is now printing!</h1>
{% endblock %}
{% if not user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) or user.mainRankId == 4 %}
<div class="ad-container ad-footer" id="footerAd">
<div class="ad-box">
<a href="http://jbox.com/r.php??series/touhou&acc=269&___store=jlist&bannerid=8" target="_blank">
<img src="https://jlist.com/js/magestore/affiliateplus/banner.php?id=8&account_id=269&store_id=2" alt="728x90 PG -- Touhou 1" title="728x90 PG -- Touhou 1" width="728" height="90" />
</a>
</div>
</div>
{% endif %}
</div>
<div class="footer">
<div class="ftsections">
<div class="copycentre">Powered by <a href="https://github.com/flashwave/sakura/" target="_blank">Sakura</a>{% if sakura.dev.showChangelog %} <a href="https://sakura.flash.moe/#r{{ sakura.versionInfo.version }}" target="_blank">r{{ sakura.versionInfo.version }}</a>{% endif %} &copy; 2013-2016 <a href="http://flash.moe/" target="_blank">Flashwave</a></div>
<ul class="ftsection">
<li class="fthead">General</li>
<li><a href="{{ urls.format('SITE_HOME') }}" title="Flashii Frontpage">Home</a></li>
<li><a href="{{ urls.format('SITE_NEWS') }}" title="Flashii News &amp; Updates">News</a></li>
<li><a href="{{ urls.format('SITE_SEARCH') }}" title="Do full-site search requests">Search</a></li>
<li><a href="{{ urls.format('INFO_PAGE', ['contact']) }}" title="Contact our Staff">Contact</a></li>
<li><a href="{{ route('main.index') }}" title="Flashii Frontpage">Home</a></li>
<li><a href="{{ route('news.index') }}" title="Flashii News &amp; Updates">News</a></li>
<li><a href="{{ route('main.search') }}" title="Do full-site search requests">Search</a></li>
<li><a href="{{ route('main.infopage', 'contact') }}" title="Contact our Staff">Contact</a></li>
<li><a href="https://sakura.flash.moe" target="_blank" title="All the changes made to Sakura are listed here">Changelog</a></li>
<li><a href="{{ urls.format('SITE_PREMIUM') }}" title="Get Tenshi and help us pay the bills">Support us</a></li>
<li><a href="{{ route('premium.index') }}" title="Get Tenshi and help us pay the bills">Support us</a></li>
</ul>
<ul class="ftsection">
<li class="fthead">Community</li>
<li><a href="{{ urls.format('FORUM_INDEX') }}" title="Read and post on our forums">Forums</a></li>
<li><a href="{{ route('forums.index') }}" title="Read and post on our forums">Forums</a></li>
<li><a href="https://twitter.com/_flashii" target="_blank" title="Follow us on Twitter for news messages that are too short for the news page">Twitter</a></li>
<li><a href="https://youtube.com/user/flashiinet" target="_blank" title="Our YouTube page where stuff barely ever gets uploaded, mainly used to archive community creations">YouTube</a></li>
<li><a href="https://steamcommunity.com/groups/flashiinet" target="_blank" title="Our Steam group, play games with other members on the site">Steam</a></li>
@ -194,73 +184,15 @@
</ul>
<ul class="ftsection">
<li class="fthead">Information</li>
<li><a href="{{ urls.format('SITE_FAQ') }}" title="Questions that get Asked Frequently but not actually">FAQ</a></li>
<li><a href="{{ urls.format('INFO_PAGE', ['rules']) }}" title="Some Rules and Information kind of summing up the ToS">Rules</a></li>
<li><a href="{{ route('main.faq') }}" title="Questions that get Asked Frequently but not actually">FAQ</a></li>
<li><a href="{{ route('main.infopage', 'rules') }}" title="Some Rules and Information kind of summing up the ToS">Rules</a></li>
<li><a href="//fiistat.us" target="_blank" title="Check the status on our Servers and related services">Server Status</a></li>
<li><a href="{{ urls.format('INFO_PAGE', ['terms']) }}" title="Our Terms of Service">Terms of Service</a></li>
<li><a href="{{ route('main.infopage', 'terms') }}" title="Our Terms of Service">Terms of Service</a></li>
</ul>
</div>
</div>
</div>
<script type="text/javascript">
// Space for things that need to happen onload
window.addEventListener("load", function() {
{% if session.checkLogin %}
// Convert href to object in logout link
prepareAjaxLink('headerLogoutLink', 'submitPost', ', true, "Logging out..."');
{% elseif not sakura.lockAuth and php.self != '/authenticate.php' %}
// Make the header login form dynamic
prepareAjaxForm('headerLoginForm', 'Logging in...');
{% endif %}
{% if session.checkLogin %}
// Make notification requests (there's a seperate one to make it happen before the first 60 seconds)
notifyRequest('{{ php.sessionid }}');
// Create interval
setInterval(function() {
notifyRequest('{{ php.sessionid }}');
}, 60000);
{% endif %}
{% if php.self == '/profile.php' and session.checkLogin and user.id != profile.id %}
// Make friend button dynamic
prepareAjaxLink('profileFriendToggle', 'submitPost', ', true, "{% if profile.friend == 0 %}Adding{% else %}Removing{% endif %} friend..."');
{% endif %}
{% if php.self == '/viewtopic.php' and session.checkLogin %}
var forumFriendToggles = document.querySelectorAll('.forum-friend-toggle');
for(var i in forumFriendToggles) {
prepareAjaxLink(forumFriendToggles[i], 'submitPost', ', true, "Please wait..."');
}
{% endif %}
{% if php.self == '/authenticate.php' and not (sakura.lockAuth or session.checkLogin) %}
// AJAX Form Submission
var forms = {
{% if not auth.changingPass %}
"loginForm": 'Logging in...',
{% if not sakura.disableRegistration %}
"registerForm": 'Processing registration...',
{% endif %}
{% if sakura.requireActivation %}
"resendForm": 'Attempting to resend activation...',
{% endif %}
"passwordForm": 'Sending password recovery mail...'
{% else %}
"passwordForm": 'Changing password...'
{% endif %}
};
for(var i in forms) {
prepareAjaxForm(i, forms[i], (i == 'registerForm'));
}
{% endif %}
});
// Parse time elements
var timeElems = document.getElementsByTagName('time');
@ -308,7 +240,7 @@
changelogLink.href = 'https://sakura.flash.moe/#r{{ sakura.versionInfo.version }}';
// Create the text container
var changelogTitleText = document.createTextNode('Changelog');
var changelogTitleText = document.createTextNode('Changelog ({{ sakura.versionInfo.version|slice(0, 4) }}-{{ sakura.versionInfo.version|slice(4, 2) }}-{{ sakura.versionInfo.version|slice(6, 2) }})');
// Append everything
changelogLink.appendChild(changelogTitleText);

View file

@ -7,35 +7,6 @@
<h1 class="stylised" style="line-height: 1.8em; text-align: center;">Authentication is currently disallowed, try again later.</h1>
{% else %}
<div class="loginPage">
<div class="loginForm">
<div class="head">
Login to {{ sakura.siteName }}
</div>
<form method="post" action="{{ urls.format('AUTH_ACTION') }}" id="loginForm">
<input type="hidden" name="redirect" value="{{ auth.redirect }}" />
<input type="hidden" name="session" value="{{ php.sessionid }}" />
<input type="hidden" name="time" value="{{ php.time }}" />
<input type="hidden" name="mode" value="login" />
<div class="leftAlign">
<label for="loginUserName">Username:</label>
</div>
<div class="centreAlign">
<input class="inputStyling" type="text" id="loginUserName" name="username" autofocus="true" />
</div>
<div class="leftAlign">
<label for="loginPassword">Password:</label>
</div>
<div class="centreAlign">
<input class="inputStyling" type="password" id="loginPassword" name="password" />
</div>
<div class="subLinks centreAlign">
<input class="inputStyling" name="remember" type="checkbox" class="ignore-css" id="loginRemember" /><label for="loginRemember">Remember Me</a>
</div>
<div class="centreAlign">
<input class="inputStyling" type="submit" id="loginButton" name="submit" value="Login" />
</div>
</form>
</div>
<div class="passwordForm">
<div class="head">
Lost Password

View file

@ -21,11 +21,10 @@
<li>You were banned on {{ ban.issued|date(sakura.dateFormat) }}.</li>
<li>{% if ban.expires %}This ban expires on {{ ban.expires|date(sakura.dateFormat) }}.{% else %}<b>You are permanently banned.</b>{% endif %}</li>
{% if ban.expires %}
<li>You were banned by <a href="{{ urls.format('USER_PROFILE', [ban.issuer.id]) }}" class="default">{{ ban.issuer.username }}</a>.</li>
<li>You were banned by <a href="{{ route('user.profile', ban.issuer.id) }}" class="default">{{ ban.issuer.username }}</a>.</li>
{% endif %}
</ul>
</div>
</div>
</div>
<iframe src="https://www.youtube.com/embed/Tao67Idz3Uc?autoplay=1&amp;loop=1&amp;playlist=Tao67Idz3Uc" style="display: none;"></iframe>
{% endblock %}

View file

@ -5,7 +5,7 @@
{% block content %}
<div class="content standalone bbcode">
<div>
{{ page.content|raw }}
{{ include(template_from_string(page.content|raw)) }}
</div>
</div>
{% endblock %}

View file

@ -1,41 +1,44 @@
{% extends 'global/master.twig' %}
{% block title %}Authentication{% endblock %}
{% block title %}Login{% endblock %}
{% block content %}
{% if sakura.lockAuth %}
<h1 class="stylised" style="line-height: 1.8em; text-align: center;">Authentication is currently disallowed, try again later.</h1>
<h1 class="stylised" style="line-height: 1.8em; text-align: center;">Logging in is disabled for security checkups! Try again later.</h1>
{% else %}
<div class="loginPage">
<div class="loginForm">
<div class="head">
Login to {{ sakura.siteName }}
<div class="loginPage">
<div class="loginForm">
<div class="head">
Login
</div>
<form method="post" action="{{ route('auth.login') }}" id="loginForm">
<input type="hidden" name="redirect" value="{{ sakura.referrer ? sakura.referrer : route('main.index') }}" />
<input type="hidden" name="session" value="{{ php.sessionid }}" />
<input type="hidden" name="time" value="{{ php.time }}" />
<input type="hidden" name="mode" value="login" />
<div class="leftAlign">
<label for="loginUserName">Username:</label>
</div>
<div class="centreAlign">
<input class="inputStyling" type="text" id="loginUserName" name="username" autofocus="true" />
</div>
<div class="leftAlign">
<label for="loginPassword">Password:</label>
</div>
<div class="centreAlign">
<input class="inputStyling" type="password" id="loginPassword" name="password" />
</div>
<div class="subLinks centreAlign">
<input class="inputStyling" name="remember" type="checkbox" class="ignore-css" id="loginRemember" /><label for="loginRemember">Remember Me</a>
</div>
<div class="centreAlign">
<input class="inputStyling" type="submit" id="loginButton" name="submit" value="Login" />
</div>
<div class="subLinks centreAlign">
future links to password forgot, reactivate and register here
</div>
</form>
</div>
<form method="post" action="{{ urls.format('AUTH_ACTION') }}" id="loginForm">
<input type="hidden" name="redirect" value="{{ auth.redirect }}" />
<input type="hidden" name="session" value="{{ php.sessionid }}" />
<input type="hidden" name="time" value="{{ php.time }}" />
<input type="hidden" name="mode" value="login" />
<div class="leftAlign">
<label for="loginUserName">Username:</label>
</div>
<div class="centreAlign">
<input class="inputStyling" type="text" id="loginUserName" name="username" autofocus="true" />
</div>
<div class="leftAlign">
<label for="loginPassword">Password:</label>
</div>
<div class="centreAlign">
<input class="inputStyling" type="password" id="loginPassword" name="password" />
</div>
<div class="subLinks centreAlign">
<input class="inputStyling" name="remember" type="checkbox" class="ignore-css" id="loginRemember" /><label for="loginRemember">Remember Me</a>
</div>
<div class="centreAlign">
<input class="inputStyling" type="submit" id="loginButton" name="submit" value="Login" />
</div>
</form>
</div>
</div>
{% endif %}
{% endblock %}

View file

@ -3,44 +3,44 @@
{% set sorts = ['boxes', 'rectangles', 'list'] %}
{% set sort = get.sort in sorts ? get.sort : sorts[0] %}
{% set notfound = memberlist.active == 0 and get.rank is defined %}
{% set notfound = rank == 0 %}
{% set rankTitle %}
{% if notfound %}Not found{% else %}{% if not memberlist.active %}All members{% else %}{{ memberlist.ranks[memberlist.active].name(true) }}{% endif %}{% endif %}
{% if notfound %}Not found{% else %}{{ ranks[rank].name(true) }}{% endif %}
{% endset %}
{% set rankDescription %}
{% if notfound %}The requested rank could not be found!{% else %}{% if not memberlist.active %}The entire user list.{% else %}{{ memberlist.ranks[memberlist.active].description }}{% endif %}{% endif %}
{% if notfound %}The requested rank could not be found!{% else %}{{ ranks[rank].description }}{% endif %}
{% endset %}
{% set users = memberlist.users|batch(memberlist.membersPerPage) %}
{% set users = ranks[rank].users|batch(membersPerPage) %}
{% set currPage = get.page|default(1) - 1 %}
{% set paginationPages = users %}
{% set paginationUrl %}{% if sort and memberlist.active %}{{ urls.format('MEMBERLIST_ALL', [sort, memberlist.active]) }}{% elseif sort %}{{ urls.format('MEMBERLIST_SORT', [sort]) }}{% elseif memberlist.active %}{{ urls.format('MEMBERLIST_RANK', [memberlist.active]) }}{% else %}{{ urls.format('MEMBERLIST_INDEX') }}{% endif %}{% endset %}
{% set paginationUrl %}{% if rank %}{{ route('members.rank', rank) }}{% else %}{{ route('members.index') }}{% endif %}{% endset %}
{% block title %}{{ rankTitle }}{% endblock %}
{% block content %}
<div class="headerNotify" style="margin-bottom: 1px;">
<h1 style="{% if memberlist.active %}text-shadow: 0 0 5px {{ memberlist.ranks[memberlist.active].colour }}; color: {{ memberlist.ranks[memberlist.active].colour }};{% else %}text-shadow: 0 0 5px #555;{% endif %}">{{ rankTitle }}</h1>
<h1 style="{% if rank %}text-shadow: 0 0 5px {{ ranks[rank].colour }}; color: {{ ranks[rank].colour }};{% else %}text-shadow: 0 0 5px #555;{% endif %}">{{ rankTitle }}</h1>
<h3>{{ rankDescription }}</h3>
</div>
<div class="membersPage" style="min-height: 500px;">
<div class="dropDown" style="margin: 0 auto; font-size: 1.5em; line-height: 1.5em; height: 30px;">
<div class="dropDownInner" style="float: left; color: #FFF;">
<a class="dropDownDesc">Rank:</a>
{% for rank in memberlist.ranks %}
{% if not rank.hidden or (rank.hidden and memberlist.active == rank.id) %}
<a href="{{ urls.format('MEMBERLIST_RANK', [rank.id]) }}" style="color: {{ rank.colour }};"{% if memberlist.active == rank.id %} class="dropDownSelected"{% endif %}>{{ rank.name(true) }}</a>
{% for r in ranks %}
{% if not r.hidden or (r.hidden and rank == r.id) %}
<a href="{{ route('members.rank', r.id) }}{{ server['QUERY_STRING'] ? '?' : '' }}{{ server['QUERY_STRING'] }}" style="color: {{ r.colour }};"{% if rank == r.id %} class="dropDownSelected"{% endif %}>{{ r.id == 0 ? 'Not found' : r.name(true) }}</a>
{% endif %}
{% endfor %}
</div>
<div class="dropDownInner" style="float: left;">
<a class="dropDownDesc">View:</a>
{% for s in sorts %}
<a href="{% if memberlist.active %}{{ urls.format('MEMBERLIST_ALL', [s, memberlist.active]) }}{% else %}{{ urls.format('MEMBERLIST_SORT', [s]) }}{% endif %}"{% if s == sort %} class="dropDownSelected"{% endif %}>{{ s|capitalize }}</a>
<a href="?{{ server['QUERY_STRING'] }}{{ server['QUERY_STRING'] ? '&' : '' }}sort={{ s }}"{% if s == sort %} class="dropDownSelected"{% endif %}>{{ s|capitalize }}</a>
{% endfor %}
</div>
</div>
@ -74,10 +74,10 @@
<tbody>
<tr>
<td>
#{{ memberlist.active ? count + 1 : count }}
#{{ rank ? count + 1 : count }}
</td>
<td>
<a href="{{ urls.format('USER_PROFILE', [user.id]) }}" class="default" style="font-weight: bold; color: {{ user.colour }}; text-shadow: 0 0 5px {{ user.colour }};">{{ user.username }}</a>
<a href="{{ route('user.profile', user.id) }}" class="default" style="font-weight: bold; color: {{ user.colour }}; text-shadow: 0 0 5px {{ user.colour }};">{{ user.username }}</a>
</td>
<td>
<time>{{ user.registered|date(sakura.dateFormat) }}</time>
@ -97,9 +97,9 @@
</table>
{% else %}
{% for user in users[currPage] %}
<a href="{{ urls.format('USER_PROFILE', [user.id]) }}">{# These comment tags are here to prevent the link extending too far
<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="{{ sakura.contentPath }}/pixel.png" alt="{{ user.username }}" style="background: url('{{ urls.format('IMAGE_AVATAR', [user.id]) }}') no-repeat center / contain;" />{#
#}<img src="{{ sakura.contentPath }}/pixel.png" alt="{{ user.username }}" style="background: url('{{ route('file.avatar', user.id) }}') no-repeat center / contain;" />{#
#}<span class="userBoxUserName" style="color: {{ user.colour }};">{#
#}{{ user.username }}{#
#}</span>{#

View file

@ -9,6 +9,7 @@
{% block title %}{% if profileHidden %}User not found!{% else %}Profile of {{ profile.username }}{% endif %}{% endblock %}
{% block js %}
{% if not profileHidden %}
<script type="text/javascript">
window.addEventListener('load', function () {
// Check if location.hash is set
@ -55,6 +56,7 @@
newMode.className = 'profile-mode-current';
}
</script>
{% endif %}
{% endblock %}
{% block content %}
@ -65,7 +67,7 @@
There are a few possible reasons for this:
<ul style="padding-left: 40px;">
<li>They changed their username.</li>
<li>They may have been <a href="{{ urls.format('SITE_FAQ') }}#abyss" class="default">abyss'd</a>.</li>
<li>They may have been restricted.</li>
<li>You made a typo.</li>
<li>They never existed.</li>
</ul>
@ -74,9 +76,9 @@
{% else %}
<div class="content new-profile">
<div class="new-profile-container">
<div class="new-profile-header" style="background-image: url({{ urls.format('IMAGE_HEADER', [profile.id]) }});">
<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({{ urls.format('IMAGE_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('file.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(sakura.dateFormat) }}." {% endif %}>{{ profile.username }}</h1>
{% if profile.isPremium[0] %}<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;" /> {% endif %}<img src="{{ sakura.contentPath }}/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

@ -13,7 +13,7 @@
<div class="head">Support {{ sakura.siteName }}</div>
<div style="font-size: .9em; margin-bottom: 10px;">
<p>In order to keep the site, its services and improvements on it going I need money but I'm not that big of a fan of asking for money without giving anything special in return thus Tenshi exists. Tenshi is the name for our supporter rank which gives you access to an extra set of features (which are listed further down on this page). With your help we can keep adding new stuff, get new hardware and keep the site awesome!</p>
<h3><a href="{{ urls.format('SITE_DONATE_TRACK') }}" class="default">Ever wonder what happens on the financial side of things? View the donation tracker!</a></h3>
<h3><a href="{{ route('premium.tracker') }}" class="default">Ever wonder what happens on the financial side of things? View the donation tracker!</a></h3>
</div>
{% if page.current[0] %}
<div class="sectionHeader">
@ -109,7 +109,7 @@
{% endif %}
</div>
{% if session.checkLogin and user.permission(constant('Sakura\\Perms\\Site::OBTAIN_PREMIUM')) %}
<form action="{{ urls.format('SITE_PREMIUM') }}" method="post" id="purchaseForm" class="hidden">
<form action="{{ route('premium.index') }}" method="post" id="purchaseForm" class="hidden">
<input type="hidden" name="mode" value="purchase" />
<input type="hidden" name="time" value="{{ php.time }}" />
<input type="hidden" name="session" value="{{ php.sessionid }}" />

View file

@ -3,7 +3,7 @@
{% block title %}Donation Tracker{% endblock %}
{% set paginationPages = tracker.table|batch(20) %}
{% set paginationUrl %}{{ urls.format('SITE_DONATE_TRACK') }}{% endset %}
{% set paginationUrl %}{{ route('premium.tracker') }}{% endset %}
{% block css %}
<style type="text/css">
@ -39,7 +39,7 @@
{% for supporter in tracker.table|batch(20)[get.page|default(1) - 1] %}
<tr>
<td>
<a href="{{ urls.format('USER_PROFILE', [tracker.users[supporter.user_id].id]) }}" class="default" style="color: {{ tracker.users[supporter.user_id].colour }}; text-shadow: 0 0 7px {% if tracker.users[supporter.user_id].colour != 'inherit' %}{{ tracker.users[supporter.user_id].colour }}{% else %}#222{% endif %};">{{ tracker.users[supporter.user_id].username }}</a>
<a href="{{ route('user.profile', tracker.users[supporter.user_id].id) }}" class="default" style="color: {{ tracker.users[supporter.user_id].colour }}; text-shadow: 0 0 7px {% if tracker.users[supporter.user_id].colour != 'inherit' %}{{ tracker.users[supporter.user_id].colour }}{% else %}#222{% endif %};">{{ tracker.users[supporter.user_id].username }}</a>
</td>
<td style="color: {% if supporter.transaction_amount > 0 %}#0A0{% else %}#A00{% endif %};">
&#8364;{{ supporter.transaction_amount|number_format(2) }}

View file

@ -1,7 +1,7 @@
{% set friends = profile.friends(2)|batch(12) %}
{% set paginationPages = friends %}
{% set paginationUrl %}{{ urls.format('USER_FRIENDS', [profile.id]) }}{% endset %}
{% set paginationUrl %}{{ route('user.profile', profile.id) }}{% endset %}
<div class="new-profile-mode-title">
<h1 class="stylised">Friends</h1>
@ -9,8 +9,8 @@
<div class="profile-friends">
{% 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="{{ urls.format('USER_PROFILE', [friend.id]) }}">
<img src="{{ urls.format('IMAGE_AVATAR', [friend.id]) }}" alt="{{ friend.username }}" class="friends-list-avatar default-avatar-setting" style="width: 150px; height: 150px;" />
<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;" />
<div class="friends-list-name" style="color: {{ friend.colour }};">{{ friend.username }}</div>
</a>
</div>