privileged bread

This commit is contained in:
flash 2015-05-29 19:27:45 +00:00
parent 2b5aad27a4
commit ef45c2668d
25 changed files with 555 additions and 134 deletions

4
.gitignore vendored
View file

@ -41,7 +41,6 @@ local.properties
################# #################
errors.log errors.log
_sakura/config/config.php
_sakura/config/config.ini _sakura/config/config.ini
content/images/avatars/* content/images/avatars/*
!content/images/avatars/.htaccess !content/images/avatars/.htaccess
@ -50,9 +49,10 @@ content/images/backgrounds/*
BingSiteAuth.xml BingSiteAuth.xml
google*.html google*.html
main/logs/* main/logs/*
main/dev/*
content/data/misaki/* content/data/misaki/*
_sakura/templates/misaki/* _sakura/templates/misaki/*
_sakura/cache/*
!_sakura/cache/.htaccess
################# #################

View file

@ -285,7 +285,7 @@ INSERT INTO `sakura_sock_perms` (`rid`, `uid`, `perms`) VALUES
(6, 0, '1,0,0,0,0,0'), (6, 0, '1,0,0,0,0,0'),
(7, 0, '1,2,1,1,1,1'), (7, 0, '1,2,1,1,1,1'),
(8, 0, '1,1,0,1,1,1'), (8, 0, '1,1,0,1,1,1'),
(9, 0, '1,1,0,1,1,1'), (9, 0, '1,1,0,1,1,1')
DROP TABLE IF EXISTS `sakura_tenshi`; DROP TABLE IF EXISTS `sakura_tenshi`;

0
_sakura/.htaccess Normal file
View file

12
_sakura/cache/.htaccess vendored Normal file
View file

@ -0,0 +1,12 @@
# Disallow external connections
# Apache <= 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
deny from all
</IfModule>
# Apache 2.4 =>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

View file

@ -15,7 +15,8 @@
"20150523", "20150523",
"20150524", "20150524",
"20150525", "20150525",
"20150526" "20150526",
"20150529"
] ]
@ -1155,6 +1156,55 @@
"change": "Removed ybabstat (for now)." "change": "Removed ybabstat (for now)."
} }
],
"20150529": [
{
"type": "ADD",
"change": "Added beginning bits for the permissioning system."
},
{
"type": "UPD",
"change": "Altered details of the built in fallback user a bit."
},
{
"type": "FIX",
"change": "Fixed feedback redirect going to a deleted forum."
},
{
"type": "ADD",
"change": "Removed all jQuery dependencies in ybabstat."
},
{
"type": "UPD",
"change": "Changed database engine handling."
},
{
"type": "UPD",
"change": "Changed local configuration handling."
},
{
"type": "ADD",
"change": "Readded GZIP compression."
},
{
"type": "FIX",
"change": "Fix issue with GZIP compression in the error handler."
},
{
"type": "FIX",
"change": "Remove chat from the global permissions (for now) and restore the old permissions table."
},
{
"type": "ADD",
"change": "Add base for a novelty Mio template port."
},
{
"type": "ADD",
"change": "Added permission checking functions."
}
] ]
} }

View file

@ -14,11 +14,18 @@ class Configuration {
// Initialise configuration, does not contain database initialisation because explained below // 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))
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 // Check if $local is an array and then store it in $_LCNF
if(is_array($local)) if(is_array($local))
self::$_LCNF = $local; self::$_LCNF = $local;
else // Otherwise trigger an error else // Otherwise trigger an error
trigger_error('Failed to load local configuration!', E_USER_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);
} }

View file

@ -0,0 +1,56 @@
<?php
/*
* Database engine container
*/
namespace Sakura;
class Database {
// Database container
public static $_DATABASE;
// Initialisation function
public static function init($engine) {
// Make the engine class name lowercase
$engine = __NAMESPACE__ .'\\'. strtolower($engine);
// Check if the class exists
if(!class_exists($engine))
trigger_error('Failed to load database driver', E_USER_ERROR);
// Initialise SQL engine
self::$_DATABASE = new $engine;
}
// Fetch from database
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);
}
// Insert into database
public static function insert($table, $data, $prefix = null) {
return self::$_DATABASE->insert($table, $data, $prefix);
}
// Update in database
public static function update($table, $data, $prefix = null) {
return self::$_DATABASE->update($table, $data, $prefix);
}
// Delete from database
public static function delete($table, $data, $prefix = null) {
return self::$_DATABASE->delete($table, $data, $prefix);
}
}

View file

