r20150913 and r20150915

Signed-off-by: Flashwave <me@flash.moe>
This commit is contained in:
flash 2015-09-14 22:51:23 +02:00
parent 967eb8e5a9
commit 26572dbd71
41 changed files with 1954 additions and 2375 deletions

View file

@ -2720,6 +2720,22 @@
"type": "ADD",
"change": "Added Linux no cron task method.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Remove old notifications after a month.",
"user": "Flashwave"
}
],
"20150914": [
"eminence",
{
"type": "UPD",
"change": "Make indentation style PSR2 standard compliant.",
"user": "Flashwave"
}
]

View file

@ -5,37 +5,35 @@
namespace Sakura;
class Bans {
class Bans
{
// Check if a user is banned
public static function checkBan($id) {
public static function checkBan($uid)
{
// Attempt to get a ban from this user
$bans = Database::fetch('bans', true, ['uid' => [$id, '=']]);
$bans = Database::fetch('bans', true, ['uid' => [$uid, '=']]);
// Reverse the array so new bans are listed first
$bans = array_reverse($bans);
// Go over each ban
foreach($bans as $ban) {
foreach ($bans as $ban) {
// Check if it hasn't expired
if($ban['ban_end'] != 0 && $ban['ban_end'] < time()) {
if ($ban['ban_end'] != 0 && $ban['ban_end'] < time()) {
// If it has delete the entry and continue
Database::delete('bans', ['id' => [$ban['id'], '=']]);
Database::delete('bans', ['id' => [$ban['uid'], '=']]);
continue;
}
// Return the ban if all checks were passed
return [
'user' => $ban['uid'],
'issuer' => $ban['mod_id'],
'issued' => $ban['ban_begin'],
'expires' => $ban['ban_end'],
'reason' => $ban['ban_reason']
'user' => $ban['uid'],
'issuer' => $ban['mod_uid'],
'issued' => $ban['ban_begin'],
'expires' => $ban['ban_end'],
'reason' => $ban['ban_reason'],
];
@ -45,5 +43,4 @@ class Bans {
return false;
}
}

View file

@ -5,8 +5,7 @@
namespace Sakura;
class Comments {
class Comments
{
}

View file

@ -5,35 +5,30 @@
namespace Sakura;
class Configuration {
class Configuration
{
// Configuration data
private static $_LCNF = [];
private static $_DCNF = [];
private static $local = [];
private static $database = [];
// Initialise configuration, does not contain database initialisation because explained below
public static function init($local) {
public static function init($local)
{
// Check if the configuration file exists
if(!file_exists($local)) {
if (!file_exists($local)) {
trigger_error('Local configuration file does not exist', E_USER_ERROR);
}
// Attempt to load the configuration file
$local = parse_ini_file($local, true);
// Check if $local is an array and then store it in $_LCNF
if(is_array($local)) {
self::$_LCNF = $local;
// Check if $local is an array and then store it in $local
if (is_array($local)) {
self::$local = $local;
} else {
// Otherwise trigger an error
trigger_error('Failed to load local configuration file, check the structure of the file to see if you made mistake somewhere', E_USER_ERROR);
}
}
@ -43,7 +38,8 @@ class Configuration {
* Different from init as that is called before the database connection is initially
* established.
*/
public static function initDB() {
public static function initDB()
{
// Get config table from the database
$_DATA = Database::fetch('config', true);
@ -52,89 +48,70 @@ class Configuration {
$_DBCN = array();
// Properly sort the values
foreach($_DATA as $_CONF) {
foreach ($_DATA as $_CONF) {
$_DBCN[$_CONF['config_name']] = $_CONF['config_value'];
}
// Assign the temporary array to the static one
self::$_DCNF = $_DBCN;
self::$database = $_DBCN;
}
// Get values from the configuration on the file system
public static function getLocalConfig($key, $subkey = null) {
public static function getLocalConfig($key, $subkey = null)
{
// Check if the key that we're looking for exists
if(array_key_exists($key, self::$_LCNF)) {
if($subkey) {
if (array_key_exists($key, self::$local)) {
if ($subkey) {
// If we also have a subkey return the proper data
return self::$_LCNF[$key][$subkey];
} else {
// else we just return the default value
return self::$_LCNF[$key];
return self::$local[$key][$subkey];
}
} else {// If it doesn't exist trigger an error to avoid explosions
trigger_error('Unable to get local configuration value "'. $key .'"', E_USER_ERROR);
// else we just return the default value
return self::$local[$key];
}
// If it doesn't exist trigger an error to avoid explosions
trigger_error('Unable to get local configuration value "' . $key . '"', E_USER_ERROR);
}
// Dynamically set local configuration values, does not update the configuration file
public static function setLocalConfig($key, $subkey, $value) {
public static function setLocalConfig($key, $subkey, $value)
{
// Check if we also do a subkey
if($subkey) {
if ($subkey) {
// If we do we make sure that the parent key is an array
if(!isset(self::$_LCNF[$key])) {
self::$_LCNF[$key] = array();
if (!isset(self::$local[$key])) {
self::$local[$key] = array();
}
// And then assign the value
self::$_LCNF[$key][$subkey] = $value;
} else {
// Otherwise we just straight up assign it
self::$_LCNF[$key] = $value;
self::$local[$key][$subkey] = $value;
}
// Otherwise we just straight up assign it
self::$local[$key] = $value;
}
// Get values from the configuration in the database
public static function getConfig($key, $returnNull = false) {
public static function getConfig($key, $returnNull = false)
{
// Check if the key that we're looking for exists
if(array_key_exists($key, self::$_DCNF)) {
if (array_key_exists($key, self::$database)) {
// Then return the value
return self::$_DCNF[$key];
} elseif($returnNull) {
return self::$database[$key];
} elseif ($returnNull) {
// Avoid the error trigger if requested
return null;
} else {
// Then return the value
trigger_error('Unable to get configuration value "'. $key .'"', E_USER_ERROR);
}
}
// Then return the value
trigger_error('Unable to get configuration value "' . $key . '"', E_USER_ERROR);
}
}

View file

@ -5,69 +5,73 @@
namespace Sakura;
class Database {
class Database
{
// Database container
public static $_DATABASE;
public static $database;
// Initialisation function
public static function init($wrapper) {
public static function init($wrapper)
{
// Make the wrapper class name lowercase
$wrapper = __NAMESPACE__ .'\DBWrapper\\'. strtolower($wrapper);
$wrapper = __NAMESPACE__ . '\DBWrapper\\' . strtolower($wrapper);
// Check if the class exists
if(!class_exists($wrapper)) {
if (!class_exists($wrapper)) {
trigger_error('Failed to load database wrapper', E_USER_ERROR);
}
// Initialise SQL wrapper
self::$_DATABASE = new $wrapper;
self::$database = new $wrapper;
}
// Select from database
public static function select($table, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null) {
public static function select($table, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
{
return self::$_DATABASE->select($table, $data, $order, $limit, $group, $distinct, $column, $prefix);
return self::$database->select($table, $data, $order, $limit, $group, $distinct, $column, $prefix);
}
// Fetch from database
public static function fetch($table, $fetchAll = true, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null) {
public static function fetch($table, $fetchAll = true, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
{
return self::$_DATABASE->fetch($table, $fetchAll, $data, $order, $limit, $group, $distinct, $column, $prefix);
return self::$database->fetch($table, $fetchAll, $data, $order, $limit, $group, $distinct, $column, $prefix);
}
// Insert into database
public static function insert($table, $data, $prefix = null) {
public static function insert($table, $data, $prefix = null)
{
return self::$_DATABASE->insert($table, $data, $prefix);
return self::$database->insert($table, $data, $prefix);
}
// Update in database
public static function update($table, $data, $prefix = null) {
public static function update($table, $data, $prefix = null)
{
return self::$_DATABASE->update($table, $data, $prefix);
return self::$database->update($table, $data, $prefix);
}
// Delete from database
public static function delete($table, $data, $prefix = null) {
public static function delete($table, $data, $prefix = null)
{
return self::$_DATABASE->delete($table, $data, $prefix);
return self::$database->delete($table, $data, $prefix);
}
// Count from database
public static function count($table, $data = null, $prefix = null) {
public static function count($table, $data = null, $prefix = null)
{
return self::$_DATABASE->count($table, $data, $prefix);
return self::$database->count($table, $data, $prefix);
}
}

View file

@ -5,22 +5,23 @@
namespace Sakura;
class Forum {
class Forum
{
// Empty forum template
public static $emptyForum = [
'forum_id' => 0,
'forum_name' => 'Forum',
'forum_desc' => '',
'forum_link' => '',
'forum_category' => 0,
'forum_type' => 1,
'forum_posts' => 0,
'forum_topics' => 0
'forum_id' => 0,
'forum_name' => 'Forum',
'forum_desc' => '',
'forum_link' => '',
'forum_category' => 0,
'forum_type' => 1,
'forum_posts' => 0,
'forum_topics' => 0,
];
// Getting the forum list
public static function getForumList() {
public static function getForumList()
{
// Get the content from the database
$forums = Database::fetch('forums');
@ -29,36 +30,32 @@ class Forum {
$return = [
0 => [
'forum' => self::$emptyForum,
'forums' => []
]
'forums' => [],
],
];
// Resort the forums
foreach($forums as $forum) {
foreach ($forums as $forum) {
// If the forum type is a category create a new one
if($forum['forum_type'] == 1) {
if ($forum['forum_type'] == 1) {
$return[$forum['forum_id']]['forum'] = $forum;
} else {
// For link and reg. forum add it to the category
$return[$forum['forum_category']]['forums'][$forum['forum_id']] = $forum;
// Get the topic count
$return[$forum['forum_category']]['forums'][$forum['forum_id']]['topic_count'] = Database::count('topics', [
'forum_id' => [$forum['forum_id'], '=']
'forum_id' => [$forum['forum_id'], '='],
])[0];
// Get the post count
$return[$forum['forum_category']]['forums'][$forum['forum_id']]['post_count'] = Database::count('posts', [
'forum_id' => [$forum['forum_id'], '=']
'forum_id' => [$forum['forum_id'], '='],
])[0];
// Get last post in forum
$lastPost = Database::fetch('posts', false, [
'forum_id' => [$forum['forum_id'], '=']
'forum_id' => [$forum['forum_id'], '='],
], ['post_id', true]);
// Add last poster data and the details about the post as well
@ -66,11 +63,9 @@ class Forum {
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main']),
'elap' => Main::timeElapsed($lastPost['post_time'])
'elap' => Main::timeElapsed($lastPost['post_time']),
];
}
}
// Return the resorted data
@ -79,7 +74,8 @@ class Forum {
}
// Get a forum or category
public static function getForum($id) {
public static function getForum($id)
{
// Get the forumlist from the database
$forums = Database::fetch('forums');
@ -91,46 +87,42 @@ class Forum {
$forum = [];
// Try to find the requested forum
foreach($forums as $list) {
foreach ($forums as $list) {
// Once found set $forum to $list and break the loop
if($list['forum_id'] == $id) {
if ($list['forum_id'] == $id) {
$forum['forum'] = $list;
break;
}
}
// If $forum is still empty after the foreach return false
if(empty($forum))
if (empty($forum)) {
return false;
}
// Create conditions for fetching the forums
$conditions['forum_category'] = [$id, '='];
// If the current category is 0 (the built in fallback) prevent getting categories
if($id == 0)
if ($id == 0) {
$conditions['forum_type'] = ['1', '!='];
}
// Check if this forum/category has any subforums
$forum['forums'] = Database::fetch('forums', true, $conditions);
// Get the userdata related to last posts
foreach($forum['forums'] as $key => $sub) {
foreach ($forum['forums'] as $key => $sub) {
// Get last post in forum
$lastPost = Database::fetch('posts', false, [
'forum_id' => [$sub['forum_id'], '=']
'forum_id' => [$sub['forum_id'], '='],
], ['post_id', true]);
$forum['forums'][$key]['last_poster'] = [
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main'])
'user' => ($lastPoster = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($lastPoster['rank_main']),
];
}
// Lastly grab the topics for this forum
@ -142,45 +134,44 @@ class Forum {
}
// Getting all topics from a forum
public static function getTopics($id) {
public static function getTopics($id)
{
// Get the topics from the database
$topics = Database::fetch('topics', true, [
'forum_id' => [$id, '=']
'forum_id' => [$id, '='],
]);
// Get the userdata related to last posts
foreach($topics as $key => $topic) {
foreach ($topics as $key => $topic) {
// Get the reply count
$topics[$key]['reply_count'] = Database::count('posts', [
'topic_id' => [$topic['topic_id'], '=']
'topic_id' => [$topic['topic_id'], '='],
])[0];
// Get first post in topics
$firstPost = Database::fetch('posts', false, [
'topic_id' => [$topic['topic_id'], '=']
'topic_id' => [$topic['topic_id'], '='],
]);
$topics[$key]['first_poster'] = [
'post' => $firstPost,
'user' => ($_FIRST_POSTER = Users::getUser($firstPost['poster_id'])),
'rank' => Users::getRank($_FIRST_POSTER['rank_main']),
'elap' => Main::timeElapsed($firstPost['post_time'])
'elap' => Main::timeElapsed($firstPost['post_time']),
];
// Get last post in topics
$lastPost = Database::fetch('posts', false, [
'topic_id' => [$topic['topic_id'], '=']
'topic_id' => [$topic['topic_id'], '='],
], ['post_id', true]);
$topics[$key]['last_poster'] = [
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main']),
'elap' => Main::timeElapsed($lastPost['post_time'])
'elap' => Main::timeElapsed($lastPost['post_time']),
];
}
return $topics;
@ -188,38 +179,38 @@ class Forum {
}
// Get posts of a thread
public static function getTopic($id, $ignoreView = false) {
public static function getTopic($id, $ignoreView = false)
{
// Get the topic data from the database
$topicInfo = Database::fetch('topics', false, [
'topic_id' => [$id, '=']
'topic_id' => [$id, '='],
]);
// Check if there actually is anything
if(empty($topicInfo))
if (empty($topicInfo)) {
return false;
}
// Up the view count
if(!$ignoreView) {
if (!$ignoreView) {
// Get the new count
$topicInfo['topic_views'] = $topicInfo['topic_views'] + 1;
// Update the count
Database::update('topics', [
[
'topic_views' => $topicInfo['topic_views']
'topic_views' => $topicInfo['topic_views'],
],
[
'topic_id' => [$id, '=']
]
'topic_id' => [$id, '='],
],
]);
}
// Get the posts from the database
$rawPosts = Database::fetch('posts', true, [
'topic_id' => [$id, '=']
'topic_id' => [$id, '='],
]);
// Create storage array
@ -233,7 +224,7 @@ class Forum {
// Get first post in topics
$firstPost = Database::fetch('posts', false, [
'topic_id' => [$topic['topic']['topic_id'], '=']
'topic_id' => [$topic['topic']['topic_id'], '='],
]);
// Get the data of the first poster
@ -241,12 +232,12 @@ class Forum {
'post' => $firstPost,
'user' => ($_FIRST_POSTER = Users::getUser($firstPost['poster_id'])),
'rank' => Users::getRank($_FIRST_POSTER['rank_main']),
'elap' => Main::timeElapsed($firstPost['post_time'])
'elap' => Main::timeElapsed($firstPost['post_time']),
];
// Get last post in topics
$lastPost = Database::fetch('posts', false, [
'topic_id' => [$topic['topic']['topic_id'], '=']
'topic_id' => [$topic['topic']['topic_id'], '='],
], ['post_id', true]);
// Get the data of the last poster
@ -254,32 +245,30 @@ class Forum {
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main']),
'elap' => Main::timeElapsed($lastPost['post_time'])
'elap' => Main::timeElapsed($lastPost['post_time']),
];
// Create space for posts
$topic['posts'] = [];
// Parse the data of every post
foreach($rawPosts as $post) {
foreach ($rawPosts as $post) {
// Add post and metadata to the global storage array
$topic['posts'][$post['post_id']] = array_merge($post, [
'is_op' => ($post['poster_id'] == $firstPost['poster_id'] ? '1' : '0'),
'user' => ($_POSTER = Users::getUser($post['poster_id'])),
'rank' => Users::getRank($_POSTER['rank_main']),
'time_elapsed' => Main::timeElapsed($post['post_time']),
'country' => Main::getCountryName($_POSTER['country']),
'is_premium' => Users::checkUserPremium($_POSTER['id'])[0],
'is_online' => Users::checkUserOnline($_POSTER['id']),
'is_friend' => Users::checkFriend($_POSTER['id']),
'parsed_post' => self::parseMarkUp($post['post_text'], $post['parse_mode'], $post['enable_emotes']),
'signature' => empty($_POSTER['userData']['signature']) ? '' : self::parseMarkUp($_POSTER['userData']['signature']['text'], $_POSTER['userData']['signature']['mode'])
'is_op' => ($post['poster_id'] == $firstPost['poster_id'] ? '1' : '0'),
'user' => ($_POSTER = Users::getUser($post['poster_id'])),
'rank' => Users::getRank($_POSTER['rank_main']),
'time_elapsed' => Main::timeElapsed($post['post_time']),
'country' => Main::getCountryName($_POSTER['country']),
'is_premium' => Users::checkUserPremium($_POSTER['id'])[0],
'is_online' => Users::checkUserOnline($_POSTER['id']),
'is_friend' => Users::checkFriend($_POSTER['id']),
'parsed_post' => self::parseMarkUp($post['post_text'], $post['parse_mode'], $post['enable_emotes']),
'signature' => empty($_POSTER['userData']['signature']) ? '' : self::parseMarkUp($_POSTER['userData']['signature']['text'], $_POSTER['userData']['signature']['mode']),
]);
// Just in case
unset($_POSTER);
}
// Return the compiled topic data
@ -288,16 +277,18 @@ class Forum {
}
// Get a topic ID from a post ID
public static function getTopicIdFromPostId($id) {
public static function getTopicIdFromPostId($id)
{
// Get the post
$post = Database::fetch('posts', false, [
'post_id' => [$id, '=']
'post_id' => [$id, '='],
]);
// Return false if nothing was returned
if(empty($post))
if (empty($post)) {
return false;
}
// Return the topic id
return $post['topic_id'];
@ -305,68 +296,67 @@ class Forum {
}
// Parse different markup flavours
public static function parseMarkUp($text, $mode, $emotes = 1) {
public static function parseMarkUp($text, $mode, $emotes = 1)
{
// Clean string
$text = Main::cleanString($text);
// Parse emotes
if($emotes)
if ($emotes) {
$text = Main::parseEmotes($text);
}
// Switch between modes
switch($mode) {
switch ($mode) {
case 1:
return Main::bbParse($text);
case 2:
return Main::mdParse($text);
case 0:
default:
return $text;
}
}
// Get forum statistics of a user
public static function getUserStats($uid) {
public static function getUserStats($uid)
{
// Collect the stats
return [
'posts' => Database::count('posts', ['poster_id' => [$uid, '=']])[0],
'topics' => count(Database::fetch('posts', true, ['poster_id' => [$uid, '=']], ['post_time'], null, ['topic_id']))
'posts' => Database::count('posts', ['poster_id' => [$uid, '=']])[0],
'topics' => count(Database::fetch('posts', true, ['poster_id' => [$uid, '=']], ['post_time'], null, ['topic_id'])),
];
}
// Creating a new post
public static function createPost($subject, $text, $enableMD, $enableSig, $forum, $type = 0, $status = 0, $topic = 0) {
public static function createPost($subject, $text, $enableMD, $enableSig, $forum, $type = 0, $status = 0, $topic = 0)
{
// Check if this post is OP
if(!$topic) {
if (!$topic) {
// If so create a new topic
Database::insert('topics', [
'forum_id' => $forum,
'topic_hidden' => 0,
'topic_title' => $subject,
'topic_time' => time(),
'topic_time_limit' => 0,
'topic_last_reply' => 0,
'topic_views' => 0,
'topic_replies' => 0,
'topic_status' => $status,
'topic_status_change' => 0,
'topic_type' => $type,
'topic_first_post_id' => 0,
'topic_first_poster_id' => Session::$userId
'forum_id' => $forum,
'topic_hidden' => 0,
'topic_title' => $subject,
'topic_time' => time(),
'topic_time_limit' => 0,
'topic_last_reply' => 0,
'topic_views' => 0,
'topic_replies' => 0,
'topic_status' => $status,
'topic_status_change' => 0,
'topic_type' => $type,
'topic_first_post_id' => 0,
'topic_first_poster_id' => Session::$userId,
]);
}
}
}

View file

@ -31,23 +31,24 @@
namespace Sakura;
class Hashing {
class Hashing
{
// These variables can be changed without break the existing hashes
private static $_PBKDF2_HASH_ALGORITHM = 'sha256';
private static $_PBKDF2_ITERATIONS = 1000;
private static $_PBKDF2_SALT_BYTES = 24;
private static $_PBKDF2_HASH_BYTES = 24;
private static $_PBKDF2_HASH_ALGORITHM = 'sha256';
private static $_PBKDF2_ITERATIONS = 1000;
private static $_PBKDF2_SALT_BYTES = 24;
private static $_PBKDF2_HASH_BYTES = 24;
// Changing these will break them though
private static $_HASH_ALGORITHM_INDEX = 0;
private static $_HASH_ITERATION_INDEX = 1;
private static $_HASH_SALT_INDEX = 2;
private static $_HASH_PBKDF2_INDEX = 3;
private static $_HASH_SECTIONS = 4;
private static $_HASH_ALGORITHM_INDEX = 0;
private static $_HASH_ITERATION_INDEX = 1;
private static $_HASH_SALT_INDEX = 2;
private static $_HASH_PBKDF2_INDEX = 3;
private static $_HASH_SECTIONS = 4;
// Returns an array formatted like: [algorithm, iterations, salt, hash]
public static function create_hash($pass) {
public static function create_hash($pass)
{
$salt = base64_encode(
\mcrypt_create_iv(
@ -71,7 +72,7 @@ class Hashing {
self::$_PBKDF2_HASH_ALGORITHM,
self::$_PBKDF2_ITERATIONS,
$salt,
$hash
$hash,
);
return $passwordData;
@ -79,10 +80,12 @@ class Hashing {
}
// Validates hashed password
public static function validate_password($password, $params) {
public static function validate_password($password, $params)
{
if(count($params) < self::$_HASH_SECTIONS)
if (count($params) < self::$_HASH_SECTIONS) {
return false;
}
$pbkdf2 = base64_decode($params[self::$_HASH_PBKDF2_INDEX]);
@ -92,7 +95,7 @@ class Hashing {
$params[self::$_HASH_ALGORITHM_INDEX],
$password,
$params[self::$_HASH_SALT_INDEX],
(int)$params[self::$_HASH_ITERATION_INDEX],
(int) $params[self::$_HASH_ITERATION_INDEX],
strlen($pbkdf2),
true
)
@ -103,12 +106,14 @@ class Hashing {
}
// Compares two strings $a and $b in length-constant time.
public static function slow_equals($a, $b) {
public static function slow_equals($a, $b)
{
$diff = strlen($a) ^ strlen($b);
for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
for ($i = 0; $i < strlen($a) && $i < strlen($b); $i++) {
$diff |= ord($a[$i]) ^ ord($b[$i]);
}
return $diff === 0;
@ -130,24 +135,26 @@ class Hashing {
* With improvements by http://www.variations-of-shadow.com
*/
private static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) {
private static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
$algorithm = strtolower($algorithm);
if(!in_array($algorithm, hash_algos(), true))
if (!in_array($algorithm, hash_algos(), true)) {
trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
}
if($count <= 0 || $key_length <= 0)
if ($count <= 0 || $key_length <= 0) {
trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);
}
if(function_exists('hash_pbkdf2')) {
if (function_exists('hash_pbkdf2')) {
// The output length is in NIBBLES (4-bits) if $raw_output is false!
if(!$raw_output)
if (!$raw_output) {
$key_length = $key_length * 2;
}
return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
}
$hash_length = strlen(hash($algorithm, '', true));
@ -155,8 +162,7 @@ class Hashing {
$output = '';
for($i = 1; $i <= $block_count; $i++) {
for ($i = 1; $i <= $block_count; $i++) {
// $i encoded as 4 bytes, big endian.
$last = $salt . pack('N', $i);
@ -164,18 +170,18 @@ class Hashing {
$last = $xorsum = hash_hmac($algorithm, $last, $password, true);
// Perform the other $count - 1 interations
for($j = 1; $j < $count; $j++)
for ($j = 1; $j < $count; $j++) {
$xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
}
$output .= $xorsum;
if($raw_output)
if ($raw_output) {
return substr($output, 0, $key_length);
else
return bin2hex(substr($output, 0, $key_length));
}
return bin2hex(substr($output, 0, $key_length));
}
}
}

View file

@ -8,10 +8,11 @@ namespace Sakura;
use Parsedown;
use PHPMailer;
class Main {
class Main
{
// Constructor
public static function init($config) {
public static function init($config)
{
// Configuration Management and local configuration
Configuration::init($config);
@ -28,32 +29,35 @@ class Main {
}
// Parse markdown
public static function mdParse($text) {
public static function mdParse($text)
{
return (new Parsedown())->text($text);
}
// Get bbcodes
public static function getBBcodes() {
public static function getBBcodes()
{
return Database::fetch('bbcodes');
}
// Parse bbcodes
public static function bbParse($text) {
public static function bbParse($text)
{
// Get bbcode regex from the database
$bbcodes = Database::fetch('bbcodes');
// Split the regex
$regex = array_map(function($arr) {
$regex = array_map(function ($arr) {
return $arr['regex'];
}, $bbcodes);
// Split the replacement
$replace = array_map(function($arr) {
$replace = array_map(function ($arr) {
return $arr['replace'];
}, $bbcodes);
@ -66,23 +70,23 @@ class Main {
}
// Get emoticons
public static function getEmotes() {
public static function getEmotes()
{
return Database::fetch('emoticons');
}
// Parsing emoticons
public static function parseEmotes($text) {
public static function parseEmotes($text)
{
// Get emoticons from the database
$emotes = Database::fetch('emoticons');
// Do the replacements
foreach($emotes as $emote) {
$text = str_replace($emote['emote_string'], '<img src="'. $emote['emote_path'] .'" class="emoticon" alt="'. $emote['emote_string'] .'" />', $text);
foreach ($emotes as $emote) {
$text = str_replace($emote['emote_string'], '<img src="' . $emote['emote_path'] . '" class="emoticon" alt="' . $emote['emote_string'] . '" />', $text);
}
// Return the parsed text
@ -91,16 +95,15 @@ class Main {
}
// Verify ReCAPTCHA
public static function verifyCaptcha($response) {
public static function verifyCaptcha($response)
{
// Attempt to get the response
$resp = @file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='. Configuration::getConfig('recaptcha_private') .'&response='. $response);
$resp = @file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . Configuration::getConfig('recaptcha_private') . '&response=' . $response);
// In the highly unlikely case that it failed to get anything forge a false
if(!$resp) {
if (!$resp) {
return false;
}
// Decode the response JSON from the servers
@ -112,49 +115,44 @@ class Main {
}
// Error Handler
public static function errorHandler($errno, $errstr, $errfile, $errline) {
public static function errorHandler($errno, $errstr, $errfile, $errline)
{
// Remove ROOT path from the error string and file location
$errstr = str_replace(ROOT, '', $errstr);
$errfile = str_replace(ROOT, '', $errfile);
$errstr = str_replace(ROOT, '', $errstr);
$errfile = str_replace(ROOT, '', $errfile);
// Attempt to log the error to the database
if(Database::$_DATABASE !== null) {
if (Database::$database !== null) {
// Encode backtrace data
$backtrace = base64_encode(json_encode(debug_backtrace()));
// Check if this error has already been logged in the past
if($past = Database::fetch('error_log', false, ['backtrace' => [$backtrace, '=', true], 'error_string' => [$errstr, '=']])) {
if ($past = Database::fetch('error_log', false, ['backtrace' => [$backtrace, '=', true], 'error_string' => [$errstr, '=']])) {
// If so assign the errid
$errid = $past['id'];
} else {
// Create an error ID
$errid = substr(md5(microtime()), rand(0, 22), 10);
// Log the error
Database::insert('error_log', [
'id' => $errid,
'timestamp' => date("r"),
'revision' => SAKURA_VERSION,
'error_type' => $errno,
'error_line' => $errline,
'error_string' => $errstr,
'error_file' => $errfile,
'backtrace' => $backtrace
'id' => $errid,
'timestamp' => date("r"),
'revision' => SAKURA_VERSION,
'error_type' => $errno,
'error_line' => $errline,
'error_string' => $errstr,
'error_file' => $errfile,
'backtrace' => $backtrace,
]);
}
}
switch ($errno) {
case E_ERROR:
case E_USER_ERROR:
$error = '<b>FATAL ERROR</b>: ' . $errstr . ' on line ' . $errline . ' in ' . $errfile;
@ -172,7 +170,6 @@ class Main {
default:
$error = '<b>Unknown error type</b> [' . $errno . ']: ' . $errstr . ' on line ' . $errline . ' in ' . $errfile;
}
// Truncate all previous outputs
@ -205,41 +202,33 @@ class Main {
<div class="inner">
<p>To prevent potential security risks or data loss Sakura has stopped execution of the script.</p>';
if(isset($errid)) {
if (isset($errid)) {
$errorPage .= '<p>The error and surrounding data has been logged.</p>
<h2>' . (SAKURA_STABLE ? 'Report the following text to a staff member' : 'Logged as') . '</h2><pre class="error">' . $errid . '</pre>';
} else {
$errorPage .= '<p>Sakura was not able to log this error which could mean that there was an error with the database connection. If you\'re the system administrator check the database credentials and make sure the server is running and if you\'re not please let the system administrator know about this error if it occurs again.</p>';
}
$errorPage .= '<p>The error and surrounding data has been logged.</p>
<h2>'. (SAKURA_STABLE ? 'Report the following text to a staff member' : 'Logged as') .'</h2><pre class="error">'. $errid .'</pre>';
} else {
$errorPage .= '<p>Sakura was not able to log this error which could mean that there was an error with the database connection. If you\'re the system administrator check the database credentials and make sure the server is running and if you\'re not please let the system administrator know about this error if it occurs again.</p>';
}
if(!SAKURA_STABLE) {
$errorPage .= ' <h2>Summary</h2>
<pre class="error">'. $error .'</pre>
if (!SAKURA_STABLE) {
$errorPage .= ' <h2>Summary</h2>
<pre class="error">' . $error . '</pre>
<h2>Backtraces</h2>';
foreach(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $num => $trace) {
foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $num => $trace) {
$errorPage .= '<h3>#' . $num . '</h3><pre class="error">';
$errorPage .= '<h3>#'. $num .'</h3><pre class="error">';
foreach ($trace as $key => $val) {
$errorPage .= str_pad('[' . $key . ']', 12) . '=> ' . (is_array($val) || is_object($val) ? json_encode($val) : $val) . "\r\n";
}
foreach($trace as $key => $val) {
$errorPage .= str_pad('['. $key .']', 12) .'=> '. (is_array($val) || is_object($val) ? json_encode($val) : $val) ."\r\n";
$errorPage .= '</pre>';
}
}
$errorPage .= '</pre>';
}
}
$errorPage .= '</div>
$errorPage .= '</div>
<div class="footer">
Sakura r'. SAKURA_VERSION .'.
Sakura r' . SAKURA_VERSION . '.
</div>
</div>
</body>
@ -251,7 +240,8 @@ $errorPage .= '</div>
}
// Send emails
public static function sendMail($to, $subject, $body) {
public static function sendMail($to, $subject, $body)
{
// Initialise PHPMailer
$mail = new PHPMailer();
@ -272,11 +262,9 @@ $errorPage .= '</div>
$mail->Port = Configuration::getConfig('smtp_port');
// If authentication is required log in as well
if(Configuration::getConfig('smtp_auth')) {
if (Configuration::getConfig('smtp_auth')) {
$mail->Username = Configuration::getConfig('smtp_username');
$mail->Password = base64_decode(Configuration::getConfig('smtp_password'));
}
// Add a reply-to header
@ -286,10 +274,8 @@ $errorPage .= '</div>
$mail->SetFrom(Configuration::getConfig('smtp_from_email'), Configuration::getConfig('smtp_from_name'));
// Set the addressee
foreach($to as $email => $name) {
foreach ($to as $email => $name) {
$mail->AddBCC($email, $name);
}
// Subject line
@ -299,12 +285,12 @@ $errorPage .= '</div>
$mail->isHTML(true);
// Set email contents
$htmlMail = file_get_contents(ROOT .'_sakura/templates/htmlEmail.tpl');
$htmlMail = file_get_contents(ROOT . '_sakura/templates/htmlEmail.tpl');
// Replace template tags
$htmlMail = str_replace('{{ sitename }}', Configuration::getConfig('sitename'), $htmlMail);
$htmlMail = str_replace('{{ siteurl }}', '//'. Configuration::getConfig('url_main'), $htmlMail);
$htmlMail = str_replace('{{ contents }}', self::mdParse($body), $htmlMail);
$htmlMail = str_replace('{{ sitename }}', Configuration::getConfig('sitename'), $htmlMail);
$htmlMail = str_replace('{{ siteurl }}', '//' . Configuration::getConfig('url_main'), $htmlMail);
$htmlMail = str_replace('{{ contents }}', self::mdParse($body), $htmlMail);
// Set HTML body
$mail->Body = $htmlMail;
@ -319,7 +305,7 @@ $errorPage .= '</div>
$mail->ClearAddresses();
// If we got an error return the error
if(!$send) {
if (!$send) {
return $mail->ErrorInfo;
@ -331,7 +317,8 @@ $errorPage .= '</div>
}
// Cleaning strings
public static function cleanString($string, $lower = false, $nospecial = false) {
public static function cleanString($string, $lower = false, $noSpecial = false)
{
// Run common sanitisation function over string
$string = htmlentities($string, ENT_NOQUOTES | ENT_HTML401, Configuration::getConfig('charset'));
@ -339,17 +326,13 @@ $errorPage .= '</div>
$string = strip_tags($string);
// If set also make the string lowercase
if($lower) {
if ($lower) {
$string = strtolower($string);
}
// If set remove all characters that aren't a-z or 0-9
if($nospecial) {
if ($noSpecial) {
$string = preg_replace('/[^a-z0-9]/', '', $string);
}
// Return clean string
@ -358,7 +341,8 @@ $errorPage .= '</div>
}
// Loading info pages
public static function loadInfoPage($id) {
public static function loadInfoPage($id)
{
// Get contents from the database
$infopage = Database::fetch('infopages', false, ['shorthand' => [$id, '=']]);
@ -369,7 +353,8 @@ $errorPage .= '</div>
}
// Validate MX records
public static function checkMXRecord($email) {
public static function checkMXRecord($email)
{
// Get the domain from the e-mail address
$domain = substr(strstr($email, '@'), 1);
@ -383,25 +368,20 @@ $errorPage .= '</div>
}
// Check IP version
public static function ipVersion($ip) {
public static function ipVersion($ip)
{
// Check if var is IP
if(filter_var($ip, FILTER_VALIDATE_IP)) {
if (filter_var($ip, FILTER_VALIDATE_IP)) {
// IPv4
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
return 4;
}
// IPv6
if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
return 6;
}
}
// Not an IP or unknown type
@ -410,7 +390,8 @@ $errorPage .= '</div>
}
// Convert inet_pton to string with bits
public static function inetToBits($inet) {
public static function inetToBits($inet)
{
// Unpack string
$unpacked = unpack('A16', $inet);
@ -422,10 +403,8 @@ $errorPage .= '</div>
$binaryIP = null;
// "Build" binary IP
foreach($unpacked as $char) {
foreach ($unpacked as $char) {
$binaryIP .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
}
// Return IP
@ -434,20 +413,19 @@ $errorPage .= '</div>
}
// Match IP subnets
public static function matchSubnet($ip, $range) {
public static function matchSubnet($ip, $range)
{
// Use the proper IP type
switch(self::ipVersion($ip)) {
switch (self::ipVersion($ip)) {
case 4:
// Break the range up in parts
list($subnet, $bits) = explode('/', $range);
// Convert IP and Subnet to long
$ip = ip2long($ip);
$ip = ip2long($ip);
$subnet = ip2long($subnet);
$mask = -1 << (32 - $bits);
$mask = -1 << (32 - $bits);
// In case the supplied subnet wasn't correctly aligned
$subnet &= $mask;
@ -456,20 +434,19 @@ $errorPage .= '</div>
return ($ip & $mask) == $subnet;
case 6:
// Break the range up in parts
list($subnet, $bits) = explode('/', $range);
// Convert subnet to packed address and convert it to binary
$subnet = inet_pton($subnet);
$binarySubnet = self::inetToBits($subnet);
$subnet = inet_pton($subnet);
$binarySubnet = self::inetToBits($subnet);
// Convert IPv6 to packed address and convert it to binary as well
$ip = inet_pton($ip);
$binaryIP = self::inetToBits($ip);
$ip = inet_pton($ip);
$binaryIP = self::inetToBits($ip);
// Return bits of the strings according to the bits
$ipBits = substr($binaryIP, 0, $bits);
$ipBits = substr($binaryIP, 0, $bits);
$subnetBits = substr($binarySubnet, 0, $bits);
return ($ipBits === $subnetBits);
@ -482,10 +459,11 @@ $errorPage .= '</div>
}
// Check if IP is a CloudFlare IP
public static function checkCFIP($ip) {
public static function checkCFIP($ip)
{
// Get CloudFlare Subnet list
$cfhosts = file_get_contents(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'cfipv'. (self::ipVersion($ip))));
$cfhosts = file_get_contents(ROOT . '_sakura/' . Configuration::getLocalConfig('data', 'cfipv' . (self::ipVersion($ip))));
// Replace \r\n with \n
$cfhosts = str_replace("\r\n", "\n", $cfhosts);
@ -494,22 +472,16 @@ $errorPage .= '</div>
$cfhosts = explode("\n", $cfhosts);
// Check if IP is in a CloudFlare subnet
foreach($cfhosts as $subnet) {
foreach ($cfhosts as $subnet) {
// Check if the subnet isn't empty (git newline prevention)
if(strlen($subnet) < 1) {
if (strlen($subnet) < 1) {
continue;
}
// Return true if found
if(self::matchSubnet($ip, $subnet)) {
if (self::matchSubnet($ip, $subnet)) {
return true;
}
}
// Return false if fails
@ -518,21 +490,18 @@ $errorPage .= '</div>
}
// Gets IP of current visitor
public static function getRemoteIP() {
public static function getRemoteIP()
{
// Assign REMOTE_ADDR to a variables
$ip = $_SERVER['REMOTE_ADDR'];
// Check if the IP is a CloudFlare IP
if(self::checkCFIP($ip)) {
if (self::checkCFIP($ip)) {
// If it is check if the CloudFlare IP header is set and if it is assign it to the ip variable
if(isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
}
// Return the correct IP
@ -541,13 +510,12 @@ $errorPage .= '</div>
}
// Get country code from CloudFlare header (which just returns XX if not found)
public static function getCountryCode() {
public static function getCountryCode()
{
// Check if the required header is set and return it
if(isset($_SERVER['HTTP_CF_IPCOUNTRY'])) {
if (isset($_SERVER['HTTP_CF_IPCOUNTRY'])) {
return $_SERVER['HTTP_CF_IPCOUNTRY'];
}
// Return XX as a fallback
@ -556,13 +524,12 @@ $errorPage .= '</div>
}
// Create a new action code
public static function newActionCode($action, $userid, $instruct) {
public static function newActionCode($action, $userid, $instruct)
{
// Make sure the user we're working with exists
if(Users::getUser($userid)['id'] == 0) {
if (Users::getUser($userid)['id'] == 0) {
return false;
}
// Convert the instruction array to a JSON
@ -573,10 +540,10 @@ $errorPage .= '</div>
// Insert the key into the database
Database::insert('actioncodes', [
'action' => $action,
'userid' => $userid,
'actkey' => $key,
'instruction' => $instruct
'action' => $action,
'userid' => $userid,
'actkey' => $key,
'instruction' => $instruct,
]);
// Return the key
@ -585,35 +552,30 @@ $errorPage .= '</div>
}
// Use an action code
public static function useActionCode($action, $key, $uid = 0) {
public static function useActionCode($action, $key, $uid = 0)
{
// Retrieve the row from the database
$keyRow = Database::fetch('actioncodes', false, [
'actkey' => [$key, '='],
'action' => [$action, '=']
'actkey' => [$key, '='],
'action' => [$action, '='],
]);
// Check if the code exists
if(count($keyRow) <= 1) {
if (count($keyRow) <= 1) {
return [0, 'INVALID_CODE'];
}
// Check if the code was intended for the user that's using this code
if($keyRow['userid'] != 0) {
if($keyRow['userid'] != $uid) {
if ($keyRow['userid'] != 0) {
if ($keyRow['userid'] != $uid) {
return [0, 'INVALID_USER'];
}
}
// Remove the key from the database
Database::delete('actioncodes', [
'id' => [$keyRow['id'], '=']
'id' => [$keyRow['id'], '='],
]);
// Return success
@ -622,7 +584,8 @@ $errorPage .= '</div>
}
// Calculate password entropy
public static function pwdEntropy($pw) {
public static function pwdEntropy($pw)
{
// Decode utf-8 chars
$pw = utf8_decode($pw);
@ -633,26 +596,25 @@ $errorPage .= '</div>
}
// Get country name from ISO 3166 code
public static function getCountryName($code) {
public static function getCountryName($code)
{
// Parse JSON file
$iso3166 = json_decode(utf8_encode(file_get_contents(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'iso3166'))), true);
$iso3166 = json_decode(utf8_encode(file_get_contents(ROOT . '_sakura/' . Configuration::getLocalConfig('data', 'iso3166'))), true);
// Check if key exists
if(array_key_exists($code, $iso3166)) {
if (array_key_exists($code, $iso3166)) {
return $iso3166[$code]; // If entry found return the full name
} else {
return 'Unknown'; // Else return unknown
}
// Else return unknown
return 'Unknown';
}
// Get FAQ data
public static function getFaqData() {
public static function getFaqData()
{
// Do database call
$faq = Database::fetch('faq', true, null, ['id']);
@ -663,16 +625,15 @@ $errorPage .= '</div>
}
// Get log type string
public static function getLogStringFromType($type) {
public static function getLogStringFromType($type)
{
// Query the database
$return = Database::fetch('logtypes', false, ['id' => [$type, '=']]);
// Check if type exists and else return a unformattable string
if(count($return) < 2) {
if (count($return) < 2) {
return 'Unknown action.';
}
// Return the string
@ -681,7 +642,8 @@ $errorPage .= '</div>
}
// Get formatted logs
public static function getUserLogs($uid = 0) {
public static function getUserLogs($uid = 0)
{
// Check if a user is specified
$conditions = ($uid ? ['uid' => [$uid, '=']] : null);
@ -693,15 +655,13 @@ $errorPage .= '</div>
$logs = array();
// Iterate over entries
foreach($logsDB as $log) {
foreach ($logsDB as $log) {
// Store usable data
$logs[$log['id']] = [
'user' => $_USER = Users::getUser($log['uid']),
'rank' => Users::getRank($_USER['rank_main']),
'string' => vsprintf(self::getLogStringFromType($log['action']), json_decode($log['attribs'], true))
'user' => $_USER = Users::getUser($log['uid']),
'rank' => Users::getRank($_USER['rank_main']),
'string' => vsprintf(self::getLogStringFromType($log['action']), json_decode($log['attribs'], true)),
];
}
// Return new logs
@ -710,7 +670,8 @@ $errorPage .= '</div>
}
// Indent JSON
public static function jsonPretty($json) {
public static function jsonPretty($json)
{
// Defines
$tab = ' ';
@ -720,70 +681,53 @@ $errorPage .= '</div>
$obj = json_decode($json);
// Validate the object
if($obj === false)
if ($obj === false) {
return false;
}
// Re-encode the json and get the length
$json = json_encode($obj);
$len = strlen($json);
// Go over the entries
for($c = 0; $c < $len; $c++) {
for ($c = 0; $c < $len; $c++) {
// Get the current character
$char = $json[$c];
switch($char) {
switch ($char) {
case '[':
case '{':
if($str) {
if ($str) {
$out .= $char;
} else {
$out .= $char ."\r\n". str_repeat($tab, $lvl + 1);
$out .= $char . "\r\n" . str_repeat($tab, $lvl + 1);
$lvl++;
}
break;
case ']':
case '}':
if($str) {
if ($str) {
$out .= $char;
} else {
$lvl--;
$out .= "\r\n". str_repeat($tab, $lvl) . $char;
$out .= "\r\n" . str_repeat($tab, $lvl) . $char;
}
break;
case ',':
if($str) {
if ($str) {
$out .= $char;
} else {
$out .= ",\r\n". str_repeat($tab, $lvl);
$out .= ",\r\n" . str_repeat($tab, $lvl);
}
break;
case ':':
if($str) {
if ($str) {
$out .= $char;
} else {
$out .= ": ";
}
break;
@ -801,53 +745,50 @@ $errorPage .= '</div>
}
// Time elapsed
public static function timeElapsed($timestamp, $append = ' ago', $none = 'Just now') {
public static function timeElapsed($timestamp, $append = ' ago', $none = 'Just now')
{
// Subtract the entered timestamp from the current timestamp
$time = time() - $timestamp;
// If the new timestamp is below 1 return a standard string
if($time < 1) {
if ($time < 1) {
return $none;
}
// Array containing time "types"
$times = [
365 * 24 * 60 * 60 => 'year',
30 * 24 * 60 * 60 => 'month',
24 * 60 * 60 => 'day',
60 * 60 => 'hour',
60 => 'minute',
1 => 'second'
30 * 24 * 60 * 60 => 'month',
24 * 60 * 60 => 'day',
60 * 60 => 'hour',
60 => 'minute',
1 => 'second',
];
foreach($times as $secs => $str) {
foreach ($times as $secs => $str) {
// Do a devision to check if the given timestamp fits in the current "type"
$calc = $time / $secs;
if($calc >= 1) {
if ($calc >= 1) {
// Round the number
$round = round($calc);
// Return the string
return $round .' '. $times[$secs] . ($round == 1 ? '' : 's') . $append;
return $round . ' ' . $times[$secs] . ($round == 1 ? '' : 's') . $append;
}
}
}
// Get the byte symbol from a value
public static function getByteSymbol($bytes) {
public static function getByteSymbol($bytes)
{
// Return nothing if the input was 0
if(!$bytes)
if (!$bytes) {
return;
}
// Array with byte symbols
$symbols = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
@ -856,7 +797,7 @@ $errorPage .= '</div>
$exp = floor(log($bytes) / log(1024));
// Format the things
$bytes = sprintf("%.2f ". $symbols[$exp], ($bytes / pow(1024, floor($exp))));
$bytes = sprintf("%.2f " . $symbols[$exp], ($bytes / pow(1024, floor($exp))));
// Return the formatted string
return $bytes;
@ -864,7 +805,8 @@ $errorPage .= '</div>
}
// Get Premium tracker data
public static function getPremiumTrackerData() {
public static function getPremiumTrackerData()
{
// Create data array
$data = [];
@ -882,18 +824,16 @@ $errorPage .= '</div>
$data['users'] = [];
// Calculate the thing
foreach($table as $row) {
foreach ($table as $row) {
// Calculate balance
$data['balance'] = $data['balance'] + $row['amount'];
// Add userdata to table
if(!array_key_exists($row['uid'], $data['users'])) {
if (!array_key_exists($row['uid'], $data['users'])) {
$data['users'][$row['uid']] = new User($row['uid']);
}
}
// Return the data
@ -902,17 +842,17 @@ $errorPage .= '</div>
}
// Update donation tracker
public static function updatePremiumTracker($id, $amount, $comment) {
public static function updatePremiumTracker($id, $amount, $comment)
{
Database::insert('premium_log', [
'uid' => $id,
'amount' => $amount,
'date' => time(),
'comment' => $comment
'uid' => $id,
'amount' => $amount,
'date' => time(),
'comment' => $comment,
]);
}
}

View file

@ -2,11 +2,10 @@
/*
* Management Class
*/
namespace Sakura;
class Manage {
class Manage
{
}

View file

@ -5,26 +5,24 @@
namespace Sakura;
class News {
private $posts = []; // Posts array
private $posters = []; // Posters array (so we don't create a new user object every time)
class News
{
private $posts = []; // Posts array
private $posters = []; // Posters array (so we don't create a new user object every time)
// Initialise the news object
function __construct($category, $comments = true) {
public function __construct($category, $comments = true)
{
// Get the news posts and assign them to $posts
$posts = Database::fetch('news', true, ['category' => [$category, '=']], ['id', true]);
// Attach poster data
foreach($posts as $post) {
foreach ($posts as $post) {
// Check if we already have an object for this user
if(!array_key_exists($post['uid'], $this->posters)) {
// Create new object
$this->posters[$post['uid']] = new User($post['uid']);
if (!array_key_exists($post['uid'], $this->posters)) {
// Create new object
$this->posters[$post['uid']] = new User($post['uid']);
}
// Parse the news post
@ -35,53 +33,50 @@ class News {
// Add post to posts array
$this->posts[$post['id']] = $post;
}
}
// Get the amount of posts
public function getCount() {
public function getCount()
{
return count($this->posts);
}
// Get the amount of posts
public function postExists($id) {
public function postExists($pid)
{
return array_key_exists($id, $this->posts) ? $id : 0;
return array_key_exists($pid, $this->posts) ? $pid : 0;
}
// Get a single post
public function getPost($id) {
public function getPost($pid)
{
return array_key_exists($id, $this->posts) ? $this->posts[$id] : 0;
return array_key_exists($pid, $this->posts) ? $this->posts[$pid] : 0;
}
// Getting posts
public function getPosts($start = null, $end = null) {
public function getPosts($start = null, $end = null)
{
// Get posts
$posts = $this->posts;
// Only return requested posts
if($start !== null && $end !== null) {
if ($start !== null && $end !== null) {
// Slice the array
$posts = array_slice($posts, $start, $end, true);
} elseif($start !== null) {
} elseif ($start !== null) {
// Devide the array in parts (pages)
$posts = array_chunk($posts, $start, true);
}
return $posts;
}
}

View file

@ -5,23 +5,24 @@
namespace Sakura;
use \PayPal\Api\Payer;
use \PayPal\Api\Amount;
use \PayPal\Api\Details;
use \PayPal\Api\Item;
use \PayPal\Api\ItemList;
use \PayPal\Api\Details;
use \PayPal\Api\Amount;
use \PayPal\Api\Transaction;
use \PayPal\Api\RedirectUrls;
use \PayPal\Api\Payer;
use \PayPal\Api\Payment;
use \PayPal\Api\PaymentExecution;
use \PayPal\Api\RedirectUrls;
use \PayPal\Api\Transaction;
class Payments {
class Payments
{
// Container for PayPal API
private static $paypal;
// Initialise PayPal API
public static function init() {
public static function init()
{
// Set PayPal object
try {
@ -31,7 +32,7 @@ class Payments {
Configuration::getConfig('paypal_secret')
)
);
} catch(Exception $e) {
} catch (Exception $e) {
return false;
}
@ -40,7 +41,8 @@ class Payments {
}
// Create transaction
public static function createTransaction($total, $itemName, $transDescription, $returnUrl) {
public static function createTransaction($total, $itemName, $transDescription, $returnUrl)
{
// Create the payer object
$payer = new Payer();
@ -52,10 +54,10 @@ class Payments {
$item = new Item();
// Set the item details
$item ->setName($itemName)
->setCurrency('EUR')
->setQuantity(1)
->setPrice($total);
$item->setName($itemName)
->setCurrency('EUR')
->setQuantity(1)
->setPrice($total);
// Create itemlist
$list = new ItemList();
@ -73,39 +75,39 @@ class Payments {
$amount = new Amount();
// Set amount data
$amount ->setCurrency('EUR')
->setTotal($total)
->setDetails($details);
$amount->setCurrency('EUR')
->setTotal($total)
->setDetails($details);
// Create transaction
$trans = new Transaction();
// Set transaction data (aka shit we already set but whatever who cares we need to set it again 500 times over again anyway, YAY TECHNOLOGY!)
$trans ->setAmount($amount)
->setItemList($list)
->setDescription($transDescription)
->setInvoiceNumber(uniqid());
$trans->setAmount($amount)
->setItemList($list)
->setDescription($transDescription)
->setInvoiceNumber(uniqid());
// Create redirect url object
$redir = new RedirectUrls();
// Set redirect url data
$redir ->setReturnUrl($returnUrl. '?mode=finish&success=true')
->setCancelUrl($returnUrl. '?mode=finish&success=false');
$redir->setReturnUrl($returnUrl . '?mode=finish&success=true')
->setCancelUrl($returnUrl . '?mode=finish&success=false');
// Create payment object
$payment = new Payment();
// Set payment data (finally)
$payment->setIntent('sale')
->setPayer($payer)
->setRedirectUrls($redir)
->setTransactions([$trans]);
->setPayer($payer)
->setRedirectUrls($redir)
->setTransactions([$trans]);
// Try to create payment
try {
$payment->create(self::$paypal);
} catch(Exception $ex) {
} catch (Exception $ex) {
return false;
}
@ -115,7 +117,8 @@ class Payments {
}
// Complete the PayPal transaction
public static function completeTransaction($paymentId, $payerId) {
public static function completeTransaction($paymentId, $payerId)
{
// Attempt to get the payment
$payment = Payment::get($paymentId, self::$paypal);
@ -129,7 +132,7 @@ class Payments {
// Attempt to charge the fucker
try {
$payment->execute($execute, self::$paypal);
} catch(Exception $ex) {
} catch (Exception $ex) {
return false;
}
@ -137,5 +140,4 @@ class Payments {
return true;
}
}

View file

@ -5,17 +5,17 @@
namespace Sakura;
class Permissions {
class Permissions
{
// Fallback permission data
private static $fallback = [
'rid' => 0,
'uid' => 0,
'siteperms' => 1,
'manageperms' => 0,
'forumperms' => 0,
'rankinherit' => 111
'rid' => 0,
'uid' => 0,
'siteperms' => 1,
'manageperms' => 0,
'forumperms' => 0,
'rankinherit' => 111,
];
@ -25,79 +25,72 @@ class Permissions {
// Site permissions
'SITE' => [
'DEACTIVATED' => 1, // Is a user deactivated
'RESTRICTED' => 2, // Is a user restricted
'ALTER_PROFILE' => 4, // Can alter their profile data
'CHANGE_AVATAR' => 8, // Can change their avatar
'CREATE_BACKGROUND' => 16, // Can create a background (different from changing)
'CHANGE_BACKGROUND' => 32, // Can change their background
'VIEW_MEMBERLIST' => 64, // Can view the memberlist
'CREATE_USERPAGE' => 128, // Can create a userpage (different from changing)
'CHANGE_USERPAGE' => 256, // Can change their userpage
'USE_MESSAGES' => 512, // Can use the Private Messaging system
'SEND_MESSAGES' => 1024, // Can send Private Messages to other users
'CHANGE_EMAIL' => 2048, // Can change their account e-mail address
'CHANGE_USERNAME' => 4096, // Can change their username
'CHANGE_USERTITLE' => 8192, // Can change their usertitle
'CHANGE_PASSWORD' => 16384, // Can change their password
'ALTER_RANKS' => 32768, // Can change their ranks
'MANAGE_SESSIONS' => 65536, // Can manage their sessions
'CREATE_REGKEYS' => 131072, // Can create registration keys
'DEACTIVATE_ACCOUNT' => 262144, // Can deactivate their account
'VIEW_PROFILE_DATA' => 524288, // Can view other's profile data
'MANAGE_FRIENDS' => 1048576, // Can manage friends (add/remove)
'REPORT_USERS' => 2097152, // Can report users to staff
'OBTAIN_PREMIUM' => 4194304, // Can obtain the premium rank
'JOIN_GROUPS' => 8388608, // Can join groups
'CREATE_GROUP' => 16777216, // Can create a group
'MULTIPLE_GROUPS' => 33554432, // Can create multiple groups (requires single group perm)
'CHANGE_NAMECOLOUR' => 67108864, // Can change their username colour
'STATIC_PREMIUM' => 134217728 // User has static premium status
'DEACTIVATED' => 1, // Is a user deactivated
'RESTRICTED' => 2, // Is a user restricted
'ALTER_PROFILE' => 4, // Can alter their profile data
'CHANGE_AVATAR' => 8, // Can change their avatar
'CREATE_BACKGROUND' => 16, // Can create a background (different from changing)
'CHANGE_BACKGROUND' => 32, // Can change their background
'VIEW_MEMBERLIST' => 64, // Can view the memberlist
'CREATE_USERPAGE' => 128, // Can create a userpage (different from changing)
'CHANGE_USERPAGE' => 256, // Can change their userpage
'USE_MESSAGES' => 512, // Can use the Private Messaging system
'SEND_MESSAGES' => 1024, // Can send Private Messages to other users
'CHANGE_EMAIL' => 2048, // Can change their account e-mail address
'CHANGE_USERNAME' => 4096, // Can change their username
'CHANGE_USERTITLE' => 8192, // Can change their usertitle
'CHANGE_PASSWORD' => 16384, // Can change their password
'ALTER_RANKS' => 32768, // Can change their ranks
'MANAGE_SESSIONS' => 65536, // Can manage their sessions
'CREATE_REGKEYS' => 131072, // Can create registration keys
'DEACTIVATE_ACCOUNT' => 262144, // Can deactivate their account
'VIEW_PROFILE_DATA' => 524288, // Can view other's profile data
'MANAGE_FRIENDS' => 1048576, // Can manage friends (add/remove)
'REPORT_USERS' => 2097152, // Can report users to staff
'OBTAIN_PREMIUM' => 4194304, // Can obtain the premium rank
'JOIN_GROUPS' => 8388608, // Can join groups
'CREATE_GROUP' => 16777216, // Can create a group
'MULTIPLE_GROUPS' => 33554432, // Can create multiple groups (requires single group perm)
'CHANGE_NAMECOLOUR' => 67108864, // Can change their username colour
'STATIC_PREMIUM' => 134217728, // User has static premium status
],
// Forum permissions
'FORUM' => [
'USE_FORUM' => 1
'USE_FORUM' => 1,
],
// Site management permissions
'MANAGE' => [
'USE_MANAGE' => 1
'USE_MANAGE' => 1,
]
],
];
// Checking if a user has the permissions to do a thing
public static function check($layer, $action, $operator, $mode = 0) {
public static function check($layer, $action, $operator, $mode = 0)
{
// Check if the permission layer and the permission itself exists
if(!array_key_exists($layer, self::$permissions) || !array_key_exists($action, self::$permissions[$layer])) {
if (!array_key_exists($layer, self::$permissions) || !array_key_exists($action, self::$permissions[$layer])) {
return false;
}
// Convert to the appropiate mode
if($mode === 2) {
if ($mode === 2) {
$operator = self::getRankPermissions($operator)[$layer];
} elseif($mode === 1) {
} elseif ($mode === 1) {
$operator = self::getUserPermissions($operator)[$layer];
}
// Perform the bitwise AND
if(bindec($operator) & self::$permissions[$layer][$action]) {
if (bindec($operator) & self::$permissions[$layer][$action]) {
return true;
}
// Else just return false
@ -106,54 +99,45 @@ class Permissions {
}
// Get permission data of a rank from the database
public static function getRankPermissions($ranks) {
public static function getRankPermissions($ranks)
{
// Container array
$getRanks = [];
$perms = [];
$getRanks = [];
$perms = [];
// Get permission row for all ranks
foreach($ranks as $rank) {
$getRanks[] = Database::fetch('permissions', false, ['rid' => [$rank, '='], 'uid' => [0 ,'=']]);
foreach ($ranks as $rank) {
$getRanks[] = Database::fetch('permissions', false, ['rid' => [$rank, '='], 'uid' => [0, '=']]);
}
// Check if getRanks is empty or if the rank id is 0 return the fallback
if(empty($getRanks) || in_array(0, $ranks)) {
if (empty($getRanks) || in_array(0, $ranks)) {
$getRanks = [self::$fallback];
}
// Go over the permission data
foreach($getRanks as $rank) {
foreach ($getRanks as $rank) {
// Check if perms is empty
if(empty($perms)) {
if (empty($perms)) {
// Store the data of the current rank in $perms
$perms = [
'SITE' => $rank['siteperms'],
'MANAGE' => $rank['manageperms'],
'FORUM' => $rank['forumperms']
'SITE' => $rank['siteperms'],
'MANAGE' => $rank['manageperms'],
'FORUM' => $rank['forumperms'],
];
} else {
// Perform a bitwise OR on the ranks
$perms = [
'SITE' => $perms['SITE'] | $rank['siteperms'],
'MANAGE' => $perms['MANAGE'] | $rank['manageperms'],
'FORUM' => $perms['FORUM'] | $rank['forumperms']
'SITE' => $perms['SITE'] | $rank['siteperms'],
'MANAGE' => $perms['MANAGE'] | $rank['manageperms'],
'FORUM' => $perms['FORUM'] | $rank['forumperms'],
];
}
}
// Return the compiled permission strings
@ -162,51 +146,43 @@ class Permissions {
}
// Get permission data for a user
public static function getUserPermissions($uid) {
public static function getUserPermissions($uid)
{
// Get user data
$user = Users::getUser($uid);
// Attempt to get the permission row of a user
$userPerms = Database::fetch('permissions', false, ['rid' => [0, '='], 'uid' => [$user['id'] ,'=']]);
$userPerms = Database::fetch('permissions', false, ['rid' => [0, '='], 'uid' => [$user['id'], '=']]);
// Get their rank permissions
$rankPerms = self::getRankPermissions(json_decode($user['ranks'], true));
// Just return the rank permissions if no special ones are set
if(empty($userPerms)) {
if (empty($userPerms)) {
return $rankPerms;
}
// Split the inherit option things up
$inheritance = str_split($userPerms['rankinherit']);
// Override site permissions
if(!$inheritance[0]) {
if (!$inheritance[0]) {
$rankPerms['SITE'] = $userPerms['siteperms'];
}
// Override management permissions
if(!$inheritance[1]) {
if (!$inheritance[1]) {
$rankPerms['MANAGE'] = $userPerms['manageperms'];
}
// Override forum permissions
if(!$inheritance[2]) {
if (!$inheritance[2]) {
$rankPerms['FORUM'] = $userPerms['forumperms'];
}
// Return permissions
return $rankPerms;
}
}

View file

@ -5,43 +5,43 @@
namespace Sakura;
class Session {
class Session
{
// Current user data
public static $userId;
public static $sessionId;
// Initiate new session
public static function init() {
public static function init()
{
// Start PHP session
if(session_status() != PHP_SESSION_ACTIVE) {
if (session_status() != PHP_SESSION_ACTIVE) {
session_start();
}
// Assign user and session IDs
self::$userId = isset($_COOKIE[Configuration::getConfig('cookie_prefix') .'id']) ? $_COOKIE[Configuration::getConfig('cookie_prefix') .'id'] : 0;
self::$sessionId = isset($_COOKIE[Configuration::getConfig('cookie_prefix') .'session']) ? $_COOKIE[Configuration::getConfig('cookie_prefix') .'session'] : '';
self::$userId = isset($_COOKIE[Configuration::getConfig('cookie_prefix') . 'id']) ? $_COOKIE[Configuration::getConfig('cookie_prefix') . 'id'] : 0;
self::$sessionId = isset($_COOKIE[Configuration::getConfig('cookie_prefix') . 'session']) ? $_COOKIE[Configuration::getConfig('cookie_prefix') . 'session'] : '';
}
// Create new session
public static function newSession($userID, $remember = false) {
public static function newSession($userId, $remember = false)
{
// Generate session key
$session = sha1($userID . base64_encode('sakura'. mt_rand(0, 99999999)) . time());
$session = sha1($userId . base64_encode('sakura' . mt_rand(0, 99999999)) . time());
// Insert the session into the database
Database::insert('sessions', [
'userip' => Main::getRemoteIP(),
'userip' => Main::getRemoteIP(),
'useragent' => Main::cleanString($_SERVER['HTTP_USER_AGENT']),
'userid' => $userID,
'skey' => $session,
'started' => time(),
'expire' => time() + 604800,
'remember' => $remember ? '1' : '0'
'userid' => $userId,
'skey' => $session,
'started' => time(),
'expire' => time() + 604800,
'remember' => $remember ? '1' : '0',
]);
// Return the session key
@ -50,77 +50,74 @@ class Session {
}
// Check session data (expiry, etc.)
public static function checkSession($userId, $sessionId) {
public static function checkSession($userId, $sessionId)
{
// Get session from database
$session = Database::fetch('sessions', true, ['userid' => [$userId, '='], 'skey' => [$sessionId, '=']]);
// Check if we actually got something in return
if(!count($session)) {
if (!count($session)) {
return false;
} else {
$session = $session[0];
}
// Check if the session expired
if($session['expire'] < time()) {
$session = $session[0];
// Check if the session expired
if ($session['expire'] < time()) {
// If it is delete the session...
self::deleteSession($session['id']);
// ...and return false
return false;
}
// Origin checking
if($ipCheck = Configuration::getConfig('session_check')) {
if ($ipCheck = Configuration::getConfig('session_check')) {
// Split both IPs up
$sessionIP = explode('.', $session['userip']);
$userIP = explode('.', Main::getRemoteIP());
$sessionIP = explode('.', $session['userip']);
$userIP = explode('.', Main::getRemoteIP());
// Take 1 off the ipCheck variable so it's equal to the array keys
$ipCheck = $ipCheck - 1;
// Check if the user's IP is similar to the session's registered IP
switch($ipCheck) {
switch ($ipCheck) {
// 000.xxx.xxx.xxx
case 3:
if($userIP[3] !== $sessionIP[3]) return false;
if ($userIP[3] !== $sessionIP[3]) {
return false;
}
// xxx.000.xxx.xxx
case 2:
case 3:
if($userIP[2] !== $sessionIP[2]) return false;
if ($userIP[2] !== $sessionIP[2]) {
return false;
}
// xxx.xxx.000.xxx
case 1:
case 2:
case 3:
if($userIP[1] !== $sessionIP[1]) return false;
if ($userIP[1] !== $sessionIP[1]) {
return false;
}
// xxx.xxx.xxx.000
case 0:
case 1:
case 2:
case 3:
if($userIP[0] !== $sessionIP[0]) return false;
if ($userIP[0] !== $sessionIP[0]) {
return false;
}
}
}
// If the remember flag is set extend the session time
if($session['remember']) {
if ($session['remember']) {
Database::update('sessions', [['expire' => time() + 604800], ['id' => [$session['id'], '=']]]);
}
// Return 2 if the remember flag is set and return 1 if not
@ -129,13 +126,12 @@ class Session {
}
// Delete a session
public static function deleteSession($sessionId, $key = false) {
public static function deleteSession($sessionId, $key = false)
{
// Check if the session exists
if(!Database::fetch('sessions', [($key ? 'skey' : 'id'), true, [$sessionId, '=']])) {
if (!Database::fetch('sessions', [($key ? 'skey' : 'id'), true, [$sessionId, '=']])) {
return false;
}
// Run the query
@ -145,5 +141,4 @@ class Session {
return true;
}
}

View file

@ -5,41 +5,38 @@
namespace Sakura;
use Twig_Loader_Filesystem;
use Twig_Environment;
use Twig_Extension_StringLoader;
use Twig_Loader_Filesystem;
class Templates {
class Templates
{
// Engine container, template folder name and options
public static $_ENG;
public static $_TPL;
public static $_CFG;
public static $engine;
public static $template;
public static $configuration;
// Initialise templating engine and data
public static function init($template) {
public static function init($template)
{
// Set template folder name
self::$_TPL = $template;
self::$template = $template;
// Assign config path to a variable so we don't have to type it out twice
$confPath = ROOT .'_sakura/templates/'. self::$_TPL .'/template.ini';
$confPath = ROOT . '_sakura/templates/' . self::$template . '/template.ini';
// Check if the configuration file exists
if(!file_exists($confPath)) {
if (!file_exists($confPath)) {
trigger_error('Template configuration does not exist', E_USER_ERROR);
}
// Parse and store the configuration
self::$_CFG = parse_ini_file($confPath, true);
self::$configuration = parse_ini_file($confPath, true);
// Make sure we're not using a manage template for the main site or the other way around
if(defined('SAKURA_MANAGE') && (bool)self::$_CFG['manage']['mode'] != (bool)SAKURA_MANAGE) {
if (defined('SAKURA_MANAGE') && (bool) self::$configuration['manage']['mode'] != (bool) SAKURA_MANAGE) {
trigger_error('Incorrect template type', E_USER_ERROR);
}
// Start Twig
@ -48,42 +45,37 @@ class Templates {
}
// Twig Loader
private static function twigLoader() {
private static function twigLoader()
{
// Initialise Twig Filesystem Loader
$twigLoader = new Twig_Loader_Filesystem(ROOT .'_sakura/templates/'. self::$_TPL);
$twigLoader = new Twig_Loader_Filesystem(ROOT . '_sakura/templates/' . self::$template);
// Environment variable
$twigEnv = [];
// Enable caching
if(Configuration::getConfig('enable_tpl_cache')) {
$twigEnv['cache'] = ROOT .'cache';
if (Configuration::getConfig('enable_tpl_cache')) {
$twigEnv['cache'] = ROOT . 'cache';
}
// And now actually initialise the templating engine
self::$_ENG = new Twig_Environment($twigLoader, $twigEnv);
self::$engine = new Twig_Environment($twigLoader, $twigEnv);
// Load String template loader
self::$_ENG->addExtension(new Twig_Extension_StringLoader());
self::$engine->addExtension(new Twig_Extension_StringLoader());
}
// Render template
public static function render($file, $tags) {
public static function render($file, $tags)
{
try {
return self::$_ENG->render($file, $tags);
} catch(\Exception $e) {
return self::$engine->render($file, $tags);
} catch (\Exception $e) {
trigger_error($e->getMessage(), E_USER_ERROR);
}
}
}

View file

@ -5,99 +5,97 @@
namespace Sakura;
class Urls {
class Urls
{
// Unformatted links [0] = no mod_rewrite, [1] = mod_rewrite
protected $urls = [
// General site sections
'SITE_HOME' => ['/', '/'],
'SITE_NEWS' => ['/news.php', '/news'],
'SITE_NEWS_PAGE' => ['/news.php?page=%u', '/news/p%u'],
'SITE_NEWS_POST' => ['/news.php?id=%u', '/news/%u'],
'SITE_NEWS_RSS' => ['/news.php?xml=true', '/news.xml'],
'SITE_SEARCH' => ['/search.php', '/search'],
'SITE_PREMIUM' => ['/support.php', '/support'],
'SITE_DONATE_TRACK' => ['/support.php?tracker=true', '/support/tracker'],
'SITE_DONATE_TRACK_PAGE' => ['/support.php?tracker=true&page=%u', '/support/tracker/%u'],
'SITE_FAQ' => ['/faq.php', '/faq'],
'SITE_LOGIN' => ['/authenticate.php', '/login'],
'SITE_LOGOUT' => ['/authenticate.php', '/logout'],
'SITE_REGISTER' => ['/authenticate.php', '/register'],
'SITE_FORGOT_PASSWORD' => ['/authenticate.php', '/forgotpassword'],
'SITE_ACTIVATE' => ['/authenticate.php', '/activate'],
'CHANGELOG' => ['/changelog.php', '/changelog'],
'INFO_PAGE' => ['/index.php?p=%s', '/p/%s'],
'AUTH_ACTION' => ['/authenticate.php', '/authenticate'],
'SITE_HOME' => ['/', '/'],
'SITE_NEWS' => ['/news.php', '/news'],
'SITE_NEWS_PAGE' => ['/news.php?page=%u', '/news/p%u'],
'SITE_NEWS_POST' => ['/news.php?id=%u', '/news/%u'],
'SITE_NEWS_RSS' => ['/news.php?xml=true', '/news.xml'],
'SITE_SEARCH' => ['/search.php', '/search'],
'SITE_PREMIUM' => ['/support.php', '/support'],
'SITE_DONATE_TRACK' => ['/support.php?tracker=true', '/support/tracker'],
'SITE_DONATE_TRACK_PAGE' => ['/support.php?tracker=true&page=%u', '/support/tracker/%u'],
'SITE_FAQ' => ['/faq.php', '/faq'],
'SITE_LOGIN' => ['/authenticate.php', '/login'],
'SITE_LOGOUT' => ['/authenticate.php', '/logout'],
'SITE_REGISTER' => ['/authenticate.php', '/register'],
'SITE_FORGOT_PASSWORD' => ['/authenticate.php', '/forgotpassword'],
'SITE_ACTIVATE' => ['/authenticate.php', '/activate'],
'CHANGELOG' => ['/changelog.php', '/changelog'],
'INFO_PAGE' => ['/index.php?p=%s', '/p/%s'],
'AUTH_ACTION' => ['/authenticate.php', '/authenticate'],
// Memberlist
'MEMBERLIST_INDEX' => ['/members.php', '/members'],
'MEMBERLIST_SORT' => ['/members.php?sort=%s', '/members/%s'],
'MEMBERLIST_RANK' => ['/members.php?rank=%u', '/members/%u'],
'MEMBERLIST_PAGE' => ['/members.php?page=%u', '/members/p%u'],
'MEMBERLIST_SORT_RANK' => ['/members.php?sort=%s&rank=%u', '/members/%s/%u'],
'MEMBERLIST_RANK_PAGE' => ['/members.php?rank=%u&page=%u', '/members/%u/p%u'],
'MEMBERLIST_SORT_PAGE' => ['/members.php?sort=%s&page=%u', '/members/%s/p%u'],
'MEMBERLIST_ALL' => ['/members.php?sort=%s&rank=%u&page=%u', '/members/%s/%u/p%u'],
'MEMBERLIST_INDEX' => ['/members.php', '/members'],
'MEMBERLIST_SORT' => ['/members.php?sort=%s', '/members/%s'],
'MEMBERLIST_RANK' => ['/members.php?rank=%u', '/members/%u'],
'MEMBERLIST_PAGE' => ['/members.php?page=%u', '/members/p%u'],
'MEMBERLIST_SORT_RANK' => ['/members.php?sort=%s&rank=%u', '/members/%s/%u'],
'MEMBERLIST_RANK_PAGE' => ['/members.php?rank=%u&page=%u', '/members/%u/p%u'],
'MEMBERLIST_SORT_PAGE' => ['/members.php?sort=%s&page=%u', '/members/%s/p%u'],
'MEMBERLIST_ALL' => ['/members.php?sort=%s&rank=%u&page=%u', '/members/%s/%u/p%u'],
// Forums
'FORUM_INDEX' => ['/index.php?forum=true', '/forum'],
'FORUM_SUB' => ['/viewforum.php?f=%u', '/forum/%u'],
'FORUM_THREAD' => ['/viewtopic.php?t=%u', '/forum/thread/%u'],
'FORUM_POST' => ['/viewtopic.php?p=%u', '/forum/post/%u'],
'FORUM_REPLY' => ['/posting.php?t=%u', '/forum/thread/%u/reply'],
'FORUM_NEW_THREAD' => ['/posting.php?f=%u', '/forum/%u/new'],
'FORUM_EDIT_POST' => ['/posting.php?p=%1$u&edit=%1$u', '/forum/post/%u/edit'],
'FORUM_DELETE_POST' => ['/posting.php?p=%1$u&delete=%1$u', '/forum/post/%u/delete'],
'FORUM_QUOTE_POST' => ['/posting.php?p=%1$u&quote=%1$u', '/forum/post/%u/quote'],
'FORUM_INDEX' => ['/index.php?forum=true', '/forum'],
'FORUM_SUB' => ['/viewforum.php?f=%u', '/forum/%u'],
'FORUM_THREAD' => ['/viewtopic.php?t=%u', '/forum/thread/%u'],
'FORUM_POST' => ['/viewtopic.php?p=%u', '/forum/post/%u'],
'FORUM_REPLY' => ['/posting.php?t=%u', '/forum/thread/%u/reply'],
'FORUM_NEW_THREAD' => ['/posting.php?f=%u', '/forum/%u/new'],
'FORUM_EDIT_POST' => ['/posting.php?p=%1$u&edit=%1$u', '/forum/post/%u/edit'],
'FORUM_DELETE_POST' => ['/posting.php?p=%1$u&delete=%1$u', '/forum/post/%u/delete'],
'FORUM_QUOTE_POST' => ['/posting.php?p=%1$u&quote=%1$u', '/forum/post/%u/quote'],
// Image serve references
'IMAGE_AVATAR' => ['/imageserve.php?m=avatar&u=%u', '/a/%u'],
'IMAGE_BACKGROUND' => ['/imageserve.php?m=background&u=%u', '/bg/%u'],
'IMAGE_HEADER' => ['/imageserve.php?m=header&u=%u', '/u/%u/header'],
'IMAGE_AVATAR' => ['/imageserve.php?m=avatar&u=%u', '/a/%u'],
'IMAGE_BACKGROUND' => ['/imageserve.php?m=background&u=%u', '/bg/%u'],
'IMAGE_HEADER' => ['/imageserve.php?m=header&u=%u', '/u/%u/header'],
// User actions
'USER_LOGOUT' => ['/authenticate.php?mode=logout&time=%u&session=%s&redirect=%s', '/logout?mode=logout&time=%u&session=%s&redirect=%s'],
'USER_REPORT' => ['/report.php?mode=user&u=%u', '/u/%u/report'],
'USER_PROFILE' => ['/profile.php?u=%s', '/u/%s'],
'USER_GROUP' => ['/group.php?g=%u', '/g/%u'],
'USER_LOGOUT' => ['/authenticate.php?mode=logout&time=%u&session=%s&redirect=%s', '/logout?mode=logout&time=%u&session=%s&redirect=%s'],
'USER_REPORT' => ['/report.php?mode=user&u=%u', '/u/%u/report'],
'USER_PROFILE' => ['/profile.php?u=%s', '/u/%s'],
'USER_GROUP' => ['/group.php?g=%u', '/g/%u'],
// Settings urls
'SETTINGS_INDEX' => ['/settings.php', '/settings'],
'SETTING_CAT' => ['/settings.php?cat=%s', '/settings/%s'],
'SETTING_MODE' => ['/settings.php?cat=%s&mode=%s', '/settings/%s/%s'],
'SETTINGS_INDEX' => ['/settings.php', '/settings'],
'SETTING_CAT' => ['/settings.php?cat=%s', '/settings/%s'],
'SETTING_MODE' => ['/settings.php?cat=%s&mode=%s', '/settings/%s/%s'],
// Friend Actions
'FRIEND_ACTION' => ['/settings.php?friend-action=true', '/friends'],
'FRIEND_ADD' => ['/settings.php?friend-action=true&add=%u&session=%s&time=%u&redirect=%s', '/friends?add=%u&session=%s&time=%u&redirect=%s'],
'FRIEND_REMOVE' => ['/settings.php?friend-action=true&remove=%u&session=%s&time=%u&redirect=%s', '/friends?remove=%u&session=%s&time=%u&redirect=%s'],
'FRIEND_ACTION' => ['/settings.php?friend-action=true', '/friends'],
'FRIEND_ADD' => ['/settings.php?friend-action=true&add=%u&session=%s&time=%u&redirect=%s', '/friends?add=%u&session=%s&time=%u&redirect=%s'],
'FRIEND_REMOVE' => ['/settings.php?friend-action=true&remove=%u&session=%s&time=%u&redirect=%s', '/friends?remove=%u&session=%s&time=%u&redirect=%s'],
// Manage urls
'MANAGE_INDEX' => ['/manage.php', '/manage'],
'MANAGE_CAT' => ['/manage.php?cat=%s', '/manage/%s'],
'MANAGE_MODE' => ['/manage.php?cat=%s&mode=%s', '/manage/%s/%s']
'MANAGE_INDEX' => ['/manage.php', '/manage'],
'MANAGE_CAT' => ['/manage.php?cat=%s', '/manage/%s'],
'MANAGE_MODE' => ['/manage.php?cat=%s&mode=%s', '/manage/%s/%s'],
];
// Get a formatted url
public function format($id, $args = [], $rewrite = null) {
public function format($lid, $args = [], $rewrite = null)
{
// Check if the requested url exists
if(!array_key_exists($id, $this->urls)) {
if (!array_key_exists($lid, $this->urls)) {
return null;
}
// Check if mod_rewrite is enabled
$rewrite = ($rewrite === null ? Configuration::getConfig('url_rewrite') : $rewrite) ? 1 : 0;
// Format urls
$formatted = vsprintf($this->urls[$id][$rewrite], $args);
$formatted = vsprintf($this->urls[$lid][$rewrite], $args);
// Return the formatted url
return $formatted;
}
}

View file

@ -5,32 +5,29 @@
namespace Sakura;
class User {
class User
{
// User data
public $data = [];
public $ranks = [];
public $mainRank = [];
public $data = [];
public $ranks = [];
public $mainRank = [];
// Initialise the user object
function __construct($id) {
public function __construct($uid)
{
// Get the user database row
$this->data = Database::fetch('users', false, ['id' => [$id, '=', true], 'username_clean' => [Main::cleanString($id, true), '=', true]]);
$this->data = Database::fetch('users', false, ['id' => [$uid, '=', true], 'username_clean' => [Main::cleanString($uid, true), '=', true]]);
// Check if anything like the username exists
if(empty($this->data)) {
$this->data = Database::fetch('users', false, ['username_clean' => ['%'. Main::cleanString($id, true) .'%', 'LIKE']]);
if (empty($this->data)) {
$this->data = Database::fetch('users', false, ['username_clean' => ['%' . Main::cleanString($uid, true) . '%', 'LIKE']]);
}
// Check if the user actually exists
if(empty($this->data)) {
if (empty($this->data)) {
// If not assign as the fallback user
$this->data = Users::$emptyUser;
}
// Decode the json in the userData column
@ -40,19 +37,15 @@ class User {
$ranks = json_decode($this->data['ranks'], true);
// Get the rows for all the ranks
foreach($ranks as $rank) {
foreach ($ranks as $rank) {
// Store the database row in the array
$this->ranks[$rank] = Database::fetch('ranks', false, ['id' => [$rank, '=']]);
}
// Check if ranks were set
if(empty($this->ranks)) {
if (empty($this->ranks)) {
// If not assign the fallback rank
$this->ranks[0] = Users::$emptyRank;
}
// Assign the user's main rank to a special variable since we'll use it a lot
@ -61,25 +54,20 @@ class User {
}
// Check if the user has the specified ranks
public function checkIfUserHasRanks($ranks) {
public function checkIfUserHasRanks($ranks)
{
// Check if the main rank is the specified rank
if(in_array($this->mainRank['id'], $ranks)) {
if (in_array($this->mainRank['id'], $ranks)) {
return true;
}
// 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
if(array_key_exists($rank, $this->ranks)) {
if (array_key_exists($rank, $this->ranks)) {
return true;
}
}
// If all fails return false
@ -88,158 +76,153 @@ class User {
}
// Get the user's colour
public function colour() {
public function colour()
{
return empty($this->data['name_colour']) ? $this->mainRank['colour'] : $this->data['name_colour'];
}
// Get the user's title
public function userTitle() {
public function userTitle()
{
return empty($this->data['usertitle']) ? $this->mainRank['title'] : $this->data['usertitle'];
}
// Get the user's long and short country names
public function country() {
public function country()
{
return [
'long' => Main::getCountryName($this->data['country']),
'short' => $this->data['country']
'long' => Main::getCountryName($this->data['country']),
'short' => $this->data['country'],
];
}
// Check if a user is online
public function checkOnline() {
public function checkOnline()
{
return $this->data['lastdate'] > (time() - Configuration::getConfig('max_online_time'));
}
// Get user's forum statistics
public function forumStats() {
public function forumStats()
{
return Forum::getUserStats($this->data['id']);
}
// Check if the user is friends with the currently authenticated
public function checkFriends($with) {
public function checkFriends($with)
{
return Users::checkFriend($this->data['id'], $with);
}
// Get all the friend of this user
public function getFriends($timestamps = false, $getData = false, $checkOnline = false) {
public function getFriends($timestamps = false, $getData = false, $checkOnline = false)
{
return Users::getFriends($this->data['id'], $timestamps, $getData, $checkOnline);
}
// Check if the user is banned
public function checkBan() {
public function checkBan()
{
return Bans::checkBan($this->data['id']);
}
// Check if the user has the proper permissions
public function checkPermission($layer, $action) {
public function checkPermission($layer, $action)
{
return Permissions::check($layer, $action, $this->data['id'], 1);
}
// Get amount of time since user events
public function elapsed($append = ' ago', $none = 'Just now') {
public function elapsed($append = ' ago', $none = 'Just now')
{
return [
'joined' => Main::timeElapsed($this->data['regdate'], $append, $none),
'lastOnline' => Main::timeElapsed($this->data['lastdate'], $append, $none),
'birth' => Main::timeElapsed(strtotime($this->data['birthday']), $append, $none)
'joined' => Main::timeElapsed($this->data['regdate'], $append, $none),
'lastOnline' => Main::timeElapsed($this->data['lastdate'], $append, $none),
'birth' => Main::timeElapsed(strtotime($this->data['birthday']), $append, $none),
];
}
// Get the user's profile fields
public function profileFields() {
public function profileFields()
{
// Get profile fields
$profileFields = Database::fetch('profilefields');
// If there's nothing just return null
if(!count($profileFields)) {
if (!count($profileFields)) {
return;
}
// Once again if nothing was returned just return null
if(empty($this->data['userData']['profileFields'])) {
if (empty($this->data['userData']['profileFields'])) {
return;
}
// Create output array
$profile = [];
// Check if profile fields aren't fake
foreach($profileFields as $field) {
foreach ($profileFields as $field) {
// Completely strip all special characters from the field name
$fieldName = Main::cleanString($field['name'], true, true);
// Check if the user has the current field set otherwise continue
if(!array_key_exists($fieldName, $this->data['userData']['profileFields'])) {
if (!array_key_exists($fieldName, $this->data['userData']['profileFields'])) {
continue;
}
// Assign field to output with value
$profile[$fieldName] = array();
$profile[$fieldName]['name'] = $field['name'];
$profile[$fieldName]['value'] = $this->data['userData']['profileFields'][$fieldName];
$profile[$fieldName]['islink'] = $field['islink'];
$profile[$fieldName] = array();
$profile[$fieldName]['name'] = $field['name'];
$profile[$fieldName]['value'] = $this->data['userData']['profileFields'][$fieldName];
$profile[$fieldName]['islink'] = $field['islink'];
// If the field is set to be a link add a value for that as well
if($field['islink']) {
if ($field['islink']) {
$profile[$fieldName]['link'] = str_replace('{{ VAL }}', $this->data['userData']['profileFields'][$fieldName], $field['linkformat']);
}
// Check if we have additional options as well
if($field['additional'] != null) {
if ($field['additional'] != null) {
// Decode the json of the additional stuff
$additional = json_decode($field['additional'], true);
// 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
if(!array_key_exists($subName, $this->data['userData']['profileFields'])) {
if (!array_key_exists($subName, $this->data['userData']['profileFields'])) {
continue;
}
// Assign field to output with value
$profile[$fieldName][$subName] = $this->data['userData']['profileFields'][$subName];
}
}
}
// Return appropiate profile data
@ -248,48 +231,39 @@ class User {
}
// Get the user's option fields
public function optionFields() {
public function optionFields()
{
// Get option fields
$optionFields = Database::fetch('optionfields');
// If there's nothing just return null
if(!count($optionFields)) {
if (!count($optionFields)) {
return;
}
// Once again if nothing was returned just return null
if(empty($this->data['userData']['userOptions'])) {
if (empty($this->data['userData']['userOptions'])) {
return;
}
// Create output array
$options = [];
// Check if profile fields aren't fake
foreach($optionFields as $field) {
foreach ($optionFields as $field) {
// Check if the user has the current field set otherwise continue
if(!array_key_exists($field['id'], $this->data['userData']['userOptions'])) {
if (!array_key_exists($field['id'], $this->data['userData']['userOptions'])) {
continue;
}
// Make sure the user has the proper permissions to use this option
if(!$this->checkPermission('SITE', $field['require_perm'])) {
if (!$this->checkPermission('SITE', $field['require_perm'])) {
continue;
}
// Assign field to output with value
$options[$field['id']] = $this->data['userData']['userOptions'][$field['id']];
}
// Return appropiate profile data
@ -298,36 +272,29 @@ class User {
}
// Check if user has Premium
public function checkPremium() {
public function checkPremium()
{
// Check if the user has static premium
if(Permissions::check('SITE', 'STATIC_PREMIUM', $this->data['id'], 1)) {
if (Permissions::check('SITE', 'STATIC_PREMIUM', $this->data['id'], 1)) {
return [2, 0, time() + 1];
}
// Attempt to retrieve the premium record from the database
$getRecord = Database::fetch('premium', false, [
'uid' => [$this->data['id'], '=']
'uid' => [$this->data['id'], '='],
]);
// If nothing was returned just return false
if(empty($getRecord)) {
if (empty($getRecord)) {
return [0];
}
// Check if the Tenshi hasn't expired
if($getRecord['expiredate'] < time()) {
if ($getRecord['expiredate'] < time()) {
Users::removeUserPremium($this->data['id']);
Users::updatePremiumMeta($this->data['id']);
return [0, $getRecord['startdate'], $getRecord['expiredate']];
}
// Else return the start and expiration date
@ -336,16 +303,16 @@ class User {
}
// Get all warnings issued to the user
public function getWarnings() {
public function getWarnings()
{
// Do the database query
$warnings = Database::fetch('warnings', true, [
'uid' => [$this->data['id'], '=']
'uid' => [$this->data['id'], '='],
]);
// Return all the warnings
return $warnings;
}
}

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@
* Released under the MIT-License
*
* The MIT License (MIT)
*
*
* Copyright (c) 2015 Flashwave
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -29,27 +29,31 @@
namespace Sakura;
class Whois {
class Whois
{
// Variables
public static $servers;
// Set the whois servers list
public static function setServers($serversFile) {
public static function setServers($serversFile)
{
// Check if the file exists and if it does get contents.
if(file_exists($serversFile))
if (file_exists($serversFile)) {
$servers = utf8_encode(file_get_contents($serversFile));
else
} else {
trigger_error('Failed to load whois servers file', E_USER_ERROR);
}
// Parse json
if(($servers = json_decode($servers, true)) != true)
if (($servers = json_decode($servers, true)) != true) {
trigger_error('Error while parsing whois servers file JSON', E_USER_ERROR);
}
// Check for neccesary keys
if(!array_key_exists('tld', $servers) || !array_key_exists('ip', $servers))
if (!array_key_exists('tld', $servers) || !array_key_exists('ip', $servers)) {
trigger_error('One or more of the required whois lists isn\'t set, please check your whois servers file', E_USER_ERROR);
}
// If everything is gucci set self::$servers
self::$servers = $servers;
@ -57,35 +61,37 @@ class Whois {
}
// Query the whois servers
public static function query($address) {
public static function query($address)
{
// Call validate to use the right whois type
switch(self::validateAddress($address)) {
switch (self::validateAddress($address)) {
case 1: // validateAddress returns 1 for a domain...
return self::lookupDomain($address);
case 2: // ...and 2 for both IPv4 and IPv6 (should be fine)...
return self::lookupIP($address);
case 0: // ...and 0 in case the type is invalid in which case...
case 0: // ...and 0 in case the type is invalid in which case...
default: // ...a false is returned by this function
return false;
}
}
// Validates an address
private static function validateAddress($address) {
private static function validateAddress($address)
{
// Check if the given address is an IP address
if(filter_var($address, FILTER_VALIDATE_IP))
if (filter_var($address, FILTER_VALIDATE_IP)) {
return 2;
}
// Check if given address is a domain name
if(preg_match("/^([-a-z0-9]{2,100})\.([a-z\.]{2,8})$/i", $address))
if (preg_match("/^([-a-z0-9]{2,100})\.([a-z\.]{2,8})$/i", $address)) {
return 1;
}
// If unsuccessful return 0
return 0;
@ -93,7 +99,8 @@ class Whois {
}
// Look up a domain
private static function lookupDomain($address) {
private static function lookupDomain($address)
{
// Get list of servers
$servers = self::$servers['tld'];
@ -105,37 +112,30 @@ class Whois {
$tld = strtolower(array_pop($addressParts));
// Get proper whois server address
if(!$server = $servers[$tld])
return 'Error: No appropriate whois server found for the TLD '. $tld .', check if the given address is correct.';
if (!$server = $servers[$tld]) {
return 'Error: No appropriate whois server found for the TLD ' . $tld . ', check if the given address is correct.';
}
// Get results from whois server
if(!$result = self::queryWhois($server, $address)) {
if (!$result = self::queryWhois($server, $address)) {
// Return an error if there's no results were retrieved.
return 'Error: No results retrieved from '. $server .' for '. $address .'.';
return 'Error: No results retrieved from ' . $server . ' for ' . $address . '.';
} else {
// Assign result with heading text to return variable
$return = $address ." domain lookup results from ". $server .":\r\n\r\n". $result;
$return = $address . " domain lookup results from " . $server . ":\r\n\r\n" . $result;
// Check if there's a secondary whois server
while(strpos($result, "Whois Server:") !== FALSE) {
while (strpos($result, "Whois Server:") !== false) {
preg_match("/Whois Server: (.*)/", $return, $matches);
// If there is call it...
if(isset($matches[1])) {
// If there is call it...
if (isset($matches[1])) {
$result = self::queryWhois(($server = $matches[1]), $address);
// ...and append the retrieved values to the return variable
$return .= "\r\n-------------\r\n\r\n". $address ." domain lookup results from ". $server .":\r\n". $result;
$return .= "\r\n-------------\r\n\r\n" . $address . " domain lookup results from " . $server . ":\r\n" . $result;
}
}
}
// If all is good return the return variable
@ -144,7 +144,8 @@ class Whois {
}
// Look up an IP
private static function lookupIP($address) {
private static function lookupIP($address)
{
// Get list of servers
$servers = self::$servers['ip'];
@ -153,31 +154,28 @@ class Whois {
$results = array();
// Query servers
foreach($servers as $server) {
foreach ($servers as $server) {
// Get results
$result = self::queryWhois($server, $address);
// Assign result to results array if not in it yet
if($result && !in_array($result, $results))
if ($result && !in_array($result, $results)) {
$results[$server] = $result;
}
}
// Create variable to keep return value
$return = "RESULTS FOUND: ". count($results);
$return = "RESULTS FOUND: " . count($results);
// Append results
foreach($results as $server => $result) {
foreach ($results as $server => $result) {
$return .= "\r\n\r\n-------------"
. "\r\nLookup results for "
. $address
. " from "
. $server
. " server:\r\n\r\n"
. $result;
. "\r\nLookup results for "
. $address
. " from "
. $server
. " server:\r\n\r\n"
. $result;
}
// Return results
@ -186,25 +184,26 @@ class Whois {
}
// Query whois server
private static function queryWhois($server, $address, $port = 43, $timeout = 10) {
private static function queryWhois($server, $address, $port = 43, $timeout = 10)
{
// Open socket
$query = @fsockopen($server, $port, $errno, $errstr, $timeout) or trigger_error('Failed to open socket: '. $errno .' - '. $errstr, E_USER_ERROR);
$query = @fsockopen($server, $port, $errno, $errstr, $timeout) or trigger_error('Failed to open socket: ' . $errno . ' - ' . $errstr, E_USER_ERROR);
// Send address
fputs($query, $address ."\r\n");
fputs($query, $address . "\r\n");
// Await output
$out = null;
while(!feof($query))
while (!feof($query)) {
$out .= fgets($query);
}
// Close socket
fclose($query);
// Return results
// Return results
return $out;
}
}

View file

@ -7,20 +7,20 @@ namespace Sakura\DBWrapper;
use PDO;
use PDOException;
use PDOStatement;
use \Sakura\Configuration;
class MySQL {
class MySQL
{
// Variable that will contain the SQL connection
// Please refrain from referring to this, unless it's for your personal branch/purpose, despite it being public
// it sort of defeats the "dynamic database system" I want to go for.
public $sql;
// Constructor
function __construct() {
public function __construct()
{
if(!extension_loaded('PDO')) {
if (!extension_loaded('PDO')) {
// Return error and die
trigger_error('PDO extension not loaded.', E_USER_ERROR);
}
@ -50,67 +50,68 @@ class MySQL {
}
// Regular IP/Hostname connection method prepare function
private function prepareHost($dbHost, $dbName, $dbPort = 3306) {
private function prepareHost($dbHost, $dbName, $dbPort = 3306)
{
$DSN = 'mysql:host=' . $dbHost . ';port=' . $dbPort . ';dbname=' . $dbName;
$dsn = 'mysql:host=' . $dbHost . ';port=' . $dbPort . ';dbname=' . $dbName;
return $DSN;
return $dsn;
}
// Unix Socket connection method prepare function
private function prepareSock($dbHost, $dbName) {
private function prepareSock($dbHost, $dbName)
{
$DSN = 'mysql:unix_socket=' . $dbHost . ';dbname=' . $dbName;
$dsn = 'mysql:unix_socket=' . $dbHost . ';dbname=' . $dbName;
return $DSN;
return $dsn;
}
// Initialise connection using default PDO stuff
private function initConnect($DSN, $dbUname, $dbPword) {
private function initConnect($dsn, $dbUname, $dbPword)
{
try {
// Connect to SQL server using PDO
$this->sql = new PDO($DSN, $dbUname, $dbPword, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
} catch(PDOException $e) {
$this->sql = new PDO($dsn, $dbUname, $dbPword, [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
]);
} catch (PDOException $e) {
// Catch connection errors
trigger_error('SQL Driver: '. $e->getMessage(), E_USER_ERROR);
trigger_error('SQL Driver: ' . $e->getMessage(), E_USER_ERROR);
}
return true;
}
public function select($table, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null) {
public function select($table, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
{
// Begin preparation of the statement
$prepare = 'SELECT '. ($distinct ? 'DISTINCT ' : '') . ($column == '*' ? '' : '`') . $column . ($column == '*' ? '' : '`') .' FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
$prepare = 'SELECT ' . ($distinct ? 'DISTINCT ' : '') . ($column == '*' ? '' : '`') . $column . ($column == '*' ? '' : '`') . ' FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
// If $data is set and is an array continue
if(is_array($data)) {
if (is_array($data)) {
$prepare .= ' WHERE';
foreach($data as $key => $value) {
foreach ($data as $key => $value) {
// Check if there's multiple statements
if(!is_array($value[0])) {
if (!is_array($value[0])) {
$temp = $value;
unset($value);
$value[0] = $temp;
}
// Go over each data thing
foreach($value as $sub => $val) {
$prepare .= ' `'. $key .'` '. $val[1] .' :'. $key .'_'. $sub . ($key == key(array_slice($data, -1, 1, true)) && $sub == key(array_slice($value, -1, 1, true)) ? '' : ' '. (isset($val[2]) && $val[2] ? 'OR' : 'AND'));
foreach ($value as $sub => $val) {
$prepare .= ' `' . $key . '` ' . $val[1] . ' :' . $key . '_' . $sub . ($key == key(array_slice($data, -1, 1, true)) && $sub == key(array_slice($value, -1, 1, true)) ? '' : ' ' . (isset($val[2]) && $val[2] ? 'OR' : 'AND'));
unset($sub);
unset($val);
}
// Unset variables to be safe
@ -122,40 +123,34 @@ class MySQL {
}
// If $group is set and is an array continue
if(is_array($group)) {
if (is_array($group)) {
$prepare .= ' GROUP BY';
foreach($group as $key => $value) {
$prepare .= ' `'. $value .'`'. ($key == key(array_slice($group, -1, 1, true)) ? '' : ',');
foreach ($group as $key => $value) {
$prepare .= ' `' . $value . '`' . ($key == key(array_slice($group, -1, 1, true)) ? '' : ',');
// Unset variables to be safe
unset($key);
unset($value);
}
}
// If $order is set and is an array continue
if(is_array($order)) {
$prepare .= ' ORDER BY `'. $order[0] .'`'. (!empty($order[1]) && $order[1] ? ' DESC' : '');
if (is_array($order)) {
$prepare .= ' ORDER BY `' . $order[0] . '`' . (!empty($order[1]) && $order[1] ? ' DESC' : '');
}
// If $limit is set and is an array continue
if(is_array($limit)) {
if (is_array($limit)) {
$prepare .= ' LIMIT';
foreach($limit as $key => $value) {
$prepare .= ' '. $value . ($key == key(array_slice($limit, -1, 1, true)) ? '' : ',');
foreach ($limit as $key => $value) {
$prepare .= ' ' . $value . ($key == key(array_slice($limit, -1, 1, true)) ? '' : ',');
// Unset variables to be safe
unset($key);
unset($value);
}
}
// Add the finishing semicolon
@ -165,35 +160,27 @@ class MySQL {
$query = $this->sql->prepare($prepare);
// Bind those parameters if $data is an array that is
if(is_array($data)) {
foreach($data as $key => $value) {
if (is_array($data)) {
foreach ($data as $key => $value) {
// Check if there's multiple statements
if(!is_array($value[0])) {
if (!is_array($value[0])) {
$temp = $value;
unset($value);
$value[0] = $temp;
}
// Go over each data thing
foreach($value as $sub => $val) {
$query->bindParam(':'. $key .'_'. $sub, $val[0]);
foreach ($value as $sub => $val) {
$query->bindParam(':' . $key . '_' . $sub, $val[0]);
unset($sub);
unset($val);
}
// Unset variables to be safe
unset($key);
unset($value);
}
}
// Execute the prepared statements with parameters bound
@ -205,10 +192,11 @@ class MySQL {
}
// Fetch array from database
public function fetch($table, $fetchAll = true, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null) {
public function fetch($table, $fetchAll = true, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
{
// Run a select statement
$query = $this->select($table, $data, $order, $limit , $group, $distinct, $column, $prefix);
$query = $this->select($table, $data, $order, $limit, $group, $distinct, $column, $prefix);
// Return the output
return $fetchAll ? $query->fetchAll(PDO::FETCH_ASSOC) : $query->fetch(PDO::FETCH_ASSOC);
@ -216,33 +204,34 @@ class MySQL {
}
// Insert data to database
public function insert($table, $data, $prefix = null) {
public function insert($table, $data, $prefix = null)
{
// Begin preparation of the statement
$prepare = 'INSERT INTO `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '` ';
// Run the foreach statement twice for (`stuff`) VALUES (:stuff)
for($i = 0; $i < 2; $i++) {
for ($i = 0; $i < 2; $i++) {
$prepare .= '(';
// Do more shit, don't feel like describing this so yeah
foreach($data as $key => $value) {
if(strlen($value))
foreach ($data as $key => $value) {
if (strlen($value)) {
$prepare .= ($i ? ':' : '`') . $key . ($i ? '' : '`') . ($key == key(array_slice($data, -1, 1, true)) ? '' : ', ');
}
}
$prepare .= ')' . ($i ? ';' : ' VALUES ');
}
// Actually prepare the preration
$query = $this->sql->prepare($prepare);
// Bind those parameters
foreach($data as $key => $value) {
if(strlen($value))
$query->bindParam(':'. $key, $value);
foreach ($data as $key => $value) {
if (strlen($value)) {
$query->bindParam(':' . $key, $value);
}
// Unset variables to be safe
unset($key);
@ -258,21 +247,21 @@ class MySQL {
}
// Update data in the database
public function update($table, $data, $prefix = null) {
public function update($table, $data, $prefix = null)
{
// Begin preparation of the statement
$prepare = 'UPDATE `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
// Run a foreach on $data and complete the statement
foreach($data as $key => $values) {
foreach ($data as $key => $values) {
// Append WHERE or SET depending on where we are
$prepare .= ' '. ($key ? 'WHERE' : 'SET');
$prepare .= ' ' . ($key ? 'WHERE' : 'SET');
// Do this complicated shit, I barely know what's going on anymore but it works
foreach($values as $column => $column_data)
$prepare .= ' `'. $column .'` '. ($key ? $column_data[1] : '=') .' :'. ($key ? 'w' : 's') .'_'. $column . ($column == key(array_slice($values, -1, 1, true)) ? ($key ? ';' : '') : ($key ? ' '. (isset($value[2]) && $value[2] ? 'OR' : 'AND') : ','));
foreach ($values as $column => $column_data) {
$prepare .= ' `' . $column . '` ' . ($key ? $column_data[1] : '=') . ' :' . ($key ? 'w' : 's') . '_' . $column . ($column == key(array_slice($values, -1, 1, true)) ? ($key ? ';' : '') : ($key ? ' ' . (isset($value[2]) && $value[2] ? 'OR' : 'AND') : ','));
}
}
// Actually prepare the preration
@ -280,31 +269,27 @@ class MySQL {
// Seperate the foreaches for the SET and WHERE clauses because it's fucking it up for some odd reason
// Bind Set Clauses
foreach($data[0] as $key => $value) {
foreach ($data[0] as $key => $value) {
// Do the binding
$query->bindParam(':s_'. $key, $value);
$query->bindParam(':s_' . $key, $value);
// Unset variables to be safe
unset($key);
unset($value);
}
// Bind Where Clauses
foreach($data[1] as $key => $values) {
foreach ($data[1] as $key => $values) {
// Assign the array entry to a variable because fuck strict standards
$value = $values[0];
// Binding two electrifying memes
$query->bindParam(':w_'. $key, $value);
$query->bindParam(':w_' . $key, $value);
// Unset variables to be safe
unset($key);
unset($value);
unset($values);
}
// Execute the prepared statements with parameters bound
@ -316,32 +301,31 @@ class MySQL {
}
// Delete data from the database
public function delete($table, $data, $prefix = null) {
public function delete($table, $data, $prefix = null)
{
// Begin preparation of the statement
$prepare = 'DELETE FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
// If $data is set and is an array continue
if(is_array($data)) {
if (is_array($data)) {
$prepare .= ' WHERE';
foreach($data as $key => $value) {
$prepare .= ' `'. $key .'` '. $value[1] .' :'. $key . ($key == key(array_slice($data, -1, 1, true)) ? '' : ' '. (isset($value[2]) && $value[2] ? 'OR' : 'AND'));
foreach ($data as $key => $value) {
$prepare .= ' `' . $key . '` ' . $value[1] . ' :' . $key . ($key == key(array_slice($data, -1, 1, true)) ? '' : ' ' . (isset($value[2]) && $value[2] ? 'OR' : 'AND'));
// Unset variables to be safe
unset($key);
unset($value);
}
}
// Actually prepare the preration
$query = $this->sql->prepare($prepare);
// Bind those parameters
foreach($data as $key => $value) {
$query->bindParam(':'. $key, $value[0]);
foreach ($data as $key => $value) {
$query->bindParam(':' . $key, $value[0]);
// Unset variables to be safe
unset($key);
@ -357,24 +341,23 @@ class MySQL {
}
// Count data from the database
public function count($table, $data = null, $prefix = null) {
public function count($table, $data = null, $prefix = null)
{
// Begin preparation of the statement
$prepare = 'SELECT COUNT(*) FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
// If $data is set and is an array continue
if(is_array($data)) {
if (is_array($data)) {
$prepare .= ' WHERE';
foreach($data as $key => $value) {
$prepare .= ' `'. $key .'` '. $value[1] .' :'. $key . ($key == key(array_slice($data, -1, 1, true)) ? '' : ' '. (isset($value[2]) && $value[2] ? 'OR' : 'AND'));
foreach ($data as $key => $value) {
$prepare .= ' `' . $key . '` ' . $value[1] . ' :' . $key . ($key == key(array_slice($data, -1, 1, true)) ? '' : ' ' . (isset($value[2]) && $value[2] ? 'OR' : 'AND'));
// Unset variables to be safe
unset($key);
unset($value);
}
}
// Add the finishing semicolon
@ -384,16 +367,14 @@ class MySQL {
$query = $this->sql->prepare($prepare);
// Bind those parameters if $data is an array that is
if(is_array($data)) {
foreach($data as $key => $value) {
$query->bindParam(':'. $key, $value[0]);
if (is_array($data)) {
foreach ($data as $key => $value) {
$query->bindParam(':' . $key, $value[0]);
// Unset variables to be safe
unset($key);
unset($value);
}
}
// Execute the prepared statements with parameters bound
@ -403,5 +384,4 @@ class MySQL {
return $query->fetch(PDO::FETCH_BOTH);
}
}

View file

@ -6,12 +6,48 @@
// Declare Namespace
namespace Sakura;
// Check if the script isn't executed by root
if (function_exists('posix_getuid')) {
if (posix_getuid() === 0) {
trigger_error('Running cron as root is disallowed for security reasons.', E_USER_ERROR);
exit;
}
}
// Define that this page won't require templating
define('SAKURA_NO_TPL', true);
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Override expiration variables
ignore_user_abort(true);
set_time_limit(0);
// Clean expired sessions
Database::delete('sessions', [
'expire' => [time(), '<'],
'remember' => ['1', '!='],
]);
// Delete notifications that are older than a month but not unread
Database::delete('notifications', [
'timestamp' => [(time() - 109500), '<'],
'notif_read' => ['1', '='],
]);
// Get expired premium accounts
$expiredPremium = Database::fetch('premium', true, [
'expiredate' => [time(), '<'],
]);
// Process expired premium accounts
foreach ($expiredPremium as $expired) {
Users::updatePremiumMeta($expired['uid']);
}

View file

@ -8,10 +8,10 @@
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20150912');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082');
define('SAKURA_STABLE', false);
define('SAKURA_VERSION', '20150914');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082');
define('SAKURA_STABLE', false);
// Define Sakura Path
define('ROOT', str_replace(basename(__DIR__), '', dirname(__FILE__)));
@ -23,79 +23,67 @@ error_reporting(SAKURA_STABLE ? 0 : -1);
mb_internal_encoding('utf-8');
// Stop the execution if the PHP Version is older than 5.4.0
if(version_compare(phpversion(), '5.4.0', '<')) {
if (version_compare(phpversion(), '5.4.0', '<')) {
die('<h3>Sakura requires at least PHP 5.4.0, please upgrade to a newer PHP version.</h3>');
}
// Include libraries
require_once ROOT .'_sakura/vendor/autoload.php';
require_once ROOT .'_sakura/components/Main.php';
require_once ROOT .'_sakura/components/Hashing.php';
require_once ROOT .'_sakura/components/Configuration.php';
require_once ROOT .'_sakura/components/Database.php';
require_once ROOT .'_sakura/components/Urls.php';
require_once ROOT .'_sakura/components/Templates.php';
require_once ROOT .'_sakura/components/Permissions.php';
require_once ROOT .'_sakura/components/Sessions.php';
require_once ROOT .'_sakura/components/User.php';
require_once ROOT .'_sakura/components/Users.php';
require_once ROOT .'_sakura/components/Forum.php';
require_once ROOT .'_sakura/components/News.php';
require_once ROOT .'_sakura/components/Comments.php';
require_once ROOT .'_sakura/components/Manage.php';
require_once ROOT .'_sakura/components/Bans.php';
require_once ROOT .'_sakura/components/Whois.php';
require_once ROOT .'_sakura/components/Payments.php';
require_once ROOT . '_sakura/vendor/autoload.php';
require_once ROOT . '_sakura/components/Main.php';
require_once ROOT . '_sakura/components/Hashing.php';
require_once ROOT . '_sakura/components/Configuration.php';
require_once ROOT . '_sakura/components/Database.php';
require_once ROOT . '_sakura/components/Urls.php';
require_once ROOT . '_sakura/components/Templates.php';
require_once ROOT . '_sakura/components/Permissions.php';
require_once ROOT . '_sakura/components/Sessions.php';
require_once ROOT . '_sakura/components/User.php';
require_once ROOT . '_sakura/components/Users.php';
require_once ROOT . '_sakura/components/Forum.php';
require_once ROOT . '_sakura/components/News.php';
require_once ROOT . '_sakura/components/Comments.php';
require_once ROOT . '_sakura/components/Manage.php';
require_once ROOT . '_sakura/components/Bans.php';
require_once ROOT . '_sakura/components/Whois.php';
require_once ROOT . '_sakura/components/Payments.php';
// Include database extensions
foreach(glob(ROOT .'_sakura/components/database/*.php') as $driver) {
foreach (glob(ROOT . '_sakura/components/database/*.php') as $driver) {
require_once $driver;
}
// Set Error handler
set_error_handler(array('Sakura\Main', 'errorHandler'));
// Initialise Main Class
Main::init(ROOT .'_sakura/config/config.ini');
Main::init(ROOT . '_sakura/config/config.ini');
// Assign servers file to whois class
Whois::setServers(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'whoisservers'));
Whois::setServers(ROOT . '_sakura/' . Configuration::getLocalConfig('data', 'whoisservers'));
// Check if we the system has a cron service
if(Configuration::getConfig('no_cron_service')) {
if (Configuration::getConfig('no_cron_service')) {
// If not do an "asynchronous" call to the cron.php script
if(Configuration::getConfig('no_cron_last') < (time() - Configuration::getConfig('no_cron_interval'))) {
if (Configuration::getConfig('no_cron_last') < (time() - Configuration::getConfig('no_cron_interval'))) {
// Check OS
if(substr(strtolower(PHP_OS), 0, 3) == 'win') {
pclose(popen('start /B '. PHP_BINDIR .'\php.exe '. addslashes(ROOT .'_sakura\cron.php'), 'r'));
if (substr(strtolower(PHP_OS), 0, 3) == 'win') {
pclose(popen('start /B ' . PHP_BINDIR . '\php.exe ' . addslashes(ROOT . '_sakura\cron.php'), 'r'));
} else {
pclose(popen(PHP_BINDIR .'/php '. ROOT .'_sakura/cron.php > /dev/null 2>/dev/null &', 'r'));
pclose(popen(PHP_BINDIR . '/php ' . ROOT . '_sakura/cron.php > /dev/null 2>/dev/null &', 'r'));
}
// Update last execution time
Database::update('config', [
[
'config_value' => time()
'config_value' => time(),
],
[
'config_name' => ['no_cron_last', '=']
]
'config_name' => ['no_cron_last', '='],
],
]);
}
@ -112,10 +100,12 @@ $currentUser = new User(Session::$userId);
$urls = new Urls();
// Prepare the name of the template to load (outside of SAKURA_NO_TPL because it's used in imageserve.php)
$templateName = defined('SAKURA_MANAGE') ? Configuration::getConfig('manage_style') : Configuration::getConfig('site_style');
if(!defined('SAKURA_NO_TPL')) {
$templateName =
defined('SAKURA_MANAGE') ?
Configuration::getConfig('manage_style') :
Configuration::getConfig('site_style');
if (!defined('SAKURA_NO_TPL')) {
// Initialise templating engine
Templates::init($templateName);
@ -135,89 +125,86 @@ if(!defined('SAKURA_NO_TPL')) {
'versionInfo' => [
'version' => SAKURA_VERSION,
'label' => SAKURA_VLABEL,
'colour' => SAKURA_COLOUR,
'stable' => SAKURA_STABLE
'version' => SAKURA_VERSION,
'label' => SAKURA_VLABEL,
'colour' => SAKURA_COLOUR,
'stable' => SAKURA_STABLE,
],
'cookie' => [
'prefix' => Configuration::getConfig('cookie_prefix'),
'domain' => Configuration::getConfig('cookie_domain'),
'path' => Configuration::getConfig('cookie_path'),
'prefix' => Configuration::getConfig('cookie_prefix'),
'domain' => Configuration::getConfig('cookie_domain'),
'path' => Configuration::getConfig('cookie_path'),
],
'urlMain' => Configuration::getConfig('url_main'),
'urlApi' => Configuration::getConfig('url_api'),
'urlMain' => Configuration::getConfig('url_main'),
'urlApi' => Configuration::getConfig('url_api'),
'contentPath' => Configuration::getConfig('content_path'),
'resources' => Configuration::getConfig('content_path') .'/data/'. strtolower(Templates::$_TPL),
'contentPath' => Configuration::getConfig('content_path'),
'resources' => Configuration::getConfig('content_path') . '/data/' . strtolower(Templates::$template),
'charset' => Configuration::getConfig('charset'),
'siteName' => Configuration::getConfig('sitename'),
'siteDesc' => Configuration::getConfig('sitedesc'),
'siteTags' => implode(", ", json_decode(Configuration::getConfig('sitetags'), true)),
'dateFormat' => Configuration::getConfig('date_format'),
'currentPage' => '//'. $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'],
'charset' => Configuration::getConfig('charset'),
'siteName' => Configuration::getConfig('sitename'),
'siteDesc' => Configuration::getConfig('sitedesc'),
'siteTags' => implode(", ", json_decode(Configuration::getConfig('sitetags'), true)),
'dateFormat' => Configuration::getConfig('date_format'),
'currentPage' => '//' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'],
'recaptchaPublic' => Configuration::getConfig('recaptcha_public'),
'recaptchaEnabled' => Configuration::getConfig('recaptcha'),
'recaptchaPublic' => Configuration::getConfig('recaptcha_public'),
'recaptchaEnabled' => Configuration::getConfig('recaptcha'),
'disableRegistration' => Configuration::getConfig('disable_registration'),
'lockSite' => Configuration::getConfig('lock_site'),
'lockSiteReason' => Configuration::getConfig('lock_site_reason'),
'lockAuth' => Configuration::getConfig('lock_authentication'),
'requireRegCodes' => Configuration::getConfig('require_registration_code'),
'requireActivation' => Configuration::getConfig('require_activation'),
'minPwdEntropy' => Configuration::getConfig('min_entropy'),
'minUsernameLength' => Configuration::getConfig('username_min_length'),
'maxUsernameLength' => Configuration::getConfig('username_max_length')
'disableRegistration' => Configuration::getConfig('disable_registration'),
'lockSite' => Configuration::getConfig('lock_site'),
'lockSiteReason' => Configuration::getConfig('lock_site_reason'),
'lockAuth' => Configuration::getConfig('lock_authentication'),
'requireRegCodes' => Configuration::getConfig('require_registration_code'),
'requireActivation' => Configuration::getConfig('require_activation'),
'minPwdEntropy' => Configuration::getConfig('min_entropy'),
'minUsernameLength' => Configuration::getConfig('username_min_length'),
'maxUsernameLength' => Configuration::getConfig('username_max_length'),
],
'php' => [
'sessionid' => \session_id(),
'time' => \time(),
'self' => $_SERVER['PHP_SELF']
'time' => \time(),
'self' => $_SERVER['PHP_SELF'],
],
'session' => [
'checkLogin' => Users::checkLogin(),
'sessionId' => Session::$sessionId,
'userId' => Session::$userId
'checkLogin' => Users::checkLogin(),
'sessionId' => Session::$sessionId,
'userId' => Session::$userId,
],
'user' => $currentUser,
'urls' => $urls
'urls' => $urls,
];
// Ban checking
if(Users::checkLogin() && $ban = Bans::checkBan(Session::$userId)) {
if (Users::checkLogin() && $ban = Bans::checkBan(Session::$userId)) {
// Additional render data
$renderData = array_merge($renderData, [
'ban' => [
'reason' => $ban['reason'],
'issued' => $ban['issued'],
'expires' => $ban['expires'],
'issuer' => Users::getUser($ban['issuer'])
]
'reason' => $ban['reason'],
'issued' => $ban['issued'],
'expires' => $ban['expires'],
'issuer' => Users::getUser($ban['issuer']),
],
]);
Users::logout();
print Templates::render('main/banned.tpl', $renderData);
exit;
}
}

View file

@ -10,7 +10,7 @@ namespace Sakura;
define('SAKURA_NO_TPL', true);
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Change to content type to text/plain and set the charset to UTF-8
header('Content-Type: text/plain; charset=utf-8');
@ -22,8 +22,7 @@ $path = ltrim($_SERVER['REQUEST_URI'], '/');
$elems = explode('/', $path);
// Correct the path if mod_rewrite isn't used
if($elems[0] == explode('/', ltrim($_SERVER['PHP_SELF'], '/'))[0]) {
if ($elems[0] == explode('/', ltrim($_SERVER['PHP_SELF'], '/'))[0]) {
// Remove the entry
unset($elems[0]);
@ -31,53 +30,45 @@ if($elems[0] == explode('/', ltrim($_SERVER['PHP_SELF'], '/'))[0]) {
$elems = array_values($elems);
// Make sure there's at least one entry (even if empty)
if(!isset($elems[0]))
if (!isset($elems[0])) {
$elems[] = "";
}
}
// Make sure the GET requests aren't present in the last entry
if(strpos($elems[max(array_keys($elems))], '?')) {
if (strpos($elems[max(array_keys($elems))], '?')) {
// If there are cut them all
$elems[max(array_keys($elems))] = strstr($elems[max(array_keys($elems))], '?', true);
}
// Predefine the return variable
$return = [];
// Select API version
switch(isset($elems[0]) ? $elems[0] : false) {
switch (isset($elems[0]) ? $elems[0] : false) {
// API Version 1
case 'v1':
switch(isset($elems[1]) ? $elems[1] : false) {
switch (isset($elems[1]) ? $elems[1] : false) {
// Authentication
case 'authenticate':
switch(isset($elems[2]) ? $elems[2] : false) {
switch (isset($elems[2]) ? $elems[2] : false) {
case 'login':
$return = ['success' => 'LOGIN_PROCESS_HERE'];
break;
default:
$return = ['error' => ['NO_DATA_REQ']];
}
break;
default:
$return = ['error' => ['NO_DATA_REQ']];
}
break;
// Default fallback
default:
$return = ['error' => ['NO_API_VERSION']];
}
echo isset($_GET['pretty']) ? Main::jsonPretty(json_encode([$return])) : json_encode([$return]);

View file

@ -10,54 +10,42 @@
// You can also create a PHP file including this SockChat.php
// file so it's always up-to-date! Don't forget to include the
// variable below in the file __BEFORE__ the include!
if(!isset($sockSakuraPath)) {
if (!isset($sockSakuraPath)) {
$sockSakuraPath = '';
}
/* * * DON'T EDIT ANYTHING BELOW THIS LINE * * */
// Include Sakura
require_once $sockSakuraPath .'/sakura.php';
require_once $sockSakuraPath . '/sakura.php';
use sockchat\Auth;
use Sakura\Session;
use Sakura\Users;
use Sakura\Permissions;
use Sakura\Session;
use Sakura\User;
use Sakura\Users;
use sockchat\Auth;
if(Auth::getPageType() == AUTH_FETCH) {
if (Auth::getPageType() == AUTH_FETCH) {
// Check if user is logged into the Sakura backend if not deny
if(Users::checkLogin()) {
if (Users::checkLogin()) {
// If so append the required arguments and accept
Auth::AppendArguments([Session::$userId, Session::$sessionId]);
Auth::Accept();
} else {
Auth::Deny();
}
} else {
// Get arguments
$uid = $_REQUEST['arg1'];
$sid = $_REQUEST['arg2'];
// Check if session is active else deny
if(Session::checkSession($uid, $sid)) {
if (Session::checkSession($uid, $sid)) {
// Check if they can access the chat
if(Permissions::check('SITE', 'DEACTIVATED', $uid, 1) && Permissions::check('SITE', 'RESTRICTED', $uid, 1)) {
if (Permissions::check('SITE', 'DEACTIVATED', $uid, 1) && Permissions::check('SITE', 'RESTRICTED', $uid, 1)) {
Auth::Deny();
Auth::Serve();
exit;
}
// Create a user object
@ -73,22 +61,18 @@ if(Auth::getPageType() == AUTH_FETCH) {
// Set the common permissions
Auth::SetCommonPermissions(
bindec(Permissions::getUserPermissions($uid)['SITE']),
Permissions::check('MANAGE', 'USE_MANAGE', $uid, 1) ? 1 : 0,
Permissions::check('SITE', 'CREATE_BACKGROUND', $uid, 1) ? 1 : 0,
Permissions::check('SITE', 'CHANGE_USERNAME', $uid, 1) ? 1 : 0,
Permissions::check('SITE', 'MULTIPLE_GROUPS', $uid, 1) ? 2 : (
Permissions::check('SITE', 'CREATE_GROUP', $uid, 1) ? 1 : 0
Permissions::check('MANAGE', 'USE_MANAGE', $uid, 1) ? 1 : 0,
Permissions::check('SITE', 'CREATE_BACKGROUND', $uid, 1) ? 1 : 0,
Permissions::check('SITE', 'CHANGE_USERNAME', $uid, 1) ? 1 : 0,
Permissions::check('SITE', 'MULTIPLE_GROUPS', $uid, 1) ? 2 : (
Permissions::check('SITE', 'CREATE_GROUP', $uid, 1) ? 1 : 0
)
);
Auth::Accept();
} else {
Auth::Deny();
}
}
// Serve the authentication data

View file

@ -7,7 +7,7 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Set 404 header
header('HTTP/1.0 404 Not Found');

View file

@ -7,205 +7,183 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Page actions
if(isset($_REQUEST['mode'])) {
if (isset($_REQUEST['mode'])) {
// Continue
$continue = true;
// Make sure we're not in activate mode since adding a timestamp and accessing the PHP session id is kind of hard when you're in an e-mail client
if(!isset($_REQUEST['mode']) || $_REQUEST['mode'] != 'activate') {
if (!isset($_REQUEST['mode']) || $_REQUEST['mode'] != 'activate') {
// Compare time and session so we know the link isn't forged
if(!isset($_REQUEST['time']) || $_REQUEST['time'] < time() - 1000) {
if (!isset($_REQUEST['time']) || $_REQUEST['time'] < time() - 1000) {
$renderData['page'] = [
'redirect' => $urls->format('AUTH_ACTION'),
'message' => 'Timestamps differ too much, refresh the page and try again.',
'success' => 0
'redirect' => $urls->format('AUTH_ACTION'),
'message' => 'Timestamps differ too much, refresh the page and try again.',
'success' => 0,
];
// Prevent
$continue = false;
}
// Match session ids for the same reason
if(!isset($_REQUEST['session']) || $_REQUEST['session'] != session_id()) {
if (!isset($_REQUEST['session']) || $_REQUEST['session'] != session_id()) {
$renderData['page'] = [
'redirect' => $urls->format('AUTH_ACTION'),
'message' => 'Invalid session, please try again.',
'success' => 0
'redirect' => $urls->format('AUTH_ACTION'),
'message' => 'Invalid session, please try again.',
'success' => 0,
];
// Prevent
$continue = false;
}
}
// Login check
if(Users::checkLogin()) {
if(!in_array($_REQUEST['mode'], ['logout'])) {
if (Users::checkLogin()) {
if (!in_array($_REQUEST['mode'], ['logout'])) {
$continue = false;
// Add page specific things
$renderData['page'] = [
'redirect' => $urls->format('SITE_HOME'),
'message' => 'You are already authenticated. Redirecting...',
'success' => 1
'redirect' => $urls->format('SITE_HOME'),
'message' => 'You are already authenticated. Redirecting...',
'success' => 1,
];
}
}
if($continue) {
switch($_REQUEST['mode']) {
if ($continue) {
switch ($_REQUEST['mode']) {
case 'logout':
// Attempt logout
$logout = Users::logout();
// Add page specific data
$renderData['page'] = [
'redirect' => ($logout ? $_REQUEST['redirect'] : $urls->format('SITE_LOGIN')),
'message' => $logout ? 'You are now logged out.' : 'An unknown error occurred.',
'success' => $logout ? 1 : 0
'redirect' => ($logout ? $_REQUEST['redirect'] : $urls->format('SITE_LOGIN')),
'message' => $logout ? 'You are now logged out.' : 'An unknown error occurred.',
'success' => $logout ? 1 : 0,
];
break;
case 'changepassword':
// Attempt change
$passforget = Users::resetPassword($_REQUEST['verk'], $_REQUEST['uid'], $_REQUEST['newpw'], $_REQUEST['verpw']);
// Array containing "human understandable" messages
$messages = [
'INVALID_VERK' => 'The verification key supplied was invalid!',
'INVALID_CODE' => 'Invalid verification key, if you think this is an error contact the administrator.',
'INVALID_USER' => 'The used verification key is not designated for this user.',
'VERK_TOO_SHIT' => 'Your verification code is too weak, try adding some special characters.',
'PASS_TOO_SHIT' => 'Your password is too weak, try adding some special characters.',
'PASS_NOT_MATCH' => 'Passwords do not match.',
'SUCCESS' => 'Successfully changed your password, you may now log in.'
'INVALID_VERK' => 'The verification key supplied was invalid!',
'INVALID_CODE' => 'Invalid verification key, if you think this is an error contact the administrator.',
'INVALID_USER' => 'The used verification key is not designated for this user.',
'VERK_TOO_SHIT' => 'Your verification code is too weak, try adding some special characters.',
'PASS_TOO_SHIT' => 'Your password is too weak, try adding some special characters.',
'PASS_NOT_MATCH' => 'Passwords do not match.',
'SUCCESS' => 'Successfully changed your password, you may now log in.',
];
// Add page specific things
$renderData['page'] = [
'redirect' => ($passforget[0] ? $urls->format('SITE_LOGIN') : $_SERVER['PHP_SELF'] .'?pw=true&uid='. $_REQUEST['uid'] .'&verk='. $_REQUEST['verk']),
'message' => $messages[$passforget[1]],
'success' => $passforget[0]
'redirect' => ($passforget[0] ? $urls->format('SITE_LOGIN') : $_SERVER['PHP_SELF'] . '?pw=true&uid=' . $_REQUEST['uid'] . '&verk=' . $_REQUEST['verk']),
'message' => $messages[$passforget[1]],
'success' => $passforget[0],
];
break;
// Activating accounts
case 'activate':
// Attempt activation
$activate = Users::activateUser($_REQUEST['u'], true, $_REQUEST['k']);
// Array containing "human understandable" messages
$messages = [
'USER_NOT_EXIST' => 'The user you tried to activate does not exist.',
'USER_ALREADY_ACTIVE' => 'The user you tried to activate is already active.',
'INVALID_CODE' => 'Invalid activation code, if you think this is an error contact the administrator.',
'INVALID_USER' => 'The used activation code is not designated for this user.',
'SUCCESS' => 'Successfully activated your account, you may now log in.'
'USER_NOT_EXIST' => 'The user you tried to activate does not exist.',
'USER_ALREADY_ACTIVE' => 'The user you tried to activate is already active.',
'INVALID_CODE' => 'Invalid activation code, if you think this is an error contact the administrator.',
'INVALID_USER' => 'The used activation code is not designated for this user.',
'SUCCESS' => 'Successfully activated your account, you may now log in.',
];
// Add page specific things
$renderData['page'] = [
'redirect' => $urls->format('SITE_LOGIN'),
'message' => $messages[$activate[1]],
'success' => $activate[0]
'redirect' => $urls->format('SITE_LOGIN'),
'message' => $messages[$activate[1]],
'success' => $activate[0],
];
break;
// Resending the activation e-mail
case 'resendactivemail':
// Attempt send
$resend = Users::resendActivationMail($_REQUEST['username'], $_REQUEST['email']);
// Array containing "human understandable" messages
$messages = [
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The user you tried to activate does not exist (confirm the username/email combination).',
'USER_ALREADY_ACTIVE' => 'The user you tried to activate is already active.',
'SUCCESS' => 'The activation e-mail has been sent to the address associated with your account.'
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The user you tried to activate does not exist (confirm the username/email combination).',
'USER_ALREADY_ACTIVE' => 'The user you tried to activate is already active.',
'SUCCESS' => 'The activation e-mail has been sent to the address associated with your account.',
];
// Add page specific things
$renderData['page'] = [
'redirect' => $urls->format('SITE_HOME'),
'message' => $messages[$resend[1]],
'success' => $resend[0]
'redirect' => $urls->format('SITE_HOME'),
'message' => $messages[$resend[1]],
'success' => $resend[0],
];
break;
// Login processing
case 'login':
// Attempt login
$login = Users::login($_REQUEST['username'], $_REQUEST['password'], isset($_REQUEST['remember']));
// Array containing "human understandable" messages
$messages = [
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The user you tried to log into does not exist.',
'INCORRECT_PASSWORD' => 'The password you entered was invalid.',
'NOT_ALLOWED' => 'Your account does not have the required permissions to log in.',
'NO_LOGIN' => 'Logging into this account is disabled.',
'LOGIN_SUCESS' => 'Login successful!'
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The user you tried to log into does not exist.',
'INCORRECT_PASSWORD' => 'The password you entered was invalid.',
'NOT_ALLOWED' => 'Your account does not have the required permissions to log in.',
'NO_LOGIN' => 'Logging into this account is disabled.',
'LOGIN_SUCESS' => 'Login successful!',
];
// Add page specific things
$renderData['page'] = [
'redirect' => $login[0] ? $_REQUEST['redirect'] : $urls->format('SITE_LOGIN'),
'message' => $messages[$login[1]],
'success' => $login[0]
'redirect' => $login[0] ? $_REQUEST['redirect'] : $urls->format('SITE_LOGIN'),
'message' => $messages[$login[1]],
'success' => $login[0],
];
break;
// Registration processing
case 'register':
// Attempt registration
$register = Users::register(
$_REQUEST['username'],
@ -228,59 +206,56 @@ if(isset($_REQUEST['mode'])) {
// Array containing "human understandable" messages
$messages = [
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'DISABLED' => 'Registration is currently disabled.',
'INVALID_REG_KEY' => 'The given registration code was invalid.',
'TOS' => 'You are required to agree to the Terms of Service.',
'CAPTCHA_FAIL' => 'Captcha verification failed, please try again.',
'USER_EXISTS' => 'A user with this username already exists, if you lost your password try using the Lost Password form.',
'NAME_TOO_SHORT' => 'Your name must be at least 3 characters long.',
'NAME_TOO_LONG' => 'Your name can\'t be longer than 16 characters.',
'PASS_TOO_SHIT' => 'Your password is too weak, try adding some special characters.',
'PASS_NOT_MATCH' => 'Passwords do not match.',
'INVALID_EMAIL' => 'Your e-mail address is formatted incorrectly.',
'INVALID_MX' => 'No valid MX-Record found on the e-mail address you supplied.',
'EMAILSENT' => 'Your registration went through! An activation e-mail has been sent.',
'SUCCESS' => 'Your registration went through! Welcome to '. Configuration::getConfig('sitename') .'!'
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'DISABLED' => 'Registration is currently disabled.',
'INVALID_REG_KEY' => 'The given registration code was invalid.',
'TOS' => 'You are required to agree to the Terms of Service.',
'CAPTCHA_FAIL' => 'Captcha verification failed, please try again.',
'USER_EXISTS' => 'A user with this username already exists, if you lost your password try using the Lost Password form.',
'NAME_TOO_SHORT' => 'Your name must be at least 3 characters long.',
'NAME_TOO_LONG' => 'Your name can\'t be longer than 16 characters.',
'PASS_TOO_SHIT' => 'Your password is too weak, try adding some special characters.',
'PASS_NOT_MATCH' => 'Passwords do not match.',
'INVALID_EMAIL' => 'Your e-mail address is formatted incorrectly.',
'INVALID_MX' => 'No valid MX-Record found on the e-mail address you supplied.',
'EMAILSENT' => 'Your registration went through! An activation e-mail has been sent.',
'SUCCESS' => 'Your registration went through! Welcome to ' . Configuration::getConfig('sitename') . '!',
];
// Add page specific things
$renderData['page'] = [
'redirect' => ($register[0] ? $urls->format('SITE_LOGIN') : $urls->format('SITE_REGISTER')),
'message' => $messages[$register[1]],
'success' => $register[0]
'redirect' => ($register[0] ? $urls->format('SITE_LOGIN') : $urls->format('SITE_REGISTER')),
'message' => $messages[$register[1]],
'success' => $register[0],
];
break;
// Unforgetting passwords
case 'forgotpassword':
// Attempt send
$passforgot = Users::sendPasswordForgot($_REQUEST['username'], $_REQUEST['email']);
// Array containing "human understandable" messages
$messages = [
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The requested user does not exist (confirm the username/email combination).',
'NOT_ALLOWED' => 'Your account does not have the required permissions to change your password.',
'SUCCESS' => 'The password reset e-mail has been sent to the address associated with your account.'
'AUTH_LOCKED' => 'Authentication is currently not allowed, try again later.',
'USER_NOT_EXIST' => 'The requested user does not exist (confirm the username/email combination).',
'NOT_ALLOWED' => 'Your account does not have the required permissions to change your password.',
'SUCCESS' => 'The password reset e-mail has been sent to the address associated with your account.',
];
// Add page specific things
$renderData['page'] = [
'redirect' => $urls->format('SITE_FORGOT_PASSWORD'),
'message' => $messages[$passforgot[1]],
'success' => $passforgot[0]
'redirect' => $urls->format('SITE_FORGOT_PASSWORD'),
'message' => $messages[$passforgot[1]],
'success' => $passforgot[0],
];
break;
}
@ -288,13 +263,13 @@ if(isset($_REQUEST['mode'])) {
}
// Print page contents or if the AJAX request is set only display the render data
print isset($_REQUEST['ajax']) ?
(
$renderData['page']['message'] .'|'.
$renderData['page']['success'] .'|'.
$renderData['page']['redirect']
) :
Templates::render('global/information.tpl', $renderData);
print isset($_REQUEST['ajax']) ?
(
$renderData['page']['message'] . '|' .
$renderData['page']['success'] . '|' .
$renderData['page']['redirect']
) :
Templates::render('global/information.tpl', $renderData);
exit;
}
@ -305,52 +280,47 @@ $renderData['auth'] = [
'redirect' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $urls->format('SITE_HOME'),
'blockRegister' => [
'do' => false
'do' => false,
]
],
];
// Check if the user is already logged in
if(Users::checkLogin()) {
if (Users::checkLogin()) {
// Add page specific things
$renderData['page'] = [
'redirect' => $urls->format('SITE_HOME'),
'message' => 'You are already logged in, log out to access this page.'
'redirect' => $urls->format('SITE_HOME'),
'message' => 'You are already logged in, log out to access this page.',
];
print Templates::render('global/information.tpl', $renderData);
exit;
}
// Check if a user has already registered from the current IP address
if(count($regUserIP = Users::getUsersByIP(Main::getRemoteIP()))) {
if (count($regUserIP = Users::getUsersByIP(Main::getRemoteIP()))) {
$renderData['auth']['blockRegister'] = [
'do' => true,
'username' => $regUserIP[array_rand($regUserIP)]['username']
'do' => true,
'username' => $regUserIP[array_rand($regUserIP)]['username'],
];
}
// If password forgot things are set display password forget thing
if(isset($_REQUEST['pw']) && $_REQUEST['pw']) {
if (isset($_REQUEST['pw']) && $_REQUEST['pw']) {
$renderData['auth']['changingPass'] = true;
$renderData['auth']['userId'] = $_REQUEST['uid'];
$renderData['auth']['userId'] = $_REQUEST['uid'];
if(isset($_REQUEST['key']))
if (isset($_REQUEST['key'])) {
$renderData['auth']['forgotKey'] = $_REQUEST['key'];
}
print Templates::render('main/forgotpassword.tpl', $renderData);
exit;
}
// Print page contents

View file

@ -10,29 +10,26 @@ namespace Sakura;
define('SAKURA_NO_TPL', true);
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Path the changelog JSON
$changelog = json_decode(file_get_contents(ROOT .'_sakura/changelog.json'), true);
$changelog = json_decode(file_get_contents(ROOT . '_sakura/changelog.json'), true);
// Create variable to store HTML in
$changelogHTML = null;
// Format HTML
foreach(array_reverse($changelog['changelog'], true) as $revisionId => $revisionData) {
foreach (array_reverse($changelog['changelog'], true) as $revisionId => $revisionData) {
$changelogHTML .= '<div class="release" id="r' . $revisionId . '">';
$changelogHTML .= '<div class="release" id="r'. $revisionId .'">';
$changelogHTML .= '<a href="#r'. $revisionId .'" class="title" style="color: '. $changelog['versions'][$revisionData[0]] .';">Revision '. $revisionId .' ('. ucfirst($revisionData[0]) .')</a>';
$changelogHTML .= '<a href="#r' . $revisionId . '" class="title" style="color: ' . $changelog['versions'][$revisionData[0]] . ';">Revision ' . $revisionId . ' (' . ucfirst($revisionData[0]) . ')</a>';
unset($revisionData[0]);
foreach(array_reverse($revisionData) as $id => $changeData) {
$changelogHTML .= '<div id="r'. $revisionId .'c'. $id .'">';
switch($changeData['type']) {
foreach (array_reverse($revisionData) as $id => $changeData) {
$changelogHTML .= '<div id="r' . $revisionId . 'c' . $id . '">';
switch ($changeData['type']) {
case 'ADD':
$changelogHTML .= '<span class="tag addition-tag">Added</span>';
break;
@ -51,34 +48,31 @@ foreach(array_reverse($changelog['changelog'], true) as $revisionId => $revision
default:
$changelogHTML .= '<span class="tag">Unknown</span>';
}
$changelogHTML .= '<span class="changedesc">';
$changelogHTML .= $changeData['change'];
$changelogHTML .= '</span>';
$changelogHTML .= '<a class="changeuser" target="_blank" href="http://bitbucket.org/'. strtolower($changeData['user']) .'">';
$changelogHTML .= '<a class="changeuser" target="_blank" href="http://bitbucket.org/' . strtolower($changeData['user']) . '">';
$changelogHTML .= $changeData['user'];
$changelogHTML .= '</a>';
$changelogHTML .= '</div>';
}
$changelogHTML .= '</div>';
}
// Get special template file
$tpl = file_get_contents(ROOT .'_sakura/templates/changeLog.tpl');
$tpl = file_get_contents(ROOT . '_sakura/templates/changeLog.tpl');
// Parse tags
$tpl = str_replace('{{ version }}', SAKURA_VERSION, $tpl);
$tpl = str_replace('{{ version_label }}', SAKURA_VLABEL, $tpl);
$tpl = str_replace('{{ version_type }}', SAKURA_STABLE ? 'Stable' : 'Development', $tpl);
$tpl = str_replace('{{ colour }}', SAKURA_COLOUR, $tpl);
$tpl = str_replace('{{ changeloghtml }}', $changelogHTML, $tpl);
$tpl = str_replace('{{ version }}', SAKURA_VERSION, $tpl);
$tpl = str_replace('{{ version_label }}', SAKURA_VLABEL, $tpl);
$tpl = str_replace('{{ version_type }}', SAKURA_STABLE ? 'Stable' : 'Development', $tpl);
$tpl = str_replace('{{ colour }}', SAKURA_COLOUR, $tpl);
$tpl = str_replace('{{ changeloghtml }}', $changelogHTML, $tpl);
// Print template
print $tpl;

View file

@ -7,13 +7,13 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Add page specific things
$renderData['page'] = [
'title' => 'Frequently Asked Questions',
'questions' => Main::getFaqData()
'title' => 'Frequently Asked Questions',
'questions' => Main::getFaqData(),
];

View file

@ -7,8 +7,7 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Print page contents
print Templates::render('group/index.tpl', $renderData);

View file

@ -10,7 +10,7 @@ namespace Sakura;
define('SAKURA_NO_TPL', true);
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Set Content type
//header('Content-Type: application/octet-stream');
@ -19,49 +19,39 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sak
$userDirPath = ROOT . Configuration::getConfig('user_uploads') . '/';
// Check if the m(ode) GET request is set
if(isset($_GET['m'])) {
switch($_GET['m']) {
if (isset($_GET['m'])) {
switch ($_GET['m']) {
case 'avatar':
// Set paths
$noAvatar = ROOT . str_replace('{{ TPL }}', $templateName, Configuration::getConfig('no_avatar_img'));
$noAvatar = ROOT . str_replace('{{ TPL }}', $templateName, Configuration::getConfig('no_avatar_img'));
$deactiveAvatar = ROOT . str_replace('{{ TPL }}', $templateName, Configuration::getConfig('deactivated_avatar_img'));
$bannedAvatar = ROOT . str_replace('{{ TPL }}', $templateName, Configuration::getConfig('banned_avatar_img'));
$bannedAvatar = ROOT . str_replace('{{ TPL }}', $templateName, Configuration::getConfig('banned_avatar_img'));
// If ?u= isn't set or if it isn't numeric
if(!isset($_GET['u']) || !is_numeric($_GET['u']) || $_GET['u'] == 0) {
if (!isset($_GET['u']) || !is_numeric($_GET['u']) || $_GET['u'] == 0) {
$serveImage = $noAvatar;
break;
}
// Get user data
$user = new User($_GET['u']);
// If user is deactivated use deactive avatar
if($user->checkIfUserHasRanks([0, 1])) {
if ($user->checkIfUserHasRanks([0, 1])) {
$serveImage = $deactiveAvatar;
break;
}
// Check if user is banned
if($user->checkBan()) {
if ($user->checkBan()) {
$serveImage = $bannedAvatar;
break;
}
// Check if user has an avatar set
if(empty($user->data['userData']['userAvatar']) || !file_exists($userDirPath . $user->data['userData']['userAvatar'])) {
if (empty($user->data['userData']['userAvatar']) || !file_exists($userDirPath . $user->data['userData']['userAvatar'])) {
$serveImage = $noAvatar;
break;
}
// Check if the avatar exist and assign it to a value
@ -73,38 +63,30 @@ if(isset($_GET['m'])) {
$noBackground = ROOT . Configuration::getConfig('no_background_img');
// If ?u= isn't set or if it isn't numeric
if(!isset($_GET['u']) || !is_numeric($_GET['u'])) {
if (!isset($_GET['u']) || !is_numeric($_GET['u'])) {
$serveImage = $noBackground;
break;
}
// Get user data
$user = new User($_GET['u']);
// If user is deactivated use deactive avatar
if($user->checkIfUserHasRanks([0, 1])) {
if ($user->checkIfUserHasRanks([0, 1])) {
$serveImage = $noBackground;
break;
}
// Check if user is banned
if(Bans::checkBan($_GET['u'])) {
if (Bans::checkBan($_GET['u'])) {
$serveImage = $noBackground;
break;
}
// Check if user has a background set
if(empty($user->data['userData']['profileBackground']) || !file_exists($userDirPath . $user->data['userData']['profileBackground'])) {
if (empty($user->data['userData']['profileBackground']) || !file_exists($userDirPath . $user->data['userData']['profileBackground'])) {
$serveImage = $noBackground;
break;
}
// Check if the avatar exist and assign it to a value
@ -116,7 +98,7 @@ if(isset($_GET['m'])) {
$noHeader = ROOT . Configuration::getConfig('no_header_img');
// If ?u= isn't set or if it isn't numeric
if(!isset($_GET['u']) || !is_numeric($_GET['u'])) {
if (!isset($_GET['u']) || !is_numeric($_GET['u'])) {
$serveImage = $noHeader;
break;
}
@ -125,27 +107,21 @@ if(isset($_GET['m'])) {
$user = new User($_GET['u']);
// If user is deactivated use deactive avatar
if($user->checkIfUserHasRanks([0, 1])) {
if ($user->checkIfUserHasRanks([0, 1])) {
$serveImage = $noHeader;
break;
}
// Check if user is banned
if(Bans::checkBan($_GET['u'])) {
if (Bans::checkBan($_GET['u'])) {
$serveImage = $noHeader;
break;
}
// Check if user has a background set
if(empty($user->data['userData']['profileHeader']) || !file_exists($userDirPath . $user->data['userData']['profileHeader'])) {
if (empty($user->data['userData']['profileHeader']) || !file_exists($userDirPath . $user->data['userData']['profileHeader'])) {
$serveImage = $noHeader;
break;
}
// Check if the avatar exist and assign it to a value
@ -156,15 +132,12 @@ if(isset($_GET['m'])) {
$serveImage = ROOT . Configuration::getConfig('pixel_img');
}
} else {
$serveImage = ROOT . Configuration::getConfig('pixel_img');
}
$serveImage = file_get_contents($serveImage);
header('Content-Type: '. getimagesizefromstring($serveImage)['mime']);
header('Content-Type: ' . getimagesizefromstring($serveImage)['mime']);
print $serveImage;

View file

@ -7,15 +7,14 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Info pages
if(isset($_GET['p'])) {
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' => Main::mdParse("# Unable to load the requested info page.\r\n\r\nCheck the URL and try again."),
];
@ -23,23 +22,20 @@ if(isset($_GET['p'])) {
$pageId = isset($_GET['p']) ? strtolower($_GET['p']) : '';
// Get info page data from the database
if($ipData = Main::loadInfoPage($pageId)) {
if ($ipData = Main::loadInfoPage($pageId)) {
// Assign new proper variable
$renderData['page'] = [
'id' => $pageId,
'title' => $ipData['pagetitle'],
'content' => Main::mdParse($ipData['content'])
'id' => $pageId,
'title' => $ipData['pagetitle'],
'content' => Main::mdParse($ipData['content']),
];
}
// Print page contents
print Templates::render('main/infopage.tpl', $renderData);
exit;
}
// Are we in forum mode?
@ -50,23 +46,23 @@ $renderData['news'] = ($forumMode ? null : (new News(Configuration::getConfig('s
$renderData['newsCount'] = Configuration::getConfig('front_page_news_posts');
$renderData['page'] = [
'friend_req' => Users::getPendingFriends()
'friend_req' => Users::getPendingFriends(),
];
$renderData['board'] = [
'forums' => ($forumMode ? Forum::getForumList() : null),
'forums' => ($forumMode ? Forum::getForumList() : null),
'viewforum' => false,
'viewtopic' => false
'viewtopic' => false,
];
$renderData['stats'] = [
'userCount' => Database::count('users', ['password_algo' => ['nologin', '!='], 'rank_main' => ['1', '!=']])[0],
'newestUser' => ($_INDEX_NEWEST_USER = new User(Users::getNewestUserId())),
'lastRegDate' => ($_INDEX_LAST_REGDATE = date_diff(date_create(date('Y-m-d', $_INDEX_NEWEST_USER->data['regdate'])), date_create(date('Y-m-d')))->format('%a')) .' day'. ($_INDEX_LAST_REGDATE == 1 ? '' : 's'),
'topicCount' => Database::count('topics')[0],
'postCount' => Database::count('posts')[0],
'onlineUsers' => Users::checkAllOnline()
'userCount' => Database::count('users', ['password_algo' => ['nologin', '!='], 'rank_main' => ['1', '!=']])[0],
'newestUser' => ($_INDEX_NEWEST_USER = new User(Users::getNewestUserId())),
'lastRegDate' => ($_INDEX_LAST_REGDATE = date_diff(date_create(date('Y-m-d', $_INDEX_NEWEST_USER->data['regdate'])), date_create(date('Y-m-d')))->format('%a')) . ' day' . ($_INDEX_LAST_REGDATE == 1 ? '' : 's'),
'topicCount' => Database::count('topics')[0],
'postCount' => Database::count('posts')[0],
'onlineUsers' => Users::checkAllOnline(),
];
// Print page contents
print Templates::render(($forumMode ? 'forum' : 'main') .'/index.tpl', $renderData);
print Templates::render(($forumMode ? 'forum' : 'main') . '/index.tpl', $renderData);

View file

@ -10,14 +10,12 @@ namespace Sakura;
define('SAKURA_MANAGE', true);
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Make sure user has the permissions to view this
if(!Permissions::check('MANAGE', 'USE_MANAGE', Session::$userId, 1)) {
if (!Permissions::check('MANAGE', 'USE_MANAGE', Session::$userId, 1)) {
header('Location: /');
exit;
}
// Management pages
@ -25,129 +23,129 @@ $managePages = [
'index' => [
'desc' => 'Index',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'reports' => [
'desc' => 'Reports',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'banning' => [
'desc' => 'Banning',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'warnings' => [
'desc' => 'Warnings',
'subs' => [
'subs' => [
'front-thing' => [
'desc' => 'thing'
]
]
'desc' => 'thing',
],
],
],
'user-notes' => [
'desc' => 'User notes',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'action-logs' => [
'desc' => 'Action logs',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'action-logs' => [
'desc' => 'Action logs',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'statistics' => [
'desc' => 'Statistics',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'general-settings' => [
'desc' => 'General Settings',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'users' => [
'desc' => 'Users',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'ranks' => [
'desc' => 'Ranks',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'permissions' => [
'desc' => 'Permissions',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'info-pages' => [
'desc' => 'Info pages',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
'desc' => 'Front Page',
],
],
],
'system' => [
'desc' => 'System',
'subs' => [
'subs' => [
'front-page' => [
'desc' => 'Front Page'
]
]
]
'desc' => 'Front Page',
],
],
],
];
@ -174,9 +172,9 @@ $renderData['page'] = [
key($_MANAGE_SUBS)
) :
key($_MANAGE_SUBS)
)
),
];
// Print page contents
print Templates::render('pages/'. $_MANAGE_ACTIVE_PAGE .'/'. $_MANAGE_ACTIVE_SUB .'.tpl', $renderData);
print Templates::render('pages/' . $_MANAGE_ACTIVE_PAGE . '/' . $_MANAGE_ACTIVE_SUB . '.tpl', $renderData);

View file

@ -7,30 +7,26 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// CHeck if the user is logged in
if(Users::checkLogin()) {
if (Users::checkLogin()) {
// Add page specific things
$renderData['page'] = [
'ranks' => ($_MEMBERLIST_RANKS = Users::getAllRanks()),
'active' => ($_MEMBERLIST_ACTIVE = (isset($_GET['rank']) && $_GET['rank'] && array_key_exists($_GET['rank'], $_MEMBERLIST_RANKS) ? $_GET['rank'] : 0)),
'notfound' => ($_MEMBERLIST_NFOUND = (isset($_GET['rank']) && !array_key_exists($_GET['rank'], $_MEMBERLIST_RANKS) && $_GET['rank'] != 0)),
'sorts' => ($_MEMBERLIST_SORTS = ['boxes', 'rectangles', 'list']),
'sort' => isset($_GET['sort']) && $_GET['sort'] && in_array($_GET['sort'], $_MEMBERLIST_SORTS) ? $_GET['sort'] : $_MEMBERLIST_SORTS[0],
'page' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
'users' => array_chunk($_MEMBERLIST_ACTIVE && !$_MEMBERLIST_NFOUND ? Users::getUsersInRank($_MEMBERLIST_ACTIVE, null, true, true) : Users::getAllUsers(), Configuration::getConfig('members_per_page'), true)
'ranks' => ($_MEMBERLIST_RANKS = Users::getAllRanks()),
'active' => ($_MEMBERLIST_ACTIVE = (isset($_GET['rank']) && $_GET['rank'] && array_key_exists($_GET['rank'], $_MEMBERLIST_RANKS) ? $_GET['rank'] : 0)),
'notfound' => ($_MEMBERLIST_NFOUND = (isset($_GET['rank']) && !array_key_exists($_GET['rank'], $_MEMBERLIST_RANKS) && $_GET['rank'] != 0)),
'sorts' => ($_MEMBERLIST_SORTS = ['boxes', 'rectangles', 'list']),
'sort' => isset($_GET['sort']) && $_GET['sort'] && in_array($_GET['sort'], $_MEMBERLIST_SORTS) ? $_GET['sort'] : $_MEMBERLIST_SORTS[0],
'page' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
'users' => array_chunk($_MEMBERLIST_ACTIVE && !$_MEMBERLIST_NFOUND ? Users::getUsersInRank($_MEMBERLIST_ACTIVE, null, true, true) : Users::getAllUsers(), Configuration::getConfig('members_per_page'), true),
];
// Print page contents
print Templates::render('main/memberlist.tpl', $renderData);
} else {
// Else return the restricted page
print Templates::render('global/restricted.tpl', $renderData);
}

View file

@ -10,39 +10,38 @@ namespace Sakura;
use DOMDocument;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Create a new News object
$news = new News(isset($_GET['cat']) ? $_GET['cat'] : Configuration::getConfig('site_news_category'));
// News XML feed
if(isset($_GET['xml'])) {
if (isset($_GET['xml'])) {
// Get the news posts
$posts = $news->getPosts();
// Meta data attributes
$metaData = [
'title' => ($_FEED_TITLE = Configuration::getConfig('sitename')) .' News',
'link' => ($_FEED_URL = 'http://'. Configuration::getConfig('url_main')),
'description' => 'News about '. $_FEED_TITLE,
'language' => 'en-gb',
'webMaster' => (new User(1))->data['email'] .' ('. $_FEED_TITLE .' Webmaster)',
'pubDate' => ($_FEED_DATE = date('r', $posts[array_keys($posts)[0]]['date'])),
'lastBuildDate' => $_FEED_DATE
'title' => ($_FEED_TITLE = Configuration::getConfig('sitename')) . ' News',
'link' => ($_FEED_URL = 'http://' . Configuration::getConfig('url_main')),
'description' => 'News about ' . $_FEED_TITLE,
'language' => 'en-gb',
'webMaster' => (new User(1))->data['email'] . ' (' . $_FEED_TITLE . ' Webmaster)',
'pubDate' => ($_FEED_DATE = date('r', $posts[array_keys($posts)[0]]['date'])),
'lastBuildDate' => $_FEED_DATE,
];
// Item attributes
$itemData = [
'title' => ['text' => '{EVAL}', 'eval' => '$post["title"]'],
'link' => ['text' => $_FEED_URL .'/news/{EVAL}', 'eval' => '$post["id"]'],
'guid' => ['text' => $_FEED_URL .'/news/{EVAL}', 'eval' => '$post["id"]'],
'pubDate' => ['text' => '{EVAL}', 'eval' => 'date("D, d M Y G:i:s O", $post["date"])'],
'dc:publisher' => ['text' => '{EVAL}', 'eval' => '$post["poster"]->data["username"]'],
'description' => ['cdata' => '{EVAL}', 'eval' => '$post["content_parsed"]']
'title' => ['text' => '{EVAL}', 'eval' => '$post["title"]'],
'link' => ['text' => $_FEED_URL . '/news/{EVAL}', 'eval' => '$post["id"]'],
'guid' => ['text' => $_FEED_URL . '/news/{EVAL}', 'eval' => '$post["id"]'],
'pubDate' => ['text' => '{EVAL}', 'eval' => 'date("D, d M Y G:i:s O", $post["date"])'],
'dc:publisher' => ['text' => '{EVAL}', 'eval' => '$post["poster"]->data["username"]'],
'description' => ['cdata' => '{EVAL}', 'eval' => '$post["content_parsed"]'],
];
@ -53,63 +52,57 @@ if(isset($_GET['xml'])) {
$fRss = $feed->createElement('rss');
// Set attributes
$fRss->setAttribute('version', '2.0');
$fRss->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom');
$fRss->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1');
$fRss->setAttribute('version', '2.0');
$fRss->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom');
$fRss->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1');
// Create the channel element
$fChannel = $feed->createElement('channel');
// Build meta elements
foreach($metaData as $name => $value) {
foreach ($metaData as $name => $value) {
// Create the elements
$mElem = $feed->createElement($name);
$mElemText = $feed->createTextNode($value);
$mElem = $feed->createElement($name);
$mElemText = $feed->createTextNode($value);
// Append them
$mElem ->appendChild($mElemText);
$fChannel ->appendChild($mElem);
$mElem->appendChild($mElemText);
$fChannel->appendChild($mElem);
// Unset the working vars
unset($mElem);
unset($mElemText);
}
// Add all the posts
foreach($posts as $post) {
foreach ($posts as $post) {
// Create item element
$fPost = $feed->createElement('item');
// Create post attributes
foreach($itemData as $tag => $valueData) {
foreach ($itemData as $tag => $valueData) {
// Create the element
$pElem = $feed->createElement($tag);
// Create value
eval('$value = '. $valueData['eval'] .';');
eval('$value = ' . $valueData['eval'] . ';');
$value = str_replace('{EVAL}', $value, $valueData[(array_key_exists('cdata', $valueData) ? 'cdata' : 'text')]);
// Create text node or cdata container
$pElemText = (array_key_exists('cdata', $valueData)) ? $feed->createCDATASection($value) : $feed->createTextNode($value);
// Append them
$pElem ->appendChild($pElemText);
$fPost ->appendChild($pElem);
$pElem->appendChild($pElemText);
$fPost->appendChild($pElem);
// Unset the working vars
unset($pElem);
unset($pElemText);
unset($value);
}
// Append the item to the channel
$fChannel->appendChild($fPost);
}
// Append the channel element to RSS
@ -121,16 +114,15 @@ if(isset($_GET['xml'])) {
// Return the feed
print $feed->saveXML();
exit;
}
$renderData = array_merge($renderData, [
'news' => $news,
'postsPerPage' => Configuration::getConfig('news_posts_per_page'),
'viewPost' => isset($_GET['id']),
'postExists' => $news->postExists(isset($_GET['id']) ? $_GET['id'] : 0),
'currentPage' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0
'news' => $news,
'postsPerPage' => Configuration::getConfig('news_posts_per_page'),
'viewPost' => isset($_GET['id']),
'postExists' => $news->postExists(isset($_GET['id']) ? $_GET['id'] : 0),
'currentPage' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
]);

View file

@ -7,11 +7,11 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Set location
$locId = isset($_GET['f']) ? $_GET['f'] : (isset($_GET['t']) ? $_GET['t'] : (isset($_GET['p']) ? Forum::getTopicIdFromPostId($_GET['p']) : 0));
$locMode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) || isset($_GET['p']) ? 't' : null);
$locId = isset($_GET['f']) ? $_GET['f'] : (isset($_GET['t']) ? $_GET['t'] : (isset($_GET['p']) ? Forum::getTopicIdFromPostId($_GET['p']) : 0));
$locMode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) || isset($_GET['p']) ? 't' : null);
// Set additional render data
$renderData = array_merge($renderData, [
@ -19,9 +19,9 @@ $renderData = array_merge($renderData, [
'posting' => [
'emoticons' => Main::getEmotes(),
'bbcodes' => Main::getBBcodes()
'bbcodes' => Main::getBBcodes(),
]
],
]);

View file

@ -7,8 +7,7 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Get the user's context
$profile = new User(isset($_GET['u']) ? $_GET['u'] : 0);

View file

@ -7,6 +7,6 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
print Templates::render('main/report.tpl', $renderData);

View file

@ -7,12 +7,12 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Add page specific things
$renderData['page'] = [
'title' => 'Search'
'title' => 'Search',
];

File diff suppressed because it is too large Load diff

View file

@ -7,66 +7,49 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Switch between modes (we only allow this to be used by logged in user)
if(isset($_REQUEST['mode']) && Users::checkLogin() && Permissions::check('SITE', 'OBTAIN_PREMIUM', Session::$userId, 1)) {
if (isset($_REQUEST['mode']) && Users::checkLogin() && Permissions::check('SITE', 'OBTAIN_PREMIUM', Session::$userId, 1)) {
// Initialise Payments class
if(!Payments::init()) {
header('Location: '. $urls->format('SITE_PREMIUM') .'?fail=true');
if (!Payments::init()) {
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
} else {
switch($_REQUEST['mode']) {
switch ($_REQUEST['mode']) {
// Create the purchase
case 'purchase':
// Compare time and session so we know the link isn't forged
if(!isset($_REQUEST['time']) || $_REQUEST['time'] < time() - 1000) {
header('Location: '. $urls->format('SITE_PREMIUM') .'?fail=true');
if (!isset($_REQUEST['time']) || $_REQUEST['time'] < time() - 1000) {
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
break;
}
// Match session ids for the same reason
if(!isset($_REQUEST['session']) || $_REQUEST['session'] != session_id()) {
header('Location: '. $urls->format('SITE_PREMIUM') .'?fail=true');
if (!isset($_REQUEST['session']) || $_REQUEST['session'] != session_id()) {
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
break;
}
// Half if shit isn't gucci
if(!isset($_POST['months']) || !is_numeric($_POST['months']) || (int)$_POST['months'] < 1 || (int)$_POST['months'] > Configuration::getConfig('premium_amount_max')) {
header('Location: '. $urls->format('SITE_PREMIUM') .'?fail=true');
if (!isset($_POST['months']) || !is_numeric($_POST['months']) || (int) $_POST['months'] < 1 || (int) $_POST['months'] > Configuration::getConfig('premium_amount_max')) {
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
} else {
// Calculate the total
$total = (float)Configuration::getConfig('premium_price_per_month') * (int)$_POST['months'];
$total = (float) Configuration::getConfig('premium_price_per_month') * (int) $_POST['months'];
$total = number_format($total, 2, '.', '');
// Generate item name
$itemName = Configuration::getConfig('sitename') .' Premium - '. (string)$_POST['months'] .' month'. ((int)$_POST['months'] == 1 ? '' : 's');
$itemName = Configuration::getConfig('sitename') . ' Premium - ' . (string) $_POST['months'] . ' month' . ((int) $_POST['months'] == 1 ? '' : 's');
// Attempt to create a transaction
if($transaction = Payments::createTransaction($total, $itemName, Configuration::getConfig('sitename') .' Premium Purchase', 'http://'. Configuration::getConfig('url_main') . $urls->format('SITE_PREMIUM'))) {
if ($transaction = Payments::createTransaction($total, $itemName, Configuration::getConfig('sitename') . ' Premium Purchase', 'http://' . Configuration::getConfig('url_main') . $urls->format('SITE_PREMIUM'))) {
// Store the amount of months in the global session array
$_SESSION['premiumMonths'] = (int)$_POST['months'];
$_SESSION['premiumMonths'] = (int) $_POST['months'];
header('Location: '. $transaction);
header('Location: ' . $transaction);
exit;
} else {
header('Location: '. $urls->format('SITE_PREMIUM') .'?fail=true');
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
}
}
@ -75,32 +58,29 @@ if(isset($_REQUEST['mode']) && Users::checkLogin() && Permissions::check('SITE',
// Finalising the purchase
case 'finish':
// Check if the success GET request is set and is true
if(isset($_GET['success']) && isset($_GET['paymentId']) && isset($_GET['PayerID']) && isset($_SESSION['premiumMonths'])) {
if (isset($_GET['success']) && isset($_GET['paymentId']) && isset($_GET['PayerID']) && isset($_SESSION['premiumMonths'])) {
// Attempt to complete the transaction
try{
try {
$finalise = Payments::completeTransaction($_GET['paymentId'], $_GET['PayerID']);
} catch(Exception $e) {}
} catch (Exception $e) {
trigger_error('Something went horribly wrong.', E_USER_ERROR);
}
// Attempt to complete the transaction
if($finalise) {
if ($finalise) {
// Make the user premium
$expiration = Users::addUserPremium(Session::$userId, (2628000 * $_SESSION['premiumMonths']));
Users::updatePremiumMeta(Session::$userId);
Main::updatePremiumTracker(Session::$userId, ((float)Configuration::getConfig('premium_price_per_month') * $_SESSION['premiumMonths']), $currentUser->data['username'] .' bought premium for '. $_SESSION['premiumMonths'] .' month'. ($_SESSION['premiumMonths'] == 1 ? '' : 's') .'.');
Main::updatePremiumTracker(Session::$userId, ((float) Configuration::getConfig('premium_price_per_month') * $_SESSION['premiumMonths']), $currentUser->data['username'] . ' bought premium for ' . $_SESSION['premiumMonths'] . ' month' . ($_SESSION['premiumMonths'] == 1 ? '' : 's') . '.');
// Redirect to the complete
header('Location: '. $urls->format('SITE_PREMIUM') .'?mode=complete');
header('Location: ' . $urls->format('SITE_PREMIUM') . '?mode=complete');
exit;
}
}
header('Location: '. $urls->format('SITE_PREMIUM') .'?fail=true');
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
break;
case 'complete':
@ -108,15 +88,15 @@ if(isset($_REQUEST['mode']) && Users::checkLogin() && Permissions::check('SITE',
'page' => [
'expiration' => ($prem = Users::checkUserPremium(Session::$userId)[2]) !== null ? $prem : 0
'expiration' => ($prem = Users::checkUserPremium(Session::$userId)[2]) !== null ? $prem : 0,
]
],
], $renderData));
], $renderData));
break;
default:
header('Location: '. $urls->format('SITE_PREMIUM'));
header('Location: ' . $urls->format('SITE_PREMIUM'));
break;
}
@ -128,28 +108,26 @@ if(isset($_REQUEST['mode']) && Users::checkLogin() && Permissions::check('SITE',
}
// Premium tracker
if(isset($_GET['tracker'])) {
if (isset($_GET['tracker'])) {
$renderData['page'] = [
'currentPage' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
'premiumData' => ($_PREMIUM = Main::getPremiumTrackerData()),
'premiumTable' => array_chunk($_PREMIUM['table'], 20, true)
'currentPage' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
'premiumData' => ($_PREMIUM = Main::getPremiumTrackerData()),
'premiumTable' => array_chunk($_PREMIUM['table'], 20, true),
];
print Templates::render('main/supporttracker.tpl', $renderData);
exit;
}
// Set default variables
$renderData['page'] = [
'fail' => isset($_GET['fail']),
'price' => Configuration::getConfig('premium_price_per_month'),
'current' => $currentUser->checkPremium(),
'amount_max' => Configuration::getConfig('premium_amount_max')
'fail' => isset($_GET['fail']),
'price' => Configuration::getConfig('premium_price_per_month'),
'current' => $currentUser->checkPremium(),
'amount_max' => Configuration::getConfig('premium_amount_max'),
];

View file

@ -7,56 +7,52 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Get the forum's data
$forum = Forum::getForum(isset($_GET['f']) ? $_GET['f'] : 0);
// Check if the forum exists
if(!$forum) {
if (!$forum) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
'message' => 'The subforum you tried to access does not exist.'
'title' => 'Information',
'message' => 'The subforum you tried to access does not exist.',
];
// Print template
print Templates::render('global/information.tpl', $renderData);
exit;
}
// Check if the forum isn't a link
if($forum['forum']['forum_type'] === 2) {
if ($forum['forum']['forum_type'] === 2) {
// Set render data
$renderData['page'] = [
'title' => 'Information',
'message' => 'The forum you tried to access is a link. You\'re being redirected.',
'redirect' => $forum['forum']['forum_link']
'title' => 'Information',
'message' => 'The forum you tried to access is a link. You\'re being redirected.',
'redirect' => $forum['forum']['forum_link'],
];
// Print template
print Templates::render('global/information.tpl', $renderData);
exit;
}
$renderData['board'] = [
'forums' => [
$forum
$forum,
],
'topics' => Forum::getTopics($forum['forum']['forum_id']),
'viewforum' => true,
'viewtopic' => false
'viewtopic' => false,
];

View file

@ -7,25 +7,23 @@
namespace Sakura;
// Include components
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sakura.php';
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sakura.php';
// Attempt to get a topic
$topic = Forum::getTopic(isset($_GET['p']) ? Forum::getTopicIdFromPostId($_GET['p']) : (isset($_GET['t']) ? $_GET['t'] : 0));
// Check if the forum exists
if(!$topic) {
if (!$topic) {
// Set render data
$renderData['page'] = [
'message' => 'The topic you tried to access does not exist.'
'message' => 'The topic you tried to access does not exist.',
];
// Print template
print Templates::render('global/information.tpl', $renderData);
exit;
}
// Set additional render data
@ -36,7 +34,7 @@ $renderData = array_merge($renderData, $topic, [
'viewforum' => false,
'viewtopic' => true,
]
],
]);