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 /config/config.ini
/cache/* /cache/*
!/cache/.sakura !/cache/.sakura
/uploads/*
!/uploads/.sakura
/vendor /vendor
!/vendor/.sakura
[Tt]humbs.db [Tt]humbs.db
ehthumbs.db ehthumbs.db
Desktop.ini Desktop.ini

View file

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

View file

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

View file

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

View file

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

View file

@ -30,7 +30,7 @@ class News
} }
// Parse the news post // 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 // Attach the poster
$post['news_poster'] = $this->posters[$post['user_id']]; $post['news_poster'] = $this->posters[$post['user_id']];

View file

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

View file

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

View file

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

View file

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

View file

@ -14,31 +14,35 @@ use Sakura\Perms\Site;
*/ */
class User class User
{ {
// User data // Variables
private $data = [ public $id = 0;
'user_id' => 0, public $username = 'User';
'username' => 'User', public $usernameClean = 'user';
'username_clean' => 'user', public $passwordHash = '';
'password_hash' => '', public $passwordSalt = '';
'password_salt' => '', public $passwordAlgo = 'disabled';
'password_algo' => 'disabled', public $passwordIter = 0;
'password_iter' => 0, public $passwordChan = 0;
'password_chan' => 0, public $email = 'user@sakura';
'email' => 'sakura@localhost', public $mainRank = null;
'rank_main' => 1, public $mainRankId = 1;
'user_colour' => '', public $ranks = [];
'register_ip' => '127.0.0.1', public $colour = '';
'last_ip' => '127.0.0.1', public $registerIp = '0.0.0.0';
'user_title' => '', public $lastIp = '0.0.0.0';
'user_registered' => 0, public $title = '';
'user_last_online' => 0, public $registered = 0;
'user_birthday' => '', public $lastOnline = 0;
'user_country' => 'XX', public $country = 'XX';
'user_data' => '[]', public $avatar = 0;
]; public $background = 0;
private $ranks = []; public $header = 0;
private $mainRank = []; public $page = '';
public $signature = '';
private $birthday = '0000-00-00';
private $permissions; private $permissions;
private $optionFields = null;
private $profileFields = null;
protected static $_userCache = []; protected static $_userCache = [];
// Static initialiser // Static initialiser
@ -58,8 +62,8 @@ class User
public static function create($username, $password, $email, $ranks = [2]) public static function create($username, $password, $email, $ranks = [2])
{ {
// Set a few variables // Set a few variables
$usernameClean = Main::cleanString($username, true); $usernameClean = Utils::cleanString($username, true);
$emailClean = Main::cleanString($email, true); $emailClean = Utils::cleanString($email, true);
$password = Hashing::createHash($password); $password = Hashing::createHash($password);
// Insert the user into the database // Insert the user into the database
@ -72,11 +76,11 @@ class User
'password_iter' => $password[1], 'password_iter' => $password[1],
'email' => $emailClean, 'email' => $emailClean,
'rank_main' => 0, 'rank_main' => 0,
'register_ip' => Main::getRemoteIP(), 'register_ip' => Utils::getRemoteIP(),
'last_ip' => Main::getRemoteIP(), 'last_ip' => Utils::getRemoteIP(),
'user_registered' => time(), 'user_registered' => time(),
'user_last_online' => 0, 'user_last_online' => 0,
'user_country' => Main::getCountryCode(), 'user_country' => Utils::getCountryCode(),
'user_data' => '[]', 'user_data' => '[]',
]); ]);
@ -100,33 +104,49 @@ class User
private function __construct($uid) private function __construct($uid)
{ {
// Get the user database row // Get the user database row
$getUser = Database::fetch( $userRow = Database::fetch(
'users', 'users',
false, false,
[ [
'user_id' => [$uid, '=', true], 'user_id' => [$uid, '=', true],
'username_clean' => [Main::cleanString($uid, true), '=', true], 'username_clean' => [Utils::cleanString($uid, true), '=', true],
] ]
); );
// Check if the user actually exists // Populate the variables
if (!empty($getUser)) { if ($userRow) {
// If not assign as the fallback user $this->id = $userRow['user_id'];
$this->data = $getUser; $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 // Get all ranks
$ranks = array_map(function ($a) { $ranks = Database::fetch('user_ranks', true, ['user_id' => [$this->id, '=']]);
return $a['rank_id'];
}, Database::fetch('user_ranks', true, ['user_id' => [$this->data['user_id'], '=']]));
// Get the rows for all the ranks // Get the rows for all the ranks
foreach ($ranks as $rank) { foreach ($ranks as $rank) {
// Store the database row in the array // 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 // Check if ranks were set
@ -135,107 +155,56 @@ class User
$this->ranks[1] = Rank::construct(1); $this->ranks[1] = Rank::construct(1);
} }
// Assign the user's main rank to a special variable since we'll use it a lot // Check if the rank is actually assigned to this user
$this->mainRank = $this->ranks[ if (!array_key_exists($this->mainRankId, $this->ranks)) {
array_key_exists($this->data['rank_main'], $this->ranks) ? $this->mainRankId = array_keys($this->ranks)[0];
$this->data['rank_main'] : $this->setMainRank($this->mainRankId);
array_keys($this->ranks)[0] }
];
// 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 // Init the permissions
$this->permissions = new Perms(Perms::SITE); $this->permissions = new Perms(Perms::SITE);
} }
// Get user id // Get user birthday
public function id() 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');
}
// Otherwise just return the birthday value
return $this->birthday;
} }
// Get username (or clean variant) // Get the user's long or short country names
public function username($clean = false) public function country($long = false)
{ {
return $this->data['username' . ($clean ? '_clean' : '')]; return $long ? Utils::getCountryName($this->country) : $this->country;
}
// Get password data
public function password()
{
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'];
} }
// Check if a user is online // Check if a user is online
public function isOnline() public function isOnline()
{ {
// Get all sessions // 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 there's no entries just straight up return false
if (!$sessions) { if (!$sessions) {
@ -243,13 +212,7 @@ class User
} }
// Otherwise use the standard method // Otherwise use the standard method
return $this->data['user_last_online'] > (time() - Config::get('max_online_time')); return $this->lastOnline > (time() - Config::get('max_online_time'));
}
// Compatibility
public function checkOnline()
{
return $this->isOnline();
} }
// Get user's forum statistics // Get user's forum statistics
@ -258,12 +221,12 @@ class User
return [ return [
'posts' => Database::count( 'posts' => Database::count(
'posts', 'posts',
['poster_id' => [$this->id(), '=']] ['poster_id' => [$this->id, '=']]
)[0], )[0],
'topics' => count(Database::fetch( 'topics' => count(Database::fetch(
'posts', 'posts',
true, true,
['poster_id' => [$this->id(), '=']], ['poster_id' => [$this->id, '=']],
['post_time'], ['post_time'],
null, null,
['topic_id'] ['topic_id']
@ -275,9 +238,13 @@ class User
public function elapsed($append = ' ago', $none = 'Just now') public function elapsed($append = ' ago', $none = 'Just now')
{ {
$times = []; $times = [];
$dates = [
'joined' => $this->registered,
'lastOnline' => $this->lastOnline,
];
foreach ($this->dates() as $key => $val) { foreach ($dates as $key => $val) {
$times[$key] = Main::timeElapsed(is_string($val) ? strtotime($val) : $val, $append, $none); $times[$key] = Utils::timeElapsed($val, $append, $none);
} }
return $times; return $times;
@ -287,13 +254,20 @@ class User
public function addRanks($ranks) public function addRanks($ranks)
{ {
// Update the ranks array // 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 // Save to the database
foreach ($ranks as $rank) { foreach ($ranks as $rank) {
Database::insert('user_ranks', [ Database::insert('user_ranks', [
'rank_id' => $rank, 'rank_id' => $rank,
'user_id' => $this->id(), 'user_id' => $this->id,
]); ]);
} }
} }
@ -302,11 +276,11 @@ class User
public function removeRanks($ranks) public function removeRanks($ranks)
{ {
// Current ranks // Current ranks
$remove = array_intersect($this->ranks(), $ranks); $remove = array_intersect(array_keys($this->ranks), $ranks);
// Iterate over the ranks // Iterate over the ranks
foreach ($remove as $rank) { 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, 'rank_main' => $rank,
], ],
[ [
'user_id' => [$this->id(), '='], 'user_id' => [$this->id, '='],
], ],
]); ]);
@ -331,14 +305,14 @@ class User
public function hasRanks($ranks) public function hasRanks($ranks)
{ {
// Check if the main rank is the specified rank // Check if the main rank is the specified rank
if (in_array($this->mainRank->id(), $ranks)) { if (in_array($this->mainRankId, $ranks)) {
return true; return true;
} }
// If not go over all ranks and check if the user has them // If not go over all ranks and check if the user has them
foreach ($ranks as $rank) { foreach ($ranks as $rank) {
// We check if $rank is in $this->ranks and if yes return true // 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; return true;
} }
} }
@ -365,13 +339,13 @@ class User
// Add friend // Add friend
Database::insert('friends', [ Database::insert('friends', [
'user_id' => $this->data['user_id'], 'user_id' => $this->id,
'friend_id' => $uid, 'friend_id' => $uid,
'friend_timestamp' => time(), 'friend_timestamp' => time(),
]); ]);
// Return true because yay // 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 // Remove a friend
@ -392,14 +366,14 @@ class User
// Remove friend // Remove friend
Database::delete('friends', [ Database::delete('friends', [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
'friend_id' => [$uid, '='], 'friend_id' => [$uid, '='],
]); ]);
// Attempt to remove the request // Attempt to remove the request
if ($deleteRequest) { if ($deleteRequest) {
Database::delete('friends', [ Database::delete('friends', [
'friend_id' => [$this->data['user_id'], '='], 'friend_id' => [$this->id, '='],
'user_id' => [$uid, '='], 'user_id' => [$uid, '='],
]); ]);
} }
@ -413,14 +387,14 @@ class User
{ {
// Accepted from this user // Accepted from this user
$user = Database::count('friends', [ $user = Database::count('friends', [
'user_id' => [$this->id(), '='], 'user_id' => [$this->id, '='],
'friend_id' => [$with, '='], 'friend_id' => [$with, '='],
])[0]; ])[0];
// And the other user // And the other user
$friend = Database::count('friends', [ $friend = Database::count('friends', [
'user_id' => [$with, '='], 'user_id' => [$with, '='],
'friend_id' => [$this->id(), '='], 'friend_id' => [$this->id, '='],
])[0]; ])[0];
if ($user && $friend) { if ($user && $friend) {
@ -443,32 +417,32 @@ class User
switch ($level) { switch ($level) {
case 2: case 2:
// Get all the current user's friends // 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 // 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 // Create a difference map
$users = array_intersect($self, $others); $users = array_intersect($self, $others);
break; break;
case 1: 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; break;
case 0: case 0:
default: default:
// Get all the current user's friends // 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 // 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 // Create a difference map
$users = array_merge($others, $self); $users = array_merge($others, $self);
break; break;
case -1: case -1:
// Get all the current user's friends // 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 // 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 // Create a difference map
$users = array_diff($others, $self); $users = array_diff($others, $self);
break; break;
@ -496,7 +470,7 @@ class User
// Check if the user is banned // Check if the user is banned
public function checkBan() public function checkBan()
{ {
return Bans::checkBan($this->data['user_id']); return Bans::checkBan($this->id);
} }
// Check if the user has the proper permissions // Check if the user has the proper permissions
@ -509,7 +483,7 @@ class User
$perm = 0; $perm = 0;
// Bitwise OR it with the permissions for this forum // 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); return $this->permissions->check($flag, $perm);
} }
@ -517,49 +491,55 @@ class User
// Get a user's profile comments // Get a user's profile comments
public function profileComments() public function profileComments()
{ {
return new Comments('profile-' . $this->data['user_id']); return new Comments('profile-' . $this->id);
} }
// Get the user's profile fields // Get the user's profile fields
public function profileFields() public function profileFields()
{ {
// Get profile fields // Check if we have cached data
$profileFields = Database::fetch('profilefields'); if ($this->profileFields) {
return $this->profileFields;
// If there's nothing just return null
if (!count($profileFields)) {
return [];
} }
// Once again if nothing was returned just return null // Create array and get values
if (empty($this->data['user_data']['profileFields'])) {
return [];
}
// Create output array
$profile = []; $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 // Check if profile fields aren't fake
foreach ($profileFields as $field) { foreach ($profileFields as $field) {
// Completely strip all special characters from the field name // 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 // 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; continue;
} }
// Assign field to output with value // Assign field to output with value
$profile[$fieldName] = []; $profile[$fieldName] = [];
$profile[$fieldName]['name'] = $field['field_name']; $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']; $profile[$fieldName]['islink'] = $field['field_link'];
// If the field is set to be a link add a value for that as well // If the field is set to be a link add a value for that as well
if ($field['field_link']) { if ($field['field_link']) {
$profile[$fieldName]['link'] = str_replace( $profile[$fieldName]['link'] = str_replace(
'{{ VAL }}', '{{ VAL }}',
$this->data['user_data']['profileFields'][$fieldName], $profileValues[$fieldName],
$field['field_linkformat'] $field['field_linkformat']
); );
} }
@ -572,16 +552,19 @@ class User
// Go over all additional forms // Go over all additional forms
foreach ($additional as $subName => $subField) { foreach ($additional as $subName => $subField) {
// Check if the user has the current field set otherwise continue // 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; continue;
} }
// Assign field to output with value // 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 appropiate profile data
return $profile; return $profile;
} }
@ -589,26 +572,32 @@ class User
// Get the user's option fields // Get the user's option fields
public function optionFields() public function optionFields()
{ {
// Get option fields // Check if we have cached data
$optionFields = Database::fetch('optionfields'); if ($this->optionFields) {
return $this->optionFields;
// If there's nothing just return null
if (!count($optionFields)) {
return [];
} }
// Once again if nothing was returned just return null // Create array and get values
if (empty($this->data['user_data']['userOptions'])) {
return [];
}
// Create output array
$options = []; $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 anything was returned
if (!$optionFields || !$optionValues) {
return $options;
}
// Check if profile fields aren't fake // Check if option fields aren't fake
foreach ($optionFields as $field) { foreach ($optionFields as $field) {
// Check if the user has the current field set otherwise continue // 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; continue;
} }
@ -618,10 +607,13 @@ class User
} }
// Assign field to output with value // 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; return $options;
} }
@ -636,7 +628,7 @@ class User
// Attempt to retrieve the premium record from the database // Attempt to retrieve the premium record from the database
$getRecord = Database::fetch('premium', false, [ $getRecord = Database::fetch('premium', false, [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
]); ]);
// If nothing was returned just return false // If nothing was returned just return false
@ -658,7 +650,7 @@ class User
{ {
// Do the database query // Do the database query
$getWarnings = Database::fetch('warnings', true, [ $getWarnings = Database::fetch('warnings', true, [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
]); ]);
// Storage array // Storage array
@ -706,26 +698,13 @@ class User
// Get a user's userpage // Get a user's userpage
public function userPage() public function userPage()
{ {
return isset($this->data['user_data']['userPage']) ? return Utils::mdParse($this->page, true);
Main::mdParse(
base64_decode(
$this->data['user_data']['userPage']
),
true
) :
null;
} }
// Get a user's signature // Get a user's signature
public function signature() public function signature()
{ {
return isset($this->data['user_data']['signature']) ? return BBcode::toHTML($this->signature);
BBcode::toHTML(
base64_decode(
$this->data['user_data']['signature']
)
) :
null;
} }
// Get username change history // Get username change history
@ -733,7 +712,7 @@ class User
{ {
// Do the database query // Do the database query
$changes = Database::fetch('username_history', true, [ $changes = Database::fetch('username_history', true, [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
], ['change_id', true]); ], ['change_id', true]);
// Return all the warnings // Return all the warnings
@ -744,7 +723,7 @@ class User
public function setUsername($username) public function setUsername($username)
{ {
// Create a cleaned version // Create a cleaned version
$username_clean = Main::cleanString($username, true); $username_clean = Utils::cleanString($username, true);
// Check if the username is too short // Check if the username is too short
if (strlen($username_clean) < Config::get('username_min_length')) { if (strlen($username_clean) < Config::get('username_min_length')) {
@ -763,7 +742,7 @@ class User
], ['change_id', true]); ], ['change_id', true]);
// Check if anything was returned // 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']]; return [0, 'TOO_RECENT', $getOld['change_time']];
} }
@ -780,11 +759,11 @@ class User
// Insert into username_history table // Insert into username_history table
Database::insert('username_history', [ Database::insert('username_history', [
'change_time' => time(), 'change_time' => time(),
'user_id' => $this->data['user_id'], 'user_id' => $this->id,
'username_new' => $username, 'username_new' => $username,
'username_new_clean' => $username_clean, 'username_new_clean' => $username_clean,
'username_old' => $this->data['username'], 'username_old' => $this->username,
'username_old_clean' => $this->data['username_clean'], 'username_old_clean' => $this->usernameClean,
]); ]);
// Update userrow // Update userrow
@ -794,7 +773,7 @@ class User
'username_clean' => $username_clean, 'username_clean' => $username_clean,
], ],
[ [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
], ],
]); ]);
@ -826,7 +805,7 @@ class User
'email' => $email, 'email' => $email,
], ],
[ [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
], ],
]); ]);
@ -838,7 +817,7 @@ class User
public function setPassword($old, $new, $confirm) public function setPassword($old, $new, $confirm)
{ {
// Validate password // Validate password
switch ($this->data['password_algo']) { switch ($this->passwordAlgo) {
// Disabled account // Disabled account
case 'disabled': case 'disabled':
return [0, 'NO_LOGIN']; return [0, 'NO_LOGIN'];
@ -846,18 +825,18 @@ class User
// Default hashing method // Default hashing method
default: default:
if (!Hashing::validatePassword($old, [ if (!Hashing::validatePassword($old, [
$this->data['password_algo'], $this->passwordAlgo,
$this->data['password_iter'], $this->passwordIter,
$this->data['password_salt'], $this->passwordSalt,
$this->data['password_hash'], $this->passwordHash,
])) { ])) {
return [0, 'INCORRECT_PASSWORD', $this->data['password_chan']]; return [0, 'INCORRECT_PASSWORD', $this->passwordChan];
} }
} }
// Check password entropy // Check password entropy
if (Main::pwdEntropy($new) < Config::get('min_entropy')) { if (Utils::pwdEntropy($new) < Config::get('min_entropy')) {
return [0, 'PASS_TOO_SHIT']; return [0, 'PASS_TOO_SHIT'];
} }
@ -879,31 +858,11 @@ class User
'password_chan' => time(), 'password_chan' => time(),
], ],
[ [
'user_id' => [$this->data['user_id'], '='], 'user_id' => [$this->id, '='],
], ],
]); ]);
// Return success // Return success
return [1, '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 // Check if we haven't hit the rate limit
$rates = Database::fetch('login_attempts', true, [ $rates = Database::fetch('login_attempts', true, [
'attempt_ip' => [Main::getRemoteIP(), '='], 'attempt_ip' => [Utils::getRemoteIP(), '='],
'attempt_timestamp' => [time() - 1800, '>'], 'attempt_timestamp' => [time() - 1800, '>'],
'attempt_success' => [0, '='], 'attempt_success' => [0, '='],
]); ]);
@ -122,7 +122,7 @@ class Users
$user = User::construct($uid); $user = User::construct($uid);
// Validate password // Validate password
switch ($user->password()['password_algo']) { switch ($user->passwordAlgo) {
// Disabled // Disabled
case 'disabled': case 'disabled':
return [0, 'NO_LOGIN']; return [0, 'NO_LOGIN'];
@ -130,22 +130,22 @@ class Users
// Default hashing method // Default hashing method
default: default:
if (!Hashing::validatePassword($password, [ if (!Hashing::validatePassword($password, [
$user->password()['password_algo'], $user->passwordAlgo,
$user->password()['password_iter'], $user->passwordIter,
$user->password()['password_salt'], $user->passwordSalt,
$user->password()['password_hash'], $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 // Check if the user has the required privs to log in
if ($user->permission(Site::DEACTIVATED)) { if ($user->permission(Site::DEACTIVATED)) {
return [0, 'NOT_ALLOWED', $user->id()]; return [0, 'NOT_ALLOWED', $user->id];
} }
// Create a new session // Create a new session
$session = new Session($user->id()); $session = new Session($user->id);
// Generate a session key // Generate a session key
$sessionKey = $session->create($remember); $sessionKey = $session->create($remember);
@ -155,7 +155,7 @@ class Users
// User ID cookie // User ID cookie
setcookie( setcookie(
Config::get('cookie_prefix') . 'id', Config::get('cookie_prefix') . 'id',
$user->id(), $user->id,
time() + 604800, time() + 604800,
Config::get('cookie_path'), Config::get('cookie_path'),
Config::get('cookie_domain') Config::get('cookie_domain')
@ -172,7 +172,7 @@ class Users
} }
// Successful login! (also has a thing for the legacy password system) // 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 // Logout and kill the session
@ -228,7 +228,7 @@ class Users
// Verify the captcha if it's enabled // Verify the captcha if it's enabled
if (Config::get('recaptcha')) { if (Config::get('recaptcha')) {
if (!Main::verifyCaptcha($captcha)['success']) { if (!Utils::verifyCaptcha($captcha)['success']) {
return [0, 'CAPTCHA_FAIL']; return [0, 'CAPTCHA_FAIL'];
} }
} }
@ -254,7 +254,7 @@ class Users
} }
// Check the MX record of the email // Check the MX record of the email
if (!Main::checkMXRecord($email)) { if (!Utils::checkMXRecord($email)) {
return [0, 'INVALID_MX']; return [0, 'INVALID_MX'];
} }
@ -264,7 +264,7 @@ class Users
} }
// Check password entropy // Check password entropy
if (Main::pwdEntropy($password) < Config::get('min_entropy')) { if (Utils::pwdEntropy($password) < Config::get('min_entropy')) {
return [0, 'PASS_TOO_SHIT']; return [0, 'PASS_TOO_SHIT'];
} }
@ -283,7 +283,7 @@ class Users
// Check if we require e-mail activation // Check if we require e-mail activation
if ($requireActive) { if ($requireActive) {
// Send activation e-mail to user // Send activation e-mail to user
self::sendActivationMail($user->id()); self::sendActivationMail($user->id);
} }
// Return true with a specific message if needed // Return true with a specific message if needed
@ -299,8 +299,8 @@ class Users
} }
// Clean username string // Clean username string
$usernameClean = Main::cleanString($username, true); $usernameClean = Utils::cleanString($username, true);
$emailClean = Main::cleanString($email, true); $emailClean = Utils::cleanString($email, true);
// Do database request // Do database request
$user = Database::fetch('users', false, [ $user = Database::fetch('users', false, [
@ -322,7 +322,7 @@ class Users
} }
// Generate the verification key // Generate the verification key
$verk = ActionCode::generate('LOST_PASS', $userObj->id()); $verk = ActionCode::generate('LOST_PASS', $userObj->id);
// Create new urls object // Create new urls object
$urls = new Urls(); $urls = new Urls();
@ -339,7 +339,7 @@ class Users
$message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature'); $message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature');
// Send the message // 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 success
return [1, 'SUCCESS']; return [1, 'SUCCESS'];
@ -354,7 +354,7 @@ class Users
} }
// Check password entropy // Check password entropy
if (Main::pwdEntropy($newpass) < Config::get('min_entropy')) { if (Utils::pwdEntropy($newpass) < Config::get('min_entropy')) {
return [0, 'PASS_TOO_SHIT']; return [0, 'PASS_TOO_SHIT'];
} }
@ -402,8 +402,8 @@ class Users
} }
// Clean username string // Clean username string
$usernameClean = Main::cleanString($username, true); $usernameClean = Utils::cleanString($username, true);
$emailClean = Main::cleanString($email, true); $emailClean = Utils::cleanString($email, true);
// Do database request // Do database request
$user = Database::fetch('users', false, [ $user = Database::fetch('users', false, [
@ -438,12 +438,12 @@ class Users
$user = User::construct($uid); $user = User::construct($uid);
// User is already activated or doesn't even exist // 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; return false;
} }
// Generate activation key // Generate activation key
$activate = ActionCode::generate('ACTIVATE', $user->id()); $activate = ActionCode::generate('ACTIVATE', $user->id);
// Create new urls object // Create new urls object
$urls = new Urls(); $urls = new Urls();
@ -452,20 +452,20 @@ class Users
$message = "Welcome to " . Config::get('sitename') . "!\r\n\r\n"; $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 .= "Please keep this e-mail for your records. Your account intormation is as follows:\r\n\r\n";
$message .= "----------------------------\r\n\r\n"; $message .= "----------------------------\r\n\r\n";
$message .= "Username: " . $user->username() . "\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 .= "Your profile: http://" . Config::get('url_main') . $urls->format('USER_PROFILE', [$user->id]) . "\r\n\r\n";
$message .= "----------------------------\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 .= "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 .= "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 .= "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 .= "Thank you for registering.\r\n\r\n";
$message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature'); $message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature');
// Send the message // Send the message
Main::sendMail( Utils::sendMail(
[ [
$user->email() => $user->username(), $user->email() => $user->username,
], ],
Config::get('sitename') . ' Activation Mail', Config::get('sitename') . ' Activation Mail',
$message $message
@ -482,7 +482,7 @@ class Users
$user = User::construct($uid); $user = User::construct($uid);
// Check if user exists // Check if user exists
if (!$user->id()) { if (!$user->id) {
return [0, 'USER_NOT_EXIST']; return [0, 'USER_NOT_EXIST'];
} }
@ -494,7 +494,7 @@ class Users
// Check if a key is set // Check if a key is set
if ($requireKey) { if ($requireKey) {
// Check the action code // 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 // Check if we got a negative return
if (!$action) { if (!$action) {
@ -515,7 +515,7 @@ class Users
public static function userExists($user, $id = true) public static function userExists($user, $id = true)
{ {
// Clean string // Clean string
$user = Main::cleanString($user, true); $user = Utils::cleanString($user, true);
// Do database request // Do database request
$user = Database::fetch('users', true, [($id ? 'user_id' : 'username_clean') => [$user, '=']]); $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 // Iterate over the fields and clean them up
foreach ($profileFields as $field) { foreach ($profileFields as $field) {
$fields[$field['field_id']] = $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); $fields[$field['field_id']]['field_additional'] = json_decode($field['field_additional'], true);
} }
@ -645,18 +645,18 @@ class Users
$check = $user->isPremium(); $check = $user->isPremium();
// Check if the user has premium // 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 // If so add the rank to them
$user->addRanks([$premiumRank]); $user->addRanks([$premiumRank]);
// Check if the user's default rank is standard user and update it to premium // 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); $user->setMainRank($premiumRank);
} }
} elseif (!$check[0]) { } elseif (!$check[0]) {
// Remove the expired entry // Remove the expired entry
Database::delete('premium', [ Database::delete('premium', [
'user_id' => [$user->id(), '='], 'user_id' => [$user->id, '='],
]); ]);
// Else remove the rank from them // Else remove the rank from them
@ -694,7 +694,7 @@ class Users
// Go over all users and check if they have the rank id // Go over all users and check if they have the rank id
foreach ($users as $user) { foreach ($users as $user) {
// If so store the user's row in the array // If so store the user's row in the array
if ($user->hasRanks([$rankId], $user->id())) { if ($user->hasRanks([$rankId], $user->id)) {
$rank[] = $user; $rank[] = $user;
} }
} }
@ -721,7 +721,7 @@ class Users
continue; continue;
} }
$users[$user->id()] = $user; $users[$user->id] = $user;
} }
// and return an array with the users // and return an array with the users

View file

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

View file

@ -195,7 +195,7 @@ if (isset($_REQUEST['mode'])) {
Database::insert('login_attempts', [ Database::insert('login_attempts', [
'attempt_success' => $login[0], 'attempt_success' => $login[0],
'attempt_timestamp' => time(), 'attempt_timestamp' => time(),
'attempt_ip' => Main::getRemoteIP(), 'attempt_ip' => Utils::getRemoteIP(),
'user_id' => isset($login[2]) ? $login[2] : 0, 'user_id' => isset($login[2]) ? $login[2] : 0,
]); ]);
} }
@ -203,7 +203,7 @@ if (isset($_REQUEST['mode'])) {
// Add page specific things // Add page specific things
$renderData['page'] = [ $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]], 'message' => $messages[$login[1]],
'success' => $login[0], 'success' => $login[0],
@ -323,7 +323,7 @@ if (Users::checkLogin()) {
} }
// Check if a user has already registered from the current IP address // 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'] = [ $renderData['auth']['blockRegister'] = [
'do' => true, 'do' => true,

