diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index bc4cd82..67557bf 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -4,12 +4,12 @@ This is a list of people who have contributed to Sakura and also a list of the l
## People
-| Name | Contribution |
-| ---- | ------------ |
-| Flashwave | Project leader and main developer. |
-| MallocNull | Internal advice and pointing out my (Flashwave) stupidity. |
-| kamilrakowski | Providing a huge pile of security advice and fixes. |
-| RandomGuy | Mostly security advice as well. |
+| Name | Contribution |
+| ------------- | ---------------------------------------------------------- |
+| Flashwave | Project leader and main developer. |
+| MallocNull | Internal advice and pointing out my (Flashwave) stupidity. |
+| kamilrakowski | Providing a huge pile of security advice and fixes. |
+| RandomGuy | Mostly security advice as well. |
## Libraries
diff --git a/_developer_data/Sockura.php b/_developer_data/Sockura.php
index 1c59006..625ea5a 100644
--- a/_developer_data/Sockura.php
+++ b/_developer_data/Sockura.php
@@ -7,8 +7,11 @@
// Filesystem path to the _sakura folder WITHOUT an ending /
// This can also be set before an include of this file in case
// you're using git to keep in sync and don't want conflicts
-if(!isset($sockSakuraPath))
- $sockSakuraPath = '';
+if(!isset($sockSakuraPath)) {
+
+ $sockSakuraPath = '';
+
+}
/* * * DON'T EDIT ANYTHING BELOW THIS LINE * * */
@@ -18,7 +21,8 @@ require_once $sockSakuraPath .'/sakura.php';
use sockchat\Auth;
use Sakura\Session;
use Sakura\Users;
-use Sakura\SockChat;
+use Sakura\Permissions;
+use Sakura\User;
if(Auth::getPageType() == AUTH_FETCH) {
@@ -29,9 +33,12 @@ if(Auth::getPageType() == AUTH_FETCH) {
Auth::AppendArguments([Session::$userId, Session::$sessionId]);
Auth::Accept();
- } else
+ } else {
+
Auth::Deny();
+ }
+
} else {
// Get arguments
@@ -41,12 +48,8 @@ if(Auth::getPageType() == AUTH_FETCH) {
// Check if session is active else deny
if(Session::checkSession($uid, $sid)) {
- // Get user and rank data
- $user = Users::getUser($uid);
- $rank = Users::getRank($user['rank_main']);
-
- // Deny group and user id 0
- if($user['id'] == 0 || $rank['id'] == 0 || $user['password_algo'] == 'nologin') {
+ // Check if they can access the chat
+ if(Permissions::check('SITE', 'DEACTIVATED', $uid, 1) && Permissions::check('SITE', 'RESTRICTED', $uid, 1)) {
Auth::Deny();
Auth::Serve();
@@ -54,39 +57,35 @@ if(Auth::getPageType() == AUTH_FETCH) {
}
+ // Create a user object
+ $user = new User($uid);
+
// Set the user's data
Auth::SetUserData(
- $user['id'],
- $user['username'],
- $user['name_colour'] == null ? $rank['colour'] : $user['name_colour']
+ $user->data['id'],
+ $user->data['username'],
+ $user->colour()
);
- // Get the user's permissions
- $perms = SockChat::getUserPermissions($user['id']);
-
- // Check if they can access the chat
- if(!$perms['access']) {
-
- Auth::Deny();
- Auth::Serve();
- exit;
-
- }
-
// Set the common permissions
Auth::SetCommonPermissions(
- $perms['rank'],
- $perms['type'],
- $perms['logs'],
- $perms['nick'],
- $perms['channel']
+ 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
+ )
);
Auth::Accept();
- } else
+ } else {
+
Auth::Deny();
+ }
+
}
// Serve the authentication data
diff --git a/_developer_data/structure.sql b/_developer_data/structure.sql
index 498fdd2..4c70568 100644
--- a/_developer_data/structure.sql
+++ b/_developer_data/structure.sql
@@ -5,8 +5,6 @@ SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
-DROP DATABASE IF EXISTS `sakura-development`;
-CREATE DATABASE `sakura-development` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */;
USE `sakura-development`;
DROP TABLE IF EXISTS `sakura_actioncodes`;
@@ -17,7 +15,7 @@ CREATE TABLE `sakura_actioncodes` (
`actkey` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'The URL key for using this code.',
`instruction` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Things the backend should do upon using this code',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_apikeys`;
@@ -54,7 +52,7 @@ CREATE TABLE `sakura_bbcodes` (
`description` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'Description of what this does.',
`on_posting` tinyint(1) unsigned NOT NULL COMMENT 'Set if this bbcode is displayed on the posting page.',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `sakura_bbcodes` (`id`, `regex`, `replace`, `title`, `description`, `on_posting`) VALUES
(1, '/\\[b\\](.*?)\\[\\/b\\]/is', '$1', 'Bold', 'Make text bold. Usage: [b]text[/b].', 1),
@@ -65,8 +63,7 @@ INSERT INTO `sakura_bbcodes` (`id`, `regex`, `replace`, `title`, `description`,
(6, '/\\[url=([a-zA-Z0-9\\.\\$\\-\\_\\.\\+\\*\\!\\\'\\(\\)\\/\\:\\#]+)\\](.*?)\\[\\/url\\]/is', '$2', 'Link', 'Embed a URL. Usage: [url=http://google.com]Link to google![/url]', 0),
(7, '/\\[url\\]([a-zA-Z0-9\\.\\$\\-\\_\\.\\+\\*\\!\\\'\\(\\)\\/\\:\\#]+)\\[\\/url\\]/is', '$1', 'Link', 'Make a link clickable (if the automatic algorithm doesn\'t do it already). Usage: [url]http://google.com[/url]', 1),
(8, '/\\[quote\\=\\\"(.+)\\\"\\](.+)\\[\\/quote]/is', '
', 'Quote', 'Quote a user\'s post. Usage: [quote=Flashwave]nookls is pretty[/quote]', 0),
-(9, '/\\[quote\\](.+)\\[\\/quote]/is', '', 'Quote', 'Quote a user\'s post. Usage: [quote]nookls is pretty[/quote]', 1)
-ON DUPLICATE KEY UPDATE `id` = VALUES(`id`), `regex` = VALUES(`regex`), `replace` = VALUES(`replace`), `title` = VALUES(`title`), `description` = VALUES(`description`), `on_posting` = VALUES(`on_posting`);
+(9, '/\\[quote\\](.+)\\[\\/quote]/is', '', 'Quote', 'Quote a user\'s post. Usage: [quote]nookls is pretty[/quote]', 1);
DROP TABLE IF EXISTS `sakura_config`;
CREATE TABLE `sakura_config` (
@@ -83,15 +80,15 @@ INSERT INTO `sakura_config` (`config_name`, `config_value`) VALUES
('cookie_path', '/'),
('site_style', 'yuuno'),
('manage_style', 'broomcloset'),
-('smtp_server', 'smtp-mail.outlook.com'),
-('smtp_auth', '1'),
-('smtp_secure', 'tls'),
-('smtp_port', '587'),
-('smtp_username', 'flashii@outlook.com'),
+('smtp_server', ''),
+('smtp_auth', ''),
+('smtp_secure', ''),
+('smtp_port', ''),
+('smtp_username', ''),
('smtp_password', ''),
('smtp_replyto_mail', 'admin@flashii.net'),
('smtp_replyto_name', 'Flashwave'),
-('smtp_from_email', 'flashii@outlook.com'),
+('smtp_from_email', ''),
('smtp_from_name', 'Flashii Noreply'),
('sitename', 'Cutting Edgii'),
('recaptcha', '0'),
@@ -117,9 +114,6 @@ INSERT INTO `sakura_config` (`config_name`, `config_value`) VALUES
('premium_amount_max', '24'),
('alumni_rank_id', '9'),
('url_main', 'flashii.test'),
-('disqus_shortname', 'flashii'),
-('disqus_api_key', ''),
-('disqus_api_secret', ''),
('front_page_news_posts', '3'),
('date_format', 'D Y-m-d H:i:s T'),
('news_posts_per_page', '3'),
@@ -131,9 +125,6 @@ INSERT INTO `sakura_config` (`config_name`, `config_value`) VALUES
('url_api', 'api.flashii.test'),
('content_path', '/content'),
('user_uploads', 'uploads'),
-('no_avatar_img', 'main/content/images/no-av.png'),
-('deactivated_avatar_img', 'main/content/images/deactivated-av.png'),
-('banned_avatar_img', 'main/content/images/banned-av.png'),
('no_background_img', 'main/content/pixel.png'),
('no_header_img', 'main/content/images/triangles.png'),
('pixel_img', 'main/content/pixel.png'),
@@ -142,8 +133,13 @@ INSERT INTO `sakura_config` (`config_name`, `config_value`) VALUES
('background_max_height', '1440'),
('background_min_height', '16'),
('background_min_width', '16'),
-('max_online_time', '500')
-ON DUPLICATE KEY UPDATE `config_name` = VALUES(`config_name`), `config_value` = VALUES(`config_value`);
+('max_online_time', '500'),
+('no_avatar_img', 'main/content/data/{{ TPL }}/images/no-av.png'),
+('deactivated_avatar_img', 'main/content/data/{{ TPL }}/images/deactivated-av.png'),
+('banned_avatar_img', 'main/content/data/{{ TPL }}/images/banned-av.png'),
+('session_check', '2'),
+('url_rewrite', '1'),
+('members_per_page', '30');
DROP TABLE IF EXISTS `sakura_emoticons`;
CREATE TABLE `sakura_emoticons` (
@@ -189,8 +185,7 @@ INSERT INTO `sakura_emoticons` (`emote_string`, `emote_path`) VALUES
(':wtf:', '/content/images/emoticons/wtf.gif'),
(':sleep:', '/content/images/emoticons/zzz.gif'),
(':what:', '/content/images/emoticons/what.png'),
-(':smug:', '/content/images/emoticons/smug.png')
-ON DUPLICATE KEY UPDATE `emote_string` = VALUES(`emote_string`), `emote_path` = VALUES(`emote_path`);
+(':smug:', '/content/images/emoticons/smug.png');
DROP TABLE IF EXISTS `sakura_faq`;
CREATE TABLE `sakura_faq` (
@@ -199,7 +194,7 @@ CREATE TABLE `sakura_faq` (
`question` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'The question.',
`answer` text COLLATE utf8_bin NOT NULL COMMENT 'The answer.',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_forums`;
@@ -212,7 +207,7 @@ CREATE TABLE `sakura_forums` (
`forum_type` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT 'Forum type, 0 for regular board, 1 for category and 2 for link.',
`forum_icon` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Display icon for the forum.',
PRIMARY KEY (`forum_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_friends`;
@@ -265,18 +260,19 @@ CREATE TABLE `sakura_messages` (
`subject` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Title of the message',
`content` text COLLATE utf8_bin NOT NULL COMMENT 'Contents of the message.',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_news`;
CREATE TABLE `sakura_news` (
- `id` bigint(128) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Automatically generated ID by MySQL for management.',
- `uid` bigint(128) unsigned NOT NULL COMMENT 'ID of user who posted this news message.',
- `date` int(64) unsigned NOT NULL COMMENT 'News post timestamp.',
+ `id` bigint(255) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Automatically generated ID by MySQL for management.',
+ `category` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Category ID.',
+ `uid` bigint(255) unsigned NOT NULL COMMENT 'ID of user who posted this news message.',
+ `date` int(11) unsigned NOT NULL COMMENT 'News post timestamp.',
`title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Title of the post.',
`content` text COLLATE utf8_bin NOT NULL COMMENT 'Contents of the post',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_notifications`;
@@ -294,7 +290,7 @@ CREATE TABLE `sakura_notifications` (
PRIMARY KEY (`id`),
KEY `uid` (`uid`),
CONSTRAINT `sakura_notifications_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `sakura_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_optionfields`;
@@ -308,8 +304,9 @@ CREATE TABLE `sakura_optionfields` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `sakura_optionfields` (`id`, `name`, `description`, `formtype`, `require_perm`) VALUES
-('profileBackgroundSiteWide', 'Display profile background site wide', 'This will make the profile background you set on your profile appear on the entire site (except on other profiles).', 'checkbox', 'CREATE_BACKGROUND')
-ON DUPLICATE KEY UPDATE `id` = VALUES(`id`), `name` = VALUES(`name`), `description` = VALUES(`description`), `formtype` = VALUES(`formtype`), `require_perm` = VALUES(`require_perm`);
+('disableProfileParallax', 'Disable Parallaxing', 'This will stop your background from responding to your mouse movement, this will only affect your background.', 'checkbox', 'CHANGE_BACKGROUND'),
+('profileBackgroundSiteWide', 'Display profile background site wide', 'This will make the profile background you set on your profile appear on the entire site (except on other profiles).', 'checkbox', 'CREATE_BACKGROUND'),
+('useMisaki', 'Use the testing style', 'This will make the site use the new Misaki style instead of Yuuno.', 'checkbox', 'ALTER_PROFILE');
DROP TABLE IF EXISTS `sakura_permissions`;
CREATE TABLE `sakura_permissions` (
@@ -322,16 +319,16 @@ CREATE TABLE `sakura_permissions` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `sakura_permissions` (`rid`, `uid`, `siteperms`, `manageperms`, `forumperms`, `rankinherit`) VALUES
-(1, 0, '0000000000000000000000000001', '000', '1', '000'),
-(2, 0, '0000111111111100111101101100', '000', '1', '000'),
-(3, 0, '0001111111111111111111111100', '011', '1', '000'),
-(4, 0, '0111111111111111111111111100', '111', '1', '000'),
-(5, 0, '0001111111111111111111111100', '101', '1', '000'),
-(6, 0, '0000111111111100111101101100', '000', '0', '000'),
-(7, 0, '0001111111111111111111111100', '011', '1', '000'),
-(8, 0, '0001111111111111111111111100', '000', '1', '000'),
-(9, 0, '0001111111111111111111111100', '000', '1', '000')
-ON DUPLICATE KEY UPDATE `rid` = VALUES(`rid`), `uid` = VALUES(`uid`), `siteperms` = VALUES(`siteperms`), `manageperms` = VALUES(`manageperms`), `forumperms` = VALUES(`forumperms`), `rankinherit` = VALUES(`rankinherit`);
+(1, 0, '0000000000000000000000000001', '00', '0', '000'),
+(2, 0, '0000111111111100111101101100', '00', '1', '000'),
+(3, 0, '0001111111111111111111111100', '11', '1', '000'),
+(4, 0, '1111111111111111111111111100', '11', '1', '000'),
+(5, 0, '0001111111111111111111111100', '11', '1', '000'),
+(6, 0, '0000111111111100111101101100', '00', '0', '000'),
+(7, 0, '0001111111111111111111111100', '01', '1', '000'),
+(8, 0, '0001111111111111111111111100', '00', '1', '000'),
+(9, 0, '0001111111111111111111111100', '00', '1', '000'),
+(10, 0, '0000000011010100101000100010', '00', '0', '000');
DROP TABLE IF EXISTS `sakura_posts`;
CREATE TABLE `sakura_posts` (
@@ -355,7 +352,7 @@ CREATE TABLE `sakura_posts` (
KEY `poster_id` (`poster_id`),
CONSTRAINT `sakura_posts_ibfk_1` FOREIGN KEY (`topic_id`) REFERENCES `sakura_topics` (`topic_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sakura_posts_ibfk_2` FOREIGN KEY (`forum_id`) REFERENCES `sakura_forums` (`forum_id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_premium`;
@@ -368,6 +365,17 @@ CREATE TABLE `sakura_premium` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+DROP TABLE IF EXISTS `sakura_premium_log`;
+CREATE TABLE `sakura_premium_log` (
+ `id` int(16) unsigned NOT NULL AUTO_INCREMENT COMMENT 'MySQL Generated ID used for sorting.',
+ `uid` bigint(255) unsigned NOT NULL COMMENT 'User ID of purchaser',
+ `amount` float NOT NULL COMMENT 'Amount that was transferred.',
+ `date` int(11) unsigned NOT NULL COMMENT 'Date when the purchase was made.',
+ `comment` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'A short description of the action taken.',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=143 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+
DROP TABLE IF EXISTS `sakura_profilefields`;
CREATE TABLE `sakura_profilefields` (
`id` int(64) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID used for ordering on the userpage.',
@@ -378,7 +386,7 @@ CREATE TABLE `sakura_profilefields` (
`description` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Description of the field displayed in the control panel.',
`additional` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Undocumented JSON array containing special options if needed (probably only going to be used for the YouTube field).',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `sakura_profilefields` (`id`, `name`, `formtype`, `islink`, `linkformat`, `description`, `additional`) VALUES
(1, 'Website', 'url', 1, '{{ VAL }}', 'URL to your website', ''),
@@ -392,8 +400,7 @@ INSERT INTO `sakura_profilefields` (`id`, `name`, `formtype`, `islink`, `linkfor
(9, 'Origin', 'text', 0, '', 'Your Origin User ID', ''),
(10, 'Xbox Live', 'text', 1, 'https://account.xbox.com/en-GB/Profile?Gamertag={{ VAL }}', 'Your Xbox User ID', ''),
(11, 'PSN', 'text', 1, 'http://psnprofiles.com/{{ VAL }}', 'Your PSN User ID', ''),
-(12, 'Last.fm', 'text', 1, 'http://last.fm/user/{{ VAL }}', 'Your Last.fm username', '')
-ON DUPLICATE KEY UPDATE `id` = VALUES(`id`), `name` = VALUES(`name`), `formtype` = VALUES(`formtype`), `islink` = VALUES(`islink`), `linkformat` = VALUES(`linkformat`), `description` = VALUES(`description`), `additional` = VALUES(`additional`);
+(12, 'Last.fm', 'text', 1, 'http://last.fm/user/{{ VAL }}', 'Your Last.fm username', '');
DROP TABLE IF EXISTS `sakura_ranks`;
CREATE TABLE `sakura_ranks` (
@@ -405,7 +412,7 @@ CREATE TABLE `sakura_ranks` (
`description` text COLLATE utf8_bin NOT NULL COMMENT 'A description of what a user of this rank can do/is supposed to do.',
`title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'Default user title if user has none set.',
PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `sakura_ranks` (`id`, `name`, `multi`, `hidden`, `colour`, `description`, `title`) VALUES
(1, 'Deactivated', 0, 1, '#555', 'Users that are yet to be activated or that deactivated their own account.', 'Deactivated'),
@@ -415,9 +422,9 @@ INSERT INTO `sakura_ranks` (`id`, `name`, `multi`, `hidden`, `colour`, `descript
(5, 'Developer', 1, 0, '#824CA0', 'Users that either create or test new features of the site.', 'Staff'),
(6, 'Bot', 1, 1, '#9E8DA7', 'Reserved user accounts for services.', 'Bot'),
(7, 'Chat moderator', 1, 0, '#09F', 'Moderators of the chat room.', 'Staff'),
-(8, 'Tenshi', 0, 0, '#EE9400', 'Users that donated $5.00 or more in order to keep the site and it\'s services alive!', 'Tenshi'),
-(9, 'Alumnii', 0, 0, '#FF69B4', 'People who have contributed to the community but have moved on or resigned.', 'Alumnii')
-ON DUPLICATE KEY UPDATE `id` = VALUES(`id`), `name` = VALUES(`name`), `multi` = VALUES(`multi`), `hidden` = VALUES(`hidden`), `colour` = VALUES(`colour`), `description` = VALUES(`description`), `title` = VALUES(`title`);
+(8, 'Tenshi', 0, 0, '#EE9400', 'Users that bought premium to help us keep the site and its services alive!', 'Tenshi'),
+(9, 'Alumnii', 0, 0, '#FF69B4', 'People who have contributed to the community but have moved on or resigned.', 'Alumnii'),
+(10, 'Restricted', 0, 1, '#333', 'Users that are restricted.', 'Restricted');
DROP TABLE IF EXISTS `sakura_regcodes`;
CREATE TABLE `sakura_regcodes` (
@@ -458,28 +465,9 @@ CREATE TABLE `sakura_sessions` (
PRIMARY KEY (`id`),
KEY `userid` (`userid`),
CONSTRAINT `sakura_sessions_ibfk_1` FOREIGN KEY (`userid`) REFERENCES `sakura_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=165 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-DROP TABLE IF EXISTS `sakura_sock_perms`;
-CREATE TABLE `sakura_sock_perms` (
- `rid` bigint(128) unsigned NOT NULL DEFAULT '0' COMMENT 'ID of rank that this permission counts for (set to 0 if user).',
- `uid` bigint(255) unsigned NOT NULL DEFAULT '0' COMMENT 'ID of the user this permission counts for (set to 0 if rank).',
- `perms` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '1,0,0,0,0,0' COMMENT 'Permission data (has access, in-chat rank, user type, log access, nick access, channel creation)'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-
-INSERT INTO `sakura_sock_perms` (`rid`, `uid`, `perms`) VALUES
-(1, 0, '0,0,0,0,0,0'),
-(2, 0, '1,0,0,0,0,0'),
-(3, 0, '1,3,1,1,1,1'),
-(4, 0, '1,4,2,1,1,2'),
-(5, 0, '1,2,1,1,1,1'),
-(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')
-ON DUPLICATE KEY UPDATE `rid` = VALUES(`rid`), `uid` = VALUES(`uid`), `perms` = VALUES(`perms`);
-
DROP TABLE IF EXISTS `sakura_topics`;
CREATE TABLE `sakura_topics` (
`topic_id` bigint(255) unsigned NOT NULL AUTO_INCREMENT COMMENT 'MySQL Generated ID used for sorting.',
@@ -496,7 +484,7 @@ CREATE TABLE `sakura_topics` (
PRIMARY KEY (`topic_id`),
KEY `forum_id` (`forum_id`),
CONSTRAINT `sakura_topics_ibfk_1` FOREIGN KEY (`forum_id`) REFERENCES `sakura_forums` (`forum_id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_users`;
@@ -520,12 +508,12 @@ CREATE TABLE `sakura_users` (
`regdate` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Timestamp of account creation.',
`lastdate` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Last time anything was done on this account.',
`lastunamechange` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Last username change.',
- `birthday` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT 'Birthdate of the user.',
- `country` varchar(4) COLLATE utf8_bin NOT NULL COMMENT 'Contains ISO 3166 country code of user''s registration location.',
+ `birthday` date DEFAULT NULL COMMENT 'Birthdate of the user.',
+ `country` char(2) COLLATE utf8_bin NOT NULL COMMENT 'Contains ISO 3166 country code of user''s registration location.',
`userData` text COLLATE utf8_bin COMMENT 'All additional profile data.',
PRIMARY KEY (`id`),
UNIQUE KEY `username_clean` (`username_clean`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `sakura_warnings`;
@@ -544,4 +532,4 @@ CREATE TABLE `sakura_warnings` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
--- 2015-08-21 22:06:54
+-- 2015-09-05 16:08:34
diff --git a/_sakura/changelog.json b/_sakura/changelog.json
index 18e90a8..83eb030 100644
--- a/_sakura/changelog.json
+++ b/_sakura/changelog.json
@@ -57,7 +57,8 @@
"20150831",
"20150902",
"20150903",
- "20150904"
+ "20150904",
+ "20150905"
]
@@ -2456,6 +2457,61 @@
"user": "Flashwave"
}
+ ],
+
+ "20150905": [
+
+ {
+ "type": "UPD",
+ "change": "Finished implementation of Urls class.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "FIX",
+ "change": "Fully fixed the user numbering bug on the List view.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "ADD",
+ "change": "Added a configuration value to change how many users are displayed on the memberlist per page.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "FIX",
+ "change": "Made the payment cancelled message look less odd.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "FIX",
+ "change": "Fixed out of line padding on info pages.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "UPD",
+ "change": "Use Twig Blocks instead of Includes.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "FIX",
+ "change": "Fixed parallax disabling not working on Yuuno.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "UPD",
+ "change": "Implemented Urls class in PHP files.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "REM",
+ "change": "Dropped SockChat class and rely on system permissions from Sock Chat permissions.",
+ "user": "Flashwave"
+ },
+ {
+ "type": "ADD",
+ "change": "Implemented IP checking in the session manager.",
+ "user": "Flashwave"
+ }
+
]
}
diff --git a/_sakura/components/Hashing.php b/_sakura/components/Hashing.php
index 9ea5368..2b46bd7 100644
--- a/_sakura/components/Hashing.php
+++ b/_sakura/components/Hashing.php
@@ -1,31 +1,31 @@
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
$mail->Subject = $subject;
@@ -222,9 +225,12 @@ class Main {
$mail->ClearAddresses();
// If we got an error return the error
- if(!$send)
+ if(!$send) {
+
return $mail->ErrorInfo;
+ }
+
// Else just return whatever
return $send;
@@ -239,13 +245,19 @@ class Main {
$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
return $string;
@@ -265,9 +277,12 @@ class Main {
$newsPosts[$newsId]['rdata'] = Users::getRank($newsPosts[$newsId]['udata']['rank_main']);
// Check if a custom name colour is set and if so overwrite the rank colour
- if($newsPosts[$newsId]['udata']['name_colour'] != null)
+ if($newsPosts[$newsId]['udata']['name_colour'] != null){
+
$newsPosts[$newsId]['rdata']['colour'] = $newsPosts[$newsId]['udata']['name_colour'];
+ }
+
}
// Return posts
@@ -307,13 +322,19 @@ class Main {
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
@@ -334,9 +355,12 @@ class Main {
$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
return $binaryIP;
@@ -406,9 +430,12 @@ class Main {
foreach($cfhosts as $subnet) {
// Return true if found
- if(self::matchSubnet($ip, $subnet))
+ if(self::matchSubnet($ip, $subnet)) {
+
return true;
+ }
+
}
// Return false if fails
@@ -426,9 +453,12 @@ class Main {
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
@@ -440,9 +470,12 @@ class Main {
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
return 'XX';
@@ -452,9 +485,12 @@ class Main {
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
$instruct = json_encode($instruct);
@@ -484,15 +520,21 @@ class Main {
]);
// 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'] != $uid) {
+
return [0, 'INVALID_USER'];
+ }
+
}
// Remove the key from the database
@@ -523,11 +565,16 @@ class Main {
$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
+
+ } else {
+
return 'Unknown'; // Else return unknown
+ }
+
}
// Get FAQ data
@@ -548,9 +595,12 @@ class Main {
$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
return $return['string'];
diff --git a/_sakura/components/Permissions.php b/_sakura/components/Permissions.php
index bac6877..f127a89 100644
--- a/_sakura/components/Permissions.php
+++ b/_sakura/components/Permissions.php
@@ -66,8 +66,7 @@ class Permissions {
// Site management permissions
'MANAGE' => [
- 'USE_MANAGE' => 1,
- 'EDIT_INFO_PAGES' => 2
+ 'USE_MANAGE' => 1
]
@@ -77,19 +76,30 @@ class Permissions {
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
return false;
@@ -103,13 +113,19 @@ class Permissions {
$perms = [];
// Get permission row for all ranks
- foreach($ranks as $rank)
+ 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) {
@@ -158,24 +174,36 @@ class 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;
diff --git a/_sakura/components/Sessions.php b/_sakura/components/Sessions.php
index f10a7b3..5a4c919 100644
--- a/_sakura/components/Sessions.php
+++ b/_sakura/components/Sessions.php
@@ -53,11 +53,16 @@ class Session {
$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
+
+ } else {
+
$session = $session[0];
+ }
+
// Check if the session expired
if($session['expire'] < time()) {
@@ -69,10 +74,52 @@ class Session {
}
+ // Origin checking
+ if($ipCheck = Configuration::getConfig('session_check')) {
+
+ // Split both IPs up
+ $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) {
+
+ // 000.xxx.xxx.xxx
+ case 3:
+ if($userIP[3] !== $sessionIP[3]) return false;
+
+ // xxx.000.xxx.xxx
+ case 2:
+ case 3:
+ if($userIP[2] !== $sessionIP[2]) return false;
+
+ // xxx.xxx.000.xxx
+ case 1:
+ case 2:
+ case 3:
+ 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 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
return $session['remember'] ? 2 : 1;
@@ -82,9 +129,12 @@ class Session {
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
Database::delete('sessions', [($key ? 'skey' : 'id') => [$sessionId, '=']]);
diff --git a/_sakura/components/SockChat.php b/_sakura/components/SockChat.php
deleted file mode 100644
index 61629f0..0000000
--- a/_sakura/components/SockChat.php
+++ /dev/null
@@ -1,128 +0,0 @@
- $perm)
- $perms[$id]['perms'] = self::decodePerms($perm['perms']);
-
- // Return the permission data
- return $perms;
-
- }
-
- // Get permission data for a specific rank
- public static function getRankPermissions($rid) {
-
- // Get data by rank id from permissions table
- $perms = Database::fetch('sock_perms', false, ['rid' => [$rid, '='], 'uid' => [0, '=']]);
-
- // Check if we got a row back
- if(empty($perms)) {
- $perms = [
- 'rid' => 0,
- 'uid' => 0,
- 'perms' => self::$_PERMS_FALLBACK
- ];
- }
-
- // Parse permission string
- $perms = self::decodePerms($perms['perms']);
-
- // Return the permission data
- return $perms;
-
- }
-
- // Get all rank permission data
- public static function getUserPermissions($uid) {
-
- // Get data by user id from permissions table
- $perms = Database::fetch('sock_perms', false, ['uid' => [$uid, '='], 'rid' => [0, '=']]);
-
- // Check if we got a row back
- if(empty($perms)) {
-
- // If we didn't get the user's rank account row
- $user = Users::getUser($uid);
-
- // Then return the data for their rank
- return self::getRankPermissions($user['rank_main']);
-
- }
-
- // Parse permission string
- $perms = self::decodePerms($perms['perms']);
-
- // Return the permission data
- return $perms;
-
- }
-
- // Decode permission string
- public static function decodePerms($perms) {
-
- // Explode the commas
- $exploded = is_array($perms) ? $perms : explode(',', $perms);
-
- // "Reset" $perms
- $perms = array();
-
- // Put the data in the correct order
- $perms['access'] = $exploded[ self::$_PERMS_ACCESS_INDEX ];
- $perms['rank'] = $exploded[ self::$_PERMS_RANK_INDEX ];
- $perms['type'] = $exploded[ self::$_PERMS_TYPE_INDEX ];
- $perms['logs'] = $exploded[ self::$_PERMS_LOGS_INDEX ];
- $perms['nick'] = $exploded[ self::$_PERMS_NICK_INDEX ];
- $perms['channel'] = $exploded[ self::$_PERMS_CHANNEL_INDEX ];
-
- // Return formatted permissions array
- return $perms;
-
- }
-
- // Encode permission string
- public static function encodePerms($perms) {
-
- // Create array
- $encoded = array();
-
- // Put the data in the correct order
- $encoded[ self::$_PERMS_ACCESS_INDEX ] = empty($perms['access']) ? 0 : $perms['access'];
- $encoded[ self::$_PERMS_RANK_INDEX ] = empty($perms['rank']) ? 0 : $perms['rank'];
- $encoded[ self::$_PERMS_TYPE_INDEX ] = empty($perms['type']) ? 0 : $perms['type'];
- $encoded[ self::$_PERMS_LOGS_INDEX ] = empty($perms['logs']) ? 0 : $perms['logs'];
- $encoded[ self::$_PERMS_NICK_INDEX ] = empty($perms['nick']) ? 0 : $perms['nick'];
- $encoded[ self::$_PERMS_CHANNEL_INDEX ] = empty($perms['channel']) ? 0 : $perms['channel'];
-
- // Implode the array
- $perms = implode(',', $encoded);
-
- // Return formatted permissions array
- return $perms;
-
- }
-
-}
diff --git a/_sakura/components/Urls.php b/_sakura/components/Urls.php
index 8f20099..5a2f0de 100644
--- a/_sakura/components/Urls.php
+++ b/_sakura/components/Urls.php
@@ -11,20 +11,34 @@ class Urls {
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_MEMBERS' => ['/members.php', '/members'],
- 'SITE_PREMIUM' => ['/support.php', '/support'],
- 'SITE_FAQ' => ['/faq.php', '/faq'],
- 'SITE_LOGIN' => ['/authenticate.php', '/login'],
- 'SITE_REGISTER' => ['/authenticate.php', '/register'],
- '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'],
// Forums
'FORUM_INDEX' => ['/index.php?forum=true', '/forum'],
@@ -44,8 +58,9 @@ class Urls {
// User actions
'USER_LOGOUT' => ['/authenticate.php?mode=logout&time=%u&session=%s&redirect=%s', '/logout?mode=logout&time=%u&session=%s&redirect=%s'],
- 'USER_PROFILE' => ['/profile.php?u=%s', '/u/%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'],
@@ -60,7 +75,9 @@ class Urls {
'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_INDEX' => ['/manage.php', '/manage'],
+ 'MANAGE_CAT' => ['/manage.php?cat=%s', '/manage/%s'],
+ 'MANAGE_MODE' => ['/manage.php?cat=%s&mode=%s', '/manage/%s/%s']
];
diff --git a/_sakura/components/Users.php b/_sakura/components/Users.php
index ccc1eca..7d40c91 100644
--- a/_sakura/components/Users.php
+++ b/_sakura/components/Users.php
@@ -64,19 +64,28 @@ class Users {
if(!$bypassCookies) {
// Check if the cookies are set
- if(!isset($_COOKIE[Configuration::getConfig('cookie_prefix') .'id']) || !isset($_COOKIE[Configuration::getConfig('cookie_prefix') .'session']))
+ if(!isset($_COOKIE[Configuration::getConfig('cookie_prefix') .'id']) || !isset($_COOKIE[Configuration::getConfig('cookie_prefix') .'session'])) {
+
return false;
+ }
+
}
// Check if the session exists
- if(!$session = Session::checkSession($uid, $sid))
+ if(!$session = Session::checkSession($uid, $sid)) {
+
return false;
+ }
+
// Check if the user is activated
- if(Permissions::check('SITE', 'DEACTIVATED', $uid, 1))
+ if(Permissions::check('SITE', 'DEACTIVATED', $uid, 1)) {
+
return false;
+ }
+
// Extend the cookie times if the remember flag is set
if($session == 2 && !$bypassCookies) {
@@ -107,13 +116,19 @@ class Users {
public static function login($username, $password, $remember = false, $cookies = true) {
// Check if authentication is disallowed
- if(Configuration::getConfig('lock_authentication'))
+ if(Configuration::getConfig('lock_authentication')) {
+
return [0, 'AUTH_LOCKED'];
+ }
+
// Check if the user that's trying to log in actually exists
- if(!$uid = self::userExists($username, false))
+ if(!$uid = self::userExists($username, false)) {
+
return [0, 'USER_NOT_EXIST'];
+ }
+
// Get account data
$user = self::getUser($uid);
@@ -140,9 +155,12 @@ class Users {
}
// Check if the user has the required privs to log in
- if(Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
return [0, 'NOT_ALLOWED'];
+ }
+
// Create a new session
$sessionKey = Session::newSession($user['id'], $remember);
@@ -155,7 +173,7 @@ class Users {
}
// Successful login! (also has a thing for the legacy password system)
- return [1, ($user['password_algo'] == 'legacy' ? 'LEGACY_SUCCESS' : 'LOGIN_SUCESS')];
+ return [1, 'LOGIN_SUCESS'];
}
@@ -163,13 +181,19 @@ class Users {
public static function logout() {
// Check if user is logged in
- if(!self::checkLogin())
+ if(!self::checkLogin()) {
+
return false;
+ }
+
// Remove the active session from the database
- if(!Session::deleteSession(Session::$sessionId, true))
+ if(!Session::deleteSession(Session::$sessionId, true)) {
+
return false;
+ }
+
// Set cookies
setcookie(Configuration::getConfig('cookie_prefix') .'id', 0, time() - 60, Configuration::getConfig('cookie_path'), Configuration::getConfig('cookie_domain'));
setcookie(Configuration::getConfig('cookie_prefix') .'session', '', time() - 60, Configuration::getConfig('cookie_path'), Configuration::getConfig('cookie_domain'));
@@ -183,62 +207,98 @@ class Users {
public static function register($username, $password, $confirmpass, $email, $tos, $captcha = null, $regkey = null) {
// Check if authentication is disallowed
- if(Configuration::getConfig('lock_authentication'))
+ if(Configuration::getConfig('lock_authentication')) {
+
return [0, 'AUTH_LOCKED'];
+ }
+
// Check if registration is even enabled
- if(Configuration::getConfig('disable_registration'))
+ if(Configuration::getConfig('disable_registration')) {
+
return [0, 'DISABLED'];
+ }
+
// Check if registration codes are required
if(Configuration::getConfig('require_registration_code')) {
// Check if the code is valid
- if(!self::checkRegistrationCode($regkey))
+ if(!self::checkRegistrationCode($regkey)) {
+
return [0, 'INVALID_REG_KEY'];
+ }
+
}
// Check if the user agreed to the ToS
- if(!$tos)
+ if(!$tos) {
+
return [0, 'TOS'];
+ }
+
// Verify the captcha if it's enabled
if(Configuration::getConfig('recaptcha')) {
- if(!Main::verifyCaptcha($captcha)['success'])
+ if(!Main::verifyCaptcha($captcha)['success']) {
+
return [0, 'CAPTCHA_FAIL'];
+ }
+
}
// Check if the username already exists
- if(self::userExists($username, false))
+ if(self::userExists($username, false)) {
+
return [0, 'USER_EXISTS'];
+ }
+
// Username too short
- if(strlen($username) < Configuration::getConfig('username_min_length'))
+ if(strlen($username) < Configuration::getConfig('username_min_length')) {
+
return [0, 'NAME_TOO_SHORT'];
+ }
+
// Username too long
- if(strlen($username) > Configuration::getConfig('username_max_length'))
+ if(strlen($username) > Configuration::getConfig('username_max_length')) {
+
return [0, 'NAME_TOO_LONG'];
+ }
+
// Check if the given email address is formatted properly
- if(!filter_var($email, FILTER_VALIDATE_EMAIL))
+ if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
+
return [0, 'INVALID_EMAIL'];
+ }
+
// Check the MX record of the email
- if(!Main::checkMXRecord($email))
+ if(!Main::checkMXRecord($email)) {
+
return [0, 'INVALID_MX'];
+ }
+
// Check password entropy
- if(Main::pwdEntropy($password) < Configuration::getConfig('min_entropy'))
+ if(Main::pwdEntropy($password) < Configuration::getConfig('min_entropy')) {
+
return [0, 'PASS_TOO_SHIT'];
+ }
+
// Passwords do not match
- if($password != $confirmpass)
+ if($password != $confirmpass) {
+
return [0, 'PASS_NOT_MATCH'];
+ }
+
// Set a few variables
$usernameClean = Main::cleanString($username, true);
$emailClean = Main::cleanString($email, true);
@@ -295,9 +355,12 @@ class Users {
public static function sendPasswordForgot($username, $email) {
// Check if authentication is disallowed
- if(Configuration::getConfig('lock_authentication'))
+ if(Configuration::getConfig('lock_authentication')) {
+
return [0, 'AUTH_LOCKED'];
+ }
+
// Clean username string
$usernameClean = Main::cleanString($username, true);
$emailClean = Main::cleanString($email, true);
@@ -309,13 +372,19 @@ class Users {
]);
// Check if user exists
- if(count($user) < 2)
+ if(count($user) < 2) {
+
return [0, 'USER_NOT_EXIST'];
+ }
+
// Check if the user has the required privs to log in
- if(Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
return [0, 'NOT_ALLOWED'];
+ }
+
// Generate the verification key
$verk = Main::newActionCode('LOST_PASS', $user['id'], [
'meta' => [
@@ -323,13 +392,16 @@ class Users {
]
]);
+ // Create new urls object
+ $urls = new Urls();
+
// Build the e-mail
$message = "Hello ". $user['username'] .",\r\n\r\n";
$message .= "You are receiving this notification because you have (or someone pretending to be you has) requested a password reset link to be sent for your account on \"". Configuration::getConfig('sitename') ."\". If you did not request this notification then please ignore it, if you keep receiving it please contact the site administrator.\r\n\r\n";
$message .= "To use this password reset key you need to go to a special page. To do this click the link provided below.\r\n\r\n";
- $message .= "http://". Configuration::getConfig('url_main') ."/forgotpassword?pw=true&uid=". $user['id'] ."&key=". $verk ."\r\n\r\n";
+ $message .= "http://". Configuration::getConfig('url_main') . $urls->format('SITE_FORGOT_PASSWORD') ."?pw=true&uid=". $user['id'] ."&key=". $verk ."\r\n\r\n";
$message .= "If successful you should be able to change your password here.\r\n\r\n";
- $message .= "Alternatively if the above method fails for some reason you can go to http://". Configuration::getConfig('url_main') ."/forgotpassword?pw=true&uid=". $user['id'] ." and use the key listed below:\r\n\r\n";
+ $message .= "Alternatively if the above method fails for some reason you can go to http://". Configuration::getConfig('url_main') . $urls->format('SITE_FORGOT_PASSWORD') ."?pw=true&uid=". $user['id'] ." and use the key listed below:\r\n\r\n";
$message .= "Verification key: ". $verk ."\r\n\r\n";
$message .= "You can of course change this password yourself via the profile page. If you have any difficulties please contact the site administrator.\r\n\r\n";
$message .= "--\r\n\r\nThanks\r\n\r\n". Configuration::getConfig('mail_signature');
@@ -346,24 +418,36 @@ class Users {
public static function resetPassword($verk, $uid, $newpass, $verpass) {
// Check if authentication is disallowed
- if(Configuration::getConfig('lock_authentication'))
+ if(Configuration::getConfig('lock_authentication')) {
+
return [0, 'AUTH_LOCKED'];
+ }
+
// Check password entropy
- if(Main::pwdEntropy($newpass) < Configuration::getConfig('min_entropy'))
+ if(Main::pwdEntropy($newpass) < Configuration::getConfig('min_entropy')) {
+
return [0, 'PASS_TOO_SHIT'];
+ }
+
// Passwords do not match
- if($newpass != $verpass)
+ if($newpass != $verpass) {
+
return [0, 'PASS_NOT_MATCH'];
+ }
+
// Check the verification key
$action = Main::useActionCode('LOST_PASS', $verk, $uid);
// Check if we got a negative return
- if(!$action[0])
+ if(!$action[0]) {
+
return [0, $action[1]];
+ }
+
// Hash the password
$password = Hashing::create_hash($newpass);
$time = time();
@@ -391,9 +475,12 @@ class Users {
public static function resendActivationMail($username, $email) {
// Check if authentication is disallowed
- if(Configuration::getConfig('lock_authentication'))
+ if(Configuration::getConfig('lock_authentication')) {
+
return [0, 'AUTH_LOCKED'];
+ }
+
// Clean username string
$usernameClean = Main::cleanString($username, true);
$emailClean = Main::cleanString($email, true);
@@ -405,13 +492,19 @@ class Users {
]);
// Check if user exists
- if(count($user) < 2)
+ if(count($user) < 2) {
+
return [0, 'USER_NOT_EXIST'];
+ }
+
// Check if a user is activated
- if(!Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(!Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
return [0, 'USER_ALREADY_ACTIVE'];
+ }
+
// Send activation e-mail
self::sendActivationMail($user['id']);
@@ -427,9 +520,12 @@ class Users {
$user = Database::fetch('users', false, ['id' => [$uid, '=']]);
// User is already activated or doesn't even exist
- if(count($user) < 2 || !Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(count($user) < 2 || !Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
return false;
+ }
+
// Generate activation key
$activate = ($customKey ? $customKey : Main::newActionCode('ACTIVATE', $uid, [
'user' => [
@@ -438,15 +534,18 @@ class Users {
]
]));
+ // Create new urls object
+ $urls = new Urls();
+
// Build the e-mail
$message = "Welcome to ". Configuration::getConfig('sitename') ."!\r\n\r\n";
$message .= "Please keep this e-mail for your records. Your account intormation is as follows:\r\n\r\n";
$message .= "----------------------------\r\n\r\n";
$message .= "Username: ". $user['username'] ."\r\n\r\n";
- $message .= "Your profile: http://". Configuration::getConfig('url_main') ."/u/". $user['id'] ."\r\n\r\n";
+ $message .= "Your profile: http://". Configuration::getConfig('url_main') . $urls->format('USER_PROFILE', [$user['id']]) ."\r\n\r\n";
$message .= "----------------------------\r\n\r\n";
$message .= "Please visit the following link in order to activate your account:\r\n\r\n";
- $message .= "http://". Configuration::getConfig('url_main') ."/activate?mode=activate&u=". $user['id'] ."&k=". $activate ."\r\n\r\n";
+ $message .= "http://". Configuration::getConfig('url_main') . $urls->format('SITE_ACTIVATE') ."?mode=activate&u=". $user['id'] ."&k=". $activate ."\r\n\r\n";
$message .= "Your password has been securely stored in our database and cannot be retrieved. ";
$message .= "In the event that it is forgotten, you will be able to reset it using the email address associated with your account.\r\n\r\n";
$message .= "Thank you for registering.\r\n\r\n";
@@ -467,13 +566,19 @@ class Users {
$user = Database::fetch('users', false, ['id' => [$uid, '=']]);
// Check if user exists
- if(!count($user) > 1)
+ if(!count($user) > 1) {
+
return [0, 'USER_NOT_EXIST'];
+ }
+
// Check if user is already activated
- if(!Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(!Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
return [0, 'USER_ALREADY_ACTIVE'];
+ }
+
// Set default values for activation
$rank = 2;
$ranks = json_encode([2]);
@@ -485,9 +590,12 @@ class Users {
$action = Main::useActionCode('ACTIVATE', $key, $uid);
// Check if we got a negative return
- if(!$action[0])
+ if(!$action[0]) {
+
return [0, $action[1]];
+ }
+
// Assign the special values
$instructionData = json_decode($action[2], true);
$rank = $instructionData['user']['rank_main'];
@@ -518,13 +626,19 @@ class Users {
$user = Database::fetch('users', false, ['id' => [$uid, '=']]);
// Check if user exists
- if(!count($user) > 1)
+ if(!count($user) > 1) {
+
return [0, 'USER_NOT_EXIST'];
+ }
+
// Check if user is already deactivated
- if(Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
return [0, 'USER_ALREADY_DEACTIVE'];
+ }
+
// Deactivate the account
Database::update('users', [
[
@@ -556,9 +670,12 @@ class Users {
public static function markRegistrationCodeUsed($code, $uid = 0) {
// Check if the code exists
- if(!$id = self::checkRegistrationCode($code))
+ if(!$id = self::checkRegistrationCode($code)) {
+
return false;
+ }
+
// Mark it as used
Database::update('regcodes', [
[
@@ -579,13 +696,19 @@ class Users {
public static function createRegistrationCode() {
// Check if we're logged in
- if(!self::checkLogin())
+ if(!self::checkLogin()) {
+
return false;
+ }
+
// Check if the user is not exceeding the maximum registration key amount
- if(count(Database::fetch('regcodes', true, ['uid' => [Session::$userId, '=']])) >= Configuration::getConfig('max_reg_keys'))
+ if(count(Database::fetch('regcodes', true, ['uid' => [Session::$userId, '=']])) >= Configuration::getConfig('max_reg_keys')) {
+
return false;
+ }
+
// Generate a code by MD5'ing some random bullshit
$code = md5('SAKURA'. rand(0, 99999999) . Session::$userId .'NOOKLSISGOD');
@@ -612,9 +735,12 @@ class Users {
$ranks = json_decode($user['ranks'], true);
// Check if the rank we're trying to set is actually there
- if(!in_array($rid, $ranks))
+ if(!in_array($rid, $ranks)) {
+
return false;
+ }
+
// Update the row
Database::update('users', [
[
@@ -709,9 +835,12 @@ class Users {
$user = $userIdIsUserData ? $userid : self::getUser($userid);
// Check if the main rank is the specified rank
- if(in_array($user['rank_main'], $ranks))
+ if(in_array($user['rank_main'], $ranks)) {
+
return true;
+ }
+
// Decode the json for the user's ranks
$uRanks = json_decode($user['ranks'], true);
@@ -750,9 +879,12 @@ class Users {
$profileFields = Database::fetch('profilefields');
// If there's nothing just return null
- if(!count($profileFields))
+ if(!count($profileFields)) {
+
return null;
+ }
+
// Create output array
$fields = [];
@@ -811,16 +943,22 @@ class Users {
$profileFields = Database::fetch('profilefields');
// If there's nothing just return null
- if(!count($profileFields))
+ if(!count($profileFields)) {
+
return null;
+ }
+
// Assign the profileData variable
$profileData = ($inputIsData ? $id : self::getUser($id)['userData']);
// Once again if nothing was returned just return null
- if(count($profileData) < 1 || $profileData == null || empty($profileData['profileFields']))
+ if(count($profileData) < 1 || $profileData == null || empty($profileData['profileFields'])) {
+
return null;
+ }
+
// Redeclare profileData
$profileData = $profileData['profileFields'];
@@ -834,9 +972,12 @@ class Users {
$fieldName = Main::cleanString($field['name'], true, true);
// Check if the user has the current field set otherwise continue
- if(!array_key_exists($fieldName, $profileData))
+ if(!array_key_exists($fieldName, $profileData)) {
+
continue;
+ }
+
// Assign field to output with value
$profile[$fieldName] = array();
$profile[$fieldName]['name'] = $field['name'];
@@ -844,9 +985,12 @@ class Users {
$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 }}', $profileData[$fieldName], $field['linkformat']);
+ }
+
// Check if we have additional options as well
if($field['additional'] != null) {
@@ -857,9 +1001,12 @@ class Users {
foreach($additional as $subName => $subField) {
// Check if the user has the current field set otherwise continue
- if(!array_key_exists($subName, $profileData))
+ if(!array_key_exists($subName, $profileData)) {
+
continue;
+ }
+
// Assign field to output with value
$profile[$fieldName][$subName] = $profileData[$subName];
@@ -905,9 +1052,12 @@ class Users {
$user = self::getUser($id);
// Return false if the user doesn't exist because a user that doesn't exist can't be online
- if(empty($user))
+ if(empty($user)) {
+
return false;
+ }
+
// Return true if the user was online in the last 5 minutes
return ($user['lastdate'] > (time() - 500));
@@ -979,18 +1129,24 @@ class Users {
public static function checkUserPremium($id) {
// Check if the user has static premium
- if(Permissions::check('SITE', 'STATIC_PREMIUM', $id, 1))
+ if(Permissions::check('SITE', 'STATIC_PREMIUM', $id, 1)) {
+
return [2, 0, time() + 1];
+ }
+
// Attempt to retrieve the premium record from the database
$getRecord = Database::fetch('premium', false, [
'uid' => [$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()) {
@@ -1021,9 +1177,12 @@ class Users {
self::addRanksToUser([$premiumRank], $id);
// Check if the user's default rank is standard user and update it to premium
- if(self::getUser($id)['rank_main'] == 2)
+ if(self::getUser($id)['rank_main'] == 2) {
+
self::setDefaultRank($id, $premiumRank);
+ }
+
} elseif($check[0] == 0 && count($check) > 1) {
// Else remove the rank from them
@@ -1040,9 +1199,12 @@ class Users {
$user = Database::fetch('users', false, ['id' => [$id, '=']]);
// Return false if no user was found
- if(empty($user))
+ if(empty($user)) {
+
$user = self::$emptyUser;
+ }
+
// Parse the json in the additional section
$user['userData'] = json_decode($user['userData'], true);
@@ -1058,9 +1220,12 @@ class Users {
$rank = Database::fetch('ranks', false, ['id' => [$id, '=']]);
// Return false if no rank was found
- if(empty($rank))
+ if(empty($rank)) {
+
return self::$emptyRank;
+ }
+
// If rank was found return rank data
return $rank;
@@ -1087,9 +1252,12 @@ class Users {
public static function getUsersInRank($rankId, $users = null, $excludeAbyss = true) {
// Get all users (or use the supplied user list to keep server load down)
- if(!$users)
+ if(!$users) {
+
$users = self::getAllUsers();
+ }
+
// Make output array
$rank = array();
@@ -1097,9 +1265,12 @@ class Users {
foreach($users as $user) {
// If so store the user's row in the array
- if(self::checkIfUserHasRanks([$rankId], $user, true) && ($excludeAbyss ? $user['password_algo'] != 'nologin' : true))
+ if(self::checkIfUserHasRanks([$rankId], $user, true) && ($excludeAbyss ? $user['password_algo'] != 'nologin' : true)) {
+
$rank[] = $user;
+ }
+
}
// Then return the array with the user rows
@@ -1120,13 +1291,19 @@ class Users {
foreach($getUsers as $user) {
// Skip abyss
- if(!$includeAbyss && $user['password_algo'] == 'nologin')
+ if(!$includeAbyss && $user['password_algo'] == 'nologin') {
+
continue;
+ }
+
// Skip if inactive and not include deactivated users
- if(!$includeInactive && Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1))
+ if(!$includeInactive && Permissions::check('SITE', 'DEACTIVATED', $user['id'], 1)) {
+
continue;
+ }
+
$users[$user['id']] = $user;
}
@@ -1146,9 +1323,12 @@ class Users {
$ranks = [];
// Reorder shit
- foreach($getRanks as $rank)
+ foreach($getRanks as $rank) {
+
$ranks[$rank['id']] = $rank;
+ }
+
// and return an array with the ranks
return $ranks;
@@ -1173,11 +1353,19 @@ class Users {
// Prepare conditions
$conditions = array();
$conditions['uid'] = [($uid ? $uid : Session::$userId), '='];
- if($timediff)
+
+ if($timediff) {
+
$conditions['timestamp'] = [time() - $timediff, '>'];
- if($excludeRead)
+
+ }
+
+ if($excludeRead) {
+
$conditions['notif_read'] = [0, '='];
+ }
+
// Get notifications for the database
$notifications = Database::fetch('notifications', true, $conditions);
@@ -1188,9 +1376,12 @@ class Users {
foreach($notifications as $notification) {
// If the notifcation is already read skip
- if($notification['notif_read'])
+ if($notification['notif_read']) {
+
continue;
+ }
+
// Mark them as read
self::markNotificationRead($notification['id']);
@@ -1273,9 +1464,12 @@ class Users {
public static function getFriends($uid = null, $timestamps = false, $getData = false, $checkOnline = false) {
// Assign $uid
- if(!$uid)
+ if(!$uid) {
+
$uid = Session::$userId;
+ }
+
// Get all friends
$getFriends = Database::fetch('friends', true, [
'uid' => [$uid, '=']
@@ -1318,9 +1512,12 @@ class Users {
public static function getPendingFriends($uid = null, $getData = false) {
// Assign $of automatically if it's not set
- if(!$uid)
+ if(!$uid) {
+
$uid = Session::$userId;
+ }
+
// Get all friend entries from other people involved the current user
$friends = Database::fetch('friends', true, [
'fid' => [$uid, '=']
@@ -1355,23 +1552,32 @@ class Users {
public static function checkFriend($fid, $uid = null) {
// Assign $uid
- if(!$uid)
+ if(!$uid) {
+
$uid = Session::$userId;
+ }
+
// Get the user's friends
$self = self::getFriends($uid);
// Check if the friend is actually in the user's array
- if(!in_array($fid, $self))
+ if(!in_array($fid, $self)) {
+
return 0;
+ }
+
// Get the friend's friends
$friend = self::getFriends($fid);
// Check if the friend is actually in the user's array
- if(in_array($uid, $friend))
+ if(in_array($uid, $friend)) {
+
return 2;
+ }
+
// Return true if all went through
return 1;
@@ -1381,13 +1587,19 @@ class Users {
public static function addFriend($uid) {
// Validate that the user exists
- if(!self::getUser($uid))
+ if(!self::getUser($uid)) {
+
return [0, 'USER_NOT_EXIST'];
+ }
+
// Check if the user already has this user a friend
- if(Database::fetch('friends', false, ['fid' => [$uid, '='], 'uid' => [Session::$userId, '=']]))
+ if(Database::fetch('friends', false, ['fid' => [$uid, '='], 'uid' => [Session::$userId, '=']])) {
+
return [0, 'ALREADY_FRIENDS'];
+ }
+
// Add friend
Database::insert('friends', [
'uid' => Session::$userId,
@@ -1404,9 +1616,12 @@ class Users {
public static function removeFriend($uid, $deleteRequest = false) {
// Check if the user has this user a friend
- if(!Database::fetch('friends', false, ['fid' => [$uid, '='], 'uid' => [Session::$userId, '=']]))
+ if(!Database::fetch('friends', false, ['fid' => [$uid, '='], 'uid' => [Session::$userId, '=']])) {
+
return [0, 'ALREADY_REMOVED'];
+ }
+
// Remove friend
Database::delete('friends', [
'uid' => [Session::$userId, '='],
diff --git a/_sakura/sakura.php b/_sakura/sakura.php
index a63f51c..72310b5 100644
--- a/_sakura/sakura.php
+++ b/_sakura/sakura.php
@@ -8,7 +8,7 @@
namespace Sakura;
// Define Sakura version
-define('SAKURA_VERSION', '20150903');
+define('SAKURA_VERSION', '20150905');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082');
define('SAKURA_STABLE', false);
@@ -48,7 +48,6 @@ 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/components/SockChat.php';
// Include database extensions
foreach(glob(ROOT .'_sakura/components/database/*.php') as $driver) {
@@ -144,10 +143,7 @@ if(!defined('SAKURA_NO_TPL')) {
'requireActivation' => Configuration::getConfig('require_activation'),
'minPwdEntropy' => Configuration::getConfig('min_entropy'),
'minUsernameLength' => Configuration::getConfig('username_min_length'),
- 'maxUsernameLength' => Configuration::getConfig('username_max_length'),
-
- 'disqus_shortname' => Configuration::getConfig('disqus_shortname'),
- 'disqus_api_key' => Configuration::getConfig('disqus_api_key')
+ 'maxUsernameLength' => Configuration::getConfig('username_max_length')
],
@@ -189,7 +185,7 @@ if(!defined('SAKURA_NO_TPL')) {
]);
Users::logout();
- print Templates::render('errors/banned.tpl', $renderData);
+ print Templates::render('main/banned.tpl', $renderData);
exit;
}
diff --git a/_sakura/templates/yuuno/errors/information.tpl b/_sakura/templates/yuuno/errors/information.tpl
deleted file mode 100644
index 8946efa..0000000
--- a/_sakura/templates/yuuno/errors/information.tpl
+++ /dev/null
@@ -1,8 +0,0 @@
-{% include 'global/header.tpl' %}
-
-
Information
-
- {{ page.message }}
- {% if page.redirect %}
Click here if you aren't being redirected.{% endif %}
-
-{% include 'global/footer.tpl' %}
diff --git a/_sakura/templates/yuuno/forum/index.tpl b/_sakura/templates/yuuno/forum/index.tpl
index eed9a21..62d272b 100644
--- a/_sakura/templates/yuuno/forum/index.tpl
+++ b/_sakura/templates/yuuno/forum/index.tpl
@@ -1,4 +1,6 @@
-{% include 'global/header.tpl' %}
+{% extends 'global/master.tpl' %}
+
+{% block content %}
{% include 'elements/indexPanel.tpl' %}
@@ -9,4 +11,4 @@
-{% include 'global/footer.tpl' %}
+{% endblock %}
diff --git a/_sakura/templates/yuuno/forum/posting.tpl b/_sakura/templates/yuuno/forum/posting.tpl
index ca4d095..0c3e784 100644
--- a/_sakura/templates/yuuno/forum/posting.tpl
+++ b/_sakura/templates/yuuno/forum/posting.tpl
@@ -1,4 +1,6 @@
-{% include 'global/header.tpl' %}
+{% extends 'global/master.tpl' %}
+
+{% block content %}
-{% include 'global/footer.tpl' %}
+{% endblock %}
diff --git a/_sakura/templates/yuuno/forum/viewforum.tpl b/_sakura/templates/yuuno/forum/viewforum.tpl
index 53f5eaf..40799e9 100644
--- a/_sakura/templates/yuuno/forum/viewforum.tpl
+++ b/_sakura/templates/yuuno/forum/viewforum.tpl
@@ -1,7 +1,9 @@
-{% include 'global/header.tpl' %}
+{% extends 'global/master.tpl' %}
+
+{% block content %}
{% include 'forum/forum.tpl' %}
-{% include 'global/footer.tpl' %}
+{% endblock %}
diff --git a/_sakura/templates/yuuno/forum/viewtopic.tpl b/_sakura/templates/yuuno/forum/viewtopic.tpl
index 7bf2350..4f0d7a2 100644
--- a/_sakura/templates/yuuno/forum/viewtopic.tpl
+++ b/_sakura/templates/yuuno/forum/viewtopic.tpl
@@ -1,4 +1,6 @@
-{% include 'global/header.tpl' %}
+{% extends 'global/master.tpl' %}
+
+{% block content %}
{{ forum.forum.forum_name }} / {{ topic.topic_title }}
@@ -56,4 +58,4 @@
{% include 'forum/forumBtns.tpl' %}
-{% include 'global/footer.tpl' %}
+{% endblock %}
diff --git a/_sakura/templates/yuuno/global/footer.tpl b/_sakura/templates/yuuno/global/footer.tpl
deleted file mode 100644
index 156a2c2..0000000
--- a/_sakura/templates/yuuno/global/footer.tpl
+++ /dev/null
@@ -1,41 +0,0 @@
-
- {% if not sakura.versionInfo.stable %}
-
- {% endif %}
-
-
-
-