diff --git a/.gitignore b/.gitignore index 4d011f7..75a5a50 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,7 @@ google*.html /config/config.ini /cache/* !/cache/.sakura -/uploads/* -!/uploads/.sakura /vendor -!/vendor/.sakura [Tt]humbs.db ehthumbs.db Desktop.ini diff --git a/libraries/BBcode.php b/libraries/BBcode.php index dfedf67..a59513b 100644 --- a/libraries/BBcode.php +++ b/libraries/BBcode.php @@ -103,8 +103,8 @@ class BBcode $parsed = nl2br(self::$bbcode->getAsHtml()); - $parsed = Main::fixCodeTags($parsed); - $parsed = Main::parseEmotes($parsed); + $parsed = Utils::fixCodeTags($parsed); + $parsed = Utils::parseEmotes($parsed); return $parsed; } diff --git a/libraries/Comments.php b/libraries/Comments.php index c774a80..cae965c 100644 --- a/libraries/Comments.php +++ b/libraries/Comments.php @@ -40,7 +40,6 @@ class Comments // Sorting public function sortComments($comments) { - // Create storage array $layer = []; @@ -54,7 +53,7 @@ class Comments // Attach the poster $comment['comment_poster'] = $this->commenters[$comment['comment_poster']]; - $comment['comment_text'] = Main::parseEmotes(Main::cleanString($comment['comment_text'])); + $comment['comment_text'] = Utils::parseEmotes(Utils::cleanString($comment['comment_text'])); // Get likes and dislikes $votes = $this->getVotes($comment['comment_id']); @@ -95,7 +94,6 @@ class Comments // Getting a single comment public function getComment($cid) { - // Get from database return Database::fetch('comments', false, [ 'comment_id' => [$cid, '='], @@ -105,7 +103,6 @@ class Comments // Getting comment votes public function getVotes($cid) { - // Get from database return Database::fetch('comment_votes', true, [ 'vote_comment' => [$cid, '='], @@ -115,7 +112,6 @@ class Comments // Creating public function makeComment($uid, $reply, $content) { - // Check if the comment is long enough if (strlen($content) < Config::get('comment_min_length')) { return [0, 'TOO_SHORT']; @@ -142,7 +138,6 @@ class Comments // Voting public function makeVote($uid, $cid, $mode) { - // Attempt to get previous vote $vote = Database::fetch('comment_votes', false, [ 'vote_user' => [$uid, '='], @@ -185,7 +180,6 @@ class Comments // Deleting public function removeComment($cid) { - // Remove from database return Database::delete('comments', [ 'comment_id' => [$cid, '='], diff --git a/libraries/File.php b/libraries/File.php index e751a5c..3fdd627 100644 --- a/libraries/File.php +++ b/libraries/File.php @@ -5,10 +5,69 @@ namespace Sakura; +use finfo; + /** * Class File * @package Sakura */ class File { + // Variables + public $id = 0; + public $user = null; + public $data = null; + public $name = null; + public $mime = null; + public $time = 0; + public $expire = 0; + + // Create a new file + public static function create($data, $name, User $user, $expire = 0) + { + // Get the mimetype + $mime = (new finfo(FILEINFO_MIME_TYPE))->buffer($data); + + // Insert it into the database + Database::insert('uploads', [ + 'user_id' => $user->id, + 'file_data' => $data, + 'file_name' => $name, + 'file_mime' => $mime, + 'file_time' => time(), + 'file_expire' => $expire, + ]); + + // Get the last insert id + $id = Database::lastInsertID(); + + // Return a new File object + return new File($id); + } + + // Constructor + public function __construct($fileId) + { + // Attempt to get the database row + $fileRow = Database::fetch('uploads', false, ['file_id' => [$fileId, '=']]); + + // If anything was returned populate the variables + if ($fileRow) { + $this->id = $fileRow['file_id']; + $this->user = User::construct($fileRow['user_id']); + $this->data = $fileRow['file_data']; + $this->name = $fileRow['file_name']; + $this->mime = $fileRow['file_mime']; + $this->time = $fileRow['file_time']; + $this->expire = $fileRow['file_expire']; + } + } + + // Delete the file + public function delete() + { + Database::delete('uploads', [ + 'file_id' => [$this->id, '='], + ]); + } } diff --git a/libraries/Forum/Post.php b/libraries/Forum/Post.php index ff3b02d..43df388 100644 --- a/libraries/Forum/Post.php +++ b/libraries/Forum/Post.php @@ -5,7 +5,7 @@ namespace Sakura\Forum; -use Sakura\Main; +use Sakura\Utils; use Sakura\Database; use Sakura\User; use Sakura\BBcode; @@ -86,8 +86,8 @@ class Post Database::insert('posts', [ 'topic_id' => $thread->id, 'forum_id' => $thread->forum, - 'poster_id' => $poster->id(), - 'poster_ip' => Main::getRemoteIP(), + 'poster_id' => $poster->id, + 'poster_ip' => Utils::getRemoteIP(), 'post_time' => time(), 'post_subject' => $subject, 'post_text' => $text, @@ -123,14 +123,14 @@ class Post 'post_id' => $this->id, 'topic_id' => $thread->id, 'forum_id' => $thread->forum, - 'poster_id' => $this->poster->id(), - 'poster_ip' => Main::getRemoteIP(), + 'poster_id' => $this->poster->id, + 'poster_ip' => Utils::getRemoteIP(), 'post_time' => $this->time, 'post_subject' => $this->subject, 'post_text' => $this->text, 'post_edit_time' => $this->editTime, 'post_edit_reason' => $this->editReason, - 'post_edit_user' => $this->editUser->id(), + 'post_edit_user' => $this->editUser->id, ], [ 'post_id' => [$this->id, '='], @@ -144,12 +144,12 @@ class Post // Time elapsed since creation public function timeElapsed() { - return Main::timeElapsed($this->time); + return Utils::timeElapsed($this->time); } // Time elapsed since last edit public function editTimeElapsed() { - return Main::timeElapsed($this->editTime); + return Utils::timeElapsed($this->editTime); } } diff --git a/libraries/Forum/Thread.php b/libraries/Forum/Thread.php index d8c6cf3..9c2332b 100644 --- a/libraries/Forum/Thread.php +++ b/libraries/Forum/Thread.php @@ -6,7 +6,7 @@ namespace Sakura\Forum; use Sakura\Database; -use Sakura\Main; +use Sakura\Utils; /** * Class Thread @@ -206,13 +206,13 @@ class Thread // Time elapsed since creation public function timeElapsed() { - return Main::timeElapsed($this->time); + return Utils::timeElapsed($this->time); } // Time elapsed since status change public function statusChangeElapsed() { - return Main::timeElapsed($this->statusChange); + return Utils::timeElapsed($this->statusChange); } // Read status diff --git a/libraries/News.php b/libraries/News.php index 20d05d7..3d01229 100644 --- a/libraries/News.php +++ b/libraries/News.php @@ -30,7 +30,7 @@ class News } // Parse the news post - $post['news_content_parsed'] = Main::mdParse($post['news_content']); + $post['news_content_parsed'] = Utils::mdParse($post['news_content']); // Attach the poster $post['news_poster'] = $this->posters[$post['user_id']]; diff --git a/libraries/Perms.php b/libraries/Perms.php index e3daba7..fcbc6e5 100644 --- a/libraries/Perms.php +++ b/libraries/Perms.php @@ -69,7 +69,7 @@ class Perms $user = User::construct($uid); // Get data from ranks - foreach ($user->ranks() as $rank) { + foreach (array_keys($user->ranks) as $rank) { $perm = $perm | $this->rank($rank, $conditions, $perm); } diff --git a/libraries/Perms/Site.php b/libraries/Perms/Site.php index 222f511..d939f0b 100644 --- a/libraries/Perms/Site.php +++ b/libraries/Perms/Site.php @@ -15,8 +15,8 @@ class Site const RESTRICTED = 2; // Is a user restricted const ALTER_PROFILE = 4; // Can alter their profile data const CHANGE_AVATAR = 8; // Can change their avatar - const CREATE_BACKGROUND = 16; // Can create a background - const CHANGE_BACKGROUND = 32; // Can change their background + const CHANGE_BACKGROUND = 16; // Can change their background + const CHANGE_HEADER = 32; // User can change their profile header const VIEW_MEMBERLIST = 64; // Can view the memberlist const CREATE_USERPAGE = 128; // Can create a userpage const CHANGE_USERPAGE = 256; // Can change their userpage diff --git a/libraries/Rank.php b/libraries/Rank.php index 6fc8583..2e630a2 100644 --- a/libraries/Rank.php +++ b/libraries/Rank.php @@ -14,17 +14,15 @@ use Sakura\Perms\Site; */ class Rank { - // Rank data - private $data = [ - 'rank_id' => 0, - 'rank_name' => 'Rank', - 'rank_hierarchy' => 0, - 'rank_multiple' => '', - 'rank_hidden' => 1, - 'rank_colour' => 'inherit', - 'rank_description' => '', - 'rank_title' => '', - ]; + // Variables + public $id = 0; + public $name = 'Rank'; + public $hierarchy = 0; + public $multiple = ''; + public $colour = 'inherit'; + public $description = ''; + public $title = ''; + private $hidden = true; private $permissions; protected static $_rankCache = []; @@ -46,7 +44,7 @@ class Rank { // Get the rank database row - $getRank = Database::fetch( + $rankRow = Database::fetch( 'ranks', false, [ @@ -55,55 +53,31 @@ class Rank ); // Check if the rank actually exists - if (!empty($getRank)) { - // If not assign as the fallback rank - $this->data = $getRank; + if ($rankRow) { + $this->id = $rankRow['rank_id']; + $this->name = $rankRow['rank_name']; + $this->hierarchy = $rankRow['rank_hierarchy']; + $this->multiple = $rankRow['rank_multiple']; + $this->hidden = (bool) $rankRow['rank_hidden']; + $this->colour = $rankRow['rank_colour']; + $this->description = $rankRow['rank_description']; + $this->title = $rankRow['rank_title']; } // Init the permissions $this->permissions = new Perms(Perms::SITE); } - // Get the rank id - public function id() - { - return $this->data['rank_id']; - } - - // Get the rank hierarchy - public function hierarchy() - { - return $this->data['rank_hierarchy']; - } - // Get the rank name public function name($multi = false) { - return $this->data['rank_name'] . ($multi ? $this->data['rank_multiple'] : null); - } - - // Get the rank title - public function title() - { - return $this->data['rank_title']; - } - - // Get the rank description - public function description() - { - return $this->data['rank_description']; - } - - // Get the rank colour - public function colour() - { - return $this->data['rank_colour']; + return $this->name . ($multi ? $this->multiple : null); } // Check if the rank is hidden public function hidden() { - return $this->data['rank_hidden'] || $this->permission(Site::DEACTIVATED) || $this->permission(Site::RESTRICTED); + return $this->hidden || $this->permission(Site::DEACTIVATED) || $this->permission(Site::RESTRICTED); } // Check if the rank has the proper permissions @@ -113,7 +87,7 @@ class Rank $perm = 0; // Bitwise OR it with the permissions for this forum - $perm = $perm | $this->permissions->rank($this->id()); + $perm = $perm | $this->permissions->rank($this->id); return $this->permissions->check($flag, $perm); } diff --git a/libraries/Session.php b/libraries/Session.php index 8a40f71..6994032 100644 --- a/libraries/Session.php +++ b/libraries/Session.php @@ -66,8 +66,8 @@ class Session // Insert the session into the database Database::insert('sessions', [ 'user_id' => $this->userId, - 'user_ip' => Main::getRemoteIP(), - 'user_agent' => Main::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'), + 'user_ip' => Utils::getRemoteIP(), + 'user_agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'), 'session_key' => $session, 'session_start' => time(), 'session_expire' => time() + 604800, @@ -105,7 +105,7 @@ class Session if ($ipCheck) { // Split both IPs up $sessionIP = explode('.', $session['user_ip']); - $userIP = explode('.', Main::getRemoteIP()); + $userIP = explode('.', Utils::getRemoteIP()); // Take 1 off the ipCheck variable so it's equal to the array keys $ipCheck = $ipCheck - 1; diff --git a/libraries/User.php b/libraries/User.php index 4934eca..65c144c 100644 --- a/libraries/User.php +++ b/libraries/User.php @@ -14,31 +14,35 @@ use Sakura\Perms\Site; */ class User { - // User data - private $data = [ - 'user_id' => 0, - 'username' => 'User', - 'username_clean' => 'user', - 'password_hash' => '', - 'password_salt' => '', - 'password_algo' => 'disabled', - 'password_iter' => 0, - 'password_chan' => 0, - 'email' => 'sakura@localhost', - 'rank_main' => 1, - 'user_colour' => '', - 'register_ip' => '127.0.0.1', - 'last_ip' => '127.0.0.1', - 'user_title' => '', - 'user_registered' => 0, - 'user_last_online' => 0, - 'user_birthday' => '', - 'user_country' => 'XX', - 'user_data' => '[]', - ]; - private $ranks = []; - private $mainRank = []; + // Variables + public $id = 0; + public $username = 'User'; + public $usernameClean = 'user'; + public $passwordHash = ''; + public $passwordSalt = ''; + public $passwordAlgo = 'disabled'; + public $passwordIter = 0; + public $passwordChan = 0; + public $email = 'user@sakura'; + public $mainRank = null; + public $mainRankId = 1; + public $ranks = []; + public $colour = ''; + public $registerIp = '0.0.0.0'; + public $lastIp = '0.0.0.0'; + public $title = ''; + public $registered = 0; + public $lastOnline = 0; + public $country = 'XX'; + public $avatar = 0; + public $background = 0; + public $header = 0; + public $page = ''; + public $signature = ''; + private $birthday = '0000-00-00'; private $permissions; + private $optionFields = null; + private $profileFields = null; protected static $_userCache = []; // Static initialiser @@ -58,8 +62,8 @@ class User public static function create($username, $password, $email, $ranks = [2]) { // Set a few variables - $usernameClean = Main::cleanString($username, true); - $emailClean = Main::cleanString($email, true); + $usernameClean = Utils::cleanString($username, true); + $emailClean = Utils::cleanString($email, true); $password = Hashing::createHash($password); // Insert the user into the database @@ -72,11 +76,11 @@ class User 'password_iter' => $password[1], 'email' => $emailClean, 'rank_main' => 0, - 'register_ip' => Main::getRemoteIP(), - 'last_ip' => Main::getRemoteIP(), + 'register_ip' => Utils::getRemoteIP(), + 'last_ip' => Utils::getRemoteIP(), 'user_registered' => time(), 'user_last_online' => 0, - 'user_country' => Main::getCountryCode(), + 'user_country' => Utils::getCountryCode(), 'user_data' => '[]', ]); @@ -100,33 +104,49 @@ class User private function __construct($uid) { // Get the user database row - $getUser = Database::fetch( + $userRow = Database::fetch( 'users', false, [ 'user_id' => [$uid, '=', true], - 'username_clean' => [Main::cleanString($uid, true), '=', true], + 'username_clean' => [Utils::cleanString($uid, true), '=', true], ] ); - // Check if the user actually exists - if (!empty($getUser)) { - // If not assign as the fallback user - $this->data = $getUser; + // Populate the variables + if ($userRow) { + $this->id = $userRow['user_id']; + $this->username = $userRow['username']; + $this->usernameClean = $userRow['username_clean']; + $this->passwordHash = $userRow['password_hash']; + $this->passwordSalt = $userRow['password_salt']; + $this->passwordAlgo = $userRow['password_algo']; + $this->passwordIter = $userRow['password_iter']; + $this->passwordChan = $userRow['password_chan']; + $this->email = $userRow['email']; + $this->mainRankId = $userRow['rank_main']; + $this->colour = $userRow['user_colour']; + $this->registerIp = $userRow['register_ip']; + $this->lastIp = $userRow['last_ip']; + $this->title = $userRow['user_title']; + $this->registered = $userRow['user_registered']; + $this->lastOnline = $userRow['user_last_online']; + $this->birthday = $userRow['user_birthday']; + $this->country = $userRow['user_country']; + $this->avatar = $userRow['user_avatar']; + $this->background = $userRow['user_background']; + $this->header = $userRow['user_header']; + $this->page = $userRow['user_page']; + $this->signature = $userRow['user_signature']; } - // Decode the json in the user_data column - $this->data['user_data'] = json_decode(!empty($this->data['user_data']) ? $this->data['user_data'] : '[]', true); - // Get all ranks - $ranks = array_map(function ($a) { - return $a['rank_id']; - }, Database::fetch('user_ranks', true, ['user_id' => [$this->data['user_id'], '=']])); + $ranks = Database::fetch('user_ranks', true, ['user_id' => [$this->id, '=']]); // Get the rows for all the ranks foreach ($ranks as $rank) { // Store the database row in the array - $this->ranks[$rank] = Rank::construct($rank); + $this->ranks[$rank['rank_id']] = Rank::construct($rank['rank_id']); } // Check if ranks were set @@ -135,107 +155,56 @@ class User $this->ranks[1] = Rank::construct(1); } - // Assign the user's main rank to a special variable since we'll use it a lot - $this->mainRank = $this->ranks[ - array_key_exists($this->data['rank_main'], $this->ranks) ? - $this->data['rank_main'] : - array_keys($this->ranks)[0] - ]; + // Check if the rank is actually assigned to this user + if (!array_key_exists($this->mainRankId, $this->ranks)) { + $this->mainRankId = array_keys($this->ranks)[0]; + $this->setMainRank($this->mainRankId); + } + + // Assign the main rank to its own var + $this->mainRank = $this->ranks[$this->mainRankId]; + + // Set user colour + $this->colour = $this->colour ? $this->colour : $this->mainRank->colour; + + // Set user title + $this->title = $this->title ? $this->title : $this->mainRank->title; // Init the permissions $this->permissions = new Perms(Perms::SITE); } - // Get user id - public function id() + // Get user birthday + public function birthday($age = false) { - return $this->data['user_id']; + // If age is requested calculate it + if ($age) { + // Create dates + $birthday = date_create($this->birthday); + $now = date_create(date('Y-m-d')); + + // Get the difference + $diff = date_diff($birthday, $now); + + // Return the difference in years + return $diff->format('%Y'); + } + + // Otherwise just return the birthday value + return $this->birthday; } - // Get username (or clean variant) - public function username($clean = false) + // Get the user's long or short country names + public function country($long = false) { - return $this->data['username' . ($clean ? '_clean' : '')]; - } - - // 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']; + return $long ? Utils::getCountryName($this->country) : $this->country; } // Check if a user is online public function isOnline() { // Get all sessions - $sessions = Database::fetch('sessions', true, ['user_id' => [$this->id(), '=']]); + $sessions = Database::fetch('sessions', true, ['user_id' => [$this->id, '=']]); // If there's no entries just straight up return false if (!$sessions) { @@ -243,13 +212,7 @@ class User } // Otherwise use the standard method - return $this->data['user_last_online'] > (time() - Config::get('max_online_time')); - } - - // Compatibility - public function checkOnline() - { - return $this->isOnline(); + return $this->lastOnline > (time() - Config::get('max_online_time')); } // Get user's forum statistics @@ -258,12 +221,12 @@ class User return [ 'posts' => Database::count( 'posts', - ['poster_id' => [$this->id(), '=']] + ['poster_id' => [$this->id, '=']] )[0], 'topics' => count(Database::fetch( 'posts', true, - ['poster_id' => [$this->id(), '=']], + ['poster_id' => [$this->id, '=']], ['post_time'], null, ['topic_id'] @@ -275,9 +238,13 @@ class User public function elapsed($append = ' ago', $none = 'Just now') { $times = []; + $dates = [ + 'joined' => $this->registered, + 'lastOnline' => $this->lastOnline, + ]; - foreach ($this->dates() as $key => $val) { - $times[$key] = Main::timeElapsed(is_string($val) ? strtotime($val) : $val, $append, $none); + foreach ($dates as $key => $val) { + $times[$key] = Utils::timeElapsed($val, $append, $none); } return $times; @@ -287,13 +254,20 @@ class User public function addRanks($ranks) { // Update the ranks array - $ranks = array_diff(array_unique(array_merge($this->ranks(), $ranks)), $this->ranks()); + $ranks = array_diff( + array_unique( + array_merge( + array_keys($this->ranks), + $ranks) + ), + array_keys($this->ranks) + ); // Save to the database foreach ($ranks as $rank) { Database::insert('user_ranks', [ 'rank_id' => $rank, - 'user_id' => $this->id(), + 'user_id' => $this->id, ]); } } @@ -302,11 +276,11 @@ class User public function removeRanks($ranks) { // Current ranks - $remove = array_intersect($this->ranks(), $ranks); + $remove = array_intersect(array_keys($this->ranks), $ranks); // Iterate over the ranks foreach ($remove as $rank) { - Database::delete('user_ranks', ['user_id' => [$this->id(), '='], 'rank_id' => [$rank, '=']]); + Database::delete('user_ranks', ['user_id' => [$this->id, '='], 'rank_id' => [$rank, '=']]); } } @@ -319,7 +293,7 @@ class User 'rank_main' => $rank, ], [ - 'user_id' => [$this->id(), '='], + 'user_id' => [$this->id, '='], ], ]); @@ -331,14 +305,14 @@ class User public function hasRanks($ranks) { // Check if the main rank is the specified rank - if (in_array($this->mainRank->id(), $ranks)) { + if (in_array($this->mainRankId, $ranks)) { return true; } // If not go over all ranks and check if the user has them foreach ($ranks as $rank) { // We check if $rank is in $this->ranks and if yes return true - if (in_array($rank, $this->ranks())) { + if (in_array($rank, array_keys($this->ranks))) { return true; } } @@ -365,13 +339,13 @@ class User // Add friend Database::insert('friends', [ - 'user_id' => $this->data['user_id'], + 'user_id' => $this->id, 'friend_id' => $uid, 'friend_timestamp' => time(), ]); // Return true because yay - return [1, $user->isFriends($this->id()) ? 'FRIENDS' : 'NOT_MUTUAL']; + return [1, $user->isFriends($this->id) ? 'FRIENDS' : 'NOT_MUTUAL']; } // Remove a friend @@ -392,14 +366,14 @@ class User // Remove friend Database::delete('friends', [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], 'friend_id' => [$uid, '='], ]); // Attempt to remove the request if ($deleteRequest) { Database::delete('friends', [ - 'friend_id' => [$this->data['user_id'], '='], + 'friend_id' => [$this->id, '='], 'user_id' => [$uid, '='], ]); } @@ -413,14 +387,14 @@ class User { // Accepted from this user $user = Database::count('friends', [ - 'user_id' => [$this->id(), '='], + 'user_id' => [$this->id, '='], 'friend_id' => [$with, '='], ])[0]; // And the other user $friend = Database::count('friends', [ 'user_id' => [$with, '='], - 'friend_id' => [$this->id(), '='], + 'friend_id' => [$this->id, '='], ])[0]; if ($user && $friend) { @@ -443,32 +417,32 @@ class User switch ($level) { case 2: // Get all the current user's friends - $self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id'); + $self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id'); // Get all the people that added this user as a friend - $others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id(), '=']]), 'user_id'); + $others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id'); // Create a difference map $users = array_intersect($self, $others); break; case 1: - $users = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id'); + $users = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id'); break; case 0: default: // Get all the current user's friends - $self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id'); + $self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id'); // Get all the people that added this user as a friend - $others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id(), '=']]), 'user_id'); + $others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id'); // Create a difference map $users = array_merge($others, $self); break; case -1: // Get all the current user's friends - $self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id(), '=']]), 'friend_id'); + $self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id'); // Get all the people that added this user as a friend - $others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id(), '=']]), 'user_id'); + $others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id'); // Create a difference map $users = array_diff($others, $self); break; @@ -496,7 +470,7 @@ class User // Check if the user is banned public function checkBan() { - return Bans::checkBan($this->data['user_id']); + return Bans::checkBan($this->id); } // Check if the user has the proper permissions @@ -509,7 +483,7 @@ class User $perm = 0; // Bitwise OR it with the permissions for this forum - $perm = $this->permissions->user($this->id()); + $perm = $this->permissions->user($this->id); return $this->permissions->check($flag, $perm); } @@ -517,49 +491,55 @@ class User // Get a user's profile comments public function profileComments() { - return new Comments('profile-' . $this->data['user_id']); + return new Comments('profile-' . $this->id); } // Get the user's profile fields public function profileFields() { - // Get profile fields - $profileFields = Database::fetch('profilefields'); - - // If there's nothing just return null - if (!count($profileFields)) { - return []; + // Check if we have cached data + if ($this->profileFields) { + return $this->profileFields; } - // Once again if nothing was returned just return null - if (empty($this->data['user_data']['profileFields'])) { - return []; - } - - // Create output array + // Create array and get values $profile = []; + $profileFields = Database::fetch('profilefields'); + $profileValuesRaw = Database::fetch('user_profilefields', true, ['user_id' => [$this->id, '=']]); + $profileValueKeys = array_map(function ($a) { + return $a['field_name']; + }, $profileValuesRaw); + $profileValueVals = array_map(function ($a) { + return $a['field_value']; + }, $profileValuesRaw); + $profileValues = array_combine($profileValueKeys, $profileValueVals); + + // Check if anything was returned + if (!$profileFields || !$profileValues) { + return $profile; + } // Check if profile fields aren't fake foreach ($profileFields as $field) { // Completely strip all special characters from the field name - $fieldName = Main::cleanString($field['field_name'], true, true); + $fieldName = Utils::cleanString($field['field_name'], true, true); // Check if the user has the current field set otherwise continue - if (!array_key_exists($fieldName, $this->data['user_data']['profileFields'])) { + if (!array_key_exists($fieldName, $profileValues)) { continue; } // Assign field to output with value $profile[$fieldName] = []; $profile[$fieldName]['name'] = $field['field_name']; - $profile[$fieldName]['value'] = $this->data['user_data']['profileFields'][$fieldName]; + $profile[$fieldName]['value'] = $profileValues[$fieldName]; $profile[$fieldName]['islink'] = $field['field_link']; // If the field is set to be a link add a value for that as well if ($field['field_link']) { $profile[$fieldName]['link'] = str_replace( '{{ VAL }}', - $this->data['user_data']['profileFields'][$fieldName], + $profileValues[$fieldName], $field['field_linkformat'] ); } @@ -572,16 +552,19 @@ class User // Go over all additional forms foreach ($additional as $subName => $subField) { // Check if the user has the current field set otherwise continue - if (!array_key_exists($subName, $this->data['user_data']['profileFields'])) { + if (!array_key_exists($subName, $profileValues)) { continue; } // Assign field to output with value - $profile[$fieldName][$subName] = $this->data['user_data']['profileFields'][$subName]; + $profile[$fieldName][$subName] = $profileValues[$subName]; } } } + // Assign cache + $this->profileFields = $profile; + // Return appropiate profile data return $profile; } @@ -589,26 +572,32 @@ class User // Get the user's option fields public function optionFields() { - // Get option fields - $optionFields = Database::fetch('optionfields'); - - // If there's nothing just return null - if (!count($optionFields)) { - return []; + // Check if we have cached data + if ($this->optionFields) { + return $this->optionFields; } - // Once again if nothing was returned just return null - if (empty($this->data['user_data']['userOptions'])) { - return []; - } - - // Create output array + // Create array and get values $options = []; + $optionFields = Database::fetch('optionfields'); + $optionValuesRaw = Database::fetch('user_optionfields', true, ['user_id' => [$this->id, '=']]); + $optionValueKeys = array_map(function ($a) { + return $a['field_name']; + }, $optionValuesRaw); + $optionValueVals = array_map(function ($a) { + return $a['field_value']; + }, $optionValuesRaw); + $optionValues = array_combine($optionValueKeys, $optionValueVals); + + // Check if 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) { // Check if the user has the current field set otherwise continue - if (!array_key_exists($field['option_id'], $this->data['user_data']['userOptions'])) { + if (!array_key_exists($field['option_id'], $optionValues)) { continue; } @@ -618,10 +607,13 @@ class User } // Assign field to output with value - $options[$field['option_id']] = $this->data['user_data']['userOptions'][$field['option_id']]; + $options[$field['option_id']] = $optionValues[$field['option_id']]; } - - // Return appropiate profile data + + // Assign cache + $this->optionFields = $options; + + // Return appropiate option data return $options; } @@ -636,7 +628,7 @@ class User // Attempt to retrieve the premium record from the database $getRecord = Database::fetch('premium', false, [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], ]); // If nothing was returned just return false @@ -658,7 +650,7 @@ class User { // Do the database query $getWarnings = Database::fetch('warnings', true, [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], ]); // Storage array @@ -706,26 +698,13 @@ class User // Get a user's userpage public function userPage() { - return isset($this->data['user_data']['userPage']) ? - Main::mdParse( - base64_decode( - $this->data['user_data']['userPage'] - ), - true - ) : - null; + return Utils::mdParse($this->page, true); } // Get a user's signature public function signature() { - return isset($this->data['user_data']['signature']) ? - BBcode::toHTML( - base64_decode( - $this->data['user_data']['signature'] - ) - ) : - null; + return BBcode::toHTML($this->signature); } // Get username change history @@ -733,7 +712,7 @@ class User { // Do the database query $changes = Database::fetch('username_history', true, [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], ], ['change_id', true]); // Return all the warnings @@ -744,7 +723,7 @@ class User public function setUsername($username) { // Create a cleaned version - $username_clean = Main::cleanString($username, true); + $username_clean = Utils::cleanString($username, true); // Check if the username is too short if (strlen($username_clean) < Config::get('username_min_length')) { @@ -763,7 +742,7 @@ class User ], ['change_id', true]); // Check if anything was returned - if ($getOld && $getOld['user_id'] != $this->id()) { + if ($getOld && $getOld['user_id'] != $this->id) { return [0, 'TOO_RECENT', $getOld['change_time']]; } @@ -780,11 +759,11 @@ class User // Insert into username_history table Database::insert('username_history', [ 'change_time' => time(), - 'user_id' => $this->data['user_id'], + 'user_id' => $this->id, 'username_new' => $username, 'username_new_clean' => $username_clean, - 'username_old' => $this->data['username'], - 'username_old_clean' => $this->data['username_clean'], + 'username_old' => $this->username, + 'username_old_clean' => $this->usernameClean, ]); // Update userrow @@ -794,7 +773,7 @@ class User 'username_clean' => $username_clean, ], [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], ], ]); @@ -826,7 +805,7 @@ class User 'email' => $email, ], [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], ], ]); @@ -838,7 +817,7 @@ class User public function setPassword($old, $new, $confirm) { // Validate password - switch ($this->data['password_algo']) { + switch ($this->passwordAlgo) { // Disabled account case 'disabled': return [0, 'NO_LOGIN']; @@ -846,18 +825,18 @@ class User // Default hashing method default: if (!Hashing::validatePassword($old, [ - $this->data['password_algo'], - $this->data['password_iter'], - $this->data['password_salt'], - $this->data['password_hash'], + $this->passwordAlgo, + $this->passwordIter, + $this->passwordSalt, + $this->passwordHash, ])) { - return [0, 'INCORRECT_PASSWORD', $this->data['password_chan']]; + return [0, 'INCORRECT_PASSWORD', $this->passwordChan]; } } // Check password entropy - if (Main::pwdEntropy($new) < Config::get('min_entropy')) { + if (Utils::pwdEntropy($new) < Config::get('min_entropy')) { return [0, 'PASS_TOO_SHIT']; } @@ -879,31 +858,11 @@ class User 'password_chan' => time(), ], [ - 'user_id' => [$this->data['user_id'], '='], + 'user_id' => [$this->id, '='], ], ]); // Return success return [1, 'SUCCESS']; } - - // Update a user's userData - public function setUserData($data) - { - // Merge the arrays - $data = array_merge($this->userData(), $data); - - // Encode it - $data = json_encode($data); - - // Save it in the database - Database::update('users', [ - [ - 'user_data' => $data, - ], - [ - 'user_id' => [$this->id(), '='], - ], - ]); - } } diff --git a/libraries/Users.php b/libraries/Users.php index 9d15016..23bdeb5 100644 --- a/libraries/Users.php +++ b/libraries/Users.php @@ -104,7 +104,7 @@ class Users // Check if we haven't hit the rate limit $rates = Database::fetch('login_attempts', true, [ - 'attempt_ip' => [Main::getRemoteIP(), '='], + 'attempt_ip' => [Utils::getRemoteIP(), '='], 'attempt_timestamp' => [time() - 1800, '>'], 'attempt_success' => [0, '='], ]); @@ -122,7 +122,7 @@ class Users $user = User::construct($uid); // Validate password - switch ($user->password()['password_algo']) { + switch ($user->passwordAlgo) { // Disabled case 'disabled': return [0, 'NO_LOGIN']; @@ -130,22 +130,22 @@ class Users // Default hashing method default: if (!Hashing::validatePassword($password, [ - $user->password()['password_algo'], - $user->password()['password_iter'], - $user->password()['password_salt'], - $user->password()['password_hash'], + $user->passwordAlgo, + $user->passwordIter, + $user->passwordSalt, + $user->passwordHash, ])) { - return [0, 'INCORRECT_PASSWORD', $user->id(), $user->password()['password_chan']]; + return [0, 'INCORRECT_PASSWORD', $user->id, $user->passwordChan]; } } // Check if the user has the required privs to log in if ($user->permission(Site::DEACTIVATED)) { - return [0, 'NOT_ALLOWED', $user->id()]; + return [0, 'NOT_ALLOWED', $user->id]; } // Create a new session - $session = new Session($user->id()); + $session = new Session($user->id); // Generate a session key $sessionKey = $session->create($remember); @@ -155,7 +155,7 @@ class Users // User ID cookie setcookie( Config::get('cookie_prefix') . 'id', - $user->id(), + $user->id, time() + 604800, Config::get('cookie_path'), Config::get('cookie_domain') @@ -172,7 +172,7 @@ class Users } // Successful login! (also has a thing for the legacy password system) - return [1, 'LOGIN_SUCCESS', $user->id()]; + return [1, 'LOGIN_SUCCESS', $user->id]; } // Logout and kill the session @@ -228,7 +228,7 @@ class Users // Verify the captcha if it's enabled if (Config::get('recaptcha')) { - if (!Main::verifyCaptcha($captcha)['success']) { + if (!Utils::verifyCaptcha($captcha)['success']) { return [0, 'CAPTCHA_FAIL']; } } @@ -254,7 +254,7 @@ class Users } // Check the MX record of the email - if (!Main::checkMXRecord($email)) { + if (!Utils::checkMXRecord($email)) { return [0, 'INVALID_MX']; } @@ -264,7 +264,7 @@ class Users } // Check password entropy - if (Main::pwdEntropy($password) < Config::get('min_entropy')) { + if (Utils::pwdEntropy($password) < Config::get('min_entropy')) { return [0, 'PASS_TOO_SHIT']; } @@ -283,7 +283,7 @@ class Users // Check if we require e-mail activation if ($requireActive) { // Send activation e-mail to user - self::sendActivationMail($user->id()); + self::sendActivationMail($user->id); } // Return true with a specific message if needed @@ -299,8 +299,8 @@ class Users } // Clean username string - $usernameClean = Main::cleanString($username, true); - $emailClean = Main::cleanString($email, true); + $usernameClean = Utils::cleanString($username, true); + $emailClean = Utils::cleanString($email, true); // Do database request $user = Database::fetch('users', false, [ @@ -322,7 +322,7 @@ class Users } // Generate the verification key - $verk = ActionCode::generate('LOST_PASS', $userObj->id()); + $verk = ActionCode::generate('LOST_PASS', $userObj->id); // Create new urls object $urls = new Urls(); @@ -339,7 +339,7 @@ class Users $message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature'); // Send the message - Main::sendMail([$user['email'] => $user['username']], Config::get('sitename') . ' password restoration', $message); + Utils::sendMail([$user['email'] => $user['username']], Config::get('sitename') . ' password restoration', $message); // Return success return [1, 'SUCCESS']; @@ -354,7 +354,7 @@ class Users } // Check password entropy - if (Main::pwdEntropy($newpass) < Config::get('min_entropy')) { + if (Utils::pwdEntropy($newpass) < Config::get('min_entropy')) { return [0, 'PASS_TOO_SHIT']; } @@ -402,8 +402,8 @@ class Users } // Clean username string - $usernameClean = Main::cleanString($username, true); - $emailClean = Main::cleanString($email, true); + $usernameClean = Utils::cleanString($username, true); + $emailClean = Utils::cleanString($email, true); // Do database request $user = Database::fetch('users', false, [ @@ -438,12 +438,12 @@ class Users $user = User::construct($uid); // User is already activated or doesn't even exist - if (!$user->id() || !$user->permission(Site::DEACTIVATED)) { + if (!$user->id || !$user->permission(Site::DEACTIVATED)) { return false; } // Generate activation key - $activate = ActionCode::generate('ACTIVATE', $user->id()); + $activate = ActionCode::generate('ACTIVATE', $user->id); // Create new urls object $urls = new Urls(); @@ -452,20 +452,20 @@ class Users $message = "Welcome to " . Config::get('sitename') . "!\r\n\r\n"; $message .= "Please keep this e-mail for your records. Your account intormation is as follows:\r\n\r\n"; $message .= "----------------------------\r\n\r\n"; - $message .= "Username: " . $user->username() . "\r\n\r\n"; - $message .= "Your profile: http://" . Config::get('url_main') . $urls->format('USER_PROFILE', [$user->id()]) . "\r\n\r\n"; + $message .= "Username: " . $user->username . "\r\n\r\n"; + $message .= "Your profile: http://" . Config::get('url_main') . $urls->format('USER_PROFILE', [$user->id]) . "\r\n\r\n"; $message .= "----------------------------\r\n\r\n"; $message .= "Please visit the following link in order to activate your account:\r\n\r\n"; - $message .= "http://" . Config::get('url_main') . $urls->format('SITE_ACTIVATE') . "?mode=activate&u=" . $user->id() . "&k=" . $activate . "\r\n\r\n"; + $message .= "http://" . Config::get('url_main') . $urls->format('SITE_ACTIVATE') . "?mode=activate&u=" . $user->id . "&k=" . $activate . "\r\n\r\n"; $message .= "Your password has been securely stored in our database and cannot be retrieved. "; $message .= "In the event that it is forgotten, you will be able to reset it using the email address associated with your account.\r\n\r\n"; $message .= "Thank you for registering.\r\n\r\n"; $message .= "--\r\n\r\nThanks\r\n\r\n" . Config::get('mail_signature'); // Send the message - Main::sendMail( + Utils::sendMail( [ - $user->email() => $user->username(), + $user->email() => $user->username, ], Config::get('sitename') . ' Activation Mail', $message @@ -482,7 +482,7 @@ class Users $user = User::construct($uid); // Check if user exists - if (!$user->id()) { + if (!$user->id) { return [0, 'USER_NOT_EXIST']; } @@ -494,7 +494,7 @@ class Users // Check if a key is set if ($requireKey) { // Check the action code - $action = ActionCode::validate('ACTIVATE', $key, $user->id()); + $action = ActionCode::validate('ACTIVATE', $key, $user->id); // Check if we got a negative return if (!$action) { @@ -515,7 +515,7 @@ class Users public static function userExists($user, $id = true) { // Clean string - $user = Main::cleanString($user, true); + $user = Utils::cleanString($user, true); // Do database request $user = Database::fetch('users', true, [($id ? 'user_id' : 'username_clean') => [$user, '=']]); @@ -541,7 +541,7 @@ class Users // Iterate over the fields and clean them up foreach ($profileFields as $field) { $fields[$field['field_id']] = $field; - $fields[$field['field_id']]['field_identity'] = Main::cleanString($field['field_name'], true, true); + $fields[$field['field_id']]['field_identity'] = Utils::cleanString($field['field_name'], true, true); $fields[$field['field_id']]['field_additional'] = json_decode($field['field_additional'], true); } @@ -645,18 +645,18 @@ class Users $check = $user->isPremium(); // Check if the user has premium - if ($check[0] && !in_array($excepted, $user->ranks())) { + if ($check[0] && !array_key_exists($excepted, $user->ranks)) { // If so add the rank to them $user->addRanks([$premiumRank]); // Check if the user's default rank is standard user and update it to premium - if ($user->mainRank() == 2) { + if ($user->mainRankId == 2) { $user->setMainRank($premiumRank); } } elseif (!$check[0]) { // Remove the expired entry Database::delete('premium', [ - 'user_id' => [$user->id(), '='], + 'user_id' => [$user->id, '='], ]); // Else remove the rank from them @@ -694,7 +694,7 @@ class Users // Go over all users and check if they have the rank id foreach ($users as $user) { // If so store the user's row in the array - if ($user->hasRanks([$rankId], $user->id())) { + if ($user->hasRanks([$rankId], $user->id)) { $rank[] = $user; } } @@ -721,7 +721,7 @@ class Users continue; } - $users[$user->id()] = $user; + $users[$user->id] = $user; } // and return an array with the users diff --git a/libraries/Main.php b/libraries/Utils.php similarity index 99% rename from libraries/Main.php rename to libraries/Utils.php index 86184df..f6de3a0 100644 --- a/libraries/Main.php +++ b/libraries/Utils.php @@ -1,6 +1,6 @@ $login[0], 'attempt_timestamp' => time(), - 'attempt_ip' => Main::getRemoteIP(), + 'attempt_ip' => Utils::getRemoteIP(), 'user_id' => isset($login[2]) ? $login[2] : 0, ]); } @@ -203,7 +203,7 @@ if (isset($_REQUEST['mode'])) { // Add page specific things $renderData['page'] = [ - 'redirect' => $login[0] ? (User::construct($login[2])->dates()['lastOnline'] ? $_REQUEST['redirect'] : $urls->format('INFO_PAGE', ['welcome'])) : $urls->format('SITE_LOGIN'), + 'redirect' => $login[0] ? (User::construct($login[2])->lastOnline ? $_REQUEST['redirect'] : $urls->format('INFO_PAGE', ['welcome'])) : $urls->format('SITE_LOGIN'), 'message' => $messages[$login[1]], 'success' => $login[0], @@ -323,7 +323,7 @@ if (Users::checkLogin()) { } // Check if a user has already registered from the current IP address -if (count($regUserIP = Users::getUsersByIP(Main::getRemoteIP()))) { +if (count($regUserIP = Users::getUsersByIP(Utils::getRemoteIP()))) { $renderData['auth']['blockRegister'] = [ 'do' => true, diff --git a/public/content/data/yuuno/css/yuuno.css b/public/content/data/yuuno/css/yuuno.css index cdc3d38..7cce262 100644 --- a/public/content/data/yuuno/css/yuuno.css +++ b/public/content/data/yuuno/css/yuuno.css @@ -2056,7 +2056,6 @@ textarea.inputStyling { width: 100%; max-height: 200px; overflow: auto; - line-height: 1em; } .forum.viewtopic .posts .post-content .signature img { diff --git a/public/content/scripts/dynload.js b/public/content/scripts/dynload.js new file mode 100644 index 0000000..7d35dcf --- /dev/null +++ b/public/content/scripts/dynload.js @@ -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; +})(); diff --git a/public/content/scripts/dynload.ts b/public/content/scripts/dynload.ts new file mode 100644 index 0000000..0dbb7c1 --- /dev/null +++ b/public/content/scripts/dynload.ts @@ -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); + } + }); + } +} diff --git a/public/faq.php b/public/faq.php index 118919b..b097c93 100644 --- a/public/faq.php +++ b/public/faq.php @@ -12,7 +12,7 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php // Add page specific things $renderData['page'] = [ 'title' => 'Frequently Asked Questions', - 'questions' => Main::getFaqData(), + 'questions' => Utils::getFaqData(), ]; // Initialise templating engine diff --git a/public/imageserve.php b/public/imageserve.php index 88ea97b..4cad769 100644 --- a/public/imageserve.php +++ b/public/imageserve.php @@ -12,9 +12,6 @@ define('SAKURA_NO_TPL', true); // Include components require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php'; -// Path to user uploads -$userDirPath = ROOT . Config::get('user_uploads') . '/'; - // Check if the m(ode) GET request is set if (isset($_GET['m'])) { switch ($_GET['m']) { @@ -58,13 +55,24 @@ if (isset($_GET['m'])) { } // Check if user has an avatar set - if (empty($user->userData()['userAvatar']) || !file_exists($userDirPath . $user->userData()['userAvatar'])) { + if (!$user->avatar) { + $serveImage = $noAvatar; + break; + } + + // Attempt to get the file + $serve = new File($user->avatar); + + // Check if the file exists + if (!$serve->id) { $serveImage = $noAvatar; break; } // Check if the avatar exist and assign it to a value - $serveImage = $userDirPath . $user->userData()['userAvatar']; + $serveImage = $serve->data; + $serveMime = $serve->mime; + $serveName = $serve->name; break; case 'background': @@ -93,14 +101,24 @@ if (isset($_GET['m'])) { } // Check if user has a background set - if (empty($user->userData()['profileBackground']) - || !file_exists($userDirPath . $user->userData()['profileBackground'])) { + if (!$user->background) { + $serveImage = $noBackground; + break; + } + + // Attempt to get the file + $serve = new File($user->background); + + // Check if the file exists + if (!$serve->id) { $serveImage = $noBackground; break; } // Check if the avatar exist and assign it to a value - $serveImage = $userDirPath . $user->userData()['profileBackground']; + $serveImage = $serve->data; + $serveMime = $serve->mime; + $serveName = $serve->name; break; case 'header': @@ -128,15 +146,25 @@ if (isset($_GET['m'])) { break; } - // Check if user has a background set - if (empty($user->userData()['profileHeader']) - || !file_exists($userDirPath . $user->userData()['profileHeader'])) { + // Check if user has a header set + if (!$user->header) { + $serveImage = $noHeader; + break; + } + + // Attempt to get the file + $serve = new File($user->header); + + // Check if the file exists + if (!$serve->id) { $serveImage = $noHeader; break; } // Check if the avatar exist and assign it to a value - $serveImage = $userDirPath . $user->userData()['profileHeader']; + $serveImage = $serve->data; + $serveMime = $serve->mime; + $serveName = $serve->name; break; default: @@ -147,12 +175,17 @@ if (isset($_GET['m'])) { $serveImage = ROOT . Config::get('pixel_img'); } -// Add original filename -header('Content-Disposition: inline; filename="' . basename($serveImage) . '"'); +// Do some more checks +if (!isset($serveName) || !isset($serveMime)) { + $serveName = basename($serveImage); + $serveImage = file_get_contents($serveImage); + $serveMime = getimagesizefromstring($serveImage)['mime']; +} -$serveImage = file_get_contents($serveImage); +// Add original filename +header('Content-Disposition: inline; filename="' . $serveName . '"'); // Set content type -header('Content-Type: ' . getimagesizefromstring($serveImage)['mime']); +header('Content-Type: ' . $serveMime); -print $serveImage; +echo $serveImage; diff --git a/public/index.php b/public/index.php index e3a6af1..f819f62 100644 --- a/public/index.php +++ b/public/index.php @@ -19,19 +19,19 @@ $template->setTemplate($templateName); if (isset($_GET['p'])) { // Set default variables $renderData['page'] = [ - 'content' => Main::mdParse("# Unable to load the requested info page.\r\n\r\nCheck the URL and try again."), + 'content' => Utils::mdParse("# Unable to load the requested info page.\r\n\r\nCheck the URL and try again."), ]; // Set page id $pageId = isset($_GET['p']) ? strtolower($_GET['p']) : ''; // Get info page data from the database - if ($ipData = Main::loadInfoPage($pageId)) { + if ($ipData = Utils::loadInfoPage($pageId)) { // Assign new proper variable $renderData['page'] = [ 'id' => $pageId, 'title' => $ipData['page_title'], - 'content' => Main::mdParse($ipData['page_content']), + 'content' => Utils::mdParse($ipData['page_content']), ]; } @@ -59,7 +59,7 @@ $renderData['stats'] = [ date_create( date( 'Y-m-d', - $_INDEX_NEWEST_USER->dates()['joined'] + $_INDEX_NEWEST_USER->registered ) ), date_create( diff --git a/public/posting.php b/public/posting.php index ec9d560..4cd86c3 100644 --- a/public/posting.php +++ b/public/posting.php @@ -40,7 +40,7 @@ $thread->forum; $forum = new Forum\Forum($forumId); // Check if the user has access to the forum -if (!$forum->permission(ForumPerms::VIEW, $currentUser->id()) || !$forum->permission(ForumPerms::REPLY, $currentUser->id())) { +if (!$forum->permission(ForumPerms::VIEW, $currentUser->id) || !$forum->permission(ForumPerms::REPLY, $currentUser->id)) { // Set render data $renderData['page'] = [ 'title' => 'Information', @@ -56,7 +56,7 @@ if (!$forum->permission(ForumPerms::VIEW, $currentUser->id()) || !$forum->permis } // Check if the user has access to the forum -if (!isset($thread) && !$forum->permission(ForumPerms::CREATE_THREADS, $currentUser->id())) { +if (!isset($thread) && !$forum->permission(ForumPerms::CREATE_THREADS, $currentUser->id)) { // Set render data $renderData['page'] = [ 'title' => 'Information', @@ -75,7 +75,7 @@ $mode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) ? 't' : (isset($_GET['p']) // Include emotes and bbcodes $posting = [ - 'emoticons' => Main::getEmotes(), + 'emoticons' => Utils::getEmotes(), ]; // Check if we're in reply mode @@ -100,7 +100,7 @@ if ($mode != 'f') { } // Prompt an error if the topic doesn't exist - if ($thread->status == 1 && !$forum->permission(ForumPerms::LOCK, $currentUser->id())) { + if ($thread->status == 1 && !$forum->permission(ForumPerms::LOCK, $currentUser->id)) { // Add page specific things $renderData['page'] = [ 'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')), @@ -121,7 +121,7 @@ if ($mode != 'f') { $post = $thread->posts()[$_GET['p']]; // Add subject to render data - $posting['text'] = '[quote=' . $post->poster->username() . ']' . BBcode::toEditor($post->text) . '[/quote]'; + $posting['text'] = '[quote=' . $post->poster->username . ']' . BBcode::toEditor($post->text) . '[/quote]'; // Post editing } elseif ($mode == 'p' && isset($_GET['edit']) && $_GET['edit'] == $_GET['p'] && array_key_exists($_GET['p'], $thread->posts())) { @@ -141,7 +141,7 @@ if ($mode != 'f') { exit; } // Checks - if ($thread->posts()[$_GET['p']]->poster->id() != $currentUser->id() && !$forum->permission(ForumPerms::EDIT_ANY, $currentUser->id())) { + if ($thread->posts()[$_GET['p']]->poster->id != $currentUser->id && !$forum->permission(ForumPerms::EDIT_ANY, $currentUser->id)) { // Add page specific things $renderData['page'] = [ 'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')), @@ -184,7 +184,7 @@ if ($mode != 'f') { } // Checks - if ($thread->posts()[$_GET['p']]->poster->id() != $currentUser->id() && !$forum->permission(ForumPerms::DELETE_ANY, $currentUser->id())) { + if ($thread->posts()[$_GET['p']]->poster->id != $currentUser->id && !$forum->permission(ForumPerms::DELETE_ANY, $currentUser->id)) { // Add page specific things $renderData['page'] = [ 'redirect' => (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('FORUM_INDEX')), diff --git a/public/profile.php b/public/profile.php index 31e6821..1c607f6 100644 --- a/public/profile.php +++ b/public/profile.php @@ -32,9 +32,9 @@ $renderData['profile'] = $profile; $renderData['profileView'] = isset($_GET['view']) && in_array($_GET['view'], $views) ? $_GET['view'] : $views[0]; // If the user id is zero check if there was a namechange -if ($profile->id() == 0) { +if ($profile->id == 0) { // Fetch from username_history - $check = Database::fetch('username_history', false, ['username_old_clean' => [Main::cleanString(isset($_GET['u']) ? $_GET['u'] : 0, true, true), '=']]); + $check = Database::fetch('username_history', false, ['username_old_clean' => [Utils::cleanString(isset($_GET['u']) ? $_GET['u'] : 0, true, true), '=']]); // Redirect if so if ($check) { @@ -66,7 +66,7 @@ if (isset($_GET['restrict']) && $_GET['restrict'] == session_id() && $currentUse $renderData['page'] = [ 'message' => 'Toggled the restricted status of the user.', - 'redirect' => $urls->format('USER_PROFILE', [$profile->id()]), + 'redirect' => $urls->format('USER_PROFILE', [$profile->id]), ]; // Set parse variables diff --git a/public/settings.php b/public/settings.php index 4d45421..b69deeb 100644 --- a/public/settings.php +++ b/public/settings.php @@ -67,34 +67,34 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification $online = $friend->isOnline(); // If true check if they're already in the array - if ($online && !in_array($friend->id(), $onlineFriends)) { + if ($online && !in_array($friend->id, $onlineFriends)) { // Add user to the online array - $_SESSION['friendsOnline'][$friend->id()] = $friend->id(); + $_SESSION['friendsOnline'][$friend->id] = $friend->id; // Add the notification to the display array if ($onlineNotify) { $notifications[] = [ 'read' => 0, - 'title' => $friend->username() . ' is online.', + 'title' => $friend->username . ' is online.', 'text' => '', 'link' => '', - 'img' => '/a/' . $friend->id(), + 'img' => '/a/' . $friend->id, 'timeout' => 2000, 'sound' => false, ]; } - } elseif (!$online && in_array($friend->id(), $onlineFriends)) { + } elseif (!$online && in_array($friend->id, $onlineFriends)) { // Remove the person from the array - unset($_SESSION['friendsOnline'][$friend->id()]); + unset($_SESSION['friendsOnline'][$friend->id]); // Add the notification to the display array if ($onlineNotify) { $notifications[] = [ 'read' => 0, - 'title' => $friend->username() . ' is offline.', + 'title' => $friend->username . ' is offline.', 'text' => '', 'link' => '', - 'img' => '/a/' . $friend->id(), + 'img' => '/a/' . $friend->id, 'timeout' => 2000, 'sound' => false, ]; @@ -177,7 +177,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification } $comments->makeVote( - $currentUser->id(), + $currentUser->id, isset($_REQUEST['id']) ? $_REQUEST['id'] : 0, isset($_REQUEST['state']) && $_REQUEST['state'] ? '1' : '0' ); @@ -213,7 +213,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification } // Check if the comment was actually made by the current user - if ($comment['comment_poster'] !== $currentUser->id()) { + if ($comment['comment_poster'] !== $currentUser->id) { $renderData['page'] = [ 'redirect' => $redirect, 'message' => 'You can\'t delete the comments of others.', @@ -243,7 +243,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification } // Attempt to make a new comment - $comment = $comments->makeComment($currentUser->id(), $_POST['replyto'], $_POST['comment']); + $comment = $comments->makeComment($currentUser->id, $_POST['replyto'], $_POST['comment']); // Messages $messages = [ @@ -308,7 +308,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification } // Compare time and session so we know the link isn't forged - if ($continue && $_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')] == $currentUser->id()) { + if ($continue && $_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')] == $currentUser->id) { $renderData['page'] = [ 'redirect' => $redirect, @@ -383,15 +383,15 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification // Create a notification if (array_key_exists($action[1], $notifStrings)) { // Get the current user's profile data - $user = User::construct($currentUser->id()); + $user = User::construct($currentUser->id); Users::createNotification( $_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')], - sprintf($notifStrings[$action[1]][0], $user->username()), + sprintf($notifStrings[$action[1]][0], $user->username), $notifStrings[$action[1]][1], 60000, - '//' . Config::get('url_main') . '/a/' . $user->id(), - '//' . Config::get('url_main') . '/u/' . $user->id(), + $urls->format('IMAGE_AVATAR', [$user->id]), + $urls->format('USER_PROFILE', [$user->id]), '1' ); } @@ -430,17 +430,16 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification } // Check session variables - if (!isset($_REQUEST['timestamp']) - || $_REQUEST['timestamp'] < time() - 1000 - || !isset($_REQUEST['sessid']) - || $_REQUEST['sessid'] != session_id() + if (!isset($_POST['timestamp']) + || !isset($_POST['mode']) + || $_POST['timestamp'] < time() - 1000 + || !isset($_POST['sessid']) + || $_POST['sessid'] != session_id() || !$continue) { $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Your session has expired, please refresh the page and try again.', 'success' => 0, - ]; $continue = false; @@ -453,24 +452,31 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification // Avatar & Background case 'avatar': case 'background': + case 'header': // Assign $_POST['mode'] to a $mode variable because I ain't typin that more than once $mode = $_POST['mode']; - // Assign the correct userData key to a variable and correct title + // Assign the correct column and title to a variable switch ($mode) { case 'background': - $userDataKey = 'profileBackground'; + $column = 'user_background'; $msgTitle = 'Background'; - $permission = ( - !empty($currentUser->userData()[$userDataKey]) - && $currentUser->permission(Site::CHANGE_BACKGROUND) - ) || $currentUser->permission(Site::CREATE_BACKGROUND); + $current = $currentUser->background; + $permission = $currentUser->permission(Site::CHANGE_BACKGROUND); + break; + + case 'header': + $column = 'user_header'; + $msgTitle = 'Header'; + $current = $currentUser->header; + $permission = $currentUser->permission(Site::CHANGE_HEADER); break; case 'avatar': default: - $userDataKey = 'userAvatar'; + $column = 'user_avatar'; $msgTitle = 'Avatar'; + $current = $currentUser->avatar; $permission = $currentUser->permission(Site::CHANGE_AVATAR); } @@ -489,20 +495,15 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification } // Set path variables - $filepath = ROOT . Config::get('user_uploads') . '/'; - $filename = $filepath . $mode . '_' . $currentUser->id(); - $currfile = isset($currentUser->userData()[$userDataKey]) - && !empty($currentUser->userData()[$userDataKey]) ? $currentUser->userData()[$userDataKey] : null; + $filename = strtolower($msgTitle) . '_' . $currentUser->id; // Check if $_FILES is set if (!isset($_FILES[$mode]) && empty($_FILES[$mode])) { // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'No file was uploaded.', 'success' => 0, - ]; break; } @@ -533,11 +534,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => $msg, 'success' => 0, - ]; break; } @@ -551,11 +550,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification if ($metadata == false) { // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Uploaded file is not an image.', 'success' => 0, - ]; break; @@ -567,13 +564,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification && ($metadata[2] !== IMAGETYPE_PNG))) { // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'This filetype is not allowed.', 'success' => 0, - ]; - break; } @@ -582,13 +576,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification || $metadata[1] > Config::get($mode . '_max_height'))) { // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'The resolution of this picture is too big.', 'success' => 0, - ]; - break; } @@ -597,13 +588,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification || $metadata[1] < Config::get($mode . '_min_height'))) { // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'The resolution of this picture is too small.', 'success' => 0, - ]; - break; } @@ -611,54 +599,46 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification if ((filesize($_FILES[$mode]['tmp_name']) > Config::get($mode . '_max_fsize'))) { // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'The filesize of this file is too large.', 'success' => 0, - ]; - break; } } - // Delete old avatar - if ($currfile && file_exists($currfile)) { - unlink($filepath . $currfile); - } + // Open the old file and remove it + $oldFile = new File($current); + $oldFile->delete(); + unset($oldFile); + $fileId = 0; if ($_FILES[$mode]['error'] != UPLOAD_ERR_NO_FILE) { // Append extension to filename $filename .= image_type_to_extension($metadata[2]); - if (!move_uploaded_file($_FILES[$mode]['tmp_name'], $filename)) { - // Set render data - $renderData['page'] = [ + // Store the file + $file = File::create(file_get_contents($_FILES[$mode]['tmp_name']), $filename, $currentUser); - 'redirect' => $redirect, - 'message' => 'Something went wrong, please try again.', - 'success' => 0, - - ]; - } - - // Create new array - $updated = [$userDataKey => basename($filename)]; - } else { - // Remove entry - $updated = [$userDataKey => null]; + // Assign the file id to a variable + $fileId = $file->id; } - // Update database - $currentUser->setUserData($updated); + // Update table + Database::update('users', [ + [ + $column => $fileId, + ], + [ + 'user_id' => [$currentUser->id, '='], + ], + ]); // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Updated your ' . strtolower($msgTitle) . '!', 'success' => 1, - ]; break; @@ -666,13 +646,17 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification case 'profile': // Get profile fields and create storage var $fields = Users::getProfileFields(); - $store = []; // Go over each field foreach ($fields as $field) { // Add to the store array if (isset($_POST['profile_' . $field['field_identity']]) && !empty($_POST['profile_' . $field['field_identity']])) { - $store[$field['field_identity']] = $_POST['profile_' . $field['field_identity']]; + Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$field['field_identity'], '=']]); + Database::insert('user_profilefields', [ + 'user_id' => $currentUser->id, + 'field_name' => $field['field_identity'], + 'field_value' => $_POST['profile_' . $field['field_identity']], + ]); } // Check if there's additional values we should keep in mind @@ -680,24 +664,22 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification // Go over each additional value foreach ($field['field_additional'] as $addKey => $addVal) { // Add to the array - $store[$addKey] = (isset($_POST['profile_additional_' . $addKey]) - || !empty($_POST['profile_additional_' . $addKey])) ? - $_POST['profile_additional_' . $addKey] : - false; + $store = (isset($_POST['profile_additional_' . $addKey]) || !empty($_POST['profile_additional_' . $addKey])) ? $_POST['profile_additional_' . $addKey] : false; + Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$addKey, '=']]); + Database::insert('user_profilefields', [ + 'user_id' => $currentUser->id, + 'field_name' => $addKey, + 'field_value' => $store, + ]); } } } - // Update database - $currentUser->setUserData(['profileFields' => $store]); - // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Your profile has been updated!', 'success' => 1, - ]; // Birthdays @@ -755,7 +737,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification 'user_birthday' => $birthdate, ], [ - 'user_id' => [$currentUser->id(), '='], + 'user_id' => [$currentUser->id, '='], ], ]); } @@ -765,32 +747,31 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification case 'options': // Get profile fields and create storage var $fields = Users::getOptionFields(); - $store = []; // Go over each field foreach ($fields as $field) { + Database::delete('user_optionfields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$field['option_id'], '=']]); + // Make sure the user has sufficient permissions to complete this action if (!$currentUser->permission(constant('Sakura\Perms\Site::' . $field['option_permission']))) { - $store[$field['option_id']] = false; continue; } - $store[$field['option_id']] = isset($_POST['option_' . $field['option_id']]) - && !empty($_POST['option_' . $field['option_id']]) ? - $_POST['option_' . $field['option_id']] : - null; + if (isset($_POST['option_' . $field['option_id']]) + && !empty($_POST['option_' . $field['option_id']])) { + Database::insert('user_optionfields', [ + 'user_id' => $currentUser->id, + 'field_name' => $field['option_id'], + 'field_value' => $_POST['option_' . $field['option_id']], + ]); + } } - // Update database - $currentUser->setUserData(['userOptions' => $store]); - // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Changed your options!', 'success' => 1, - ]; break; @@ -799,11 +780,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification // Check permissions if (!$currentUser->permission(Site::CHANGE_USERTITLE)) { $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'You aren\'t allowed to change your usertitle.', 'success' => 0, - ]; break; } @@ -828,7 +807,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification 'user_title' => (isset($_POST['usertitle']) ? $_POST['usertitle'] : null), ], [ - 'user_id' => [$currentUser->id(), '='], + 'user_id' => [$currentUser->id, '='], ], ] ); @@ -952,64 +931,208 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification ]; break; - // Deactivation - case 'deactivate': - // Check permissions - if (!$currentUser->permission(Site::DEACTIVATE_ACCOUNT)) { - $renderData['page'] = [ - - 'redirect' => $redirect, - 'message' => 'You aren\'t allowed to deactivate your own account.', - 'success' => 0, - - ]; - - break; - } - - // Set render data - $renderData['page'] = [ - - 'redirect' => $redirect, - 'message' => 'Nothing happened.', - 'success' => 1, - - ]; - break; - // Userpage case 'userpage': - // Base64 encode the userpage - $userPage = base64_encode($_POST['userpage']); + if (!isset($_POST['userpage'])) { + // Set render data + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'No userpage was supplied.', + 'success' => 0, + ]; + } // Update database - $currentUser->setUserData(['userPage' => $userPage]); + Database::update('users', [['user_page' => $_POST['userpage']], ['user_id' => [$currentUser->id, '=']]]); // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Your userpage has been updated!', 'success' => 1, - ]; break; // Signature case 'signature': - // Base64 encode the signature - $signature = base64_encode($_POST['signature']); + if (!isset($_POST['signature'])) { + // Set render data + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'No signature was supplied.', + 'success' => 0, + ]; + } // Update database - $currentUser->setUserData(['signature' => $signature]); + Database::update('users', [['user_signature' => $_POST['signature']], ['user_id' => [$currentUser->id, '=']]]); // Set render data $renderData['page'] = [ - 'redirect' => $redirect, 'message' => 'Your signature has been updated!', 'success' => 1, + ]; + break; + // Ranks + case 'ranks': + // Check submit data + if (!isset($_POST['rank'])) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'No rank was set.', + 'success' => 0, + ]; + break; + } + + // Check if the user is part of the rank + if (!$currentUser->hasRanks([$_POST['rank']])) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'You are not in this rank.', + 'success' => 0, + ]; + break; + } + + // Leaving + if (isset($_POST['remove'])) { + // Check if we're not trying to leave hardranks + if ($_POST['rank'] <= 2) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'You can\'t remove this rank.', + 'success' => 0, + ]; + break; + } + + // Remove the rank + $currentUser->removeRanks([$_POST['rank']]); + + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'Removed the rank from your account.', + 'success' => 0, + ]; + break; + } + + // Set as default + $currentUser->setMainRank($_POST['rank']); + + // Set render data + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'Changed your main rank!', + 'success' => 0, + ]; + break; + + // Sessions + case 'sessions': + // Check if sessionid is set + if (!isset($_POST['sessionid'])) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'A required field wasn\'t set.', + 'success' => 0, + ]; + break; + } + + // Check if sessionid is set to all + if ($_POST['sessionid'] === 'all') { + // Delete all sessions assigned to the current user + Database::delete('sessions', [ + 'user_id' => [$currentUser->id, '='], + ]); + + // Set render data + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'Killed all active sessions!', + 'success' => 1, + ]; + break; + } + + // Check if the session is owned by the current user + if (!Database::fetch('sessions', false, ['user_id' => [$currentUser->id, '='], 'session_id' => [$_POST['sessionid'], '=']])) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'The session you tried to kill doesn\'t exist.', + 'success' => 0, + ]; + break; + } + + // Delete the session + Database::delete('sessions', [ + 'session_id' => [$_POST['sessionid'], '='], + ]); + + // Set render data + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'Killed the session!', + 'success' => 1, + ]; + break; + + // Deactivation + case 'deactivate': + // Check permissions + if (!$currentUser->permission(Site::DEACTIVATE_ACCOUNT)) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'You aren\'t allowed to deactivate your account.', + 'success' => 0, + ]; + + break; + } + + // Check fields + if (!isset($_POST['username']) + || !isset($_POST['password']) + || !isset($_POST['email']) + || !isset($_POST['sensitive'])) { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'One or more forms wasn\'t set.', + 'success' => 0, + ]; + + break; + } + + // Check values + if ($_POST['username'] !== $currentUser->username + || !Hashing::validatePassword($_POST['password'], [$currentUser->passwordAlgo, $currentUser->passwordIter, $currentUser->passwordSalt, $currentUser->passwordHash]) + || $_POST['email'] !== $currentUser->email + || md5($_POST['sensitive']) !== '81df445067d92dd02db9098ba82b0167') { + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'One or more forms wasn\'t correct.', + 'success' => 0, + ]; + + break; + } + + // Deactivate account + $currentUser->removeRanks(array_keys($currentUser->ranks)); + $currentUser->addRanks([1]); + $currentUser->setMainRank(1); + + // Set render data + $renderData['page'] = [ + 'redirect' => $redirect, + 'message' => 'Your account has been deactivated!', + 'success' => 1, ]; break; @@ -1172,10 +1295,18 @@ if (Users::checkLogin()) { minimum image size is {{ background.min_width }}x{{ background.min_height }}, maximum file size is {{ background.max_size_view }}.', ], - 'access' => ( - isset($currentUser->userData()['profileBackground']) - && $currentUser->permission(Site::CHANGE_BACKGROUND) - ) || $currentUser->permission(Site::CREATE_BACKGROUND), + 'access' => $currentUser->permission(Site::CHANGE_BACKGROUND), + 'menu' => true, + ], + 'header' => [ + 'title' => 'Header', + 'description' => [ + 'The header that is displayed on your profile.', + 'Maximum image size is {{ header.max_width }}x{{ header.max_height }}, + minimum image size is {{ header.min_width }}x{{ header.min_height }}, + maximum file size is {{ header.max_size_view }}.', + ], + 'access' => $currentUser->permission(Site::CHANGE_HEADER), 'menu' => true, ], 'userpage' => [ @@ -1184,7 +1315,7 @@ if (Users::checkLogin()) { 'The custom text that is displayed on your profile.', ], 'access' => ( - isset($currentUser->userData()['userPage']) + $currentUser->page && $currentUser->permission(Site::CHANGE_USERPAGE) ) || $currentUser->permission(Site::CREATE_USERPAGE), 'menu' => true, @@ -1364,34 +1495,25 @@ if (Users::checkLogin()) { // Avatar and background sizes case 'appearance.avatar': case 'appearance.background': + case 'appearance.header': $renderData[$mode] = [ 'max_width' => Config::get($mode . '_max_width'), 'max_height' => Config::get($mode . '_max_height'), 'min_width' => Config::get($mode . '_min_width'), 'min_height' => Config::get($mode . '_min_height'), 'max_size' => Config::get($mode . '_max_fsize'), - 'max_size_view' => Main::getByteSymbol(Config::get($mode . '_max_fsize')), + 'max_size_view' => Utils::getByteSymbol(Config::get($mode . '_max_fsize')), ]; break; - // User page - case 'appearance.userpage': - $renderData['userPage'] = isset($currentUser->userData()['userPage']) ? base64_decode($currentUser->userData()['userPage']) : ''; - break; - - // Signature - case 'appearance.signature': - $renderData['signature'] = isset($currentUser->userData()['signature']) ? base64_decode($currentUser->userData()['signature']) : ''; - break; - // Username changing case 'account.username': - $renderData['difference'] = $currentUser->getUsernameHistory() ? Main::timeElapsed($currentUser->getUsernameHistory()[0]['change_time']) : 0; + $renderData['difference'] = $currentUser->getUsernameHistory() ? Utils::timeElapsed($currentUser->getUsernameHistory()[0]['change_time']) : 0; break; // Sessions case 'advanced.sessions': - $renderData['sessions'] = Database::fetch('sessions', true, ['user_id' => [$currentUser->id(), '=']]); + $renderData['sessions'] = Database::fetch('sessions', true, ['user_id' => [$currentUser->id, '=']]); break; } diff --git a/public/support.php b/public/support.php index 4797875..9eea190 100644 --- a/public/support.php +++ b/public/support.php @@ -96,12 +96,12 @@ if (isset($_REQUEST['mode']) // Attempt to complete the transaction if ($finalise) { // Make the user premium - $expiration = Users::addUserPremium($currentUser->id(), (2628000 * $_SESSION['premiumMonths'])); - Users::updatePremiumMeta($currentUser->id()); - Main::updatePremiumTracker( - $currentUser->id(), + $expiration = Users::addUserPremium($currentUser->id, (2628000 * $_SESSION['premiumMonths'])); + Users::updatePremiumMeta($currentUser->id); + Utils::updatePremiumTracker( + $currentUser->id, ((float) Config::get('premium_price_per_month') * $_SESSION['premiumMonths']), - $currentUser->username() + $currentUser->username . ' bought premium for ' . $_SESSION['premiumMonths'] . ' month' @@ -144,7 +144,7 @@ if (isset($_REQUEST['mode']) // Premium tracker if (isset($_GET['tracker'])) { - $renderData['tracker'] = Main::getPremiumTrackerData(); + $renderData['tracker'] = Utils::getPremiumTrackerData(); // Set parse variables $template->setVariables($renderData); diff --git a/public/viewforum.php b/public/viewforum.php index 43be097..ad36927 100644 --- a/public/viewforum.php +++ b/public/viewforum.php @@ -37,7 +37,7 @@ if ($forum->id < 0) { } // Check if the user has access to the forum -if (!$forum->permission(ForumPerms::VIEW, $currentUser->id())) { +if (!$forum->permission(ForumPerms::VIEW, $currentUser->id)) { // Set render data $renderData['page'] = [ 'title' => 'Information', @@ -72,7 +72,7 @@ if ($forum->type === 2) { // Check if we're marking as read if (isset($_GET['read']) && $_GET['read'] && isset($_GET['session']) && $_GET['session'] == session_id()) { // Run the function - $forum->trackUpdateAll($currentUser->id()); + $forum->trackUpdateAll($currentUser->id); // Set render data $renderData['page'] = [ diff --git a/public/viewtopic.php b/public/viewtopic.php index 458b06b..2c7af53 100644 --- a/public/viewtopic.php +++ b/public/viewtopic.php @@ -44,7 +44,7 @@ if (!$thread) { } // Check if the user has access to the forum -if (!$forum->permission(ForumPerms::VIEW, $currentUser->id())) { +if (!$forum->permission(ForumPerms::VIEW, $currentUser->id)) { // Set render data $renderData['page'] = [ 'message' => 'You do not have access to this thread.', @@ -60,7 +60,7 @@ if (!$forum->permission(ForumPerms::VIEW, $currentUser->id())) { } // Sticky thread -if (isset($_GET['sticky']) && $_GET['sticky'] == session_id() && $forum->permission(ForumPerms::STICKY, $currentUser->id())) { +if (isset($_GET['sticky']) && $_GET['sticky'] == session_id() && $forum->permission(ForumPerms::STICKY, $currentUser->id)) { // Check the status if ($thread->type == 1) { $thread->type = 0; @@ -86,7 +86,7 @@ if (isset($_GET['sticky']) && $_GET['sticky'] == session_id() && $forum->permiss } // Announce thread -if (isset($_GET['announce']) && $_GET['announce'] == session_id() && $forum->permission(ForumPerms::ANNOUNCEMENT, $currentUser->id())) { +if (isset($_GET['announce']) && $_GET['announce'] == session_id() && $forum->permission(ForumPerms::ANNOUNCEMENT, $currentUser->id)) { // Check the status if ($thread->type == 2) { $thread->type = 0; @@ -111,7 +111,7 @@ if (isset($_GET['announce']) && $_GET['announce'] == session_id() && $forum->per } // Lock thread -if (isset($_GET['lock']) && $_GET['lock'] == session_id() && $forum->permission(ForumPerms::LOCK, $currentUser->id())) { +if (isset($_GET['lock']) && $_GET['lock'] == session_id() && $forum->permission(ForumPerms::LOCK, $currentUser->id)) { // Check the status if ($thread->status == 1) { $thread->status = 0; @@ -136,7 +136,7 @@ if (isset($_GET['lock']) && $_GET['lock'] == session_id() && $forum->permission( } // Trash thread -if (isset($_GET['trash']) && $_GET['trash'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id())) { +if (isset($_GET['trash']) && $_GET['trash'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id)) { // Check the status if ($thread->forum != Config::get('forum_trash_id')) { $thread->move(Config::get('forum_trash_id')); @@ -163,7 +163,7 @@ if (isset($_GET['trash']) && $_GET['trash'] == session_id() && $forum->permissio } // Restore thread -if (isset($_GET['restore']) && $_GET['restore'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id())) { +if (isset($_GET['restore']) && $_GET['restore'] == session_id() && $forum->permission(ForumPerms::MOVE, $currentUser->id)) { // Check the status if ($thread->oldForum) { // Move thread @@ -191,7 +191,7 @@ if (isset($_GET['restore']) && $_GET['restore'] == session_id() && $forum->permi } // Prune thread -if (isset($_GET['prune']) && $_GET['prune'] == session_id() && $forum->permission(ForumPerms::DELETE_ANY, $currentUser->id())) { +if (isset($_GET['prune']) && $_GET['prune'] == session_id() && $forum->permission(ForumPerms::DELETE_ANY, $currentUser->id)) { // Check the status if ($thread->forum == Config::get('forum_trash_id')) { $thread->delete(); @@ -218,7 +218,7 @@ if (isset($_GET['prune']) && $_GET['prune'] == session_id() && $forum->permissio } // Update the tracking status -$thread->trackUpdate($currentUser->id()); +$thread->trackUpdate($currentUser->id); // Update views $thread->viewsUpdate(); diff --git a/sakura.php b/sakura.php index 223c673..814904d 100644 --- a/sakura.php +++ b/sakura.php @@ -8,7 +8,7 @@ namespace Sakura; // Define Sakura version -define('SAKURA_VERSION', '20160114'); +define('SAKURA_VERSION', '20160117'); define('SAKURA_VLABEL', 'Amethyst'); define('SAKURA_COLOUR', '#9966CC'); @@ -41,7 +41,6 @@ require_once ROOT . 'libraries/CSRF.php'; require_once ROOT . 'libraries/Database.php'; require_once ROOT . 'libraries/File.php'; require_once ROOT . 'libraries/Hashing.php'; -require_once ROOT . 'libraries/Main.php'; require_once ROOT . 'libraries/Manage.php'; require_once ROOT . 'libraries/News.php'; require_once ROOT . 'libraries/Payments.php'; @@ -53,6 +52,7 @@ require_once ROOT . 'libraries/Trick.php'; require_once ROOT . 'libraries/Urls.php'; require_once ROOT . 'libraries/User.php'; require_once ROOT . 'libraries/Users.php'; +require_once ROOT . 'libraries/Utils.php'; require_once ROOT . 'libraries/Whois.php'; require_once ROOT . 'libraries/Forum/Forum.php'; require_once ROOT . 'libraries/Forum/Post.php'; @@ -67,7 +67,7 @@ foreach (glob(ROOT . 'libraries/DBWrapper/*.php') as $driver) { } // Set Error handler -set_error_handler(['Sakura\Main', 'errorHandler']); +set_error_handler(['Sakura\Utils', 'errorHandler']); // Load the local configuration Config::init(ROOT . 'config/config.ini'); @@ -206,7 +206,7 @@ if (!defined('SAKURA_NO_TPL')) { } // Ban checking - if ($authCheck && !in_array($_SERVER['PHP_SELF'], [$urls->format('AUTH_ACTION', [], false)]) && $ban = Bans::checkBan($currentUser->id())) { + if ($authCheck && !in_array($_SERVER['PHP_SELF'], [$urls->format('AUTH_ACTION', [], false)]) && $ban = Bans::checkBan($currentUser->id)) { // Additional render data $renderData = array_merge($renderData, [ 'ban' => [ diff --git a/server.php b/server.php new file mode 100644 index 0000000..d3f69d7 --- /dev/null +++ b/server.php @@ -0,0 +1,12 @@ + {{ block('css') }} +