View file

@ -2056,7 +2056,6 @@ textarea.inputStyling {
width: 100%; width: 100%;
max-height: 200px; max-height: 200px;
overflow: auto; overflow: auto;
line-height: 1em;
} }
.forum.viewtopic .posts .post-content .signature img { .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 // Add page specific things
$renderData['page'] = [ $renderData['page'] = [
'title' => 'Frequently Asked Questions', 'title' => 'Frequently Asked Questions',
'questions' => Main::getFaqData(), 'questions' => Utils::getFaqData(),
]; ];
// Initialise templating engine // Initialise templating engine

View file

@ -12,9 +12,6 @@ define('SAKURA_NO_TPL', true);
// Include components // Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php'; 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 // Check if the m(ode) GET request is set
if (isset($_GET['m'])) { if (isset($_GET['m'])) {
switch ($_GET['m']) { switch ($_GET['m']) {
@ -58,13 +55,24 @@ if (isset($_GET['m'])) {
} }
// Check if user has an avatar set // 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; $serveImage = $noAvatar;
break; break;
} }
// Check if the avatar exist and assign it to a value // 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; break;
case 'background': case 'background':
@ -93,14 +101,24 @@ if (isset($_GET['m'])) {
} }
// Check if user has a background set // Check if user has a background set
if (empty($user->userData()['profileBackground']) if (!$user->background) {
|| !file_exists($userDirPath . $user->userData()['profileBackground'])) { $serveImage = $noBackground;
break;
}
// Attempt to get the file
$serve = new File($user->background);
// Check if the file exists
if (!$serve->id) {
$serveImage = $noBackground; $serveImage = $noBackground;
break; break;
} }
// Check if the avatar exist and assign it to a value // 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; break;
case 'header': case 'header':
@ -128,15 +146,25 @@ if (isset($_GET['m'])) {
break; break;
} }
// Check if user has a background set // Check if user has a header set
if (empty($user->userData()['profileHeader']) if (!$user->header) {
|| !file_exists($userDirPath . $user->userData()['profileHeader'])) { $serveImage = $noHeader;
break;
}
// Attempt to get the file
$serve = new File($user->header);
// Check if the file exists
if (!$serve->id) {
$serveImage = $noHeader; $serveImage = $noHeader;
break; break;
} }
// Check if the avatar exist and assign it to a value // 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; break;
default: default:
@ -147,12 +175,17 @@ if (isset($_GET['m'])) {
$serveImage = ROOT . Config::get('pixel_img'); $serveImage = ROOT . Config::get('pixel_img');
} }
// Add original filename // Do some more checks
header('Content-Disposition: inline; filename="' . basename($serveImage) . '"'); if (!isset($serveName) || !isset($serveMime)) {
$serveName = basename($serveImage);
$serveImage = file_get_contents($serveImage);
$serveMime = getimagesizefromstring($serveImage)['mime'];
}
$serveImage = file_get_contents($serveImage); // Add original filename
header('Content-Disposition: inline; filename="' . $serveName . '"');
// Set content type // 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'])) { if (isset($_GET['p'])) {
// Set default variables // Set default variables
$renderData['page'] = [ $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 // Set page id
$pageId = isset($_GET['p']) ? strtolower($_GET['p']) : ''; $pageId = isset($_GET['p']) ? strtolower($_GET['p']) : '';
// Get info page data from the database // Get info page data from the database
if ($ipData = Main::loadInfoPage($pageId)) { if ($ipData = Utils::loadInfoPage($pageId)) {
// Assign new proper variable // Assign new proper variable
$renderData['page'] = [ $renderData['page'] = [
'id' => $pageId, 'id' => $pageId,
'title' => $ipData['page_title'], '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_create(
date( date(
'Y-m-d', 'Y-m-d',
$_INDEX_NEWEST_USER->dates()['joined'] $_INDEX_NEWEST_USER->registered
) )
), ),
date_create( date_create(

View file

@ -40,7 +40,7 @@ $thread->forum;
$forum = new Forum\Forum($forumId); $forum = new Forum\Forum($forumId);
// Check if the user has access to the forum // 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 // Set render data
$renderData['page'] = [ $renderData['page'] = [
'title' => 'Information', 'title' => 'Information',
@ -56,7 +56,7 @@ if (!$forum->permission(ForumPerms::VIEW, $currentUser->id()) || !$forum->permis
} }
// Check if the user has access to the forum // 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 // Set render data
$renderData['page'] = [ $renderData['page'] = [
'title' => 'Information', 'title' => 'Information',
@ -75,7 +75,7 @@ $mode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) ? 't' : (isset($_GET['p'])
// Include emotes and bbcodes // Include emotes and bbcodes
$posting = [ $posting = [
'emoticons' => Main::getEmotes(), 'emoticons' => Utils::getEmotes(),
]; ];
// Check if we're in reply mode // Check if we're in reply mode
@ -100,7 +100,7 @@ if ($mode != 'f') {
} }
// Prompt an error if the topic doesn't exist // 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 // Add page specific things
$renderData['page'] = [ $renderData['page'] = [
'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')), 'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')),
@ -121,7 +121,7 @@ if ($mode != 'f') {
$post = $thread->posts()[$_GET['p']]; $post = $thread->posts()[$_GET['p']];
// Add subject to render data // 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 // Post editing
} elseif ($mode == 'p' && isset($_GET['edit']) && $_GET['edit'] == $_GET['p'] && array_key_exists($_GET['p'], $thread->posts())) { } 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; exit;
} }
// Checks // 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 // Add page specific things
$renderData['page'] = [ $renderData['page'] = [
'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')), 'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')),
@ -184,7 +184,7 @@ if ($mode != 'f') {
} }
// Checks // 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 // Add page specific things
$renderData['page'] = [ $renderData['page'] = [
'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')), '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]; $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 the user id is zero check if there was a namechange
if ($profile->id() == 0) { if ($profile->id == 0) {
// Fetch from username_history // 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 // Redirect if so
if ($check) { if ($check) {
@ -66,7 +66,7 @@ if (isset($_GET['restrict']) && $_GET['restrict'] == session_id() && $currentUse
$renderData['page'] = [ $renderData['page'] = [
'message' => 'Toggled the restricted status of the user.', '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 // Set parse variables

View file

@ -67,34 +67,34 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
$online = $friend->isOnline(); $online = $friend->isOnline();
// If true check if they're already in the array // 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 // 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 // Add the notification to the display array
if ($onlineNotify) { if ($onlineNotify) {
$notifications[] = [ $notifications[] = [
'read' => 0, 'read' => 0,
'title' => $friend->username() . ' is online.', 'title' => $friend->username . ' is online.',
'text' => '', 'text' => '',
'link' => '', 'link' => '',
'img' => '/a/' . $friend->id(), 'img' => '/a/' . $friend->id,
'timeout' => 2000, 'timeout' => 2000,
'sound' => false, 'sound' => false,
]; ];
} }
} elseif (!$online && in_array($friend->id(), $onlineFriends)) { } elseif (!$online && in_array($friend->id, $onlineFriends)) {
// Remove the person from the array // Remove the person from the array
unset($_SESSION['friendsOnline'][$friend->id()]); unset($_SESSION['friendsOnline'][$friend->id]);
// Add the notification to the display array // Add the notification to the display array
if ($onlineNotify) { if ($onlineNotify) {
$notifications[] = [ $notifications[] = [
'read' => 0, 'read' => 0,
'title' => $friend->username() . ' is offline.', 'title' => $friend->username . ' is offline.',
'text' => '', 'text' => '',
'link' => '', 'link' => '',
'img' => '/a/' . $friend->id(), 'img' => '/a/' . $friend->id,
'timeout' => 2000, 'timeout' => 2000,
'sound' => false, 'sound' => false,
]; ];
@ -177,7 +177,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
} }
$comments->makeVote( $comments->makeVote(
$currentUser->id(), $currentUser->id,
isset($_REQUEST['id']) ? $_REQUEST['id'] : 0, isset($_REQUEST['id']) ? $_REQUEST['id'] : 0,
isset($_REQUEST['state']) && $_REQUEST['state'] ? '1' : '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 // 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'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'You can\'t delete the comments of others.', '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 // 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
$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 // 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'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
@ -383,15 +383,15 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Create a notification // Create a notification
if (array_key_exists($action[1], $notifStrings)) { if (array_key_exists($action[1], $notifStrings)) {
// Get the current user's profile data // Get the current user's profile data
$user = User::construct($currentUser->id()); $user = User::construct($currentUser->id);
Users::createNotification( Users::createNotification(
$_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')], $_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')],
sprintf($notifStrings[$action[1]][0], $user->username()), sprintf($notifStrings[$action[1]][0], $user->username),
$notifStrings[$action[1]][1], $notifStrings[$action[1]][1],
60000, 60000,
'//' . Config::get('url_main') . '/a/' . $user->id(), $urls->format('IMAGE_AVATAR', [$user->id]),
'//' . Config::get('url_main') . '/u/' . $user->id(), $urls->format('USER_PROFILE', [$user->id]),
'1' '1'
); );
} }
@ -430,17 +430,16 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
} }
// Check session variables // Check session variables
if (!isset($_REQUEST['timestamp']) if (!isset($_POST['timestamp'])
|| $_REQUEST['timestamp'] < time() - 1000 || !isset($_POST['mode'])
|| !isset($_REQUEST['sessid']) || $_POST['timestamp'] < time() - 1000
|| $_REQUEST['sessid'] != session_id() || !isset($_POST['sessid'])
|| $_POST['sessid'] != session_id()
|| !$continue) { || !$continue) {
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Your session has expired, please refresh the page and try again.', 'message' => 'Your session has expired, please refresh the page and try again.',
'success' => 0, 'success' => 0,
]; ];
$continue = false; $continue = false;
@ -453,24 +452,31 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Avatar & Background // Avatar & Background
case 'avatar': case 'avatar':
case 'background': case 'background':
case 'header':
// Assign $_POST['mode'] to a $mode variable because I ain't typin that more than once // Assign $_POST['mode'] to a $mode variable because I ain't typin that more than once
$mode = $_POST['mode']; $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) { switch ($mode) {
case 'background': case 'background':
$userDataKey = 'profileBackground'; $column = 'user_background';
$msgTitle = 'Background'; $msgTitle = 'Background';
$permission = ( $current = $currentUser->background;
!empty($currentUser->userData()[$userDataKey]) $permission = $currentUser->permission(Site::CHANGE_BACKGROUND);
&& $currentUser->permission(Site::CHANGE_BACKGROUND) break;
) || $currentUser->permission(Site::CREATE_BACKGROUND);
case 'header':
$column = 'user_header';
$msgTitle = 'Header';
$current = $currentUser->header;
$permission = $currentUser->permission(Site::CHANGE_HEADER);
break; break;
case 'avatar': case 'avatar':
default: default:
$userDataKey = 'userAvatar'; $column = 'user_avatar';
$msgTitle = 'Avatar'; $msgTitle = 'Avatar';
$current = $currentUser->avatar;
$permission = $currentUser->permission(Site::CHANGE_AVATAR); $permission = $currentUser->permission(Site::CHANGE_AVATAR);
} }
@ -489,20 +495,15 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
} }
// Set path variables // Set path variables
$filepath = ROOT . Config::get('user_uploads') . '/'; $filename = strtolower($msgTitle) . '_' . $currentUser->id;
$filename = $filepath . $mode . '_' . $currentUser->id();
$currfile = isset($currentUser->userData()[$userDataKey])
&& !empty($currentUser->userData()[$userDataKey]) ? $currentUser->userData()[$userDataKey] : null;
// Check if $_FILES is set // Check if $_FILES is set
if (!isset($_FILES[$mode]) && empty($_FILES[$mode])) { if (!isset($_FILES[$mode]) && empty($_FILES[$mode])) {
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'No file was uploaded.', 'message' => 'No file was uploaded.',
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -533,11 +534,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => $msg, 'message' => $msg,
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -551,11 +550,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
if ($metadata == false) { if ($metadata == false) {
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Uploaded file is not an image.', 'message' => 'Uploaded file is not an image.',
'success' => 0, 'success' => 0,
]; ];
break; break;
@ -567,13 +564,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
&& ($metadata[2] !== IMAGETYPE_PNG))) { && ($metadata[2] !== IMAGETYPE_PNG))) {
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'This filetype is not allowed.', 'message' => 'This filetype is not allowed.',
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -582,13 +576,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|| $metadata[1] > Config::get($mode . '_max_height'))) { || $metadata[1] > Config::get($mode . '_max_height'))) {
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'The resolution of this picture is too big.', 'message' => 'The resolution of this picture is too big.',
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -597,13 +588,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|| $metadata[1] < Config::get($mode . '_min_height'))) { || $metadata[1] < Config::get($mode . '_min_height'))) {
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'The resolution of this picture is too small.', 'message' => 'The resolution of this picture is too small.',
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -611,54 +599,46 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
if ((filesize($_FILES[$mode]['tmp_name']) > Config::get($mode . '_max_fsize'))) { if ((filesize($_FILES[$mode]['tmp_name']) > Config::get($mode . '_max_fsize'))) {
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'The filesize of this file is too large.', 'message' => 'The filesize of this file is too large.',
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
} }
// Delete old avatar // Open the old file and remove it
if ($currfile && file_exists($currfile)) { $oldFile = new File($current);
unlink($filepath . $currfile); $oldFile->delete();
} unset($oldFile);
$fileId = 0;
if ($_FILES[$mode]['error'] != UPLOAD_ERR_NO_FILE) { if ($_FILES[$mode]['error'] != UPLOAD_ERR_NO_FILE) {
// Append extension to filename // Append extension to filename
$filename .= image_type_to_extension($metadata[2]); $filename .= image_type_to_extension($metadata[2]);
if (!move_uploaded_file($_FILES[$mode]['tmp_name'], $filename)) { // Store the file
// Set render data $file = File::create(file_get_contents($_FILES[$mode]['tmp_name']), $filename, $currentUser);
$renderData['page'] = [
'redirect' => $redirect, // Assign the file id to a variable
'message' => 'Something went wrong, please try again.', $fileId = $file->id;
'success' => 0,
];
}
// Create new array
$updated = [$userDataKey => basename($filename)];
} else {
// Remove entry
$updated = [$userDataKey => null];
} }
// Update database // Update table
$currentUser->setUserData($updated); Database::update('users', [
[
$column => $fileId,
],
[
'user_id' => [$currentUser->id, '='],
],
]);
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Updated your ' . strtolower($msgTitle) . '!', 'message' => 'Updated your ' . strtolower($msgTitle) . '!',
'success' => 1, 'success' => 1,
]; ];
break; break;
@ -666,13 +646,17 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
case 'profile': case 'profile':
// Get profile fields and create storage var // Get profile fields and create storage var
$fields = Users::getProfileFields(); $fields = Users::getProfileFields();
$store = [];
// Go over each field // Go over each field
foreach ($fields as $field) { foreach ($fields as $field) {
// Add to the store array // Add to the store array
if (isset($_POST['profile_' . $field['field_identity']]) && !empty($_POST['profile_' . $field['field_identity']])) { 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 // 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 // Go over each additional value
foreach ($field['field_additional'] as $addKey => $addVal) { foreach ($field['field_additional'] as $addKey => $addVal) {
// Add to the array // Add to the array
$store[$addKey] = (isset($_POST['profile_additional_' . $addKey]) $store = (isset($_POST['profile_additional_' . $addKey]) || !empty($_POST['profile_additional_' . $addKey])) ? $_POST['profile_additional_' . $addKey] : false;
|| !empty($_POST['profile_additional_' . $addKey])) ? Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$addKey, '=']]);
$_POST['profile_additional_' . $addKey] : Database::insert('user_profilefields', [
false; 'user_id' => $currentUser->id,
'field_name' => $addKey,
'field_value' => $store,
]);
} }
} }
} }
// Update database
$currentUser->setUserData(['profileFields' => $store]);
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Your profile has been updated!', 'message' => 'Your profile has been updated!',
'success' => 1, 'success' => 1,
]; ];
// Birthdays // Birthdays
@ -755,7 +737,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'user_birthday' => $birthdate, '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': case 'options':
// Get profile fields and create storage var // Get profile fields and create storage var
$fields = Users::getOptionFields(); $fields = Users::getOptionFields();
$store = [];
// Go over each field // Go over each field
foreach ($fields as $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 // Make sure the user has sufficient permissions to complete this action
if (!$currentUser->permission(constant('Sakura\Perms\Site::' . $field['option_permission']))) { if (!$currentUser->permission(constant('Sakura\Perms\Site::' . $field['option_permission']))) {
$store[$field['option_id']] = false;
continue; continue;
} }
$store[$field['option_id']] = isset($_POST['option_' . $field['option_id']]) if (isset($_POST['option_' . $field['option_id']])
&& !empty($_POST['option_' . $field['option_id']]) ? && !empty($_POST['option_' . $field['option_id']])) {
$_POST['option_' . $field['option_id']] : Database::insert('user_optionfields', [
null; '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 // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Changed your options!', 'message' => 'Changed your options!',
'success' => 1, 'success' => 1,
]; ];
break; break;
@ -799,11 +780,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
// Check permissions // Check permissions
if (!$currentUser->permission(Site::CHANGE_USERTITLE)) { if (!$currentUser->permission(Site::CHANGE_USERTITLE)) {
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'You aren\'t allowed to change your usertitle.', 'message' => 'You aren\'t allowed to change your usertitle.',
'success' => 0, 'success' => 0,
]; ];
break; break;
} }
@ -828,7 +807,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
'user_title' => (isset($_POST['usertitle']) ? $_POST['usertitle'] : null), '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; 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 // Userpage
case 'userpage': case 'userpage':
// Base64 encode the userpage if (!isset($_POST['userpage'])) {
$userPage = base64_encode($_POST['userpage']); // Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'No userpage was supplied.',
'success' => 0,
];
}
// Update database // Update database
$currentUser->setUserData(['userPage' => $userPage]); Database::update('users', [['user_page' => $_POST['userpage']], ['user_id' => [$currentUser->id, '=']]]);
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Your userpage has been updated!', 'message' => 'Your userpage has been updated!',
'success' => 1, 'success' => 1,
]; ];
break; break;
// Signature // Signature
case 'signature': case 'signature':
// Base64 encode the signature if (!isset($_POST['signature'])) {
$signature = base64_encode($_POST['signature']); // Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'No signature was supplied.',
'success' => 0,
];
}
// Update database // Update database
$currentUser->setUserData(['signature' => $signature]); Database::update('users', [['user_signature' => $_POST['signature']], ['user_id' => [$currentUser->id, '=']]]);
// Set render data // Set render data
$renderData['page'] = [ $renderData['page'] = [
'redirect' => $redirect, 'redirect' => $redirect,
'message' => 'Your signature has been updated!', 'message' => 'Your signature has been updated!',
'success' => 1, '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; break;
@ -1172,10 +1295,18 @@ if (Users::checkLogin()) {
minimum image size is {{ background.min_width }}x{{ background.min_height }}, minimum image size is {{ background.min_width }}x{{ background.min_height }},
maximum file size is {{ background.max_size_view }}.', maximum file size is {{ background.max_size_view }}.',
], ],
'access' => ( 'access' => $currentUser->permission(Site::CHANGE_BACKGROUND),
isset($currentUser->userData()['profileBackground']) 'menu' => true,
&& $currentUser->permission(Site::CHANGE_BACKGROUND) ],
) || $currentUser->permission(Site::CREATE_BACKGROUND), '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, 'menu' => true,
], ],
'userpage' => [ 'userpage' => [
@ -1184,7 +1315,7 @@ if (Users::checkLogin()) {
'The custom text that is displayed on your profile.', 'The custom text that is displayed on your profile.',
], ],
'access' => ( 'access' => (
isset($currentUser->userData()['userPage']) $currentUser->page
&& $currentUser->permission(Site::CHANGE_USERPAGE) && $currentUser->permission(Site::CHANGE_USERPAGE)
) || $currentUser->permission(Site::CREATE_USERPAGE), ) || $currentUser->permission(Site::CREATE_USERPAGE),
'menu' => true, 'menu' => true,
@ -1364,34 +1495,25 @@ if (Users::checkLogin()) {
// Avatar and background sizes // Avatar and background sizes
case 'appearance.avatar': case 'appearance.avatar':
case 'appearance.background': case 'appearance.background':
case 'appearance.header':
$renderData[$mode] = [ $renderData[$mode] = [
'max_width' => Config::get($mode . '_max_width'), 'max_width' => Config::get($mode . '_max_width'),
'max_height' => Config::get($mode . '_max_height'), 'max_height' => Config::get($mode . '_max_height'),
'min_width' => Config::get($mode . '_min_width'), 'min_width' => Config::get($mode . '_min_width'),
'min_height' => Config::get($mode . '_min_height'), 'min_height' => Config::get($mode . '_min_height'),
'max_size' => Config::get($mode . '_max_fsize'), '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; 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 // Username changing
case 'account.username': 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; break;
// Sessions // Sessions
case 'advanced.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; break;
} }

View file

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

View file

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

View file

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

View file

@ -8,7 +8,7 @@
namespace Sakura; namespace Sakura;
// Define Sakura version // Define Sakura version
define('SAKURA_VERSION', '20160114'); define('SAKURA_VERSION', '20160117');
define('SAKURA_VLABEL', 'Amethyst'); define('SAKURA_VLABEL', 'Amethyst');
define('SAKURA_COLOUR', '#9966CC'); define('SAKURA_COLOUR', '#9966CC');
@ -41,7 +41,6 @@ require_once ROOT . 'libraries/CSRF.php';
require_once ROOT . 'libraries/Database.php'; require_once ROOT . 'libraries/Database.php';
require_once ROOT . 'libraries/File.php'; require_once ROOT . 'libraries/File.php';
require_once ROOT . 'libraries/Hashing.php'; require_once ROOT . 'libraries/Hashing.php';
require_once ROOT . 'libraries/Main.php';
require_once ROOT . 'libraries/Manage.php'; require_once ROOT . 'libraries/Manage.php';
require_once ROOT . 'libraries/News.php'; require_once ROOT . 'libraries/News.php';
require_once ROOT . 'libraries/Payments.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/Urls.php';
require_once ROOT . 'libraries/User.php'; require_once ROOT . 'libraries/User.php';
require_once ROOT . 'libraries/Users.php'; require_once ROOT . 'libraries/Users.php';
require_once ROOT . 'libraries/Utils.php';
require_once ROOT . 'libraries/Whois.php'; require_once ROOT . 'libraries/Whois.php';
require_once ROOT . 'libraries/Forum/Forum.php'; require_once ROOT . 'libraries/Forum/Forum.php';
require_once ROOT . 'libraries/Forum/Post.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
set_error_handler(['Sakura\Main', 'errorHandler']); set_error_handler(['Sakura\Utils', 'errorHandler']);
// Load the local configuration // Load the local configuration
Config::init(ROOT . 'config/config.ini'); Config::init(ROOT . 'config/config.ini');
@ -206,7 +206,7 @@ if (!defined('SAKURA_NO_TPL')) {
} }
// Ban checking // 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 // Additional render data
$renderData = array_merge($renderData, [ $renderData = array_merge($renderData, [
'ban' => [ '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" /> <link rel="stylesheet" type="text/css" href="{{ sakura.resources }}/css/misaki.css" />
{{ block('css') }} {{ block('css') }}
<!-- JS --> <!-- 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" src="{{ sakura.resources }}/js/misaki.js"></script>
<script type="text/javascript"> <script type="text/javascript">
@ -61,7 +62,7 @@
// Space for things that need to happen onload // Space for things that need to happen onload
window.addEventListener("load", function() { 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'); initialiseParallax('userBackground');
{% endif %} {% endif %}
@ -76,7 +77,7 @@
<div class="header-fade"></div> <div class="header-fade"></div>
<div id="notifications"></div> <div id="notifications"></div>
<div id="wrapper"> <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> <div id="userBackground" style="background-image: url('{{ urls.format('IMAGE_BACKGROUND', [(php.self == '/profile.php' ? profile : user).id]) }}');"></div>
{% endif %} {% endif %}
<div id="navigation"> <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>. 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> <div class="head">Online Users</div>
{% if stats.onlineUsers %} {% 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 %}
{% for amount,onlineUser in stats.onlineUsers %} <table class="panelTable">
<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 %} {% for amount,onlineUser in stats.onlineUsers %}
{% endfor %} {% 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 %} {% else %}
There were no online users in the past {{ sakura.onlineTimeout / 60 }} minute{% if sakura.onlineTimeout != 60 %}s{% endif %}. There were no online users in the past {{ sakura.onlineTimeout / 60 }} minute{% if sakura.onlineTimeout != 60 %}s{% endif %}.
{% endif %} {% endif %}

View file

@ -9,7 +9,7 @@
<div class="subforums"> <div class="subforums">
Subforums: Subforums:
{% for forum in forum.forums %} {% 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 %} {% endfor %}
</div> </div>
{% endif %} {% endif %}

View file

@ -90,8 +90,8 @@
<a class="username">[deleted user]</a> <a class="username">[deleted user]</a>
{% endif %} {% endif %}
<div class="userdata"> <div class="userdata">
<div class="usertitle">{{ post.poster.userTitle }}</div> <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.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 %} <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 %} {% if session.checkLogin %}
<div class="actions"> <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) %} {% 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')) %} {% if post.poster.signature and post.poster.permission(constant('Sakura\\Perms\\Site::CHANGE_SIGNATURE')) %}
<div class="clear"></div> <div class="clear"></div>
<div class="signature bbcode"> <div class="signature bbcode">
{{ post.poster.signature|raw|nl2br }} {{ post.poster.signature()|raw|nl2br }}
</div> </div>
{% endif %} {% endif %}
</td> </td>

View file

@ -133,10 +133,8 @@
{% endif %} {% 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'); initialiseParallax('userBackground');
{% endif %} {% endif %}
}); });
@ -191,7 +189,7 @@
</div> </div>
<div id="contentwrapper"> <div id="contentwrapper">
<div id="notifications"></div> <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> <div id="userBackground" style="background-image: url('{{ urls.format('IMAGE_BACKGROUND', [(php.self == '/profile.php' ? profile : user).id]) }}');"></div>
{% endif %} {% endif %}
{% if not session.checkLogin and php.self != '/authenticate.php' %} {% if not session.checkLogin and php.self != '/authenticate.php' %}

View file

@ -25,47 +25,49 @@
{% else %} {% else %}
<div class="content profile"> <div class="content profile">
<div class="content-right content-column"> <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 /> <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 %} {% if profile.mainRankId > 1 and profile.checkBan|length < 1 %}
<span style="font-size: .8em;">{{ profile.userTitle }}</span> <div class="profile-details">
<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> <span style="font-size: .8em;">{{ profile.title }}</span>
{% 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> <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 session.checkLogin %} {% 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>
<div class="user-actions"> {% if session.checkLogin %}
{% if user.id == profile.id %} <div class="user-actions">
{% if user.id == profile.id %}
<a class="fa fa-pencil-square-o" title="Edit your profile" href="{{ urls.format('SETTING_MODE', ['general', 'profile']) }}"></a> <a class="fa fa-pencil-square-o" title="Edit your profile" href="{{ urls.format('SETTING_MODE', ['general', 'profile']) }}"></a>
{% else %} {% else %}
{% if user.isFriends(profile.id) != 0 %}<a class="fa fa-{% if user.isFriends(profile.id) == 2 %}heart{% else %}star{% endif %}" title="You are friends"></a>{% endif %} {% if user.isFriends(profile.id) != 0 %}<a class="fa fa-{% if user.isFriends(profile.id) == 2 %}heart{% else %}star{% endif %}" title="You are friends"></a>{% endif %}
<a class="fa fa-user-{% if user.isFriends(profile.id) == 0 %}plus{% else %}times{% endif %}" title="{% if user.isFriends(profile.id) == 0 %}Add {{ profile.username }} as a friend{% else %}Remove friend{% endif %}" href="{% if user.isFriends(profile.id) == 0 %}{{ urls.format('FRIEND_ADD', [profile.id, php.sessionid, php.time, sakura.currentPage]) }}{% else %}{{ urls.format('FRIEND_REMOVE', [profile.id, php.sessionid, php.time, sakura.currentPage]) }}{% endif %}" id="profileFriendToggle"></a> <a class="fa fa-user-{% if user.isFriends(profile.id) == 0 %}plus{% else %}times{% endif %}" title="{% if user.isFriends(profile.id) == 0 %}Add {{ profile.username }} as a friend{% else %}Remove friend{% endif %}" href="{% if user.isFriends(profile.id) == 0 %}{{ urls.format('FRIEND_ADD', [profile.id, php.sessionid, php.time, sakura.currentPage]) }}{% else %}{{ urls.format('FRIEND_REMOVE', [profile.id, php.sessionid, php.time, sakura.currentPage]) }}{% endif %}" id="profileFriendToggle"></a>
<a class="fa fa-exclamation-circle" title="Report {{ profile.username }}" href="{{ urls.format('USER_REPORT', [profile.id]) }}"></a> <a class="fa fa-exclamation-circle" title="Report {{ profile.username }}" href="{{ urls.format('USER_REPORT', [profile.id]) }}"></a>
{% endif %} {% endif %}
{% if user.permission(constant('Sakura\\Perms\\Manage::CAN_RESTRICT_USERS'), constant('Sakura\\Perms::MANAGE')) %} {% if user.permission(constant('Sakura\\Perms\\Manage::CAN_RESTRICT_USERS'), constant('Sakura\\Perms::MANAGE')) %}
<a class="fa fa-trash" title="Restrict {{ profile.username }}" href="?restrict={{ php.sessionid }}"></a> <a class="fa fa-trash" title="Restrict {{ profile.username }}" href="?restrict={{ php.sessionid }}"></a>
{% endif %} {% endif %}
<hr class="default" /> <hr class="default" />
<a class="fa fa-file-text-o" title="View {{ profile.username }}'s user page" href="{{ urls.format('USER_PROFILE', [profile.id]) }}"></a> <a class="fa fa-file-text-o" title="View {{ profile.username }}'s user page" href="{{ urls.format('USER_PROFILE', [profile.id]) }}"></a>
{#<a class="fa fa-list" title="View {{ profile.username }}'s threads" href="{{ urls.format('USER_THREADS', [profile.id]) }}"></a> {#<a class="fa fa-list" title="View {{ profile.username }}'s threads" href="{{ urls.format('USER_THREADS', [profile.id]) }}"></a>
<a class="fa fa-reply" title="View {{ profile.username }}'s posts" href="{{ urls.format('USER_POSTS', [profile.id]) }}"></a> <a class="fa fa-reply" title="View {{ profile.username }}'s posts" href="{{ urls.format('USER_POSTS', [profile.id]) }}"></a>
<a class="fa fa-star" title="View {{ profile.username }}'s friends" href="{{ urls.format('USER_FRIENDS', [profile.id]) }}"></a> shh #} <a class="fa fa-star" title="View {{ profile.username }}'s friends" href="{{ urls.format('USER_FRIENDS', [profile.id]) }}"></a> shh #}
{#<a class="fa fa-users" title="View {{ profile.username }}'s groups" href="{{ urls.format('USER_GROUPS', [profile.id]) }}"></a>#} {#<a class="fa fa-users" title="View {{ profile.username }}'s groups" href="{{ urls.format('USER_GROUPS', [profile.id]) }}"></a>#}
{% if not noUserpage %} {% if not noUserpage %}
<a class="fa fa-comments-o" title="View {{ profile.username }}'s profile comments" href="{{ urls.format('USER_COMMENTS', [profile.id]) }}"></a> <a class="fa fa-comments-o" title="View {{ profile.username }}'s profile comments" href="{{ urls.format('USER_COMMENTS', [profile.id]) }}"></a>
{% endif %} {% endif %}
</div>
</div> </div>
{% endif %} {% endif %}
<hr class="default" /> <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 /> <br />
{% if profile.dates.lastOnline < 1 %} {% if profile.lastOnline < 1 %}
<b>{{ profile.username }} hasn't logged in yet.</b> <b>{{ profile.username }} hasn't logged in yet.</b>
{% else %} {% 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 %} {% endif %}
<br /> <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> <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 %} {% if profile.birthday != '0000-00-00' and profile.birthday|split('-')[0] > 0 %}
<br /><b>Age</b> <span title="{{ profile.dates.birth }}">{{ profile.elapsed(' old').birth }}</span> <br /><b>Age</b> <span title="{{ profile.birthday }}">{{ profile.birthday(true) }} years old</span>
{% endif %} {% endif %}
{% if profile.profileFields or user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %} {% if profile.profileFields or user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
<hr class="default" /> <hr class="default" />
@ -98,11 +100,11 @@
</tr> </tr>
<tr> <tr>
<td style="text-align: left; font-weight: bold;">Register IP</td> <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>
<tr> <tr>
<td style="text-align: left; font-weight: bold;">Last IP</td> <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> </tr>
{% endif %} {% endif %}
</table> </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="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" /> <input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="usertitle" /> <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 class="profile-field">
<div><h2>Usertitle</h2></div> <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> <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" /> <input type="hidden" name="mode" value="deactivate" />
<div class="profile-field"> <div class="profile-field">
<div><h2>Username</h2></div> <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>
<div class="profile-field"> <div class="profile-field">
<div><h2>Password</h2></div> <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><input type="text" name="sensitive" placeholder="Are you 100% case sensitively sure?" class="inputStyling" /></div>
</div> </div>
<div class="profile-field"> <div class="profile-field">
<div><h2>Verification</h2></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 style="text-align: center;">{% include 'elements/captcha.twig' %}</div> <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>
<div class="profile-save"> <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> </div>
</form> </form>
<script type="text/javascript"> <script type="text/javascript">

View file

@ -1,13 +1,41 @@
<table class="settings-table"> <table class="settings-table">
<thead> <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> </thead>
<tfoot> <tfoot>
<tr><th>IP</th><th>Useragent</th><th>Login time</th><th></th></tr> <tr><th>IP</th><th>Useragent</th><th>Login time</th><th></th></tr>
</tfoot> </tfoot>
<tbody> <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 %} {% endfor %}
</tbody> </tbody>
</table> </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 }}"> <form enctype="multipart/form-data" method="post" action="{{ setting.action }}">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" /> <input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" /> <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="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" /> <input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="signature" /> <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"> <div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" /> <input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" 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="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" /> <input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="userpage" /> <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"> <div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" /> <input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" 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"> <form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="editProfileForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" /> <input type="hidden" name="sessid" value="{{ php.sessionid }}" />

View file

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