r20160116/17

This commit is contained in:
flash 2016-01-17 02:58:31 +01:00
parent d6e22f1258
commit fa8b2b366d
45 changed files with 934 additions and 632 deletions

3
.gitignore vendored
View file

@ -6,10 +6,7 @@ google*.html
/config/config.ini
/cache/*
!/cache/.sakura
/uploads/*
!/uploads/.sakura
/vendor
!/vendor/.sakura
[Tt]humbs.db
ehthumbs.db
Desktop.ini

View file

@ -103,8 +103,8 @@ class BBcode
$parsed = nl2br(self::$bbcode->getAsHtml());
$parsed = Main::fixCodeTags($parsed);
$parsed = Main::parseEmotes($parsed);
$parsed = Utils::fixCodeTags($parsed);
$parsed = Utils::parseEmotes($parsed);
return $parsed;
}

View file

@ -40,7 +40,6 @@ class Comments
// Sorting
public function sortComments($comments)
{
// Create storage array
$layer = [];
@ -54,7 +53,7 @@ class Comments
// Attach the poster
$comment['comment_poster'] = $this->commenters[$comment['comment_poster']];
$comment['comment_text'] = Main::parseEmotes(Main::cleanString($comment['comment_text']));
$comment['comment_text'] = Utils::parseEmotes(Utils::cleanString($comment['comment_text']));
// Get likes and dislikes
$votes = $this->getVotes($comment['comment_id']);
@ -95,7 +94,6 @@ class Comments
// Getting a single comment
public function getComment($cid)
{
// Get from database
return Database::fetch('comments', false, [
'comment_id' => [$cid, '='],
@ -105,7 +103,6 @@ class Comments
// Getting comment votes
public function getVotes($cid)
{
// Get from database
return Database::fetch('comment_votes', true, [
'vote_comment' => [$cid, '='],
@ -115,7 +112,6 @@ class Comments
// Creating
public function makeComment($uid, $reply, $content)
{
// Check if the comment is long enough
if (strlen($content) < Config::get('comment_min_length')) {
return [0, 'TOO_SHORT'];
@ -142,7 +138,6 @@ class Comments
// Voting
public function makeVote($uid, $cid, $mode)
{
// Attempt to get previous vote
$vote = Database::fetch('comment_votes', false, [
'vote_user' => [$uid, '='],
@ -185,7 +180,6 @@ class Comments
// Deleting
public function removeComment($cid)
{
// Remove from database
return Database::delete('comments', [
'comment_id' => [$cid, '='],

View file

@ -5,10 +5,69 @@
namespace Sakura;
use finfo;
/**
* Class File
* @package Sakura
*/
class File
{
// Variables
public $id = 0;
public $user = null;
public $data = null;
public $name = null;
public $mime = null;
public $time = 0;
public $expire = 0;
// Create a new file
public static function create($data, $name, User $user, $expire = 0)
{
// Get the mimetype
$mime = (new finfo(FILEINFO_MIME_TYPE))->buffer($data);
// Insert it into the database
Database::insert('uploads', [
'user_id' => $user->id,
'file_data' => $data,
'file_name' => $name,
'file_mime' => $mime,
'file_time' => time(),
'file_expire' => $expire,
]);
// Get the last insert id
$id = Database::lastInsertID();
// Return a new File object
return new File($id);
}
// Constructor
public function __construct($fileId)
{
// Attempt to get the database row
$fileRow = Database::fetch('uploads', false, ['file_id' => [$fileId, '=']]);
// If anything was returned populate the variables
if ($fileRow) {
$this->id = $fileRow['file_id'];
$this->user = User::construct($fileRow['user_id']);
$this->data = $fileRow['file_data'];
$this->name = $fileRow['file_name'];
$this->mime = $fileRow['file_mime'];
$this->time = $fileRow['file_time'];
$this->expire = $fileRow['file_expire'];
}
}
// Delete the file
public function delete()
{
Database::delete('uploads', [
'file_id' => [$this->id, '='],
]);
}
}

View file