@ -21,7 +21,7 @@ class Main {
Configuration::init($config); Configuration::init($config);
// Database // Database
Database::init(); Database::init(Configuration::getLocalConfig('database', 'driver'));
// "Dynamic" Configuration // "Dynamic" Configuration
Configuration::initDB(); Configuration::initDB();
@ -36,7 +36,7 @@ class Main {
Templates::init(self::$_MANAGE_MODE ? Configuration::getConfig('manage_style') : Configuration::getConfig('site_style')); Templates::init(self::$_MANAGE_MODE ? Configuration::getConfig('manage_style') : Configuration::getConfig('site_style'));
// Assign servers file to whois class // Assign servers file to whois class
Whois::setServers(Configuration::getLocalConfig('etc', 'whoisservers')); Whois::setServers(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'whoisservers'));
// Markdown Parser // Markdown Parser
self::initMD(); self::initMD();
@ -113,6 +113,7 @@ class Main {
// Truncate all previous outputs // Truncate all previous outputs
ob_clean(); ob_clean();
ob_end_clean();
// Die and display error message // Die and display error message
die($error); die($error);
@ -364,7 +365,7 @@ class Main {
public static function checkCFIP($ip) { public static function checkCFIP($ip) {
// Get CloudFlare Subnet list // Get CloudFlare Subnet list
$cfhosts = file_get_contents(Configuration::getLocalConfig('etc', 'cfipv'. (self::ipVersion($ip)))); $cfhosts = file_get_contents(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'cfipv'. (self::ipVersion($ip))));
// Replace \r\n with \n // Replace \r\n with \n
$cfhosts = str_replace("\r\n", "\n", $cfhosts); $cfhosts = str_replace("\r\n", "\n", $cfhosts);
@ -490,7 +491,7 @@ class Main {
public static function getCountryName($code) { public static function getCountryName($code) {
// Parse JSON file // Parse JSON file
$iso3166 = json_decode(file_get_contents(Configuration::getLocalConfig('etc', 'iso3166')), true); $iso3166 = json_decode(file_get_contents(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'iso3166')), true);
// Check if key exists // Check if key exists
if(array_key_exists($code, $iso3166)) if(array_key_exists($code, $iso3166))

View file

@ -0,0 +1,160 @@
<?php
/*
* Permission Handler
*/
namespace Sakura;
class Permissions {
// Global permissions table
protected static $permissions = [
// Site permissions
'SITE' => [
'DEACTIVATED' => 1, // Is a user in this group deactivated
'USE_CHAT' => 2, // Can use the chatroom
'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
'CHANGE_DEFAULT_RANK' => 32768, // Can change their default rank
'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
],
// Forum permissions
'FORUM' => [
'USE_FORUM' => 1
],
// Site management permissions
'MANAGE' => [
'USE_MANAGE' => 1
]
];
// Checking if a user has the permissions to do a thing
public static function check($layer, $action, $perm) {
// Check if the permission layer and the permission itself exists
if(!array_key_exists($layer, self::$permissions) || !array_key_exists($action, self::$permission[$layer]))
return false;
// Perform the bitwise AND
if((bindec($perm) & self::$permission[$layer][$action]) != 0)
return true;
// Else just return false
return false;
}
// Get permission data of a rank from the database
public static function getRankPermissions($ranks) {
// Container array
$getRanks = [];
$perms = [];
// Get permission row for all ranks
foreach($ranks as $rank)
$getRanks[] = Database::fetch('permissions', false, ['rid' => [$rank, '='], 'uid' => [0 ,'=']]);
// Go over the permission data
foreach($getRanks as $rank) {
// Check if perms is empty
if(empty($perms)) {
// Store the data of the current rank in $perms
$perms = [
'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']
];
}
}
// Return the compiled permission strings
return $perms;
}
// Get permission data for a user
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'] ,'=']]);
// 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))
return $rankPerms;
// Split the inherit option things up
$inheritance = str_split($userPerms['rankinherit']);
// Override site permissions
if(!$inheritance[0])
$rankPerms['SITE'] = $userPerms['siteperms'];
// Override management permissions
if(!$inheritance[1])
$rankPerms['MANAGE'] = $userPerms['manageperms'];
// Override forum permissions
if(!$inheritance[2])
$rankPerms['FORUM'] = $userPerms['forumperms'];
// Return permissions
return $rankPerms;
}
}

View file

@ -129,11 +129,11 @@ class SockChat {
public static function getOnlineUsers() { public static function getOnlineUsers() {
// If the sock chat extensions are disabled return an empty array // If the sock chat extensions are disabled return an empty array
if(!Configuration::getLocalConfig('sock', 'enable')) if(!Configuration::getLocalConfig('sockchat', 'enabled'))
return []; return [];
// Get contents of the table // Get contents of the table
$sockUsers = Database::fetch('online_users', true, null, null, null, null, false, '*', Configuration::getLocalConfig('sock', 'sqlpref')); $sockUsers = Database::fetch('online_users', true, null, null, null, null, false, '*', Configuration::getLocalConfig('sockchat', 'prefix'));
return $sockUsers; return $sockUsers;

View file

@ -10,21 +10,21 @@ class Users {
// Empty user template // Empty user template
public static $emptyUser = [ public static $emptyUser = [
'id' => 0, 'id' => 0,
'username' => 'Deleted User', 'username' => 'Sakura User',
'username_clean' => 'deleted user', 'username_clean' => 'sakura user',
'password_hash' => '', 'password_hash' => '',
'password_salt' => '', 'password_salt' => '',
'password_algo' => 'nologin', 'password_algo' => 'nologin',
'password_iter' => 1000, 'password_iter' => 1000,
'password_chan' => 0, 'password_chan' => 0,
'password_new' => '', 'password_new' => '',
'email' => 'deleted@flashii.net', 'email' => 'sakura@localhost',
'rank_main' => 0, 'rank_main' => 0,
'ranks' => '[0]', 'ranks' => '[0]',
'name_colour' => '', 'name_colour' => '',
'register_ip' => '127.0.0.1', 'register_ip' => '127.0.0.1',
'last_ip' => '127.0.0.1', 'last_ip' => '127.0.0.1',
'usertitle' => 'Non-existent user account', 'usertitle' => 'Internal fallback account',
'profile_md' => '', 'profile_md' => '',
'avatar_url' => '', 'avatar_url' => '',
'background_url' => '', 'background_url' => '',
@ -40,7 +40,7 @@ class Users {
// Empty rank template // Empty rank template
public static $emptyRank = [ public static $emptyRank = [
'id' => 0, 'id' => 0,
'rankname' => 'Non-existent Rank', 'rankname' => 'Sakura Rank',
'multi' => 0, 'multi' => 0,
'colour' => '#444', 'colour' => '#444',
'description' => 'A hardcoded dummy rank for fallback.', 'description' => 'A hardcoded dummy rank for fallback.',
@ -134,9 +134,9 @@ class Users {
} }
// Check if the user is deactivated // Check if the user has the required privs to log in
if(self::checkIfUserHasRanks([0, 1], $user, true)) if(self::checkIfUserHasRanks([0, 1], $user, true))
return [0, 'DEACTIVATED']; return [0, 'NOT_ALLOWED'];
// Create a new session // Create a new session
$sessionKey = Session::newSession($user['id'], $remember); $sessionKey = Session::newSession($user['id'], $remember);

View file

@ -9,47 +9,47 @@ use PDO;
use PDOException; use PDOException;
use PDOStatement; use PDOStatement;
class Database { class MySQL {
// Variable that will contain the SQL connection // 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 // 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. // it sort of defeats the "dynamic database system" I want to go for.
public static $sql; public $sql;
// Constructor // Constructor
public static function init() { function __construct() {
if(!extension_loaded('PDO')) { if(!extension_loaded('PDO')) {
// Return error and die // Return error and die
trigger_error('<b>SQL Driver</b>: PDO extension not loaded.', E_USER_ERROR); trigger_error('PDO extension not loaded.', E_USER_ERROR);
} }
// Initialise connection // Initialise connection
self::initConnect( $this->initConnect(
( (
Configuration::getLocalConfig('db', 'unixsocket') ? Configuration::getLocalConfig('database', 'unixsocket') ?
self::prepareSock( $this->prepareSock(
Configuration::getLocalConfig('db', 'host'), Configuration::getLocalConfig('database', 'host'),
Configuration::getLocalConfig('db', 'database') Configuration::getLocalConfig('database', 'database')
) : ) :
self::prepareHost( $this->prepareHost(
Configuration::getLocalConfig('db', 'host'), Configuration::getLocalConfig('database', 'host'),
Configuration::getLocalConfig('db', 'database'), Configuration::getLocalConfig('database', 'database'),
( (
Configuration::getLocalConfig('db', 'port') !== null ? Configuration::getLocalConfig('database', 'port') !== null ?
Configuration::getLocalConfig('db', 'port') : Configuration::getLocalConfig('database', 'port') :
3306 3306
) )
) )
), ),
Configuration::getLocalConfig('db', 'username'), Configuration::getLocalConfig('database', 'username'),
Configuration::getLocalConfig('db', 'password') Configuration::getLocalConfig('database', 'password')
); );
} }
// Regular IP/Hostname connection method prepare function // Regular IP/Hostname connection method prepare function
private static 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;
@ -58,7 +58,7 @@ class Database {
} }
// Unix Socket connection method prepare function // Unix Socket connection method prepare function
private static function prepareSock($dbHost, $dbName) { private function prepareSock($dbHost, $dbName) {
$DSN = 'mysql:unix_socket=' . $dbHost . ';dbname=' . $dbName; $DSN = 'mysql:unix_socket=' . $dbHost . ';dbname=' . $dbName;
@ -67,11 +67,11 @@ class Database {
} }
// Initialise connection using default PDO stuff // Initialise connection using default PDO stuff
private static function initConnect($DSN, $dbUname, $dbPword) { private function initConnect($DSN, $dbUname, $dbPword) {
try { try {
// Connect to SQL server using PDO // Connect to SQL server using PDO
self::$sql = new PDO($DSN, $dbUname, $dbPword, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING)); $this->sql = new PDO($DSN, $dbUname, $dbPword, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
} catch(PDOException $e) { } catch(PDOException $e) {
// Catch connection errors // Catch connection errors
trigger_error('SQL Driver: '. $e->getMessage(), E_USER_ERROR); trigger_error('SQL Driver: '. $e->getMessage(), E_USER_ERROR);
@ -82,10 +82,10 @@ class Database {
} }
// Fetch array from database // Fetch array from database
public static 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) {
// Begin preparation of the statement // Begin preparation of the statement
$prepare = 'SELECT '. ($distinct ? 'DISTINCT ' : '') . ($column == '*' ? '' : '`') . $column . ($column == '*' ? '' : '`') .' FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('db', '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 $data is set and is an array continue
if(is_array($data)) { if(is_array($data)) {
@ -143,10 +143,11 @@ class Database {
$prepare .= ';'; $prepare .= ';';
// Actually prepare the preration // Actually prepare the preration
$query = self::$sql->prepare($prepare); $query = $this->sql->prepare($prepare);
// Bind those parameters if $data is an array that is // Bind those parameters if $data is an array that is
if(is_array($data)) { if(is_array($data)) {
foreach($data as $key => $value) { foreach($data as $key => $value) {
$query->bindParam(':'. $key, $value[0]); $query->bindParam(':'. $key, $value[0]);
@ -154,28 +155,22 @@ class Database {
unset($key); unset($key);
unset($value); unset($value);
} }
} }
// Execute the prepared statements with parameters bound // Execute the prepared statements with parameters bound
$query->execute(); $query->execute();
// Do fetch or fetchAll // Return the output
if($fetchAll) return $fetchAll ? $query->fetchAll(PDO::FETCH_BOTH) : $query->fetch(PDO::FETCH_BOTH);
$result = $query->fetchAll(PDO::FETCH_BOTH);
else
$result = $query->fetch(PDO::FETCH_BOTH);
// And return the output
return $result;
} }
// Insert data to database // Insert data to database
public static function insert($table, $data, $prefix = null) { public function insert($table, $data, $prefix = null) {
// Begin preparation of the statement // Begin preparation of the statement
$prepare = 'INSERT INTO `' . ($prefix ? $prefix : Configuration::getLocalConfig('db', 'prefix')) . $table . '` '; $prepare = 'INSERT INTO `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '` ';
// Run the foreach statement twice for (`stuff`) VALUES (:stuff) // Run the foreach statement twice for (`stuff`) VALUES (:stuff)
for($i = 0; $i < 2; $i++) { for($i = 0; $i < 2; $i++) {
@ -193,7 +188,7 @@ class Database {
} }
// Actually prepare the preration // Actually prepare the preration
$query = self::$sql->prepare($prepare); $query = $this->sql->prepare($prepare);
// Bind those parameters // Bind those parameters
foreach($data as $key => $value) { foreach($data as $key => $value) {
@ -214,10 +209,10 @@ class Database {
} }
// Update data in the database // Update data in the database
public static function update($table, $data, $prefix = null) { public function update($table, $data, $prefix = null) {
// Begin preparation of the statement // Begin preparation of the statement
$prepare = 'UPDATE `' . ($prefix ? $prefix : Configuration::getLocalConfig('db', 'prefix')) . $table . '`'; $prepare = 'UPDATE `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
// Run a foreach on $data and complete the statement // Run a foreach on $data and complete the statement
foreach($data as $key => $values) { foreach($data as $key => $values) {
@ -232,7 +227,7 @@ class Database {
} }
// Actually prepare the preration // Actually prepare the preration
$query = self::$sql->prepare($prepare); $query = $this->sql->prepare($prepare);
// Seperate the foreaches for the SET and WHERE clauses because it's fucking it up for some odd reason // Seperate the foreaches for the SET and WHERE clauses because it's fucking it up for some odd reason
// Bind Set Clauses // Bind Set Clauses
@ -272,10 +267,10 @@ class Database {
} }
// Delete data from the database // Delete data from the database
public static function delete($table, $data, $prefix = null) { public function delete($table, $data, $prefix = null) {
// Begin preparation of the statement // Begin preparation of the statement
$prepare = 'DELETE FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('db', 'prefix')) . $table . '`'; $prepare = 'DELETE FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('database', 'prefix')) . $table . '`';
// If $data is set and is an array continue // If $data is set and is an array continue
if(is_array($data)) { if(is_array($data)) {
@ -293,7 +288,7 @@ class Database {
} }
// Actually prepare the preration // Actually prepare the preration
$query = self::$sql->prepare($prepare); $query = $this->sql->prepare($prepare);
// Bind those parameters // Bind those parameters
foreach($data as $key => $value) { foreach($data as $key => $value) {

View file

@ -9,7 +9,7 @@
driver = mysql driver = mysql
; Use a Unix system socket (if the library supports it), doesn't work on Windows servers. ; Use a Unix system socket (if the library supports it), doesn't work on Windows servers.
unix_socket = 0 unixsocket = false
; URI to SQL server (usually localhost or 127.0.0.1) or in the case that you're using Unix sockets ; URI to SQL server (usually localhost or 127.0.0.1) or in the case that you're using Unix sockets
; the path to the socket. ; the path to the socket.
@ -22,7 +22,7 @@ port = 3306
username = sakura username = sakura
; Password for the same purpose ; Password for the same purpose
password = password password = "password"
; Database (not table) name used. ; Database (not table) name used.
database = sakura database = sakura
@ -65,7 +65,7 @@ iso3166 = config/iso3166.json
; These only work properly if Sock Chat uses the same database as the rest of Sakura ; These only work properly if Sock Chat uses the same database as the rest of Sakura
[sockchat] [sockchat]
; Set whether the Sock Chat extensions should be used or not ; Set whether the Sock Chat extensions should be used or not
enabled = 1 enabled = true
; The table prefix used for Sock Chat ; The table prefix used for Sock Chat
prefix = sock_ prefix = sock_

View file

@ -1,35 +0,0 @@
<?php
// Sakura Configuration
$sakuraConf = array(); // Define configuration array
// PDO Database Connection
$sakuraConf['db'] = array();
$sakuraConf['db']['driver'] = 'mysql'; // SQL Driver contained in the components/database folder
$sakuraConf['db']['unixsocket'] = false; // Use internal UNIX system sockets (would not work on Windows)
$sakuraConf['db']['host'] = 'localhost'; // SQL Hosts (or path to socket in the case that you're using them)
$sakuraConf['db']['port'] = 3306; // SQL Port (does nothing when UNIX sockets are used)
$sakuraConf['db']['username'] = 'sakura'; // Database authentication username
$sakuraConf['db']['password'] = 'password'; // Database authentication password
$sakuraConf['db']['database'] = 'sakura'; // Database name
$sakuraConf['db']['prefix'] = 'sakura_'; // Table Prefix
// URLs (for modularity)
$sakuraConf['urls'] = array();
$sakuraConf['urls']['main'] = 'flashii.net'; // Main site url
$sakuraConf['urls']['api'] = 'api.flashii.net'; // API url
$sakuraConf['urls']['content'] = 'cdn.flashii.net'; // Content directory url
$sakuraConf['urls']['chat'] = 'chat.flashii.net'; // Chat url
$sakuraConf['urls']['manage'] = 'manage.flashii.net'; // Moderator panel url
$sakuraConf['urls']['forum'] = 'forum.flashii.net'; // Forum url
// Errata
$sakuraConf['etc'] = array();
$sakuraConf['etc']['cfipv4'] = ROOT .'_sakura/config/cloudflare.ipv4'; // Cloudflare IPv4 subnets file
$sakuraConf['etc']['cfipv6'] = ROOT .'_sakura/config/cloudflare.ipv6'; // Cloudflare IPv6 subnets file
$sakuraConf['etc']['whoisservers'] = ROOT .'_sakura/config/whois.json'; // JSON with Whois servers
$sakuraConf['etc']['iso3166'] = ROOT .'_sakura/config/iso3166.json'; // JSON with country codes
// Sock Chat extensions
$sakuraConf['sock'] = array();
$sakuraConf['sock']['enable'] = true; // Ability to disable the extension in case you're using Sakura without Sock Chat, mind that this extension only works when using the same database
$sakuraConf['sock']['sqlpref'] = 'sock_'; // Sock Chat table prefixes

View file

@ -1,14 +1,14 @@
<?php <?php
/* /*
* Sakura Community Management System * Sakura Community Management System
* (c)Flashwave/Flashii.net 2013-2015 <http://flash.moe> * (c) 2013-2015 Flashwave <http://flash.moe> & Circlestorm <http://circlestorm.net>
*/ */
// Declare namespace // Declare namespace
namespace Sakura; namespace Sakura;
// Define Sakura version // Define Sakura version
define('SAKURA_VERSION', '20150526'); define('SAKURA_VERSION', '20150529');
define('SAKURA_VLABEL', 'Eminence'); define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_VTYPE', 'Development'); define('SAKURA_VTYPE', 'Development');
define('SAKURA_COLOUR', '#6C3082'); define('SAKURA_COLOUR', '#6C3082');
@ -19,18 +19,14 @@ define('ROOT', str_replace(basename(__DIR__), '', dirname(__FILE__)));
// Error Reporting: 0 for production and -1 for testing // Error Reporting: 0 for production and -1 for testing
error_reporting(-1); error_reporting(-1);
// Start output buffering
ob_start();
// Include Configuration
require_once ROOT .'_sakura/config/config.php';
// Include libraries // Include libraries
require_once ROOT .'_sakura/vendor/autoload.php'; require_once ROOT .'_sakura/vendor/autoload.php';
require_once ROOT .'_sakura/components/Main.php'; require_once ROOT .'_sakura/components/Main.php';
require_once ROOT .'_sakura/components/Hashing.php'; require_once ROOT .'_sakura/components/Hashing.php';
require_once ROOT .'_sakura/components/Configuration.php'; require_once ROOT .'_sakura/components/Configuration.php';
require_once ROOT .'_sakura/components/Database.php';
require_once ROOT .'_sakura/components/Templates.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/Sessions.php';
require_once ROOT .'_sakura/components/Users.php'; require_once ROOT .'_sakura/components/Users.php';
require_once ROOT .'_sakura/components/Forum.php'; require_once ROOT .'_sakura/components/Forum.php';
@ -38,23 +34,22 @@ require_once ROOT .'_sakura/components/Manage.php';
require_once ROOT .'_sakura/components/Whois.php'; require_once ROOT .'_sakura/components/Whois.php';
require_once ROOT .'_sakura/components/SockChat.php'; require_once ROOT .'_sakura/components/SockChat.php';
// Generate path to database driver // Include database extensions
$_DBNGNPATH = ROOT .'_sakura/components/database/'. $sakuraConf['db']['driver'] .'.php'; foreach(glob(ROOT .'_sakura/components/database/*.php') as $driver)
require_once($driver);
// Include database driver
if(file_exists($_DBNGNPATH))
require_once $_DBNGNPATH;
else
die('<h1>Failed to load database driver.</h1>');
// Set Error handler // Set Error handler
set_error_handler(array('Sakura\Main', 'errorHandler')); set_error_handler(array('Sakura\Main', 'errorHandler'));
// Initialise Flashii Class // Initialise Flashii Class
Main::init($sakuraConf); Main::init(ROOT .'_sakura/config/config.ini');
// Start output buffering
ob_start(Configuration::getConfig('use_gzip') ? 'ob_gzhandler' : null);
// Set base page rendering data // Set base page rendering data
$renderData = array( $renderData = [
'sakura' => [ 'sakura' => [
'version' => SAKURA_VERSION, 'version' => SAKURA_VERSION,
'vlabel' => SAKURA_VLABEL, 'vlabel' => SAKURA_VLABEL,
@ -67,6 +62,8 @@ $renderData = array(
'recaptcha_enable' => Configuration::getConfig('recaptcha'), 'recaptcha_enable' => Configuration::getConfig('recaptcha'),
'resources' => '//'. Configuration::getLocalConfig('urls')['content'] .'/data/'. strtolower(Templates::$_TPL), 'resources' => '//'. Configuration::getLocalConfig('urls')['content'] .'/data/'. strtolower(Templates::$_TPL),
'disableregister' => Configuration::getConfig('disable_registration'), 'disableregister' => Configuration::getConfig('disable_registration'),
'locksite' => Configuration::getConfig('lock_site'),
'locksitereason' => Configuration::getConfig('lock_site_reason'),
'lockauth' => Configuration::getConfig('lock_authentication'), 'lockauth' => Configuration::getConfig('lock_authentication'),
'requireregcodes' => Configuration::getConfig('require_registration_code'), 'requireregcodes' => Configuration::getConfig('require_registration_code'),
'requireactiveate' => Configuration::getConfig('require_activation'), 'requireactiveate' => Configuration::getConfig('require_activation'),
@ -80,11 +77,13 @@ $renderData = array(
'minusernamelength' => Configuration::getConfig('username_min_length'), 'minusernamelength' => Configuration::getConfig('username_min_length'),
'maxusernamelength' => Configuration::getConfig('username_max_length') 'maxusernamelength' => Configuration::getConfig('username_max_length')
], ],
'php' => [ 'php' => [
'sessionid' => \session_id(), 'sessionid' => \session_id(),
'time' => \time(), 'time' => \time(),
'self' => $_SERVER['PHP_SELF'] 'self' => $_SERVER['PHP_SELF']
], ],
'user' => [ 'user' => [
'checklogin' => Users::checkLogin(), 'checklogin' => Users::checkLogin(),
'session' => Session::$sessionId, 'session' => Session::$sessionId,
@ -92,4 +91,5 @@ $renderData = array(
'rank' => ($_init_rdata = Users::getRank($_init_udata['rank_main'])), 'rank' => ($_init_rdata = Users::getRank($_init_udata['rank_main'])),
'colour' => ($_init_udata['name_colour'] == null ? $_init_rdata['colour'] : $_init_udata['name_colour']) 'colour' => ($_init_udata['name_colour'] == null ? $_init_rdata['colour'] : $_init_udata['name_colour'])
] ]
);
];

View file

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Flashii Internal Error</title> <title>Sakura Internal Error</title>
<style type="text/css"> <style type="text/css">
body { body {
margin: 0; margin: 0;
@ -11,25 +11,25 @@
color: #000; color: #000;
font: 12px/20px Verdana, Arial, Helvetica, sans-serif; font: 12px/20px Verdana, Arial, Helvetica, sans-serif;
} }
h1 { h1 {
font-weight: 100; font-weight: 100;
background: #CAA; background: #CAA;
padding: 8px 5px 10px; padding: 8px 5px 10px;
margin: 0; margin: 0;
} }
.container { .container {
border: 1px solid #CAA; border: 1px solid #CAA;
margin: 10px; margin: 10px;
background: #FFF; background: #FFF;
box-shadow: 2px 2px 1em #888; box-shadow: 2px 2px 1em #888;
} }
.container .inner { .container .inner {
padding: 0px 10px; padding: 0px 10px;
} }
.container .inner .error { .container .inner .error {
background: #555; background: #555;
color: #EEE; color: #EEE;
@ -38,22 +38,22 @@
text-shadow: 0px 1px 1px #888; text-shadow: 0px 1px 1px #888;
font-family: monospace; font-family: monospace;
} }
.container .contact { .container .contact {
border-top: 1px solid #CAA; border-top: 1px solid #CAA;
font-size: x-small; font-size: x-small;
padding: 0px 5px 1px; padding: 0px 5px 1px;
} }
a { a {
color: #77E; color: #77E;
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
text-decoration: underline; text-decoration: underline;
} }
a:active { a:active {
color: #E77; color: #E77;
} }

View file

@ -0,0 +1,5 @@
{% if newsPosts|length > 1 %}<h3 class="miotitle" id="{{ newsPost.id }}">{{ newsPost.title }} by <a href="/u/{{ newsPost.uid }}" style="text-decoration: none !important; color: {{ newsPost.rdata.colour }} !important;">{{ newsPost.udata.username }}</a> - {{ newsPost.date|date("D Y-m-d H:i:s T") }}<span class="permalink"><a href="/news#{{ newsPost.id }}" title="Permalink">#</a> <a href="/news/{{ newsPost.id }}" title="Direct Link">@</a></span></h3>{% endif %}
<div class="postcontent">
{{ newsPost.parsed|raw }}
</div>
<br />

View file

@ -0,0 +1,17 @@
<div class="navbar">
<ul>
<li class="first current"><a href="//{{ sakura.urls.main }}/">Home</a></li>
<li class="notcurrent"><a href="//{{ sakura.urls.main }}/news">News</a></li>
<li class="notcurrent"><a href="//{{ sakura.urls.chat }}/">Chat</a></li>
<li class="notcurrent"><a href="//{{ sakura.urls.main }}/members">Members</a></li>
<li class="notcurrent"><a href="//{{ sakura.urls.main }}/donate">Donate</a></li>
<li class="notcurrent"><a href="//status.flashii.net/">Status</a></li>
</ul>
</div>
<div class="copyright">
<div>Copyright &copy; 2013-2015 <a href="//flash.moe/" target="_blank">Flashwave</a> &amp; <a href="//circlestorm.net/" target="_blank">Circlestorm</a>, <a href="//{{ sakura.urls.main }}/credits">et al</a>.</div>
<div><a href="//{{ sakura.urls.main }}/r/terms">Terms of Service</a> | <a href="//{{ sakura.urls.main }}/contact">Contact</a> | <a href="//{{ sakura.urls.main }}/faq">FAQ</a> | <a href="//{{ sakura.urls.main }}/feedback">Feedback</a> | <a href="//{{ sakura.urls.main }}/r/rules">Rules</a> | <a href="//{{ sakura.urls.main }}/changelog">Changelog</a></div>
</div>
<br />
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<!-- META -->
<meta charset="{{ sakura.charset }}" />
<title>{{ page.title }}</title>
<meta name="description" content="{{ sakura.sitedesc }}" />
<meta name="keywords" content="{{ sakura.sitetags }}" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
{% if page.redirect %}
<meta http-equiv="refresh" content="3; URL={{ page.redirect }}" />
{% endif %}
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="{{ sakura.resources }}/css/mio.css" />
{% if page.style %}
<style type="text/css">
{% for element,properties in page.style %}
{{ element|raw }} {
{% for property,value in properties %}
{{ property|raw }}: {{ value|raw }};
{% endfor %}
}
{% endfor %}
</style>
{% endif %}
<!-- JS -->
<script type="text/javascript" src="{{ sakura.resources }}/js/mio.js"></script>
</head>
<body>
<div class="flashii-bar">
<a href="//{{ sakura.urls.main }}/login"<!-- onclick="flashii_login(true);"-->Login</a> |
<a href="//{{ sakura.urls.main }}/register">Register</a>
</div>
<a href="//{{ sakura.urls.main }}/">
<img class="logo" src="//{{ sakura.urls.content }}/pixel.png" alt="{{ sakura.sitename }}" />
</a>
<br />

View file

@ -0,0 +1,36 @@
{% include 'global/header.tpl' %}
<div class="mioboards">
<h3 class="miotitle" style="margin: 0;">Welcome!</h3>
<br />
Welcome to Flashii! This is a site for a bunch of friends to hang out, nothing special.<br />Anyone is pretty much welcome to register so why not have a go?
<br />
<br />
<a class="registerbutton" href="//{{ sakura.urls.main }}/register">Register!</a>
<a class="loginbutton" href="//{{ sakura.urls.main }}/login">Login</a>
</div>
<div class="mioblog">
<h3 class="miotitle" style="margin: 0;">Latest News Posts<span class="windowbutton-container" onclick="hidePageSection('latestnewsposts',1);"><img class="minbutton" src="//{{ sakura.urls.content }}/pixel.png" alt="_"></span></h3>
<div class="mioboxcontent sub" style="margin: 0;">
{% for newsPost in newsPosts %}
{% include 'elements/newsPost.tpl' %}
{% endfor %}
</div>
</div>
<div class="mioblog">
<h3 class="miotitle" style="margin: 0;">Statistics<span class="windowbutton-container" onclick="hidePageSection('sitestatistics',1);"><img class="minbutton" src="//{{ sakura.urls.content }}/pixel.png" alt="_"></span></h3>
<div class="mioboxcontent sub" style="margin: 0;">
<table class="miotable" style="text-align:center;">
<tbody>
<tr>
<td style="width:50%;">We have {{ stats.userCount }} registered users.</td>
<td>Our newest member is <a href="/u/{{ stats.newestUser.id }}">{{ stats.newestUser.username }}</a>.</td>
</tr>
<tr>
<td>It has been {{ stats.lastRegDate }} since the last user registered.</td>
<td>{{ stats.chatOnline }} in chat right now.</td>
</tr>
</tbody>
</table>
</div>
</div>
{% include 'global/footer.tpl' %}

View file

@ -23,7 +23,7 @@ img.logo {
height: 150px; height: 150px;
width: 450px; width: 450px;
border: 0px; border: 0px;
background: url('//cdn.flashii.net/img/logo.png') no-repeat scroll left top transparent; background: url('../images/logo.png') no-repeat scroll left top transparent;
background-size: cover; background-size: cover;
} }
@ -424,7 +424,7 @@ div.ucp_avatar_cont {
height: 23px; height: 23px;
width: 23px; width: 23px;
border: 0px; border: 0px;
background: url('//cdn.flashii.net/img/window-sprite.png') no-repeat scroll 0px 0px transparent; background: url('../images/window-sprite.png') no-repeat scroll 0px 0px transparent;
} }
.maxbutton { .maxbutton {
@ -432,7 +432,7 @@ div.ucp_avatar_cont {
height: 23px; height: 23px;
width: 23px; width: 23px;
border: 0px; border: 0px;
background: url('//cdn.flashii.net/img/window-sprite.png') no-repeat scroll 0px -23px transparent; background: url('../images/window-sprite.png') no-repeat scroll 0px -23px transparent;
} }
.minbutton { .minbutton {
@ -440,7 +440,7 @@ div.ucp_avatar_cont {
height: 23px; height: 23px;
width: 23px; width: 23px;
border: 0px; border: 0px;
background: url('//cdn.flashii.net/img/window-sprite.png') no-repeat scroll 0px -46px transparent; background: url('../images/window-sprite.png') no-repeat scroll 0px -46px transparent;
} }
.donate-btn { .donate-btn {
@ -448,7 +448,7 @@ div.ucp_avatar_cont {
height: 26px; height: 26px;
width: 90px; width: 90px;
border: 0px; border: 0px;
background: url('//cdn.flashii.net/img/donate-btn.png') no-repeat scroll 0px 0px transparent; background: url('../images/donate-btn.png') no-repeat scroll 0px 0px transparent;
} }
div.topLeftBar { div.topLeftBar {

View file

@ -0,0 +1,79 @@
var illuminati = [];
var startTime = (new Date()).getTime();
function hideYourMind(conflictions) {
var twoThousandTwelveIsTheYearWeAscendToSpaceRobots = conflictions.keyCode;
illuminati.push(twoThousandTwelveIsTheYearWeAscendToSpaceRobots);
if(illuminati[0] == 68 && illuminati[1] == 73 && illuminati[2] == 67 && illuminati[3] == 75 && illuminati[4] == 83) {
var dicksAre = document.createElement('audio');
var forMyFriends = document.createElement('source');
var whenTheyCome = document.createElement('source');
forMyFriends.setAttribute('type', 'audio/mp3');
whenTheyCome.setAttribute('type', 'audio/ogg');
forMyFriends.setAttribute('src', '//' + sakuraVars.urls.content + '/sounds/dicks.mp3');
whenTheyCome.setAttribute('src', '//' + sakuraVars.urls.content + '/sounds/dicks.ogg');
dicksAre.appendChild(forMyFriends);
dicksAre.appendChild(whenTheyCome);
var toMyHouse = dicksAre;
toMyHouse.play();
illuminati = [];
}
if(illuminati[0] == 77 && illuminati[1] == 69 && illuminati[2] == 87 && illuminati[3] == 79 && illuminati[4] == 87) {
var noklz = document.createElement('audio');
var von = document.createElement('source');
var schnitzel = document.createElement('source');
von.setAttribute('type', 'audio/mp3');
schnitzel.setAttribute('type', 'audio/ogg');
von.setAttribute('src', '//' + sakuraVars.urls.content + '/sounds/mewow.mp3');
schnitzel.setAttribute('src', '//' + sakuraVars.urls.content + '/sounds/mewow.ogg');
noklz.appendChild(von);
noklz.appendChild(schnitzel);
noklz.play();
document.body.style.animation = 'spin 5s infinite linear';
illuminati = [];
}
if(illuminati[0] == 83 && illuminati[1] == 79 && illuminati[2] == 67 && illuminati[3] == 75 && illuminati[4] == 67 && illuminati[5] == 72 && illuminati[6] == 65 && illuminati[7] == 84) {
setInterval("twoThousandSixteenIsTheYearWePhysicallyMergeWithCats();", 17);
illuminati = [];
}
}
function twoThousandSixteenIsTheYearWePhysicallyMergeWithCats() {
var diff = (new Date()).getTime() - startTime;
var vals = [-7 * 1 / Math.cos((diff / 500) * (.85 * Math.PI)), -7 * Math.tan((diff / 250) * (.85 * Math.PI))];
document.body.style.position = 'absolute';
document.body.style.left = vals[0] + 'px';
document.body.style.top = vals[1] + 'px';
document.body.style.fontSize = vals[0] + 'px';
}
document.addEventListener("onkeydown", hideYourMind, false);
document.addEventListener("keydown", hideYourMind, false);

View file

@ -14,7 +14,7 @@ RewriteBase /
Options +FollowSymLinks -Indexes Options +FollowSymLinks -Indexes
# Rewrite Rules # Rewrite Rules
RewriteRule ^feedback/?$ http://forum.flash.moe/viewforum.php?f=22 RewriteRule ^feedback/?$ https://github.com/circlestorm/Sakura/issues
RewriteRule ^credits/?$ credits.php RewriteRule ^credits/?$ credits.php
RewriteRule ^index/?$ index.php RewriteRule ^index/?$ index.php
RewriteRule ^login/?$|logout?/?$|activate?/?$|register?/?$|forgotpassword?/?|authenticate?/?$ authenticate.php RewriteRule ^login/?$|logout?/?$|activate?/?$|register?/?$|forgotpassword?/?|authenticate?/?$ authenticate.php

View file

@ -95,7 +95,7 @@ if(isset($_REQUEST['mode'])) {
$messages = [ $messages = [
'USER_NOT_LOGIN' => 'What are you doing, you\'re not even logged in. GO AWAY!', 'USER_NOT_LOGIN' => 'What are you doing, you\'re not even logged in. GO AWAY!',
'INCORRECT_PASSWORD' => 'The password you entered was invalid.', 'INCORRECT_PASSWORD' => 'The password you entered was invalid.',
'DEACTIVATED' => 'Your account is deactivated.', 'NOT_ALLOWED' => 'Your account does not have the required permissions to log in.',
'NO_LOGIN' => 'Logging into this account is disabled.', 'NO_LOGIN' => 'Logging into this account is disabled.',
'PASS_TOO_SHIT' => 'Your password 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.', 'PASS_NOT_MATCH' => 'Passwords do not match.',

View file

@ -37,6 +37,7 @@ if(isset($_GET['u'])) {
'data' => Users::getUserProfileData($_PROFILE_USER_DATA['id']), 'data' => Users::getUserProfileData($_PROFILE_USER_DATA['id']),
'warnings' => Users::getWarnings($_PROFILE_USER_DATA['id']) 'warnings' => Users::getWarnings($_PROFILE_USER_DATA['id'])
]; ];
$renderData['page'] = [ $renderData['page'] = [
'title' => ($_PROFILE_USER_DATA['id'] < 1 || $_PROFILE_USER_DATA['password_algo'] == 'nologin' ? 'User not found!' : 'Profile of '. $_PROFILE_USER_DATA['username']), 'title' => ($_PROFILE_USER_DATA['id'] < 1 || $_PROFILE_USER_DATA['password_algo'] == 'nologin' ? 'User not found!' : 'Profile of '. $_PROFILE_USER_DATA['username']),
'style' => ($_PROFILE_USER_DATA['background_url'] ? [ 'style' => ($_PROFILE_USER_DATA['background_url'] ? [