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
_sakura/config/config.php
_sakura/config/config.ini
content/images/avatars/*
!content/images/avatars/.htaccess
@ -50,9 +49,10 @@ content/images/backgrounds/*
BingSiteAuth.xml
google*.html
main/logs/*
main/dev/*
content/data/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'),
(7, 0, '1,2,1,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`;

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",
"20150524",
"20150525",
"20150526"
"20150526",
"20150529"
]
@ -1155,6 +1156,55 @@
"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
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
if(is_array($local))
self::$_LCNF = $local;
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);
// Database
Database::init();
Database::init(Configuration::getLocalConfig('database', 'driver'));
// "Dynamic" Configuration
Configuration::initDB();
@ -36,7 +36,7 @@ class Main {
Templates::init(self::$_MANAGE_MODE ? Configuration::getConfig('manage_style') : Configuration::getConfig('site_style'));
// Assign servers file to whois class
Whois::setServers(Configuration::getLocalConfig('etc', 'whoisservers'));
Whois::setServers(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'whoisservers'));
// Markdown Parser
self::initMD();
@ -113,6 +113,7 @@ class Main {
// Truncate all previous outputs
ob_clean();
ob_end_clean();
// Die and display error message
die($error);
@ -364,7 +365,7 @@ class Main {
public static function checkCFIP($ip) {
// 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
$cfhosts = str_replace("\r\n", "\n", $cfhosts);
@ -490,7 +491,7 @@ class Main {
public static function getCountryName($code) {
// 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
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() {
// If the sock chat extensions are disabled return an empty array
if(!Configuration::getLocalConfig('sock', 'enable'))
if(!Configuration::getLocalConfig('sockchat', 'enabled'))
return [];
// 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;

View file

@ -10,21 +10,21 @@ class Users {
// Empty user template
public static $emptyUser = [
'id' => 0,
'username' => 'Deleted User',
'username_clean' => 'deleted user',
'username' => 'Sakura User',
'username_clean' => 'sakura user',
'password_hash' => '',
'password_salt' => '',
'password_algo' => 'nologin',
'password_iter' => 1000,
'password_chan' => 0,
'password_new' => '',
'email' => 'deleted@flashii.net',
'email' => 'sakura@localhost',
'rank_main' => 0,
'ranks' => '[0]',
'name_colour' => '',
'register_ip' => '127.0.0.1',
'last_ip' => '127.0.0.1',
'usertitle' => 'Non-existent user account',
'usertitle' => 'Internal fallback account',
'profile_md' => '',
'avatar_url' => '',
'background_url' => '',
@ -40,7 +40,7 @@ class Users {
// Empty rank template
public static $emptyRank = [
'id' => 0,
'rankname' => 'Non-existent Rank',
'rankname' => 'Sakura Rank',
'multi' => 0,
'colour' => '#444',
'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))
return [0, 'DEACTIVATED'];
return [0, 'NOT_ALLOWED'];
// Create a new session
$sessionKey = Session::newSession($user['id'], $remember);

View file

@ -9,47 +9,47 @@ use PDO;
use PDOException;
use PDOStatement;
class Database {
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 static $sql;
public $sql;
// Constructor
public static function init() {
function __construct() {
if(!extension_loaded('PDO')) {
// 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
self::initConnect(
$this->initConnect(
(
Configuration::getLocalConfig('db', 'unixsocket') ?
self::prepareSock(
Configuration::getLocalConfig('db', 'host'),
Configuration::getLocalConfig('db', 'database')
Configuration::getLocalConfig('database', 'unixsocket') ?
$this->prepareSock(
Configuration::getLocalConfig('database', 'host'),
Configuration::getLocalConfig('database', 'database')
) :
self::prepareHost(
Configuration::getLocalConfig('db', 'host'),
Configuration::getLocalConfig('db', 'database'),
$this->prepareHost(
Configuration::getLocalConfig('database', 'host'),
Configuration::getLocalConfig('database', 'database'),
(
Configuration::getLocalConfig('db', 'port') !== null ?
Configuration::getLocalConfig('db', 'port') :
Configuration::getLocalConfig('database', 'port') !== null ?
Configuration::getLocalConfig('database', 'port') :
3306
)
)
),
Configuration::getLocalConfig('db', 'username'),
Configuration::getLocalConfig('db', 'password')
Configuration::getLocalConfig('database', 'username'),
Configuration::getLocalConfig('database', 'password')
);
}
// 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;
@ -58,7 +58,7 @@ class Database {
}
// Unix Socket connection method prepare function
private static function prepareSock($dbHost, $dbName) {
private function prepareSock($dbHost, $dbName) {
$DSN = 'mysql:unix_socket=' . $dbHost . ';dbname=' . $dbName;
@ -67,11 +67,11 @@ class Database {
}
// Initialise connection using default PDO stuff
private static function initConnect($DSN, $dbUname, $dbPword) {
private function initConnect($DSN, $dbUname, $dbPword) {
try {
// 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 connection errors
trigger_error('SQL Driver: '. $e->getMessage(), E_USER_ERROR);
@ -82,10 +82,10 @@ class 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
$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(is_array($data)) {
@ -143,10 +143,11 @@ class Database {
$prepare .= ';';
// Actually prepare the preration
$query = self::$sql->prepare($prepare);
$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]);
@ -154,28 +155,22 @@ class Database {
unset($key);
unset($value);
}
}
// Execute the prepared statements with parameters bound
$query->execute();
// Do fetch or fetchAll
if($fetchAll)
$result = $query->fetchAll(PDO::FETCH_BOTH);
else
$result = $query->fetch(PDO::FETCH_BOTH);
// And return the output
return $result;
// Return the output
return $fetchAll ? $query->fetchAll(PDO::FETCH_BOTH) : $query->fetch(PDO::FETCH_BOTH);
}
// Insert data to database
public static 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('db', 'prefix')) . $table . '` ';
$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++) {
@ -193,7 +188,7 @@ class Database {
}
// Actually prepare the preration
$query = self::$sql->prepare($prepare);
$query = $this->sql->prepare($prepare);
// Bind those parameters
foreach($data as $key => $value) {
@ -214,10 +209,10 @@ class 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
$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
foreach($data as $key => $values) {
@ -232,7 +227,7 @@ class Database {
}
// 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
// Bind Set Clauses
@ -272,10 +267,10 @@ class 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
$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(is_array($data)) {
@ -293,7 +288,7 @@ class Database {
}
// Actually prepare the preration
$query = self::$sql->prepare($prepare);
$query = $this->sql->prepare($prepare);
// Bind those parameters
foreach($data as $key => $value) {

View file

@ -9,7 +9,7 @@
driver = mysql
; 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
; the path to the socket.
@ -22,7 +22,7 @@ port = 3306
username = sakura
; Password for the same purpose
password = password
password = "password"
; Database (not table) name used.
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
[sockchat]
; Set whether the Sock Chat extensions should be used or not
enabled = 1
enabled = true
; The table prefix used for Sock Chat
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
/*
* 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
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20150526');
define('SAKURA_VERSION', '20150529');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_VTYPE', 'Development');
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(-1);
// Start output buffering
ob_start();
// Include Configuration
require_once ROOT .'_sakura/config/config.php';
// 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/Templates.php';
require_once ROOT .'_sakura/components/Permissions.php';
require_once ROOT .'_sakura/components/Sessions.php';
require_once ROOT .'_sakura/components/Users.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/SockChat.php';
// Generate path to database driver
$_DBNGNPATH = ROOT .'_sakura/components/database/'. $sakuraConf['db']['driver'] .'.php';
// Include database driver
if(file_exists($_DBNGNPATH))
require_once $_DBNGNPATH;
else
die('<h1>Failed to load database driver.</h1>');
// Include database extensions
foreach(glob(ROOT .'_sakura/components/database/*.php') as $driver)
require_once($driver);
// Set Error handler
set_error_handler(array('Sakura\Main', 'errorHandler'));
// 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
$renderData = array(
$renderData = [
'sakura' => [
'version' => SAKURA_VERSION,
'vlabel' => SAKURA_VLABEL,
@ -67,6 +62,8 @@ $renderData = array(
'recaptcha_enable' => Configuration::getConfig('recaptcha'),
'resources' => '//'. Configuration::getLocalConfig('urls')['content'] .'/data/'. strtolower(Templates::$_TPL),
'disableregister' => 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'),
'requireactiveate' => Configuration::getConfig('require_activation'),
@ -80,11 +77,13 @@ $renderData = array(
'minusernamelength' => Configuration::getConfig('username_min_length'),
'maxusernamelength' => Configuration::getConfig('username_max_length')
],
'php' => [
'sessionid' => \session_id(),
'time' => \time(),
'self' => $_SERVER['PHP_SELF']
],
'user' => [
'checklogin' => Users::checkLogin(),
'session' => Session::$sessionId,
@ -92,4 +91,5 @@ $renderData = array(
'rank' => ($_init_rdata = Users::getRank($_init_udata['rank_main'])),
'colour' => ($_init_udata['name_colour'] == null ? $_init_rdata['colour'] : $_init_udata['name_colour'])
]
);
];

View file

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

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
# 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 ^index/?$ index.php
RewriteRule ^login/?$|logout?/?$|activate?/?$|register?/?$|forgotpassword?/?|authenticate?/?$ authenticate.php

View file

@ -95,7 +95,7 @@ if(isset($_REQUEST['mode'])) {
$messages = [
'USER_NOT_LOGIN' => 'What are you doing, you\'re not even logged in. GO AWAY!',
'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.',
'PASS_TOO_SHIT' => 'Your password is too weak, try adding some special characters.',
'PASS_NOT_MATCH' => 'Passwords do not match.',

View file

@ -37,6 +37,7 @@ if(isset($_GET['u'])) {
'data' => Users::getUserProfileData($_PROFILE_USER_DATA['id']),
'warnings' => Users::getWarnings($_PROFILE_USER_DATA['id'])
];
$renderData['page'] = [
'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'] ? [