@ -5,7 +5,7 @@
namespace Sakura\Forum;
use Sakura\Main;
use Sakura\Utils;
use Sakura\Database;
use Sakura\User;
use Sakura\BBcode;
@ -86,8 +86,8 @@ class Post
Database::insert('posts', [
'topic_id' => $thread->id,
'forum_id' => $thread->forum,
'poster_id' => $poster->id(),
'poster_ip' => Main::getRemoteIP(),
'poster_id' => $poster->id,
'poster_ip' => Utils::getRemoteIP(),
'post_time' => time(),
'post_subject' => $subject,
'post_text' => $text,
@ -123,14 +123,14 @@ class Post
'post_id' => $this->id,
'topic_id' => $thread->id,
'forum_id' => $thread->forum,
'poster_id' => $this->poster->id(),
'poster_ip' => Main::getRemoteIP(),
'poster_id' => $this->poster->id,
'poster_ip' => Utils::getRemoteIP(),
'post_time' => $this->time,
'post_subject' => $this->subject,
'post_text' => $this->text,
'post_edit_time' => $this->editTime,
'post_edit_reason' => $this->editReason,
'post_edit_user' => $this->editUser->id(),
'post_edit_user' => $this->editUser->id,
],
[
'post_id' => [$this->id, '='],
@ -144,12 +144,12 @@ class Post
// Time elapsed since creation
public function timeElapsed()
{
return Main::timeElapsed($this->time);
return Utils::timeElapsed($this->time);
}
// Time elapsed since last edit
public function editTimeElapsed()
{
return Main::timeElapsed($this->editTime);
return Utils::timeElapsed($this->editTime);
}
}

View file

@ -6,7 +6,7 @@
namespace Sakura\Forum;
use Sakura\Database;
use Sakura\Main;
use Sakura\Utils;
/**
* Class Thread
@ -206,13 +206,13 @@ class Thread
// Time elapsed since creation
public function timeElapsed()
{
return Main::timeElapsed($this->time);
return Utils::timeElapsed($this->time);
}
// Time elapsed since status change
public function statusChangeElapsed()
{
return Main::timeElapsed($this->statusChange);
return Utils::timeElapsed($this->statusChange);
}
// Read status

View file

@ -30,7 +30,7 @@ class News
}
// Parse the news post
$post['news_content_parsed'] = Main::mdParse($post['news_content']);
$post['news_content_parsed'] = Utils::mdParse($post['news_content']);
// Attach the poster
$post['news_poster'] = $this->posters[$post['user_id']];

View file

@ -69,7 +69,7 @@ class Perms
$user = User::construct($uid);
// Get data from ranks
foreach ($user->ranks() as $rank) {
foreach (array_keys($user->ranks) as $rank) {
$perm = $perm | $this->rank($rank, $conditions, $perm);
}

View file

@ -15,8 +15,8 @@ class Site
const RESTRICTED = 2; // Is a user restricted
const ALTER_PROFILE = 4; // Can alter their profile data
const CHANGE_AVATAR = 8; // Can change their avatar
const CREATE_BACKGROUND = 16; // Can create a background
const CHANGE_BACKGROUND = 32; // Can change their background
const CHANGE_BACKGROUND = 16; // Can change their background
const CHANGE_HEADER = 32; // User can change their profile header
const VIEW_MEMBERLIST = 64; // Can view the memberlist
const CREATE_USERPAGE = 128; // Can create a userpage
const CHANGE_USERPAGE = 256; // Can change their userpage

View file

@ -14,17 +14,15 @@ use Sakura\Perms\Site;
*/
class Rank
{
// Rank data
private $data = [
'rank_id' => 0,
'rank_name' => 'Rank',
'rank_hierarchy' => 0,
'rank_multiple' => '',
'rank_hidden' => 1,
'rank_colour' => 'inherit',
'rank_description' => '',
'rank_title' => '',
];
// Variables
public $id = 0;
public $name = 'Rank';
public $hierarchy = 0;
public $multiple = '';
public $colour = 'inherit';
public $description = '';
public $title = '';
private $hidden = true;
private $permissions;
protected static $_rankCache = [];
@ -46,7 +44,7 @@ class Rank
{
// Get the rank database row
$getRank = Database::fetch(
$rankRow = Database::fetch(
'ranks',
false,
[
@ -55,55 +53,31 @@ class Rank
);
// Check if the rank actually exists
if (!empty($getRank)) {
// If not assign as the fallback rank
$this->data = $getRank;
if ($rankRow) {
$this->id = $rankRow['rank_id'];
$this->name = $rankRow['rank_name'];
$this->hierarchy = $rankRow['rank_hierarchy'];
$this->multiple = $rankRow['rank_multiple'];
$this->hidden = (bool) $rankRow['rank_hidden'];
$this->colour = $rankRow['rank_colour'];
$this->description = $rankRow['rank_description'];
$this->title = $rankRow['rank_title'];
}
// Init the permissions
$this->permissions = new Perms(Perms::SITE);
}
// Get the rank id
public function id()
{
return $this->data['rank_id'];
}
// Get the rank hierarchy
public function hierarchy()
{
return $this->data['rank_hierarchy'];
}
// Get the rank name
public function name($multi = false)
{
return $this->data['rank_name'] . ($multi ? $this->data['rank_multiple'] : null);
}
// Get the rank title
public function title()
{
return $this->data['rank_title'];
}
// Get the rank description
public function description()
{
return $this->data['rank_description'];
}
// Get the rank colour
public function colour()
{
return $this->data['rank_colour'];
return $this->name . ($multi ? $this->multiple : null);
}
// Check if the rank is hidden
public function hidden()
{
return $this->data['rank_hidden'] || $this->permission(Site::DEACTIVATED) || $this->permission(Site::RESTRICTED);
return $this->hidden || $this->permission(Site::DEACTIVATED) || $this->permission(Site::RESTRICTED);
}
// Check if the rank has the proper permissions
@ -113,7 +87,7 @@ class Rank
$perm = 0;
// Bitwise OR it with the permissions for this forum
$perm = $perm | $this->permissions->rank($this->id());
$perm = $perm | $this->permissions->rank($this->id);
return $this->permissions->check($flag, $perm);
}

View file

@ -66,8 +66,8 @@ class Session
// Insert the session into the database
Database::insert('sessions', [
'user_id' => $this->userId,
'user_ip' => Main::getRemoteIP(),
'user_agent' => Main::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
'user_ip' => Utils::getRemoteIP(),
'user_agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
'session_key' => $session,
'session_start' => time(),
'session_expire' => time() + 604800,
@ -105,7 +105,7 @@ class Session
if ($ipCheck) {
// Split both IPs up
$sessionIP = explode('.', $session['user_ip']);
$userIP = explode('.', Main::getRemoteIP());
$userIP = explode('.', Utils::getRemoteIP());
// Take 1 off the ipCheck variable so it's equal to the array keys
$ipCheck = $ipCheck - 1;

View file

@ -14,31 +14,35 @@ use Sakura\Perms\Site;
*/
class User
{
// User data
private $data = [
'user_id' => 0,
'username' => 'User',
'username_clean' => 'user',
'password_hash' => '',
'password_salt' => '',
'password_algo' => 'disabled',
'password_iter' => 0,
'password_chan' => 0,
'email' => 'sakura@localhost',
'rank_main' => 1,
'user_colour' => '',
'register_ip' => '127.0.0.1',
'last_ip' => '127.0.0.1',
'user_title' => '',
'user_registered' => 0,
'user_last_online' => 0,
'user_birthday' => '',
'user_country' => 'XX',
'user_data' => '[]',
];
private $ranks = [];
private $mainRank = [];
// Variables
public $id = 0;
public $username = 'User';
public $usernameClean = 'user';
public $passwordHash = '';
public $passwordSalt = '';
public $passwordAlgo = 'disabled';
public $passwordIter = 0;
public $passwordChan = 0;
public $email = 'user@sakura';
public $mainRank = null;
public $mainRankId = 1;
public $ranks = [];
public $colour = '';
public $registerIp = '0.0.0.0';
public $lastIp = '0.0.0.0';
public $title = '';
public $registered = 0;
public $lastOnline = 0;
public $country = 'XX';
public $avatar = 0;
public $background = 0;
public $header = 0;
public $page = '';
public $signature = '';
private $birthday = '0000-00-00';
private $permissions;
private $optionFields = null;
private $profileFields = null;
protected static $_userCache = [];
// Static initialiser
@ -58,8 +62,8 @@ class User
public static function create($username, $password, $email, $ranks = [2])
{
// Set a few variables
$usernameClean = Main::cleanString($username, true);
$emailClean = Main::cleanString($email, true);
$usernameClean = Utils::cleanString($username, true);
$emailClean = Utils::cleanString($email, true);
$password = Hashing::createHash($password);
// Insert the user into the database
@ -72,11 +76,11 @@ class User
'password_iter' => $password[1],
'email' => $emailClean,
'rank_main' => 0,
'register_ip' => Main::getRemoteIP(),
'last_ip' => Main::getRemoteIP(),
'register_ip' => Utils::getRemoteIP(),
'last_ip' => Utils::getRemoteIP(),
'user_registered' => time(),
'user_last_online' => 0,
'user_country' => Main::getCountryCode(),
'user_country' => Utils::getCountryCode(),
'user_data' => '[]',
]);
@ -100,33 +104,49 @@ class User
private function __construct($uid)
{
// Get the user database row
$getUser = Database::fetch(
$userRow = Database::fetch(
'users',
false,
[
'user_id' => [$uid, '=', true],
'username_clean' => [Main::cleanString($uid, true), '=', true],
'username_clean' => [Utils::cleanString($uid, true), '=', true],
]
);
// Check if the user actually exists
if (!empty($getUser)) {
// If not assign as the fallback user
$this->data = $getUser;
// Populate the variables
if ($userRow) {
$this->id = $userRow['user_id'];
$this->username = $userRow['username'];
$this->usernameClean = $userRow['username_clean'];
$this->passwordHash = $userRow['password_hash'];
$this->passwordSalt = $userRow['password_salt'];
$this->passwordAlgo = $userRow['password_algo'];
$this->passwordIter = $userRow['password_iter'];
$this->passwordChan = $userRow['password_chan'];
$this->email = $userRow['email'];
$this->mainRankId = $userRow['rank_main'];
$this->colour = $userRow['user_colour'];
$this->registerIp = $userRow['register_ip'];
$this->lastIp = $userRow['last_ip'];
$this->title = $userRow['user_title'];
$this->registered = $userRow['user_registered'];
$this->lastOnline = $userRow['user_last_online'];
$this->birthday = $userRow['user_birthday'];
$this->country = $userRow['user_country'];
$this->avatar = $userRow['user_avatar'];
$this->background = $userRow['user_background'];
$this->header = $userRow['user_header'];
$this->page = $userRow['user_page'];
$this->signature = $userRow['user_signature'];
}
// Decode the json in the user_data column
$this->data['user_data'] = json_decode(!empty($this->data['user_data']) ? $this->data['user_data'] : '[]', true);
// Get all ranks
$ranks = array_map(function ($a) {
return $a['rank_id'];
}, Database::fetch('user_ranks', true, ['user_id' => [$this->data['user_id'], '=']]));
$ranks = Database::fetch('user_ranks', true, ['user_id' => [$this->id, '=']]);
// Get the rows for all the ranks
foreach ($ranks as $rank) {
// Store the database row in the array
$this->ranks[$rank] = Rank::construct($rank);
$this->ranks[$rank['rank_id']] = Rank::construct($rank['rank_id']);
}
// Check if ranks were set
@ -135,107 +155,56 @@ class User
$this->ranks[1] = Rank::construct(1);
}
// Assign the user's main rank to a special variable since we'll use it a lot
$this->mainRank = $this->ranks[
array_key_exists($this->data['rank_main'], $this->ranks) ?
$this->data['rank_main'] :
array_keys($this->ranks)[0]
];
// Check if the rank is actually assigned to this user
if (!array_key_exists($this->mainRankId, $this->ranks)) {
$this->mainRankId = array_keys($this->ranks)[0];
$this->setMainRank($this->mainRankId);
}
// Assign the main rank to its own var
$this->mainRank = $this->ranks[$this->mainRankId];
// Set user colour
$this->colour = $this->colour ? $this->colour : $this->mainRank->colour;
// Set user title
$this->title = $this->title ? $this->title : $this->mainRank->title;
// Init the permissions
$this->permissions = new Perms(Perms::SITE);
}
// Get user id
public function id()
// Get user birthday
public function birthday($age = false)
{
return $this->data['user_id'];
// If age is requested calculate it
if ($age) {
// Create dates
$birthday = date_create($this->birthday);
$now = date_create(date('Y-m-d'));
// Get the difference
$diff = date_diff($birthday, $now);
// Return the difference in years
return $diff->format('%Y');
}
// Get username (or clean variant)
public function username($clean = false)
{
return $this->data['username' . ($clean ? '_clean' : '')];
// Otherwise just return the birthday value
return $this->birthday;
}
// Get password data
public function password()
// Get the user's long or short country names
public function country($long = false)
{
return [
'password_hash' => $this->data['password_hash'],
'password_salt' => $this->data['password_salt'],
'password_algo' => $this->data['password_algo'],
'password_iter' => $this->data['password_iter'],
'password_chan' => $this->data['password_chan'],
];
}
// Get email
public function email()
{
return $this->data['email'];
}
// Get main rank id
public function mainRank()
{
return $this->data['rank_main'];
}
// Get all rank ids
public function ranks($obj = false)
{
return $obj ? $this->ranks : array_keys($this->ranks);
}
// Get the user's colour
public function colour()
{
return empty($this->data['user_colour']) ? $this->mainRank->colour() : $this->data['user_colour'];
}
// Get the user's ip
public function ip($last = false)
{
return $this->data[($last ? 'last' : 'register') . '_ip'];
}
// Get the user's title
public function userTitle()
{
return empty($this->data['user_title']) ? $this->mainRank->title() : $this->data['user_title'];
}
// Get user event times
public function dates()
{
return [
'joined' => $this->data['user_registered'],
'lastOnline' => $this->data['user_last_online'],
'birth' => $this->data['user_birthday'],
];
}
// Get the user's long and short country names
public function country()
{
return [
'long' => Main::getCountryName($this->data['user_country']),
'short' => $this->data['user_country'],
];
}
// Get the user's raw additional settings
public function userData()
{
return $this->data['user_data'];
return $long ? Utils::getCountryName($this->country) : $this->country;
}
// Check if a user is online
public function isOnline()
{
// Get all sessions
$sessions = Database::fetch('sessions', true, ['user_id' => [$this->id(), '=']]);
$sessions = Database::fetch('sessions', true, ['user_id' => [$this->id, '=']]);
// If there's no entries just straight up return false
if (!$sessions) {
@ -243,13 +212,7 @@ class User
}
// Otherwise use the standard method
return $this->data['user_last_online'] > (time() - Config::get('max_online_time'));
}
// Compatibility
public function checkOnline()
{
return $this->isOnline();
return $this->lastOnline > (time() - Config::get('max_online_time'));
}
// Get user's forum statistics
@ -258,12 +221,12 @@ class User
return [
'posts' => Database::count(
'posts',
['poster_id' => [$this->id(), '=']]
['poster_id' => [$this->id, '=']]
)[0],
'topics' => count(Database::fetch(
'posts',
true,
['poster_id' => [$this->id(), '=']],
['poster_id' => [$this->id, '=']],
['post_time'],
null,
['topic_id']
@ -275,9 +238,13 @@ class User
public function elapsed($append = ' ago', $none = 'Just now')
{
$times = [];
$dates = [
'joined' => $this->registered,
'lastOnline' => $this->lastOnline,
];
foreach ($this->dates() as $key => $val) {
$times[$key] = Main::timeElapsed(is_string($val) ? strtotime($val) : $val, $append, $none);
foreach ($dates as $key => $val) {
$times[$key] = Utils::timeElapsed($val, $append, $none);
}
return $times;
@ -287,13 +254,20 @@ class User
public function addRanks($ranks)
{
// Update the ranks array
$ranks = array_diff(array_unique(array_merge($this->ranks(), $ranks)), $this->ranks());
$ranks = array_diff(
array_unique(
array_merge(
array_keys($this->ranks),
$ranks)
),
array_keys($this->ranks)
);
// Save to the database
foreach ($ranks as $rank) {
Database::insert('user_ranks', [
'rank_id' => $rank,
'user_id' => $this->id(),
'user_id' => $this->id,
]);
}
}
@ -302,11 +276,11 @@ class User
public function removeRanks($ranks)
{
// Current ranks
$remove = array_intersect($this->ranks(), $ranks);
$remove = array_intersect(array_keys($this->ranks), $ranks);
// Iterate over the ranks
foreach ($remove as $rank) {
Database::delete('user_ranks', ['user_id' => [$this->id(), '='], 'rank_id' => [$rank, '=']]);
Database::delete('user_ranks', ['user_id' => [$this->id, '='], 'rank_id' => [$rank, '=']]);
}
}
@ -319,7 +293,7 @@ class User
'rank_main' => $rank,
],
[
'user_id' => [$this->id(), '='],
'user_id' => [$this->id, '='],
],
]);
@ -331,14 +305,14 @@ class User
public function hasRanks($ranks)
{
// Check if the main rank is the specified rank
if (in_array($this->mainRank->id(), $ranks)) {
if (in_array($this->mainRankId, $ranks)) {
return true;
}
// If not go over all ranks and check if the user has them
foreach ($ranks as $rank) {
// We check if $rank is in $this->ranks and if yes return true
if (in_array($rank, $this->ranks())) {
if (in_array($rank, array_keys($this->ranks))) {
return true;
}
}
@ -365,13 +339,13 @@ class User
// Add friend
Database::insert('friends', [
'user_id' => $this->data['user_id'],
'user_id' => $this->id,
'friend_id' => $uid,
'friend_timestamp' => time(),
]);
// Return true because yay
return [1, $user->isFriends($this->id()) ? 'FRIENDS' : 'NOT_MUTUAL'];
return [1, $user->isFriends($this->id) ? 'FRIENDS' : 'NOT_MUTUAL'];
}
// Remove a friend
@ -392,14 +366,14 @@ class User
// Remove friend
Database::delete('friends', [
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
'friend_id' => [$uid, '='],
]);
// Attempt to remove the request
if ($deleteRequest) {
Database::delete('friends', [
'friend_id' => [$this->data['user_id'], '='],
'friend_id' => [$this->id, '='],
'user_id' => [$uid, '='],
]);
}
@ -413,14 +387,14 @@ class User
{
// Accepted from this user
$user = Database::count('friends', [
'user_id' => [$this->id(), '='],
'user_id' => [$this->id, '='],
'friend_id' => [$with, '='],
])[0];
// And the other user
$friend = Database::count('friends', [
'user_id' => [$with, '='],
'friend_id' => [$this->id(), '='],
'friend_id' => [$this->id, '='],
])[0];
if ($user && $friend) {
@ -443,32 +417,32 @@ class User
switch ($level) {
case 2:
// Get all the current user's friends
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id');
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
// Get all the people that added this user as a friend
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id(), '=']]), 'user_id');
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id');
// Create a difference map
$users = array_intersect($self, $others);
break;
case 1:
$users = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id');
$users = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
break;
case 0:
default:
// Get all the current user's friends
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id');
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
// Get all the people that added this user as a friend
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id(), '=']]), 'user_id');
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id');
// Create a difference map
$users = array_merge($others, $self);
break;
case -1:
// Get all the current user's friends
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id');
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
// Get all the people that added this user as a friend
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id(), '=']]), 'user_id');
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id');
// Create a difference map
$users = array_diff($others, $self);
break;
@ -496,7 +470,7 @@ class User
// Check if the user is banned
public function checkBan()
{
return Bans::checkBan($this->data['user_id']);
return Bans::checkBan($this->id);
}
// Check if the user has the proper permissions
@ -509,7 +483,7 @@ class User
$perm = 0;
// Bitwise OR it with the permissions for this forum
$perm = $this->permissions->user($this->id());
$perm = $this->permissions->user($this->id);
return $this->permissions->check($flag, $perm);
}
@ -517,49 +491,55 @@ class User
// Get a user's profile comments
public function profileComments()
{
return new Comments('profile-' . $this->data['user_id']);
return new Comments('profile-' . $this->id);
}
// Get the user's profile fields
public function profileFields()
{
// Get profile fields
$profileFields = Database::fetch('profilefields');
// If there's nothing just return null
if (!count($profileFields)) {
return [];
// Check if we have cached data
if ($this->profileFields) {
return $this->profileFields;
}
// Once again if nothing was returned just return null
if (empty($this->data['user_data']['profileFields'])) {
return [];
}
// Create output array
// Create array and get values
$profile = [];
$profileFields = Database::fetch('profilefields');
$profileValuesRaw = Database::fetch('user_profilefields', true, ['user_id' => [$this->id, '=']]);
$profileValueKeys = array_map(function ($a) {
return $a['field_name'];
}, $profileValuesRaw);
$profileValueVals = array_map(function ($a) {
return $a['field_value'];
}, $profileValuesRaw);
$profileValues = array_combine($profileValueKeys, $profileValueVals);
// Check if anything was returned
if (!$profileFields || !$profileValues) {
return $profile;
}
// Check if profile fields aren't fake
foreach ($profileFields as $field) {
// Completely strip all special characters from the field name
$fieldName = Main::cleanString($field['field_name'], true, true);
$fieldName = Utils::cleanString($field['field_name'], true, true);
// Check if the user has the current field set otherwise continue
if (!array_key_exists($fieldName, $this->data['user_data']['profileFields'])) {
if (!array_key_exists($fieldName, $profileValues)) {
continue;
}
// Assign field to output with value
$profile[$fieldName] = [];
$profile[$fieldName]['name'] = $field['field_name'];
$profile[$fieldName]['value'] = $this->data['user_data']['profileFields'][$fieldName];
$profile[$fieldName]['value'] = $profileValues[$fieldName];
$profile[$fieldName]['islink'] = $field['field_link'];
// If the field is set to be a link add a value for that as well
if ($field['field_link']) {
$profile[$fieldName]['link'] = str_replace(
'{{ VAL }}',
$this->data['user_data']['profileFields'][$fieldName],
$profileValues[$fieldName],
$field['field_linkformat']
);
}
@ -572,16 +552,19 @@ class User
// Go over all additional forms
foreach ($additional as $subName => $subField) {
// Check if the user has the current field set otherwise continue
if (!array_key_exists($subName, $this->data['user_data']['profileFields'])) {
if (!array_key_exists($subName, $profileValues)) {
continue;
}
// Assign field to output with value
$profile[$fieldName][$subName] = $this->data['user_data']['profileFields'][$subName];
$profile[$fieldName][$subName] = $profileValues[$subName];
}
}
}
// Assign cache
$this->profileFields = $profile;
// Return appropiate profile data
return $profile;
}
@ -589,26 +572,32 @@ class User
// Get the user's option fields
public function optionFields()
{
// Get option fields
$optionFields = Database::fetch('optionfields');
// If there's nothing just return null
if (!count($optionFields)) {
return [];
// Check if we have cached data
if ($this->optionFields) {
return $this->optionFields;
}
// Once again if nothing was returned just return null
if (empty($this->data['user_data']['userOptions'])) {
return [];
}
// Create output array
// Create array and get values
$options = [];
$optionFields = Database::fetch('optionfields');
$optionValuesRaw = Database::fetch('user_optionfields', true, ['user_id' => [$this->id, '=']]);
$optionValueKeys = array_map(function ($a) {
return $a['field_name'];
}, $optionValuesRaw);
$optionValueVals = array_map(function ($a) {
return $a['field_value'];
}, $optionValuesRaw);
$optionValues = array_combine($optionValueKeys, $optionValueVals);
// Check if profile fields aren't fake
// Check if anything was returned
if (!$optionFields || !$optionValues) {
return $options;
}
// Check if option fields aren't fake
foreach ($optionFields as $field) {
// Check if the user has the current field set otherwise continue
if (!array_key_exists($field['option_id'], $this->data['user_data']['userOptions'])) {
if (!array_key_exists($field['option_id'], $optionValues)) {
continue;
}
@ -618,10 +607,13 @@ class User
}
// Assign field to output with value
$options[$field['option_id']] = $this->data['user_data']['userOptions'][$field['option_id']];
$options[$field['option_id']] = $optionValues[$field['option_id']];
}
// Return appropiate profile data
// Assign cache
$this->optionFields = $options;
// Return appropiate option data
return $options;
}
@ -636,7 +628,7 @@ class User
// Attempt to retrieve the premium record from the database
$getRecord = Database::fetch('premium', false, [
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
]);
// If nothing was returned just return false
@ -658,7 +650,7 @@ class User
{
// Do the database query
$getWarnings = Database::fetch('warnings', true, [
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
]);
// Storage array
@ -706,26 +698,13 @@ class User
// Get a user's userpage
public function userPage()
{
return isset($this->data['user_data']['userPage']) ?
Main::mdParse(
base64_decode(
$this->data['user_data']['userPage']
),
true
) :
null;
return Utils::mdParse($this->page, true);
}
// Get a user's signature
public function signature()
{
return isset($this->data['user_data']['signature']) ?
BBcode::toHTML(
base64_decode(
$this->data['user_data']['signature']
)
) :
null;
return BBcode::toHTML($this->signature);
}
// Get username change history
@ -733,7 +712,7 @@ class User
{
// Do the database query
$changes = Database::fetch('username_history', true, [
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
], ['change_id', true]);
// Return all the warnings
@ -744,7 +723,7 @@ class User
public function setUsername($username)
{
// Create a cleaned version
$username_clean = Main::cleanString($username, true);
$username_clean = Utils::cleanString($username, true);
// Check if the username is too short
if (strlen($username_clean) < Config::get('username_min_length')) {
@ -763,7 +742,7 @@ class User
], ['change_id', true]);
// Check if anything was returned
if ($getOld && $getOld['user_id'] != $this->id()) {
if ($getOld && $getOld['user_id'] != $this->id) {
return [0, 'TOO_RECENT', $getOld['change_time']];
}
@ -780,11 +759,11 @@ class User
// Insert into username_history table
Database::insert('username_history', [
'change_time' => time(),
'user_id' => $this->data['user_id'],
'user_id' => $this->id,
'username_new' => $username,
'username_new_clean' => $username_clean,
'username_old' => $this->data['username'],
'username_old_clean' => $this->data['username_clean'],
'username_old' => $this->username,
'username_old_clean' => $this->usernameClean,
]);
// Update userrow
@ -794,7 +773,7 @@ class User
'username_clean' => $username_clean,
],
[
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
],
]);
@ -826,7 +805,7 @@ class User
'email' => $email,
],
[
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
],
]);
@ -838,7 +817,7 @@ class User
public function setPassword($old, $new, $confirm)
{
// Validate password
switch ($this->data['password_algo']) {
switch ($this->passwordAlgo) {
// Disabled account
case 'disabled':
return [0, 'NO_LOGIN'];
@ -846,18 +825,18 @@ class User
// Default hashing method
default:
if (!Hashing::validatePassword($old, [
$this->data['password_algo'],
$this->data['password_iter'],
$this->data['password_salt'],
$this->data['password_hash'],
$this->passwordAlgo,
$this->passwordIter,
$this->passwordSalt,
$this->passwordHash,
])) {
return [0, 'INCORRECT_PASSWORD', $this->data['password_chan']];
return [0, 'INCORRECT_PASSWORD', $this->passwordChan];
}
}
// Check password entropy
if (Main::pwdEntropy($new) < Config::get('min_entropy')) {
if (Utils::pwdEntropy($new) < Config::get('min_entropy')) {
return [0, 'PASS_TOO_SHIT'];
}
@ -879,31 +858,11 @@ class User
'password_chan' => time(),
],
[
'user_id' => [$this->data['user_id'], '='],
'user_id' => [$this->id, '='],
],
]);
// Return success
return [1, 'SUCCESS'];
}
// Update a user's userData
public function setUserData($data)
{
// Merge the arrays
$data = array_merge($this->userData(), $data);
// Encode it
$data = json_encode($data);
// Save it in the database
Database::update('users', [
[
'user_data' => $data,
],
[
'user_id' => [$this->id(), '='],
],
]);
}
}

View file

@ -104,7 +104,7 @@ class Users
// Check if we haven't hit the rate limit
$rates = Database::fetch('login_attempts', true, [
'attempt_ip' => [Main::getRemoteIP(), '='],
'attempt_ip' => [Utils::getRemoteIP(), '='],
'attempt_timestamp' => [time() - 1800, '>'],
'attempt_success' => [0, '='],
]);
@ -122,7 +122,7 @@ class Users
$user = User::construct($uid);
// Validate password
switch ($user->password()['password_algo']) {
switch ($user->passwordAlgo) {
// Disabled
case 'disabled':
return [0, 'NO_LOGIN'];
@ -130,22 +130,22 @@ class Users
// Default hashing method
default:
if (!Hashing::validatePassword($password, [
$user->password()['password_algo'],
$user->password()['password_iter'],
$user->password()['password_salt'],
$user->password()['password_hash'],
$user->passwordAlgo,
$user->passwordIter,
$user->passwordSalt,
$user->passwordHash,
])) {
return [0, 'INCORRECT_PASSWORD', $user->id(), $user->password()['password_chan']];
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()];
return [0, 'NOT_ALLOWED', $user->id];
}
// Create a new session
$session = new Session($user->id());
$session = new Session($user->id);
// Generate a session key
$sessionKey = $session->create($remember);
@ -155,7 +155,7 @@ class Users
// User ID cookie
setcookie(
Config::get('cookie_prefix') . 'id',
$user->id(),
$user->id,
time() + 604800,
Config::get('cookie_path'),
Config::get('cookie_domain')
@ -172,7 +172,7 @@ class Users
}
// Successful login! (also has a thing for the legacy password system)
return [1, 'LOGIN_SUCCESS', $user->id()];
return [1, 'LOGIN_SUCCESS', $user->id];
}
// Logout and kill the session
@ -228,7 +228,7 @@ class Users
// Verify the captcha if it's enabled
if (Config::get('recaptcha')) {
if (!Main::verifyCaptcha($captcha)['success']) {
if (!Utils::verifyCaptcha($captcha)['success']) {
return [0, 'CAPTCHA_FAIL'];
}
}
@ -254,7 +254,7 @@ class Users
}
// Check the MX record of the email
if (!Main::checkMXRecord($email)) {
if (!Utils::checkMXRecord($email)) {
return [0, 'INVALID_MX'];
}
@ -264,7 +264,7 @@ class Users
}
// Check password entropy
if (Main::pwdEntropy($password) < Config::get('min_entropy')) {
if (Utils::pwdEntropy($password) < Config::get('min_entropy')) {
return [0, 'PASS_TOO_SHIT'];
}
@ -283,7 +283,7 @@ class Users
// Check if we require e-mail activation
if ($requireActive) {
// Send activation e-mail to user
self::sendActivationMail($user->id());
self::sendActivationMail($user->id);
}
// Return true with a specific message if needed
@ -299,8 +299,8 @@ class Users
}
// Clean username string
$usernameClean = Main::cleanString($username, true);
$emailClean = Main::cleanString($email, true);
$usernameClean = Utils::cleanString($username, true);
$emailClean = Utils::cleanString($email, true);
// Do database request
$user = Database::fetch('users', false, [
@ -322,7 +322,7 @@ class Users
}
// Generate the verification key
$verk = ActionCode::generate('LOST_PASS', $userObj->id());
$verk = ActionCode::generate('LOST_PASS', $userObj->id);
// Create new urls object
$urls = new Urls();
@ -339,7 +339,7 @@ class Users
$message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature');
// Send the message
Main::sendMail([$user['email'] => $user['username']], Config::get('sitename') . ' password restoration', $message);
Utils::sendMail([$user['email'] => $user['username']], Config::get('sitename') . ' password restoration', $message);
// Return success
return [1, 'SUCCESS'];
@ -354,7 +354,7 @@ class Users
}
// Check password entropy
if (Main::pwdEntropy($newpass) < Config::get('min_entropy')) {
if (Utils::pwdEntropy($newpass) < Config::get('min_entropy')) {
return [0, 'PASS_TOO_SHIT'];
}
@ -402,8 +402,8 @@ class Users
}
// Clean username string
$usernameClean = Main::cleanString($username, true);
$emailClean = Main::cleanString($email, true);
$usernameClean = Utils::cleanString($username, true);
$emailClean = Utils::cleanString($email, true);
// Do database request
$user = Database::fetch('users', false, [
@ -438,12 +438,12 @@ class Users
$user = User::construct($uid);
// User is already activated or doesn't even exist
if (!$user->id() || !$user->permission(Site::DEACTIVATED)) {
if (!$user->id || !$user->permission(Site::DEACTIVATED)) {
return false;
}
// Generate activation key
$activate = ActionCode::generate('ACTIVATE', $user->id());
$activate = ActionCode::generate('ACTIVATE', $user->id);
// Create new urls object
$urls = new Urls();
@ -452,20 +452,20 @@ class Users
$message = "Welcome to " . Config::get('sitename') . "!\r\n\r\n";
$message .= "Please keep this e-mail for your records. Your account intormation is as follows:\r\n\r\n";
$message .= "----------------------------\r\n\r\n";
$message .= "Username: " . $user->username() . "\r\n\r\n";
$message .= "Your profile: http://" . Config::get('url_main') . $urls->format('USER_PROFILE', [$user->id()]) . "\r\n\r\n";
$message .= "Username: " . $user->username . "\r\n\r\n";
$message .= "Your profile: http://" . Config::get('url_main') . $urls->format('USER_PROFILE', [$user->id]) . "\r\n\r\n";
$message .= "----------------------------\r\n\r\n";
$message .= "Please visit the following link in order to activate your account:\r\n\r\n";
$message .= "http://" . Config::get('url_main') . $urls->format('SITE_ACTIVATE') . "?mode=activate&u=" . $user->id() . "&k=" . $activate . "\r\n\r\n";
$message .= "http://" . Config::get('url_main') . $urls->format('SITE_ACTIVATE') . "?mode=activate&u=" . $user->id . "&k=" . $activate . "\r\n\r\n";
$message .= "Your password has been securely stored in our database and cannot be retrieved. ";
$message .= "In the event that it is forgotten, you will be able to reset it using the email address associated with your account.\r\n\r\n";
$message .= "Thank you for registering.\r\n\r\n";
$message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature');
// Send the message
Main::sendMail(
Utils::sendMail(
[
$user->email() => $user->username(),
$user->email() => $user->username,
],
Config::get('sitename') . ' Activation Mail',
$message
@ -482,7 +482,7 @@ class Users
$user = User::construct($uid);
// Check if user exists
if (!$user->id()) {
if (!$user->id) {
return [0, 'USER_NOT_EXIST'];
}
@ -494,7 +494,7 @@ class Users
// Check if a key is set
if ($requireKey) {
// Check the action code
$action = ActionCode::validate('ACTIVATE', $key, $user->id());
$action = ActionCode::validate('ACTIVATE', $key, $user->id);
// Check if we got a negative return
if (!$action) {
@ -515,7 +515,7 @@ class Users
public static function userExists($user, $id = true)
{
// Clean string
$user = Main::cleanString($user, true);
$user = Utils::cleanString($user, true);
// Do database request
$user = Database::fetch('users', true, [($id ? 'user_id' : 'username_clean') => [$user, '=']]);
@ -541,7 +541,7 @@ class Users
// Iterate over the fields and clean them up
foreach ($profileFields as $field) {
$fields[$field['field_id']] = $field;
$fields[$field['field_id']]['field_identity'] = Main::cleanString($field['field_name'], true, true);
$fields[$field['field_id']]['field_identity'] = Utils::cleanString($field['field_name'], true, true);
$fields[$field['field_id']]['field_additional'] = json_decode($field['field_additional'], true);
}
@ -645,18 +645,18 @@ class Users
$check = $user->isPremium();
// Check if the user has premium
if ($check[0] && !in_array($excepted, $user->ranks())) {
if ($check[0] && !array_key_exists($excepted, $user->ranks)) {
// If so add the rank to them
$user->addRanks([$premiumRank]);
// Check if the user's default rank is standard user and update it to premium
if ($user->mainRank() == 2) {
if ($user->mainRankId == 2) {
$user->setMainRank($premiumRank);
}
} elseif (!$check[0]) {
// Remove the expired entry
Database::delete('premium', [
'user_id' => [$user->id(), '='],
'user_id' => [$user->id, '='],
]);
// Else remove the rank from them
@ -694,7 +694,7 @@ class Users
// Go over all users and check if they have the rank id
foreach ($users as $user) {
// If so store the user's row in the array
if ($user->hasRanks([$rankId], $user->id())) {
if ($user->hasRanks([$rankId], $user->id)) {
$rank[] = $user;
}
}
@ -721,7 +721,7 @@ class Users
continue;
}
$users[$user->id()] = $user;
$users[$user->id] = $user;
}
// and return an array with the users

View file

@ -1,6 +1,6 @@
<?php
/*
* Main Class
* Utils Class
*/
namespace Sakura;
@ -9,10 +9,10 @@ use Parsedown;
use PHPMailer;
/**
* Class Main
* Class Utils
* @package Sakura
*/
class Main
class Utils
{
// Parse markdown
public static function mdParse($text, $escape = false)
@ -598,7 +598,7 @@ class Main
return $logs;
}
// Time elapsed
// Time elapsed, doesn't account for leap years
public static function timeElapsed($timestamp, $append = ' ago', $none = 'Just now')
{

View file

@ -195,7 +195,7 @@ if (isset($_REQUEST['mode'])) {
Database::insert('login_attempts', [
'attempt_success' => $login[0],
'attempt_timestamp' => time(),
'attempt_ip' => Main::getRemoteIP(),
'attempt_ip' => Utils::getRemoteIP(),
'user_id' => isset($login[2]) ? $login[2] : 0,
]);
}
@ -203,7 +203,7 @@ if (isset($_REQUEST['mode'])) {
// Add page specific things
$renderData['page'] = [
'redirect' => $login[0] ? (User::construct($login[2])->dates()['lastOnline'] ? $_REQUEST['redirect'] : $urls->format('INFO_PAGE', ['welcome'])) : $urls->format('SITE_LOGIN'),
'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],
@ -323,7 +323,7 @@ if (Users::checkLogin()) {
}
// Check if a user has already registered from the current IP address
if (count($regUserIP = Users::getUsersByIP(Main::getRemoteIP()))) {
if (count($regUserIP = Users::getUsersByIP(Utils::getRemoteIP()))) {
$renderData['auth']['blockRegister'] = [
'do' => true,

View file

@ -2056,7 +2056,6 @@ textarea.inputStyling {
width: 100%;
max-height: 200px;
overflow: auto;
line-height: 1em;
}
.forum.viewtopic .posts .post-content .signature img {

View file

@ -0,0 +1,35 @@
/*
* Dynamic load project
*/
var DynLoad = (function () {
function DynLoad() {
}
// Add the hooks
DynLoad.init = function () {
// Add an event listener to the document
document.addEventListener("click", function (e) {
// Check if a href attribute is set
if (e.target['href']) {
// Prevent the default action
e.preventDefault();
// Create a new ajax object
var loader = new AJAX();
// Set the url
loader.setUrl(e.target['href']);
// Add callbacks
loader.addCallback(200, function () {
var doc = (new DOMParser()).parseFromString(loader.response(), "text/html");
history.pushState(null, null, e.target['href']);
document.head.innerHTML = doc.head.innerHTML;
document.getElementById("content").innerHTML = doc.getElementById("content").innerHTML;
var evt = document.createEvent('Event');
evt.initEvent('load', false, false);
window.dispatchEvent(evt);
});
// Send request
loader.start(HTTPMethods.GET);
}
});
};
return DynLoad;
})();

View file

@ -0,0 +1,37 @@
/*
* Dynamic load project
*/
class DynLoad {
// Add the hooks
public static init(): void {
// Add an event listener to the document
document.addEventListener("click", (e) => {
// Check if a href attribute is set
if (e.target['href']) {
// Prevent the default action
e.preventDefault();
// Create a new ajax object
var loader: AJAX = new AJAX();
// Set the url
loader.setUrl(e.target['href']);
// Add callbacks
loader.addCallback(200, () => {
var doc = (new DOMParser()).parseFromString(loader.response(), "text/html");
history.pushState(null, null, e.target['href']);
document.head.innerHTML = doc.head.innerHTML;
document.getElementById("content").innerHTML = doc.getElementById("content").innerHTML;
var evt = document.createEvent('Event');
evt.initEvent('load', false, false);
window.dispatchEvent(evt);
});
// Send request
loader.start(HTTPMethods.GET);
}
});
}
}

View file

@ -12,7 +12,7 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php
// Add page specific things
$renderData['page'] = [
'title' => 'Frequently Asked Questions',
'questions' => Main::getFaqData(),
'questions' => Utils::getFaqData(),
];
// Initialise templating engine

View file

@ -12,9 +12,6 @@ define('SAKURA_NO_TPL', true);
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php';
// Path to user uploads
$userDirPath = ROOT . Config::get('user_uploads') . '/';
// Check if the m(ode) GET request is set
if (isset($_GET['m'])) {
switch ($_GET['m']) {
@ -58,13 +55,24 @@ if (isset($_GET['m'])) {
}
// Check if user has an avatar set
if (empty($user->userData()['userAvatar']) || !file_exists($userDirPath . $user->userData()['userAvatar'])) {
if (!$user->avatar) {
$serveImage = $noAvatar;
break;
}
// Attempt to get the file
$serve = new File($user->avatar);
// Check if the file exists
if (!$serve->id) {
$serveImage = $noAvatar;
break;
}
// Check if the avatar exist and assign it to a value
$serveImage = $userDirPath . $user->userData()['userAvatar'];
$serveImage = $serve->data;
$serveMime = $serve->mime;
$serveName = $serve->name;
break;
case 'background':
@ -93,14 +101,24 @@ if (isset($_GET['m'])) {
}
// Check if user has a background set
if (empty($user->userData()['profileBackground'])
|| !file_exists($userDirPath . $user->userData()['profileBackground'])) {
if (!$user->background) {
$serveImage = $noBackground;
break;
}
// Attempt to get the file
$serve = new File($user->background);
// Check if the file exists
if (!$serve->id) {
$serveImage = $noBackground;
break;
}
// Check if the avatar exist and assign it to a value
$serveImage = $userDirPath . $user->userData()['profileBackground'];
$serveImage = $serve->data;
$serveMime = $serve->mime;
$serveName = $serve->name;
break;
case 'header':
@ -128,15 +146,25 @@ if (isset($_GET['m'])) {
break;
}
// Check if user has a background set
if (empty($user->userData()['profileHeader'])
|| !file_exists($userDirPath . $user->userData()['profileHeader'])) {
// Check if user has a header set
if (!$user->header) {
$serveImage = $noHeader;
break;
}
// Attempt to get the file
$serve = new File($user->header);
// Check if the file exists
if (!$serve->id) {
$serveImage = $noHeader;
break;
}
// Check if the avatar exist and assign it to a value
$serveImage = $userDirPath . $user->userData()['profileHeader'];
$serveImage = $serve->data;
$serveMime = $serve->mime;
$serveName = $serve->name;
break;
default:
@ -147,12 +175,17 @@ if (isset($_GET['m'])) {
$serveImage = ROOT . Config::get('pixel_img');
}
// Add original filename
header('Content-Disposition: inline; filename="' . basename($serveImage) . '"');
// Do some more checks
if (!isset($serveName) || !isset($serveMime)) {
$serveName = basename($serveImage);
$serveImage = file_get_contents($serveImage);
$serveMime = getimagesizefromstring($serveImage)['mime'];
}
// Add original filename
header('Content-Disposition: inline; filename="' . $serveName . '"');
// Set content type
header('Content-Type: ' . getimagesizefromstring($serveImage)['mime']);
header('Content-Type: ' . $serveMime);
print $serveImage;
echo $serveImage;

View file

@ -19,19 +19,19 @@ $template->setTemplate($templateName);
if (isset($_GET['p'])) {
// Set default variables
$renderData['page'] = [
'content' => Main::mdParse("# Unable to load the requested info page.\r\n\r\nCheck the URL and try again."),
'content' => Utils::mdParse("# Unable to load the requested info page.\r\n\r\nCheck the URL and try again."),
];
// Set page id
$pageId = isset($_GET['p']) ? strtolower($_GET['p']) : '';
// Get info page data from the database
if ($ipData = Main::loadInfoPage($pageId)) {
if ($ipData = Utils::loadInfoPage($pageId)) {
// Assign new proper variable
$renderData['page'] = [
'id' => $pageId,
'title' => $ipData['page_title'],
'content' => Main::mdParse($ipData['page_content']),
'content' => Utils::mdParse($ipData['page_content']),
];
}
@ -59,7 +59,7 @@ $renderData['stats'] = [
date_create(
date(
'Y-m-d',
$_INDEX_NEWEST_USER->dates()['joined']
$_INDEX_NEWEST_USER->registered
)
),
date_create(

View file

@ -40,7 +40,7 @@ $thread->forum;
$forum = new Forum\Forum($forumId);
// Check if the user has access to the forum
if (!$forum->permission(ForumPerms::VIEW, $currentUser->id()) || !$forum->permission(ForumPerms::REPLY, $currentUser->id())) {
if (!$forum->permission(ForumPerms::VIEW, $currentUser->id) || !$forum->permission(ForumPerms::REPLY, $currentUser->id)) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
@ -56,7 +56,7 @@ if (!$forum->permission(ForumPerms::VIEW, $currentUser->id()) || !$forum->permis
}
// Check if the user has access to the forum
if (!isset($thread) && !$forum->permission(ForumPerms::CREATE_THREADS, $currentUser->id())) {
if (!isset($thread) && !$forum->permission(ForumPerms::CREATE_THREADS, $currentUser->id)) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
@ -75,7 +75,7 @@ $mode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) ? 't' : (isset($_GET['p'])
// Include emotes and bbcodes
$posting = [
'emoticons' => Main::getEmotes(),
'emoticons' => Utils::getEmotes(),
];
// Check if we're in reply mode
@ -100,7 +100,7 @@ if ($mode != 'f') {
}
// Prompt an error if the topic doesn't exist
if ($thread->status == 1 && !$forum->permission(ForumPerms::LOCK, $currentUser->id())) {
if ($thread->status == 1 && !$forum->permission(ForumPerms::LOCK, $currentUser->id)) {
// Add page specific things
$renderData['page'] = [
'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')),
@ -121,7 +121,7 @@ if ($mode != 'f') {
$post = $thread->posts()[$_GET['p']];
// Add subject to render data
$posting['text'] = '[quote=' . $post->poster->username() . ']' . BBcode::toEditor($post->text) . '[/quote]';
$posting['text'] = '[quote=' . $post->poster->username . ']' . BBcode::toEditor($post->text) . '[/quote]';
// Post editing
} elseif ($mode == 'p' && isset($_GET['edit']) && $_GET['edit'] == $_GET['p'] && array_key_exists($_GET['p'], $thread->posts())) {
@ -141,7 +141,7 @@ if ($mode != 'f') {
exit;
}
// Checks
if ($thread->posts()[$_GET['p']]->poster->id() != $currentUser->id() && !$forum->permission(ForumPerms::EDIT_ANY, $currentUser->id())) {
if ($thread->posts()[$_GET['p']]->poster->id != $currentUser->id && !$forum->permission(ForumPerms::EDIT_ANY, $currentUser->id)) {
// Add page specific things
$renderData['page'] = [
'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')),
@ -184,7 +184,7 @@ if ($mode != 'f') {
}
// Checks
if ($thread->posts()[$_GET['p']]->poster->id() != $currentUser->id() && !$forum->permission(ForumPerms::DELETE_ANY, $currentUser->id())) {
if ($thread->posts()[$_GET['p']]->poster->id != $currentUser->id && !$forum->permission(ForumPerms::DELETE_ANY, $currentUser->id)) {
// Add page specific things
$renderData['page'] = [
'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')),

View file

@ -32,9 +32,9 @@ $renderData['profile'] = $profile;
$renderData['profileView'] = isset($_GET['view']) && in_array($_GET['view'], $views) ? $_GET['view'] : $views[0];
// 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 = Database::fetch('username_history', false, ['username_old_clean' => [Main::cleanString(isset($_GET['u']) ? $_GET['u'] : 0, true, true), '=']]);
$check = Database::fetch('username_history', false, ['username_old_clean' => [Utils::cleanString(isset($_GET['u']) ? $_GET['u'] : 0, true, true), '=']]);
// Redirect if so
if ($check) {
@ -66,7 +66,7 @@ if (isset($_GET['restrict']) && $_GET['restrict'] == session_id() && $currentUse
$renderData['page'] = [
'message' => 'Toggled the restricted status of the user.',
'redirect' => $urls->format('USER_PROFILE', [$profile->id()]),
'redirect' => $urls->format('USER_PROFILE', [$profile->id]),
];
// Set parse variables

View file

@ -67,34 +67,34 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
$online = $friend->isOnline();
// If true check if they're already in the array
if ($online && !in_array($friend->id(), $onlineFriends)) {
if ($online && !in_array($friend->id, $onlineFriends)) {
// Add user to the online array
$_SESSION['friendsOnline'][$friend->id()] = $friend->id();
$_SESSION['friendsOnline'][$friend->id] = $friend->id;
// Add the notification to the display array
if ($onlineNotify) {
$notifications[] = [
'read' => 0,
'title' => $friend->username() . ' is online.',
'title' => $friend->username . ' is online.',
'text' => '',
'link' => '',
'img' => '/a/' . $friend->id(),
'img' => '/a/' . $friend->id,
'timeout' => 2000,
'sound' => false,
];
}
} elseif (!$online && in_array($friend->id(), $onlineFriends)) {
} elseif (!$online && in_array($friend->id, $onlineFriends)) {
// Remove the person from the array
unset($_SESSION['friendsOnline'][$friend->id()]);
unset($_SESSION['friendsOnline'][$friend->id]);
// Add the notification to the display array
if ($onlineNotify) {
$notifications[] = [
'read' => 0,
'title' => $friend->username() . ' is offline.',
'title' => $friend->username . ' is offline.',
'text' => '',
'link' => '',
'img' => '/a/' . $friend->id(),
'img' => '/a/' . $friend->id,
'timeout' => 2000,
'sound' => false,
];
@ -177,7 +177,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
}
$comments->makeVote(
$currentUser->id(),
$currentUser->id,
isset($_REQUEST['id']) ? $_REQUEST['id'] : 0,
isset($_REQUEST['state']) && $_REQUEST['state'] ? '1' : '0'
);
@ -213,7 +213,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
}
// Check if the comment was actually made by the current user
if ($comment['comment_poster'] !== $currentUser->id()) {
if ($comment['comment_poster'] !== $currentUser->id) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You can\'t delete the comments of others.',
@ -243,7 +243,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
}
// Attempt to make a new comment
$comment = $comments->makeComment($currentUser->id(), $_POST['replyto'], $_POST['comment']);
$comment = $comments->makeComment($currentUser->id, $_POST['replyto'], $_POST['comment']);
// Messages
$messages = [
@ -308,7 +308,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
}
// Compare time and session so we know the link isn't forged
if ($continue && $_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')] == $currentUser->id()) {
if ($continue && $_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')] == $currentUser->id) {
$renderData['page'] = [
'redirect' => $redirect,
@ -383,15 +383,15 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Create a notification
if (array_key_exists($action[1], $notifStrings)) {
// Get the current user's profile data
$user = User::construct($currentUser->id());
$user = User::construct($currentUser->id);
Users::createNotification(
$_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')],
sprintf($notifStrings[$action[1]][0], $user->username()),
sprintf($notifStrings[$action[1]][0], $user->username),
$notifStrings[$action[1]][1],
60000,
'//' . Config::get('url_main') . '/a/' . $user->id(),
'//' . Config::get('url_main') . '/u/' . $user->id(),
$urls->format('IMAGE_AVATAR', [$user->id]),
$urls->format('USER_PROFILE', [$user->id]),
'1'
);
}
@ -430,17 +430,16 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
}
// Check session variables
if (!isset($_REQUEST['timestamp'])
|| $_REQUEST['timestamp'] < time() - 1000
|| !isset($_REQUEST['sessid'])
|| $_REQUEST['sessid'] != session_id()
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;
@ -453,24 +452,31 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// 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 userData key to a variable and correct title
// Assign the correct column and title to a variable
switch ($mode) {
case 'background':
$userDataKey = 'profileBackground';
$column = 'user_background';
$msgTitle = 'Background';
$permission = (
!empty($currentUser->userData()[$userDataKey])
&& $currentUser->permission(Site::CHANGE_BACKGROUND)
) || $currentUser->permission(Site::CREATE_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:
$userDataKey = 'userAvatar';
$column = 'user_avatar';
$msgTitle = 'Avatar';
$current = $currentUser->avatar;
$permission = $currentUser->permission(Site::CHANGE_AVATAR);
}
@ -489,20 +495,15 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
}
// Set path variables
$filepath = ROOT . Config::get('user_uploads') . '/';
$filename = $filepath . $mode . '_' . $currentUser->id();
$currfile = isset($currentUser->userData()[$userDataKey])
&& !empty($currentUser->userData()[$userDataKey]) ? $currentUser->userData()[$userDataKey] : null;
$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;
}
@ -533,11 +534,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => $msg,
'success' => 0,
];
break;
}
@ -551,11 +550,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
if ($metadata == false) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Uploaded file is not an image.',
'success' => 0,
];
break;
@ -567,13 +564,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
&& ($metadata[2] !== IMAGETYPE_PNG))) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'This filetype is not allowed.',
'success' => 0,
];
break;
}
@ -582,13 +576,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|| $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;
}
@ -597,13 +588,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|| $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;
}
@ -611,54 +599,46 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
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;
}
}
// Delete old avatar
if ($currfile && file_exists($currfile)) {
unlink($filepath . $currfile);
}
// 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]);
if (!move_uploaded_file($_FILES[$mode]['tmp_name'], $filename)) {
// Set render data
$renderData['page'] = [
// Store the file
$file = File::create(file_get_contents($_FILES[$mode]['tmp_name']), $filename, $currentUser);
'redirect' => $redirect,
'message' => 'Something went wrong, please try again.',
'success' => 0,
];
// Assign the file id to a variable
$fileId = $file->id;
}
// Create new array
$updated = [$userDataKey => basename($filename)];
} else {
// Remove entry
$updated = [$userDataKey => null];
}
// Update database
$currentUser->setUserData($updated);
// Update table
Database::update('users', [
[
$column => $fileId,
],
[
'user_id' => [$currentUser->id, '='],
],
]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Updated your ' . strtolower($msgTitle) . '!',
'success' => 1,
];
break;
@ -666,13 +646,17 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
case 'profile':
// Get profile fields and create storage var
$fields = Users::getProfileFields();
$store = [];
// Go over each field
foreach ($fields as $field) {
// Add to the store array
if (isset($_POST['profile_' . $field['field_identity']]) && !empty($_POST['profile_' . $field['field_identity']])) {
$store[$field['field_identity']] = $_POST['profile_' . $field['field_identity']];
Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$field['field_identity'], '=']]);
Database::insert('user_profilefields', [
'user_id' => $currentUser->id,
'field_name' => $field['field_identity'],
'field_value' => $_POST['profile_' . $field['field_identity']],
]);
}
// Check if there's additional values we should keep in mind
@ -680,24 +664,22 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Go over each additional value
foreach ($field['field_additional'] as $addKey => $addVal) {
// Add to the array
$store[$addKey] = (isset($_POST['profile_additional_' . $addKey])
|| !empty($_POST['profile_additional_' . $addKey])) ?
$_POST['profile_additional_' . $addKey] :
false;
$store = (isset($_POST['profile_additional_' . $addKey]) || !empty($_POST['profile_additional_' . $addKey])) ? $_POST['profile_additional_' . $addKey] : false;
Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$addKey, '=']]);
Database::insert('user_profilefields', [
'user_id' => $currentUser->id,
'field_name' => $addKey,
'field_value' => $store,
]);
}
}
}
// Update database
$currentUser->setUserData(['profileFields' => $store]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Your profile has been updated!',
'success' => 1,
];
// Birthdays
@ -755,7 +737,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'user_birthday' => $birthdate,
],
[
'user_id' => [$currentUser->id(), '='],
'user_id' => [$currentUser->id, '='],
],
]);
}
@ -765,32 +747,31 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
case 'options':
// Get profile fields and create storage var
$fields = Users::getOptionFields();
$store = [];
// Go over each field
foreach ($fields as $field) {
Database::delete('user_optionfields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$field['option_id'], '=']]);
// Make sure the user has sufficient permissions to complete this action
if (!$currentUser->permission(constant('Sakura\Perms\Site::' . $field['option_permission']))) {
$store[$field['option_id']] = false;
continue;
}
$store[$field['option_id']] = isset($_POST['option_' . $field['option_id']])
&& !empty($_POST['option_' . $field['option_id']]) ?
$_POST['option_' . $field['option_id']] :
null;
if (isset($_POST['option_' . $field['option_id']])
&& !empty($_POST['option_' . $field['option_id']])) {
Database::insert('user_optionfields', [
'user_id' => $currentUser->id,
'field_name' => $field['option_id'],
'field_value' => $_POST['option_' . $field['option_id']],
]);
}
}
// Update database
$currentUser->setUserData(['userOptions' => $store]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Changed your options!',
'success' => 1,
];
break;
@ -799,11 +780,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Check permissions
if (!$currentUser->permission(Site::CHANGE_USERTITLE)) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to change your usertitle.',
'success' => 0,
];
break;
}
@ -828,7 +807,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'user_title' => (isset($_POST['usertitle']) ? $_POST['usertitle'] : null),
],
[
'user_id' => [$currentUser->id(), '='],
'user_id' => [$currentUser->id, '='],
],
]
);
@ -952,64 +931,208 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
];
break;
// Deactivation
case 'deactivate':
// Check permissions
if (!$currentUser->permission(Site::DEACTIVATE_ACCOUNT)) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to deactivate your own account.',
'success' => 0,
];
break;
}
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Nothing happened.',
'success' => 1,
];
break;
// Userpage
case 'userpage':
// Base64 encode the userpage
$userPage = base64_encode($_POST['userpage']);
if (!isset($_POST['userpage'])) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'No userpage was supplied.',
'success' => 0,
];
}
// Update database
$currentUser->setUserData(['userPage' => $userPage]);
Database::update('users', [['user_page' => $_POST['userpage']], ['user_id' => [$currentUser->id, '=']]]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Your userpage has been updated!',
'success' => 1,
];
break;
// Signature
case 'signature':
// Base64 encode the signature
$signature = base64_encode($_POST['signature']);
if (!isset($_POST['signature'])) {
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'No signature was supplied.',
'success' => 0,
];
}
// Update database
$currentUser->setUserData(['signature' => $signature]);
Database::update('users', [['user_signature' => $_POST['signature']], ['user_id' => [$currentUser->id, '=']]]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Your signature has been updated!',
'success' => 1,
];
break;
// Ranks
case 'ranks':
// Check submit data
if (!isset($_POST['rank'])) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'No rank was set.',
'success' => 0,
];
break;
}
// Check if the user is part of the rank
if (!$currentUser->hasRanks([$_POST['rank']])) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You are not in this rank.',
'success' => 0,
];
break;
}
// Leaving
if (isset($_POST['remove'])) {
// Check if we're not trying to leave hardranks
if ($_POST['rank'] <= 2) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You can\'t remove this rank.',
'success' => 0,
];
break;
}
// Remove the rank
$currentUser->removeRanks([$_POST['rank']]);
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Removed the rank from your account.',
'success' => 0,
];
break;
}
// Set as default
$currentUser->setMainRank($_POST['rank']);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Changed your main rank!',
'success' => 0,
];
break;
// Sessions
case 'sessions':
// Check if sessionid is set
if (!isset($_POST['sessionid'])) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'A required field wasn\'t set.',
'success' => 0,
];
break;
}
// Check if sessionid is set to all
if ($_POST['sessionid'] === 'all') {
// Delete all sessions assigned to the current user
Database::delete('sessions', [
'user_id' => [$currentUser->id, '='],
]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Killed all active sessions!',
'success' => 1,
];
break;
}
// Check if the session is owned by the current user
if (!Database::fetch('sessions', false, ['user_id' => [$currentUser->id, '='], 'session_id' => [$_POST['sessionid'], '=']])) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'The session you tried to kill doesn\'t exist.',
'success' => 0,
];
break;
}
// Delete the session
Database::delete('sessions', [
'session_id' => [$_POST['sessionid'], '='],
]);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Killed the session!',
'success' => 1,
];
break;
// Deactivation
case 'deactivate':
// Check permissions
if (!$currentUser->permission(Site::DEACTIVATE_ACCOUNT)) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to deactivate your account.',
'success' => 0,
];
break;
}
// Check fields
if (!isset($_POST['username'])
|| !isset($_POST['password'])
|| !isset($_POST['email'])
|| !isset($_POST['sensitive'])) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'One or more forms wasn\'t set.',
'success' => 0,
];
break;
}
// Check values
if ($_POST['username'] !== $currentUser->username
|| !Hashing::validatePassword($_POST['password'], [$currentUser->passwordAlgo, $currentUser->passwordIter, $currentUser->passwordSalt, $currentUser->passwordHash])
|| $_POST['email'] !== $currentUser->email
|| md5($_POST['sensitive']) !== '81df445067d92dd02db9098ba82b0167') {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'One or more forms wasn\'t correct.',
'success' => 0,
];
break;
}
// Deactivate account
$currentUser->removeRanks(array_keys($currentUser->ranks));
$currentUser->addRanks([1]);
$currentUser->setMainRank(1);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Your account has been deactivated!',
'success' => 1,
];
break;
@ -1172,10 +1295,18 @@ if (Users::checkLogin()) {
minimum image size is {{ background.min_width }}x{{ background.min_height }},
maximum file size is {{ background.max_size_view }}.',
],
'access' => (
isset($currentUser->userData()['profileBackground'])
&& $currentUser->permission(Site::CHANGE_BACKGROUND)
) || $currentUser->permission(Site::CREATE_BACKGROUND),
'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' => [
@ -1184,7 +1315,7 @@ if (Users::checkLogin()) {
'The custom text that is displayed on your profile.',
],
'access' => (
isset($currentUser->userData()['userPage'])
$currentUser->page
&& $currentUser->permission(Site::CHANGE_USERPAGE)
) || $currentUser->permission(Site::CREATE_USERPAGE),
'menu' => true,
@ -1364,34 +1495,25 @@ if (Users::checkLogin()) {
// 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' => Main::getByteSymbol(Config::get($mode . '_max_fsize')),
'max_size_view' => Utils::getByteSymbol(Config::get($mode . '_max_fsize')),
];
break;
// User page
case 'appearance.userpage':
$renderData['userPage'] = isset($currentUser->userData()['userPage']) ? base64_decode($currentUser->userData()['userPage']) : '';
break;
// Signature
case 'appearance.signature':
$renderData['signature'] = isset($currentUser->userData()['signature']) ? base64_decode($currentUser->userData()['signature']) : '';
break;
// Username changing
case 'account.username':
$renderData['difference'] = $currentUser->getUsernameHistory() ? Main::timeElapsed($currentUser->getUsernameHistory()[0]['change_time']) : 0;
$renderData['difference'] = $currentUser->getUsernameHistory() ? Utils::timeElapsed($currentUser->getUsernameHistory()[0]['change_time']) : 0;
break;
// Sessions
case 'advanced.sessions':
$renderData['sessions'] = Database::fetch('sessions', true, ['user_id' => [$currentUser->id(), '=']]);
$renderData['sessions'] = Database::fetch('sessions', true, ['user_id' => [$currentUser->id, '=']]);
break;
}

View file

@ -96,12 +96,12 @@ if (isset($_REQUEST['mode'])
// Attempt to complete the transaction
if ($finalise) {
// Make the user premium
$expiration = Users::addUserPremium($currentUser->id(), (2628000 * $_SESSION['premiumMonths']));
Users::updatePremiumMeta($currentUser->id());
Main::updatePremiumTracker(
$currentUser->id(),
$expiration = Users::addUserPremium($currentUser->id, (2628000 * $_SESSION['premiumMonths']));
Users::updatePremiumMeta($currentUser->id);
Utils::updatePremiumTracker(
$currentUser->id,
((float) Config::get('premium_price_per_month') * $_SESSION['premiumMonths']),
$currentUser->username()
$currentUser->username
. ' bought premium for '
. $_SESSION['premiumMonths']
. ' month'
@ -144,7 +144,7 @@ if (isset($_REQUEST['mode'])
// Premium tracker
if (isset($_GET['tracker'])) {
$renderData['tracker'] = Main::getPremiumTrackerData();
$renderData['tracker'] = Utils::getPremiumTrackerData();
// Set parse variables
$template->setVariables($renderData);

View file

@ -37,7 +37,7 @@ if ($forum->id < 0) {
}
// Check if the user has access to the forum
if (!$forum->permission(ForumPerms::VIEW, $currentUser->id())) {
if (!$forum->permission(ForumPerms::VIEW, $currentUser->id)) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
@ -72,7 +72,7 @@ if ($forum->type === 2) {
// Check if we're marking as read
if (isset($_GET['read']) && $_GET['read'] && isset($_GET['session']) && $_GET['session'] == session_id()) {
// Run the function
$forum->trackUpdateAll($currentUser->id());
$forum->trackUpdateAll($currentUser->id);
// Set render data
$renderData['page'] = [

View file

@ -44,7 +44,7 @@ if (!$thread) {
}
// Check if the user has access to the forum
if (!$forum->permission(ForumPerms::VIEW, $currentUser->id())) {
if (!$forum->permission(ForumPerms::VIEW, $currentUser->id)) {
// Set render data
$renderData['page'] = [
'message' => 'You do not have access to this thread.',
@ -60,7 +60,7 @@ if (!$forum->permission(ForumPerms::VIEW, $currentUser->id())) {
}
// Sticky thread
if (isset($_GET['sticky']) && $_GET['sticky'] == session_id() && $forum->permission(ForumPerms::STICKY, $currentUser->id())) {
if (isset($_GET['sticky']) && $_GET['sticky'] == session_id() && $forum->permission(ForumPerms::STICKY, $currentUser->id)) {
// Check the status
if ($thread->type == 1) {
$thread->type = 0;
@ -86,7 +86,7 @@ if (isset($_GET['sticky']) && $_GET['sticky'] == session_id() && $forum->permiss
}
// Announce thread
if (isset($_GET['announce']) && $_GET['announce'] == session_id() && $forum->permission(ForumPerms::ANNOUNCEMENT, $currentUser->id())) {
if (isset($_GET['announce']) && $_GET['announce'] == session_id() && $forum->permission(ForumPerms::ANNOUNCEMENT, $currentUser->id)) {
// Check the status
if ($thread->type == 2) {
$thread->type = 0;
@ -111,7 +111,7 @@ if (isset($_GET['announce']) && $_GET['announce'] == session_id() && $forum->per
}
// Lock thread
if (isset($_GET['lock']) && $_GET['lock'] == session_id() && $forum->permission(ForumPerms::LOCK, $currentUser->id())) {
if (isset($_GET['lock']) && $_GET['lock'] == session_id() && $forum->permission(ForumPerms::LOCK, $currentUser->id)) {
// Check the status
if ($thread->status == 1) {
$thread->status = 0;
@ -136,7 +136,7 @@ if (isset($_GET['lock']) && $_GET['lock'] == session_id() && $forum->permission(
}
// Trash thread
if (isset($_GET['trash']) && $_GET['trash'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id())) {
if (isset($_GET['trash']) && $_GET['trash'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id)) {
// Check the status
if ($thread->forum != Config::get('forum_trash_id')) {
$thread->move(Config::get('forum_trash_id'));
@ -163,7 +163,7 @@ if (isset($_GET['trash']) && $_GET['trash'] == session_id() && $forum->permissio
}
// Restore thread
if (isset($_GET['restore']) && $_GET['restore'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id())) {
if (isset($_GET['restore']) && $_GET['restore'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id)) {
// Check the status
if ($thread->oldForum) {
// Move thread
@ -191,7 +191,7 @@ if (isset($_GET['restore']) && $_GET['restore'] == session_id() && $forum->permi
}
// Prune thread
if (isset($_GET['prune']) && $_GET['prune'] == session_id() && $forum->permission(ForumPerms::DELETE_ANY, $currentUser->id())) {
if (isset($_GET['prune']) && $_GET['prune'] == session_id() && $forum->permission(ForumPerms::DELETE_ANY, $currentUser->id)) {
// Check the status
if ($thread->forum == Config::get('forum_trash_id')) {
$thread->delete();
@ -218,7 +218,7 @@ if (isset($_GET['prune']) && $_GET['prune'] == session_id() && $forum->permissio
}
// Update the tracking status
$thread->trackUpdate($currentUser->id());
$thread->trackUpdate($currentUser->id);
// Update views
$thread->viewsUpdate();

View file

@ -8,7 +8,7 @@
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20160114');
define('SAKURA_VERSION', '20160117');
define('SAKURA_VLABEL', 'Amethyst');
define('SAKURA_COLOUR', '#9966CC');
@ -41,7 +41,6 @@ require_once ROOT . 'libraries/CSRF.php';
require_once ROOT . 'libraries/Database.php';
require_once ROOT . 'libraries/File.php';
require_once ROOT . 'libraries/Hashing.php';
require_once ROOT . 'libraries/Main.php';
require_once ROOT . 'libraries/Manage.php';
require_once ROOT . 'libraries/News.php';
require_once ROOT . 'libraries/Payments.php';
@ -53,6 +52,7 @@ require_once ROOT . 'libraries/Trick.php';
require_once ROOT . 'libraries/Urls.php';
require_once ROOT . 'libraries/User.php';
require_once ROOT . 'libraries/Users.php';
require_once ROOT . 'libraries/Utils.php';
require_once ROOT . 'libraries/Whois.php';
require_once ROOT . 'libraries/Forum/Forum.php';
require_once ROOT . 'libraries/Forum/Post.php';
@ -67,7 +67,7 @@ foreach (glob(ROOT . 'libraries/DBWrapper/*.php') as $driver) {
}
// Set Error handler
set_error_handler(['Sakura\Main', 'errorHandler']);
set_error_handler(['Sakura\Utils', 'errorHandler']);
// Load the local configuration
Config::init(ROOT . 'config/config.ini');
@ -206,7 +206,7 @@ if (!defined('SAKURA_NO_TPL')) {
}
// Ban checking
if ($authCheck && !in_array($_SERVER['PHP_SELF'], [$urls->format('AUTH_ACTION', [], false)]) && $ban = Bans::checkBan($currentUser->id())) {
if ($authCheck && !in_array($_SERVER['PHP_SELF'], [$urls->format('AUTH_ACTION', [], false)]) && $ban = Bans::checkBan($currentUser->id)) {
// Additional render data
$renderData = array_merge($renderData, [
'ban' => [

12
server.php Normal file
View file

@ -0,0 +1,12 @@
<?php
/*
* mod_rewrite emulator for php's build in server
*/
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
if ($uri !== '/' && file_exists(__DIR__ . '/public' . $uri)) {
return false;
}
require_once __DIR__ . '/public/index.php';

View file

@ -32,6 +32,7 @@
<link rel="stylesheet" type="text/css" href="{{ sakura.resources }}/css/misaki.css" />
{{ block('css') }}
<!-- JS -->
<script type="text/javascript" src="{{ sakura.contentPath }}/scripts/sakura.js"></script>
<script type="text/javascript" src="{{ sakura.resources }}/js/misaki.js"></script>
<script type="text/javascript">
@ -61,7 +62,7 @@
// Space for things that need to happen onload
window.addEventListener("load", function() {
{% if php.self == '/profile.php' ? (profile.userData.profileBackground and not profile.optionFields.disableProfileParallax) : (user.permission(constant('Sakura\\Perms\\Site::CREATE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.userData.profileBackground and not user.optionFields.disableProfileParallax) %}
{% if php.self == '/profile.php' ? (profile.userData.profileBackground and not profile.optionFields.disableProfileParallax) : (user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.userData.profileBackground and not user.optionFields.disableProfileParallax) %}
initialiseParallax('userBackground');
{% endif %}
@ -76,7 +77,7 @@
<div class="header-fade"></div>
<div id="notifications"></div>
<div id="wrapper">
{% if php.self == '/profile.php' ? profile.userData.profileBackground : (user.permission(constant('Sakura\\Perms\\Site::CREATE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.userData.profileBackground) %}
{% if php.self == '/profile.php' ? profile.userData.profileBackground : (user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.userData.profileBackground) %}
<div id="userBackground" style="background-image: url('{{ urls.format('IMAGE_BACKGROUND', [(php.self == '/profile.php' ? profile : user).id]) }}');"></div>
{% endif %}
<div id="navigation">

View file

@ -29,10 +29,13 @@
it has been <b>{{ stats.lastRegDate }}</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 %}:<br />
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 %}
<a href="{{ urls.format('USER_PROFILE', [onlineUser.id]) }}" style="font-weight: bold; color: {{ onlineUser.colour }};" class="default">{{ onlineUser.username }}</a>{% if amount != (stats.onlineUsers|length - 1) %}, {% endif %}
{% if amount != (stats.onlineUsers|length - 1) %}, {% endif %}
<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 title="{{ onlineUser.lastOnline|date(sakura.dateFormat) }}" style="text-align: right;">{{ onlineUser.elapsed.lastOnline }}</td></tr>
{% endfor %}
</table>
{% else %}
There were no online users in the past {{ sakura.onlineTimeout / 60 }} minute{% if sakura.onlineTimeout != 60 %}s{% endif %}.
{% endif %}

View file

@ -9,7 +9,7 @@
<div class="subforums">
Subforums:
{% for forum in forum.forums %}
<a href="{% if forum.type == 2 %}{{ forum.link }}{% else %}{{ urls.format('FORUM_SUB', [forum.id]) }}{% endif %}" class="default">{{ forum.name }}</a>
{% if forum.unread(user.id) %}<span style="font-variant: small-caps; color: #6C5D7B; text-shadow: 0px 0px 5px #9475B2;">[!]</span>{% endif %} <a href="{% if forum.type == 2 %}{{ forum.link }}{% else %}{{ urls.format('FORUM_SUB', [forum.id]) }}{% endif %}" class="default">{{ forum.name }}</a>
{% endfor %}
</div>
{% endif %}

View file

@ -90,8 +90,8 @@
<a class="username">[deleted user]</a>
{% endif %}
<div class="userdata">
<div class="usertitle">{{ post.poster.userTitle }}</div>
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not post.poster.isPremium[0] %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ post.poster.country.short|lower }}.png" alt="{{ post.poster.country.long }}" />{% if post.poster.id == (thread.posts|first).poster.id %} <img src="{{ sakura.contentPath }}/images/op.png" alt="OP" title="Original Poster" />{% endif %}
<div class="usertitle">{{ post.poster.title }}</div>
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not post.poster.isPremium[0] %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ post.poster.country|lower }}.png" alt="{{ post.poster.country(true) }}" />{% if post.poster.id == (thread.posts|first).poster.id %} <img src="{{ sakura.contentPath }}/images/op.png" alt="OP" title="Original Poster" />{% endif %}
{% if session.checkLogin %}
<div class="actions">
{% if (user.id == post.poster.id and forum.permission(constant('Sakura\\Perms\\Forum::EDIT_OWN'), user.id)) or forum.permission(constant('Sakura\\Perms\\Forum::EDIT_ANY'), user.id) %}
@ -128,7 +128,7 @@
{% if post.poster.signature and post.poster.permission(constant('Sakura\\Perms\\Site::CHANGE_SIGNATURE')) %}
<div class="clear"></div>
<div class="signature bbcode">
{{ post.poster.signature|raw|nl2br }}
{{ post.poster.signature()|raw|nl2br }}
</div>
{% endif %}
</td>

View file

@ -133,10 +133,8 @@
{% endif %}
{% if php.self == '/profile.php' ? (profile.userData.profileBackground and not profile.optionFields.disableProfileParallax) : (user.permission(constant('Sakura\\Perms\\Site::CREATE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.userData.profileBackground and not user.optionFields.disableProfileParallax) %}
{% if php.self == '/profile.php' ? (profile.background and not profile.optionFields.disableProfileParallax) : (user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.background and not user.optionFields.disableProfileParallax) %}
initialiseParallax('userBackground');
{% endif %}
});
@ -191,7 +189,7 @@
</div>
<div id="contentwrapper">
<div id="notifications"></div>
{% if php.self == '/profile.php' ? profile.userData.profileBackground : (user.permission(constant('Sakura\\Perms\\Site::CREATE_BACKGROUND')) and user.optionFields.profileBackgroundSiteWide and user.userData.profileBackground) %}
{% 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' %}

View file

@ -25,12 +25,13 @@
{% else %}
<div class="content profile">
<div class="content-right content-column">
<div style="text-align: center;">
<div style="text-align: center;{% if profile.header %} background: url({{ urls.format('IMAGE_HEADER', [profile.id]) }}) no-repeat center top; background-size: 336px;{% endif %}">
<img src="{{ urls.format('IMAGE_AVATAR', [profile.id]) }}" alt="{{ profile.username }}'s Avatar" class="default-avatar-setting" style="box-shadow: 0 3px 7px #{% if profile.checkOnline %}484{% else %}844{% endif %};" /><br />
{% if profile.mainRank > 1 and profile.checkBan|length < 1 %}
<span style="font-size: .8em;">{{ profile.userTitle }}</span>
<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.short|lower }}.png" alt="{{ profile.country.short }}" style="vertical-align: middle;" /> <span style="font-size: .8em; line-height: 11px;">{{ profile.country.long }}</span>
{% if profile.mainRankId > 1 and profile.checkBan|length < 1 %}
<div class="profile-details">
<span style="font-size: .8em;">{{ profile.title }}</span>
<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]['chahttp://flashii.test/u/2/headernge_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.short }}" style="vertical-align: middle;" /> <span style="font-size: .8em; line-height: 11px;">{{ profile.country.long }}</span>
{% if session.checkLogin %}
<div class="user-actions">
{% if user.id == profile.id %}
@ -53,19 +54,20 @@
<a class="fa fa-comments-o" title="View {{ profile.username }}'s profile comments" href="{{ urls.format('USER_COMMENTS', [profile.id]) }}"></a>
{% endif %}
</div>
</div>
{% endif %}
<hr class="default" />
<b>Joined</b> <span title="{{ profile.dates.joined|date(sakura.dateFormat) }}">{{ profile.elapsed.joined }}</span>
<b>Joined</b> <span title="{{ profile.registered|date(sakura.dateFormat) }}">{{ profile.elapsed.joined }}</span>
<br />
{% if profile.dates.lastOnline < 1 %}
{% if profile.lastOnline < 1 %}
<b>{{ profile.username }} hasn't logged in yet.</b>
{% else %}
<b>Last online</b> <span title="{{ profile.dates.lastOnline|date(sakura.dateFormat) }}">{{ profile.elapsed.lastOnline }}</span>
<b>Last online</b> <span title="{{ profile.lastOnline|date(sakura.dateFormat) }}">{{ profile.elapsed.lastOnline }}</span>
{% endif %}
<br />
<b>{{ profile.username }} has {% if not profile.forumStats.posts %}no{% else %}{{ profile.forumStats.posts }}{% endif %} forum post{% if profile.forumStats.posts != 1 %}s{% endif %}.</b>
{% if profile.dates.birth != '0000-00-00' and profile.dates.birth|split('-')[0] > 0 %}
<br /><b>Age</b> <span title="{{ profile.dates.birth }}">{{ profile.elapsed(' old').birth }}</span>
{% if profile.birthday != '0000-00-00' and profile.birthday|split('-')[0] > 0 %}
<br /><b>Age</b> <span title="{{ profile.birthday }}">{{ profile.birthday(true) }} years old</span>
{% endif %}
{% if profile.profileFields or user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
<hr class="default" />
@ -98,11 +100,11 @@
</tr>
<tr>
<td style="text-align: left; font-weight: bold;">Register IP</td>
<td style="text-align: right;">{{ profile.ip(false) }}</td>
<td style="text-align: right;">{{ profile.registerIp }}</td>
</tr>
<tr>
<td style="text-align: left; font-weight: bold;">Last IP</td>
<td style="text-align: right;">{{ profile.ip(true) }}</td>
<td style="text-align: right;">{{ profile.lastIp }}</td>
</tr>
{% endif %}
</table>

View file

@ -0,0 +1,22 @@
<table class="settings-table">
<tbody>
{% for rank in user.ranks %}
<tr {% if rank.id == user.mainRankId %} class="current-session" {% endif %}>
<td style="font-weight: bold; color: {{ rank.colour }}; text-shadow: 0 0 7px {{ rank.colour }}; text-align: left;">
<a href="{{ urls.format('MEMBERLIST_RANK', [rank.id]) }}" class="clean">{{ rank.name }}</a>
</td>
<td style="width: 90px;">
<form method="post" action="{{ sakura.currentPage }}">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="rank" value="{{ rank.id }}" />
<input type="hidden" name="mode" value="ranks" />
<input type="hidden" name="submit" value="hello" />
<button class="inputStyling small" name="default">Set as main</button>
<button class="inputStyling small" name="remove" {% if rank.id <= 2 %}disabled="disabled"{% endif %}>Remove</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View file

@ -2,7 +2,7 @@
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="usertitle" />
<h3 style="text-align: center;">Your current user title is:<br /><span style="font-weight: 700;">{{ user.userTitle }}</span></h3>
<h3 style="text-align: center;">Your current user title is:<br /><span style="font-weight: 700;">{{ user.title }}</span></h3>
<div class="profile-field">
<div><h2>Usertitle</h2></div>
<div><input type="text" name="usertitle" placeholder="Enter your new user title (Max 64 characters)" class="inputStyling" value="{{ user.userTitle }}" /></div>

View file

@ -4,7 +4,7 @@
<input type="hidden" name="mode" value="deactivate" />
<div class="profile-field">
<div><h2>Username</h2></div>
<div><input type="text" name="username" placeholder="Case sensitive" class="inputStyling" /></div>
<div><input type="text" name="username" placeholder="Case sensitive, must match completely" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Password</h2></div>
@ -19,11 +19,15 @@
<div><input type="text" name="sensitive" placeholder="Are you 100% case sensitively sure?" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Verification</h2></div>
<div style="text-align: center;">{% include 'elements/captcha.twig' %}</div>
<div style="max-width: 512px; text-align: center; margin: 10px auto 0; background: repeating-linear-gradient(-45deg, #B33, #B33 10px, #B00 10px, #B00 20px); color: #FFF; border: 1px solid #C00; box-shadow: 0 0 3px #C00;">
<div>Before continuing realise that deactivating your account will remove you from every rank you're in and active Tenshi will not pause.</div>
<div>If your e-mail address is valid you can reactivate your account using the &quot;Resend Activation E-mail&quot; form on the authentication page.</div>
<div>Forum posts and other data you've published on the site <u><b>won't</b></u> be removed upon deactivation, if you want these gone you can go through them yourself.</div>
<div><h2>TL;DR: Deactivation removes all ranks from your account and won't be readded (except automated Tenshi) even if it was a joke.</h2></div>
</div>
</div>
<div class="profile-save">
<input type="submit" value="Goodbye!" name="submit" class="inputStyling" />
<input style="background: repeating-linear-gradient(-45deg, #B33, #B33 10px, #B00 10px, #B00 20px); color: #FFF; border: 1px solid #C00; box-shadow: 0 0 3px #C00, inset 0 0 3px #C00;" type="submit" value="I understand, deactivate my account" name="submit" class="inputStyling" />
</div>
</form>
<script type="text/javascript">

View file

@ -1,13 +1,41 @@
<table class="settings-table">
<thead>
<tr><th>IP</th><th style="width: 370px;">Useragent</th><th>Login time</th><th></th></tr>
<tr><th style="width: 100px;">IP</th><th>Useragent</th><th style="width: 120px;">Login time</th><th></th></tr>
</thead>
<tfoot>
<tr><th>IP</th><th>Useragent</th><th>Login time</th><th></th></tr>
</tfoot>
<tbody>
{% for session in sessions %}
{% for s in sessions %}
<tr {% if s.session_key == session.sessionId %} class="current-session"{% endif %}>
<td>
{{ s.user_ip }}
</td>
<td>
{{ s.user_agent }}
</td>
<td>
{{ s.session_start|date(sakura.dateFormat) }}
</td>
<td style="width: 90px;">
<form method="post" action="{{ sakura.currentPage }}">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="sessionid" value="{{ s.session_id }}" />
<input type="hidden" name="mode" value="sessions" />
<button class="inputStyling small" name="submit">Kill</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="profile-save">
<form method="post" action="{{ sakura.currentPage }}">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="sessionid" value="all" />
<input type="hidden" name="mode" value="sessions" />
<button class="inputStyling" name="submit">Kill all active sessions</button>
</form>
</div>

View file

@ -1,4 +1,4 @@
{% if (user.userData.profileBackground is defined and user.permission(constant('Sakura\\Perms\\Site::CHANGE_BACKGROUND'))) or user.permission(constant('Sakura\\Perms\\Site::CREATE_BACKGROUND')) %}
{% 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="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />

View file

@ -0,0 +1,24 @@
{% 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="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<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>
<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 header.</h1>
{% endif %}

View file

@ -2,7 +2,7 @@
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="signature" />
<div><textarea name="signature" id="signatureEditor" class="inputStyling" style="width: calc(100% - 12px); height: 400px;">{{ signature }}</textarea></div>
<div><textarea name="signature" id="signatureEditor" class="inputStyling" style="width: calc(100% - 12px); height: 400px;">{{ user.signature }}</textarea></div>
<div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" />

View file

@ -12,7 +12,7 @@
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="userpage" />
<div><textarea name="userpage" id="userPageEditor" placeholder="# Welcome to my user page!" class="inputStyling" style="width: calc(100% - 12px); height: 400px;">{% if userPage %}{{ userPage }}{% else %}# Welcome to my user page!{% endif %}</textarea></div>
<div><textarea name="userpage" id="userPageEditor" placeholder="# Welcome to my user page!" class="inputStyling" style="width: calc(100% - 12px); height: 400px;">{% if user.page %}{{ user.page }}{% else %}# Welcome to my user page!{% endif %}</textarea></div>
<div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" />

View file

@ -1,4 +1,4 @@
{% set birthday = user.dates.birth|split('-') %}
{% set birthday = user.birthday|split('-') %}
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="editProfileForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />

View file

@ -1 +0,0 @@
# To make sure Git keeps this folder here