premium stuff
This commit is contained in:
parent
9280706a0a
commit
6da8eb931d
24 changed files with 541 additions and 505 deletions
20
cron.php
20
cron.php
|
@ -6,14 +6,6 @@
|
||||||
// Declare Namespace
|
// Declare Namespace
|
||||||
namespace Sakura;
|
namespace Sakura;
|
||||||
|
|
||||||
// Check if the script isn't executed by root
|
|
||||||
if (function_exists('posix_getuid')) {
|
|
||||||
if (posix_getuid() === 0) {
|
|
||||||
trigger_error('Running cron as root is disallowed for security reasons.', E_USER_ERROR);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define that this page won't require templating
|
// Define that this page won't require templating
|
||||||
define('SAKURA_NO_TPL', true);
|
define('SAKURA_NO_TPL', true);
|
||||||
|
|
||||||
|
@ -35,9 +27,13 @@ DB::table('notifications')
|
||||||
// Get expired premium accounts
|
// Get expired premium accounts
|
||||||
$expiredPremium = DB::table('premium')
|
$expiredPremium = DB::table('premium')
|
||||||
->where('premium_expire', '<', time())
|
->where('premium_expire', '<', time())
|
||||||
->get();
|
->get(['user_id']);
|
||||||
|
|
||||||
// Process expired premium accounts, make this not stupid in the future
|
foreach ($expiredPremium as $premium) {
|
||||||
foreach ($expiredPremium as $expired) {
|
DB::table('premium')
|
||||||
Users::updatePremiumMeta($expired->user_id);
|
->where('user_id', $premium->user_id)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
User::construct($premium->user_id)
|
||||||
|
->isPremium();
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ class BBcode
|
||||||
|
|
||||||
$parsed = nl2br(self::$bbcode->getAsHtml());
|
$parsed = nl2br(self::$bbcode->getAsHtml());
|
||||||
|
|
||||||
$parsed = Utils::fixCodeTags($parsed);
|
$parsed = self::fixCodeTags($parsed);
|
||||||
$parsed = self::parseEmoticons($parsed);
|
$parsed = self::parseEmoticons($parsed);
|
||||||
|
|
||||||
return $parsed;
|
return $parsed;
|
||||||
|
@ -178,4 +178,37 @@ class BBcode
|
||||||
|
|
||||||
return self::$bbcode->getAsText();
|
return self::$bbcode->getAsText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up the contents of <code> tags.
|
||||||
|
*
|
||||||
|
* @param string $text Dirty
|
||||||
|
*
|
||||||
|
* @return string Clean
|
||||||
|
*/
|
||||||
|
public static function fixCodeTags($text)
|
||||||
|
{
|
||||||
|
$parts = explode('<code>', $text);
|
||||||
|
$newStr = '';
|
||||||
|
|
||||||
|
if (count($parts) > 1) {
|
||||||
|
foreach ($parts as $p) {
|
||||||
|
$parts2 = explode('</code>', $p);
|
||||||
|
if (count($parts2) > 1) {
|
||||||
|
$code = str_replace('<br />', '', $parts2[0]);
|
||||||
|
$code = str_replace('<br/>', '', $code);
|
||||||
|
$code = str_replace('<br>', '', $code);
|
||||||
|
$code = str_replace('<', '<', $code);
|
||||||
|
$newStr .= '<code>' . $code . '</code>';
|
||||||
|
$newStr .= $parts2[1];
|
||||||
|
} else {
|
||||||
|
$newStr .= $p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$newStr = $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newStr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,17 +28,28 @@ use Sakura\Utils;
|
||||||
*/
|
*/
|
||||||
class AuthController extends Controller
|
class AuthController extends Controller
|
||||||
{
|
{
|
||||||
protected function touchRateLimit($user, $mode = 0)
|
/**
|
||||||
|
* Touch the login rate limit.
|
||||||
|
*
|
||||||
|
* @param $user int The ID of the user that attempted to log in.
|
||||||
|
* @param $sucess bool Whether the login attempt was successful.
|
||||||
|
*/
|
||||||
|
protected function touchRateLimit($user, $success = false)
|
||||||
{
|
{
|
||||||
DB::table('login_attempts')
|
DB::table('login_attempts')
|
||||||
->insert([
|
->insert([
|
||||||
'attempt_success' => $mode,
|
'attempt_success' => $success ? 1 : 0,
|
||||||
'attempt_timestamp' => time(),
|
'attempt_timestamp' => time(),
|
||||||
'attempt_ip' => Net::pton(Net::IP()),
|
'attempt_ip' => Net::pton(Net::ip()),
|
||||||
'user_id' => $user,
|
'user_id' => $user,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End the current session.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function logout()
|
public function logout()
|
||||||
{
|
{
|
||||||
// Check if user is logged in
|
// Check if user is logged in
|
||||||
|
@ -65,11 +76,21 @@ class AuthController extends Controller
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the login page.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function loginGet()
|
public function loginGet()
|
||||||
{
|
{
|
||||||
return Template::render('auth/login');
|
return Template::render('auth/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a login attempt.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function loginPost()
|
public function loginPost()
|
||||||
{
|
{
|
||||||
// Preliminarily set login to failed
|
// Preliminarily set login to failed
|
||||||
|
@ -91,7 +112,7 @@ class AuthController extends Controller
|
||||||
|
|
||||||
// Check if we haven't hit the rate limit
|
// Check if we haven't hit the rate limit
|
||||||
$rates = DB::table('login_attempts')
|
$rates = DB::table('login_attempts')
|
||||||
->where('attempt_ip', Net::pton(Net::IP()))
|
->where('attempt_ip', Net::pton(Net::ip()))
|
||||||
->where('attempt_timestamp', '>', time() - 1800)
|
->where('attempt_timestamp', '>', time() - 1800)
|
||||||
->where('attempt_success', '0')
|
->where('attempt_success', '0')
|
||||||
->count();
|
->count();
|
||||||
|
@ -172,7 +193,7 @@ class AuthController extends Controller
|
||||||
Config::get('cookie_path')
|
Config::get('cookie_path')
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->touchRateLimit($user->id, 1);
|
$this->touchRateLimit($user->id, true);
|
||||||
|
|
||||||
$success = 1;
|
$success = 1;
|
||||||
|
|
||||||
|
@ -189,12 +210,17 @@ class AuthController extends Controller
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the registration page.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function registerGet()
|
public function registerGet()
|
||||||
{
|
{
|
||||||
// Attempt to check if a user has already registered from the current IP
|
// Attempt to check if a user has already registered from the current IP
|
||||||
$getUserIP = DB::table('users')
|
$getUserIP = DB::table('users')
|
||||||
->where('register_ip', Net::pton(Net::IP()))
|
->where('register_ip', Net::pton(Net::ip()))
|
||||||
->orWhere('last_ip', Net::pton(Net::IP()))
|
->orWhere('last_ip', Net::pton(Net::ip()))
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
if ($getUserIP) {
|
if ($getUserIP) {
|
||||||
|
@ -207,6 +233,11 @@ class AuthController extends Controller
|
||||||
return Template::render('auth/register');
|
return Template::render('auth/register');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a registration attempt.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function registerPost()
|
public function registerPost()
|
||||||
{
|
{
|
||||||
// Preliminarily set registration to failed
|
// Preliminarily set registration to failed
|
||||||
|
@ -366,6 +397,11 @@ class AuthController extends Controller
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a activation attempt.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function activate()
|
public function activate()
|
||||||
{
|
{
|
||||||
// Preliminarily set activation to failed
|
// Preliminarily set activation to failed
|
||||||
|
@ -426,11 +462,21 @@ class AuthController extends Controller
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the reactivation request form.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function reactivateGet()
|
public function reactivateGet()
|
||||||
{
|
{
|
||||||
return Template::render('auth/reactivate');
|
return Template::render('auth/reactivate');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a reactivation preparation attempt.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function reactivatePost()
|
public function reactivatePost()
|
||||||
{
|
{
|
||||||
// Preliminarily set registration to failed
|
// Preliminarily set registration to failed
|
||||||
|
@ -498,11 +544,21 @@ class AuthController extends Controller
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password reset forum.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function resetPasswordGet()
|
public function resetPasswordGet()
|
||||||
{
|
{
|
||||||
return Template::render('auth/resetpassword');
|
return Template::render('auth/resetpassword');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a password reset attempt.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function resetPasswordPost()
|
public function resetPasswordPost()
|
||||||
{
|
{
|
||||||
// Preliminarily set action to failed
|
// Preliminarily set action to failed
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
namespace Sakura\Controllers;
|
namespace Sakura\Controllers;
|
||||||
|
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
use Sakura\User;
|
|
||||||
use Sakura\File;
|
use Sakura\File;
|
||||||
use Sakura\Perms\Site;
|
use Sakura\Perms\Site;
|
||||||
|
use Sakura\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File controller, handles user uploads like avatars.
|
* File controller, handles user uploads like avatars.
|
||||||
|
@ -20,18 +20,28 @@ use Sakura\Perms\Site;
|
||||||
*/
|
*/
|
||||||
class FileController extends Controller
|
class FileController extends Controller
|
||||||
{
|
{
|
||||||
private function serveImage($data, $mime, $name)
|
/**
|
||||||
|
* The base for serving a file.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function serve($data, $mime, $name)
|
||||||
{
|
{
|
||||||
// Add original filename
|
// Add original filename
|
||||||
header('Content-Disposition: inline; filename="' . $name . '"');
|
header("Content-Disposition: inline; filename={$name}");
|
||||||
|
|
||||||
// Set content type
|
// Set content type
|
||||||
header('Content-Type: ' . $mime);
|
header("Content-Type: {$mime}");
|
||||||
|
|
||||||
// Return image data
|
// Return image data
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to get an avatar.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function avatar($id = 0)
|
public function avatar($id = 0)
|
||||||
{
|
{
|
||||||
global $templateName;
|
global $templateName;
|
||||||
|
@ -72,26 +82,32 @@ class FileController extends Controller
|
||||||
$user = User::construct($id);
|
$user = User::construct($id);
|
||||||
|
|
||||||
if ($user->permission(Site::DEACTIVATED)) {
|
if ($user->permission(Site::DEACTIVATED)) {
|
||||||
return $this->serveImage($deactive['data'], $deactive['mime'], $deactive['name']);
|
return $this->serve($deactive['data'], $deactive['mime'], $deactive['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user->checkBan() || $user->permission(Site::RESTRICTED)) {
|
if ($user->checkBan()
|
||||||
return $this->serveImage($banned['data'], $banned['mime'], $banned['name']);
|
|| $user->permission(Site::RESTRICTED)) {
|
||||||
|
return $this->serve($banned['data'], $banned['mime'], $banned['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user->avatar) {
|
if (!$user->avatar) {
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$serve = new File($user->avatar);
|
$serve = new File($user->avatar);
|
||||||
|
|
||||||
if (!$serve->id) {
|
if (!$serve->id) {
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->serveImage($serve->data, $serve->mime, $serve->name);
|
return $this->serve($serve->data, $serve->mime, $serve->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to get a background.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function background($id = 0)
|
public function background($id = 0)
|
||||||
{
|
{
|
||||||
global $templateName;
|
global $templateName;
|
||||||
|
@ -104,24 +120,32 @@ class FileController extends Controller
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::construct($id);
|
$user = User::construct($id);
|
||||||
|
|
||||||
if ($user->permission(Site::DEACTIVATED) || $user->checkBan() || $user->permission(Site::RESTRICTED) || !$user->background) {
|
if ($user->permission(Site::DEACTIVATED)
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
|| $user->checkBan()
|
||||||
|
|| $user->permission(Site::RESTRICTED)
|
||||||
|
|| !$user->background) {
|
||||||
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$serve = new File($user->background);
|
$serve = new File($user->background);
|
||||||
|
|
||||||
if (!$serve->id) {
|
if (!$serve->id) {
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->serveImage($serve->data, $serve->mime, $serve->name);
|
return $this->serve($serve->data, $serve->mime, $serve->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to get a profile header.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function header($id = 0)
|
public function header($id = 0)
|
||||||
{
|
{
|
||||||
global $templateName;
|
global $templateName;
|
||||||
|
@ -134,21 +158,24 @@ class FileController extends Controller
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::construct($id);
|
$user = User::construct($id);
|
||||||
|
|
||||||
if ($user->permission(Site::DEACTIVATED) || $user->checkBan() || $user->permission(Site::RESTRICTED) || !$user->header) {
|
if ($user->permission(Site::DEACTIVATED)
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
|| $user->checkBan()
|
||||||
|
|| $user->permission(Site::RESTRICTED)
|
||||||
|
|| !$user->header) {
|
||||||
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$serve = new File($user->header);
|
$serve = new File($user->header);
|
||||||
|
|
||||||
if (!$serve->id) {
|
if (!$serve->id) {
|
||||||
return $this->serveImage($none['data'], $none['mime'], $none['name']);
|
return $this->serve($none['data'], $none['mime'], $none['name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->serveImage($serve->data, $serve->mime, $serve->name);
|
return $this->serve($serve->data, $serve->mime, $serve->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ class ForumController extends Controller
|
||||||
/**
|
/**
|
||||||
* Serves the forum index.
|
* Serves the forum index.
|
||||||
*
|
*
|
||||||
* @return mixed HTML for the forum index.
|
* @return string HTML for the forum index.
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
@ -119,6 +119,11 @@ class ForumController extends Controller
|
||||||
return Template::render('forum/index');
|
return Template::render('forum/index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a forum page.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function forum($id = 0)
|
public function forum($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -182,6 +187,11 @@ class ForumController extends Controller
|
||||||
return Template::render('forum/viewforum');
|
return Template::render('forum/viewforum');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a forum as read.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function markForumRead($id = 0)
|
public function markForumRead($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -246,6 +256,11 @@ class ForumController extends Controller
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View a thread.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function thread($id = 0)
|
public function thread($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -283,6 +298,11 @@ class ForumController extends Controller
|
||||||
return Template::render('forum/viewtopic');
|
return Template::render('forum/viewtopic');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moderate a thread.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function threadModerate($id = 0)
|
public function threadModerate($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -409,14 +429,17 @@ class ForumController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the variables
|
// Set the variables
|
||||||
Template::vars([
|
Template::vars(compact('message', 'redirect'));
|
||||||
'page' => compact('message', 'redirect'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
// Print page contents
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect to the position of a post in a thread.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function post($id = 0)
|
public function post($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -462,6 +485,11 @@ class ForumController extends Controller
|
||||||
return header("Location: {$threadLink}#p{$post->id}");
|
return header("Location: {$threadLink}#p{$post->id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the raw text of a post.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function postRaw($id = 0)
|
public function postRaw($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -485,6 +513,11 @@ class ForumController extends Controller
|
||||||
return $post->text;
|
return $post->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reply to a thread.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function threadReply($id = 0)
|
public function threadReply($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -571,6 +604,11 @@ class ForumController extends Controller
|
||||||
return header("Location: {$postLink}");
|
return header("Location: {$postLink}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a thread.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function createThread($id = 0)
|
public function createThread($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -664,6 +702,11 @@ class ForumController extends Controller
|
||||||
return Template::render('forum/viewtopic');
|
return Template::render('forum/viewtopic');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit a post.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function editPost($id = 0)
|
public function editPost($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
@ -781,6 +824,11 @@ class ForumController extends Controller
|
||||||
return header("Location: {$postLink}");
|
return header("Location: {$postLink}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a post.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function deletePost($id = 0)
|
public function deletePost($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
|
|
@ -17,9 +17,14 @@ use Sakura\BBcode;
|
||||||
*/
|
*/
|
||||||
class HelperController extends Controller
|
class HelperController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Parsed BBcode from a post request
|
||||||
|
*
|
||||||
|
* @return string The parsed BBcode
|
||||||
|
*/
|
||||||
public function bbcodeParse()
|
public function bbcodeParse()
|
||||||
{
|
{
|
||||||
$text = isset($_POST['text']) ? $_POST['text'] : null;
|
$text = isset($_POST['text']) ? $_POST['text'] : '';
|
||||||
|
|
||||||
$text = BBcode::toHTML($text);
|
$text = BBcode::toHTML($text);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ use Sakura\DB;
|
||||||
use Sakura\News;
|
use Sakura\News;
|
||||||
use Sakura\Template;
|
use Sakura\Template;
|
||||||
use Sakura\User;
|
use Sakura\User;
|
||||||
use Sakura\Users;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meta page controllers (sections that aren't big enough to warrant a dedicated controller).
|
* Meta page controllers (sections that aren't big enough to warrant a dedicated controller).
|
||||||
|
@ -29,6 +28,38 @@ class MetaController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
// Get the newest user
|
||||||
|
$newestUserId = DB::table('users')
|
||||||
|
->where('rank_main', '!=', Config::get('restricted_rank_id'))
|
||||||
|
->where('rank_main', '!=', Config::get('deactive_rank_id'))
|
||||||
|
->orderBy('user_id', 'desc')
|
||||||
|
->limit(1)
|
||||||
|
->get(['user_id']);
|
||||||
|
$newestUser = User::construct($newestUserId ? $newestUserId[0]->user_id : 0);
|
||||||
|
|
||||||
|
// Get all the currently online users
|
||||||
|
$timeRange = time() - Config::get('max_online_time');
|
||||||
|
|
||||||
|
// Create a storage variable
|
||||||
|
$onlineUsers = [];
|
||||||
|
|
||||||
|
// Get all online users
|
||||||
|
$getOnline = DB::table('users')
|
||||||
|
->where('user_last_online', '>', $timeRange)
|
||||||
|
->get(['user_id']);
|
||||||
|
$getOnline = array_column($getOnline, 'user_id');
|
||||||
|
|
||||||
|
foreach ($getOnline as $user) {
|
||||||
|
$user = User::construct($user);
|
||||||
|
|
||||||
|
// Do a second check
|
||||||
|
if (!$user->isOnline()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$onlineUsers[$user->id] = $user;
|
||||||
|
}
|
||||||
|
|
||||||
// Merge index specific stuff with the global render data
|
// Merge index specific stuff with the global render data
|
||||||
Template::vars([
|
Template::vars([
|
||||||
'news' => new News(Config::get('site_news_category')),
|
'news' => new News(Config::get('site_news_category')),
|
||||||
|
@ -38,14 +69,14 @@ class MetaController extends Controller
|
||||||
->where('password_algo', '!=', 'disabled')
|
->where('password_algo', '!=', 'disabled')
|
||||||
->whereNotIn('rank_main', [1, 10])
|
->whereNotIn('rank_main', [1, 10])
|
||||||
->count(),
|
->count(),
|
||||||
'newestUser' => User::construct(Users::getNewestUserId()),
|
'newestUser' => $newestUser,
|
||||||
'lastRegDate' => date_diff(
|
'lastRegDate' => date_diff(
|
||||||
date_create(date('Y-m-d', User::construct(Users::getNewestUserId())->registered)),
|
date_create(date('Y-m-d', $newestUser->registered)),
|
||||||
date_create(date('Y-m-d'))
|
date_create(date('Y-m-d'))
|
||||||
)->format('%a'),
|
)->format('%a'),
|
||||||
'topicCount' => DB::table('topics')->count(),
|
'topicCount' => DB::table('topics')->count(),
|
||||||
'postCount' => DB::table('posts')->count(),
|
'postCount' => DB::table('posts')->count(),
|
||||||
'onlineUsers' => Users::checkAllOnline(),
|
'onlineUsers' => $onlineUsers,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -153,14 +184,6 @@ class MetaController extends Controller
|
||||||
*/
|
*/
|
||||||
public function search()
|
public function search()
|
||||||
{
|
{
|
||||||
// Set parse variables
|
|
||||||
Template::vars([
|
|
||||||
'page' => [
|
|
||||||
'title' => 'Search',
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
|
||||||
return Template::render('main/search');
|
return Template::render('main/search');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,10 @@ namespace Sakura\Controllers;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
use Sakura\Template;
|
|
||||||
use Sakura\User;
|
|
||||||
use Sakura\Users;
|
|
||||||
use Sakura\Utils;
|
|
||||||
use Sakura\Payments;
|
use Sakura\Payments;
|
||||||
use Sakura\Perms\Site;
|
use Sakura\Perms\Site;
|
||||||
|
use Sakura\Router;
|
||||||
|
use Sakura\Template;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Premium pages controller.
|
* Premium pages controller.
|
||||||
|
@ -24,144 +22,164 @@ use Sakura\Perms\Site;
|
||||||
*/
|
*/
|
||||||
class PremiumController extends Controller
|
class PremiumController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The amount of premium a user received per period.
|
||||||
|
*/
|
||||||
|
const PERIOD_PER_PAYMENT = 2628000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
Payments::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the premium purchase index.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
global $currentUser, $urls;
|
global $currentUser;
|
||||||
|
|
||||||
// Switch between modes (we only allow this to be used by logged in user)
|
$price = Config::get('premium_price_per_month');
|
||||||
if (isset($_REQUEST['mode'])
|
$amountLimit = Config::get('premium_amount_max');
|
||||||
&& Users::checkLogin()
|
|
||||||
&& $currentUser->permission(Site::OBTAIN_PREMIUM)) {
|
|
||||||
// Initialise Payments class
|
|
||||||
if (!Payments::init()) {
|
|
||||||
header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
|
|
||||||
} else {
|
|
||||||
switch ($_REQUEST['mode']) {
|
|
||||||
// Create the purchase
|
|
||||||
case 'purchase':
|
|
||||||
// Compare time and session so we know the link isn't forged
|
|
||||||
if (!isset($_REQUEST['time'])
|
|
||||||
|| $_REQUEST['time'] < time() - 1000) {
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match session ids for the same reason
|
Template::vars(compact('price', 'amountLimit'));
|
||||||
if (!isset($_REQUEST['session'])
|
|
||||||
|| $_REQUEST['session'] != session_id()) {
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Half if shit isn't gucci
|
|
||||||
if (!isset($_POST['months'])
|
|
||||||
|| !is_numeric($_POST['months'])
|
|
||||||
|| (int) $_POST['months'] < 1
|
|
||||||
|| (int) $_POST['months'] > Config::get('premium_amount_max')) {
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
|
|
||||||
} else {
|
|
||||||
// Calculate the total
|
|
||||||
$total = (float) Config::get('premium_price_per_month') * (int) $_POST['months'];
|
|
||||||
$total = number_format($total, 2, '.', '');
|
|
||||||
|
|
||||||
// Generate item name
|
|
||||||
$itemName = Config::get('sitename')
|
|
||||||
. ' Premium - '
|
|
||||||
. (string) $_POST['months']
|
|
||||||
. ' month'
|
|
||||||
. ((int) $_POST['months'] == 1 ? '' : 's');
|
|
||||||
|
|
||||||
// Attempt to create a transaction
|
|
||||||
if ($transaction = Payments::createTransaction(
|
|
||||||
$total,
|
|
||||||
$itemName,
|
|
||||||
Config::get('sitename') . ' Premium Purchase',
|
|
||||||
'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . Config::get('url_main') . $urls->format('SITE_PREMIUM')
|
|
||||||
)) {
|
|
||||||
// Store the amount of months in the global session array
|
|
||||||
$_SESSION['premiumMonths'] = (int) $_POST['months'];
|
|
||||||
|
|
||||||
return header('Location: ' . $transaction);
|
|
||||||
} else {
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finalising the purchase
|
|
||||||
case 'finish':
|
|
||||||
// Check if the success GET request is set and is true
|
|
||||||
if (isset($_GET['success'])
|
|
||||||
&& isset($_GET['paymentId'])
|
|
||||||
&& isset($_GET['PayerID'])
|
|
||||||
&& isset($_SESSION['premiumMonths'])) {
|
|
||||||
// Attempt to complete the transaction
|
|
||||||
try {
|
|
||||||
$finalise = Payments::completeTransaction($_GET['paymentId'], $_GET['PayerID']);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
return trigger_error('Something went horribly wrong.', E_USER_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to complete the transaction
|
|
||||||
if ($finalise) {
|
|
||||||
// Make the user premium
|
|
||||||
Users::addUserPremium($currentUser->id, (2628000 * $_SESSION['premiumMonths']));
|
|
||||||
Users::updatePremiumMeta($currentUser->id);
|
|
||||||
Utils::updatePremiumTracker(
|
|
||||||
$currentUser->id,
|
|
||||||
((float) Config::get('premium_price_per_month') * $_SESSION['premiumMonths']),
|
|
||||||
$currentUser->username
|
|
||||||
. ' bought premium for '
|
|
||||||
. $_SESSION['premiumMonths']
|
|
||||||
. ' month'
|
|
||||||
. ($_SESSION['premiumMonths'] == 1 ? '' : 's')
|
|
||||||
. '.'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Redirect to the complete
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM') . '?mode=complete');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM') . '?fail=true');
|
|
||||||
|
|
||||||
case 'complete':
|
|
||||||
// Set parse variables
|
|
||||||
Template::vars([
|
|
||||||
'page' => [
|
|
||||||
'expiration' => ($prem = $currentUser->isPremium()[2]) !== null ? $prem : 0,
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
|
||||||
return Template::render('main/premiumcomplete');
|
|
||||||
|
|
||||||
default:
|
|
||||||
return header('Location: ' . $urls->format('SITE_PREMIUM'));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set parse variables
|
|
||||||
Template::vars([
|
|
||||||
'page' => [
|
|
||||||
'fail' => isset($_GET['fail']),
|
|
||||||
'price' => Config::get('premium_price_per_month'),
|
|
||||||
'current' => $currentUser->isPremium(),
|
|
||||||
'amount_max' => Config::get('premium_amount_max'),
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
|
||||||
return Template::render('main/support');
|
return Template::render('main/support');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tracker()
|
/**
|
||||||
|
* Handles a purchase request.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function purchase()
|
||||||
{
|
{
|
||||||
// Set parse variables
|
global $currentUser;
|
||||||
Template::vars([
|
|
||||||
'tracker' => Utils::getPremiumTrackerData(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
// Get values from post
|
||||||
return Template::render('main/supporttracker');
|
$session = isset($_POST['session']) ? $_POST['session'] : '';
|
||||||
|
$months = isset($_POST['months']) ? $_POST['months'] : 0;
|
||||||
|
|
||||||
|
// Check if the session is valid
|
||||||
|
if ($session !== session_id()
|
||||||
|
|| $currentUser->permission(Site::DEACTIVATED)
|
||||||
|
|| !$currentUser->permission(Site::OBTAIN_PREMIUM)) {
|
||||||
|
$message = "You are not allowed to get premium!";
|
||||||
|
$redirect = Router::route('premium.index');
|
||||||
|
|
||||||
|
Template::vars(compact('message', 'redirect'));
|
||||||
|
|
||||||
|
return Template::render('global/information');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the limit
|
||||||
|
$amountLimit = Config::get('premium_amount_max');
|
||||||
|
|
||||||
|
// Check months
|
||||||
|
if ($months < 1
|
||||||
|
|| $months > $amountLimit) {
|
||||||
|
$message = "An incorrect amount of months was specified, stop messing with the source.";
|
||||||
|
$redirect = Router::route('premium.index');
|
||||||
|
|
||||||
|
Template::vars(compact('message', 'redirect'));
|
||||||
|
|
||||||
|
return Template::render('global/information');
|
||||||
|
}
|
||||||
|
|
||||||
|
$pricePerMonth = Config::get('premium_price_per_month');
|
||||||
|
$total = number_format($pricePerMonth * $months, 2, '.', '');
|
||||||
|
|
||||||
|
$siteName = Config::get('sitename');
|
||||||
|
$multiMonths = $months !== 1 ? 's' : '';
|
||||||
|
|
||||||
|
$siteUrl = 'http'
|
||||||
|
. (isset($_SERVER['HTTPS']) ? 's' : '')
|
||||||
|
. "://{$_SERVER['SERVER_NAME']}"
|
||||||
|
. ($_SERVER['SERVER_PORT'] != 80 ? ":{$_SERVER['SERVER_PORT']}" : '');
|
||||||
|
$handlerRoute = Router::route('premium.handle');
|
||||||
|
|
||||||
|
$itemName = "{$siteName} Premium - {$months} month{$multiMonths}";
|
||||||
|
$transactionName = "{$siteName} premium purchase";
|
||||||
|
$handlerUrl = "{$siteUrl}{$handlerRoute}";
|
||||||
|
|
||||||
|
// Create the transaction
|
||||||
|
$transaction = Payments::createTransaction(
|
||||||
|
$total,
|
||||||
|
$itemName,
|
||||||
|
$transactionName,
|
||||||
|
$handlerUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
// Attempt to create a transaction
|
||||||
|
if (!$transaction) {
|
||||||
|
$message = "Something went wrong while preparing the transaction.";
|
||||||
|
$redirect = Router::route('premium.index');
|
||||||
|
|
||||||
|
Template::vars(compact('message', 'redirect'));
|
||||||
|
|
||||||
|
return Template::render('global/information');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the amount of months in the global session array
|
||||||
|
$_SESSION['premiumMonths'] = (int) $months;
|
||||||
|
|
||||||
|
return header("Location: {$transaction}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the data returned by PayPal.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
global $currentUser;
|
||||||
|
|
||||||
|
$success = isset($_GET['success']);
|
||||||
|
$payment = isset($_GET['paymentId']) ? $_GET['paymentId'] : null;
|
||||||
|
$payer = isset($_GET['PayerID']) ? $_GET['PayerID'] : null;
|
||||||
|
$months = isset($_SESSION['premiumMonths']) ? $_SESSION['premiumMonths'] : null;
|
||||||
|
|
||||||
|
$successRoute = Router::route('premium.complete');
|
||||||
|
$failRoute = Router::route('premium.index') . "?fail=true";
|
||||||
|
|
||||||
|
if (!$success
|
||||||
|
|| !$payment
|
||||||
|
|| !$payer
|
||||||
|
|| !$months) {
|
||||||
|
return header("Location: {$failRoute}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to complete the transaction
|
||||||
|
try {
|
||||||
|
$finalise = Payments::completeTransaction($_GET['paymentId'], $_GET['PayerID']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$finalise = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$finalise) {
|
||||||
|
return header("Location: {$failRoute}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$pricePerMonth = Config::get('premium_price_per_month');
|
||||||
|
|
||||||
|
$currentUser->addPremium(self::PERIOD_PER_PAYMENT * $months);
|
||||||
|
|
||||||
|
return header("Location: {$successRoute}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Presents the user with a thank you <3.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function complete()
|
||||||
|
{
|
||||||
|
return Template::render('main/premiumcomplete');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,46 +49,18 @@ class UserController extends Controller
|
||||||
|
|
||||||
// Redirect if so
|
// Redirect if so
|
||||||
if ($check) {
|
if ($check) {
|
||||||
Template::vars([
|
$message = "This user changed their username! Redirecting you to their new profile.";
|
||||||
'page' => [
|
$redirect = Router::route('user.profile', $check[0]->user_id);
|
||||||
'message' => 'The user this profile belongs to changed their username, you are being redirected.',
|
|
||||||
'redirect' => Router::route('user.profile', $check[0]->user_id),
|
Template::vars(compact('message', 'redirect'));
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
// Print page contents
|
||||||
return Template::render('global/information');
|
return Template::render('global/information');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're trying to restrict
|
|
||||||
if (isset($_GET['restrict']) && $_GET['restrict'] == session_id() && $currentUser->permission(\Sakura\Perms\Manage::CAN_RESTRICT_USERS, \Sakura\Perms::MANAGE)) {
|
|
||||||
// Check restricted status
|
|
||||||
$restricted = $profile->permission(\Sakura\Perms\Site::RESTRICTED);
|
|
||||||
|
|
||||||
if ($restricted) {
|
|
||||||
$profile->removeRanks([Config::get('restricted_rank_id')]);
|
|
||||||
$profile->addRanks([2]);
|
|
||||||
} else {
|
|
||||||
$profile->addRanks([Config::get('restricted_rank_id')]);
|
|
||||||
$profile->removeRanks(array_keys($profile->ranks));
|
|
||||||
}
|
|
||||||
|
|
||||||
Template::vars([
|
|
||||||
'page' => [
|
|
||||||
'message' => 'Toggled the restricted status of the user.',
|
|
||||||
'redirect' => Router::route('user.profile', $profile->id),
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
|
||||||
return Template::render('global/information');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set parse variables
|
// Set parse variables
|
||||||
Template::vars([
|
Template::vars(compact('profile'));
|
||||||
'profile' => $profile,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Print page contents
|
// Print page contents
|
||||||
return Template::render('main/profile');
|
return Template::render('main/profile');
|
||||||
|
@ -128,17 +100,21 @@ class UserController extends Controller
|
||||||
// Get the active rank
|
// Get the active rank
|
||||||
$rank = array_key_exists($rank, $ranks) ? $rank : ($rank ? 0 : 2);
|
$rank = array_key_exists($rank, $ranks) ? $rank : ($rank ? 0 : 2);
|
||||||
|
|
||||||
|
// Get members per page
|
||||||
|
$membersPerPage = Config::get('members_per_page');
|
||||||
|
|
||||||
// Set parse variables
|
// Set parse variables
|
||||||
Template::vars([
|
Template::vars(compact('ranks', 'rank', 'membersPerPage'));
|
||||||
'ranks' => $ranks,
|
|
||||||
'rank' => $rank,
|
|
||||||
'membersPerPage' => Config::get('members_per_page'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Render the template
|
// Render the template
|
||||||
return Template::render('main/memberlist');
|
return Template::render('main/memberlist');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification JSON object for the currently authenticated user.
|
||||||
|
*
|
||||||
|
* @return string The JSON object.
|
||||||
|
*/
|
||||||
public function notifications()
|
public function notifications()
|
||||||
{
|
{
|
||||||
// TODO: add friend on/offline messages
|
// TODO: add friend on/offline messages
|
||||||
|
@ -153,6 +129,13 @@ class UserController extends Controller
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a notification as read.
|
||||||
|
*
|
||||||
|
* @param int The ID of the notification.
|
||||||
|
*
|
||||||
|
* @return string Not entirely set on this one yet but 1 for success and 0 for fail.
|
||||||
|
*/
|
||||||
public function markNotification($id = 0)
|
public function markNotification($id = 0)
|
||||||
{
|
{
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
|
|
@ -168,7 +168,7 @@ class Post
|
||||||
'topic_id' => $thread->id,
|
'topic_id' => $thread->id,
|
||||||
'forum_id' => $thread->forum,
|
'forum_id' => $thread->forum,
|
||||||
'poster_id' => $poster->id,
|
'poster_id' => $poster->id,
|
||||||
'poster_ip' => Net::IP(),
|
'poster_ip' => Net::ip(),
|
||||||
'post_time' => time(),
|
'post_time' => time(),
|
||||||
'post_subject' => $subject,
|
'post_subject' => $subject,
|
||||||
'post_text' => $text,
|
'post_text' => $text,
|
||||||
|
@ -206,7 +206,7 @@ class Post
|
||||||
'topic_id' => $thread->id,
|
'topic_id' => $thread->id,
|
||||||
'forum_id' => $thread->forum,
|
'forum_id' => $thread->forum,
|
||||||
'poster_id' => $this->poster->id,
|
'poster_id' => $this->poster->id,
|
||||||
'poster_ip' => Net::pton(Net::IP()),
|
'poster_ip' => Net::pton(Net::ip()),
|
||||||
'post_time' => $this->time,
|
'post_time' => $this->time,
|
||||||
'post_subject' => $this->subject,
|
'post_subject' => $this->subject,
|
||||||
'post_text' => $this->text,
|
'post_text' => $this->text,
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Net
|
||||||
*
|
*
|
||||||
* @return string The IP.
|
* @return string The IP.
|
||||||
*/
|
*/
|
||||||
public static function IP()
|
public static function ip()
|
||||||
{
|
{
|
||||||
return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
|
return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ class Net
|
||||||
{
|
{
|
||||||
// Generate an address from the mask
|
// Generate an address from the mask
|
||||||
$addr = str_repeat("f", $mask / 4);
|
$addr = str_repeat("f", $mask / 4);
|
||||||
|
|
||||||
// Append uneven bit
|
// Append uneven bit
|
||||||
switch ($mask % 4) {
|
switch ($mask % 4) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -178,10 +178,10 @@ class Net
|
||||||
$addr .= 'e';
|
$addr .= 'e';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad the address with zeroes
|
// Pad the address with zeroes
|
||||||
$addr = str_pad($addr, 32, '0');
|
$addr = str_pad($addr, 32, '0');
|
||||||
|
|
||||||
// Pack the address
|
// Pack the address
|
||||||
$addr = pack('H*', $addr);
|
$addr = pack('H*', $addr);
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ class Session
|
||||||
DB::table('sessions')
|
DB::table('sessions')
|
||||||
->insert([
|
->insert([
|
||||||
'user_id' => $this->userId,
|
'user_id' => $this->userId,
|
||||||
'user_ip' => Net::pton(Net::IP()),
|
'user_ip' => Net::pton(Net::ip()),
|
||||||
'user_agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
|
'user_agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
|
||||||
'session_key' => $session,
|
'session_key' => $session,
|
||||||
'session_start' => time(),
|
'session_start' => time(),
|
||||||
|
@ -141,7 +141,7 @@ class Session
|
||||||
if ($ipCheck) {
|
if ($ipCheck) {
|
||||||
// Split both IPs up
|
// Split both IPs up
|
||||||
$sessionIP = explode('.', $session[0]->user_ip);
|
$sessionIP = explode('.', $session[0]->user_ip);
|
||||||
$userIP = explode('.', Net::IP());
|
$userIP = explode('.', Net::ip());
|
||||||
|
|
||||||
// Take 1 off the ipCheck variable so it's equal to the array keys
|
// Take 1 off the ipCheck variable so it's equal to the array keys
|
||||||
$ipCheck = $ipCheck - 1;
|
$ipCheck = $ipCheck - 1;
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Sakura;
|
||||||
|
|
||||||
use Sakura\Perms;
|
use Sakura\Perms;
|
||||||
use Sakura\Perms\Site;
|
use Sakura\Perms\Site;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Everything you'd ever need from a specific user.
|
* Everything you'd ever need from a specific user.
|
||||||
|
@ -268,8 +269,8 @@ class User
|
||||||
'password_iter' => $password[1],
|
'password_iter' => $password[1],
|
||||||
'email' => $emailClean,
|
'email' => $emailClean,
|
||||||
'rank_main' => 0,
|
'rank_main' => 0,
|
||||||
'register_ip' => Net::pton(Net::IP()),
|
'register_ip' => Net::pton(Net::ip()),
|
||||||
'last_ip' => Net::pton(Net::IP()),
|
'last_ip' => Net::pton(Net::ip()),
|
||||||
'user_registered' => time(),
|
'user_registered' => time(),
|
||||||
'user_last_online' => 0,
|
'user_last_online' => 0,
|
||||||
'user_country' => Utils::getCountryCode(),
|
'user_country' => Utils::getCountryCode(),
|
||||||
|
@ -913,37 +914,99 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this user have premium?
|
* Add premium in seconds.
|
||||||
*
|
*
|
||||||
* @return array Premium status information.
|
* @param int $seconds The amount of seconds.
|
||||||
|
*
|
||||||
|
* @return int The new expiry date.
|
||||||
*/
|
*/
|
||||||
public function isPremium()
|
public function addPremium($seconds)
|
||||||
{
|
{
|
||||||
|
// Check if there's already a record of premium for this user in the database
|
||||||
// Check if the user has static premium
|
$getUser = DB::table('premium')
|
||||||
if ($this->permission(Site::STATIC_PREMIUM)) {
|
|
||||||
return [2, 0, time() + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to retrieve the premium record from the database
|
|
||||||
$getRecord = DB::table('premium')
|
|
||||||
->where('user_id', $this->id)
|
->where('user_id', $this->id)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// If nothing was returned just return false
|
// Calculate the (new) start and expiration timestamp
|
||||||
if (empty($getRecord)) {
|
$start = $getUser ? $getUser[0]->premium_start : time();
|
||||||
return [0];
|
$expire = $getUser ? $getUser[0]->premium_expire + $seconds : time() + $seconds;
|
||||||
|
|
||||||
|
// If the user already exists do an update call, otherwise an insert call
|
||||||
|
if ($getUser) {
|
||||||
|
DB::table('premium')
|
||||||
|
->where('user_id', $this->id)
|
||||||
|
->update([
|
||||||
|
'premium_expire' => $expire,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
DB::table('premium')
|
||||||
|
->insert([
|
||||||
|
'user_id' => $this->id,
|
||||||
|
'premium_start' => $start,
|
||||||
|
'premium_expire' => $expire,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$getRecord = $getRecord[0];
|
// Return the expiration timestamp
|
||||||
|
return $expire;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the Tenshi hasn't expired
|
/**
|
||||||
if ($getRecord->premium_expire < time()) {
|
* Does this user have premium?
|
||||||
return [0, $getRecord->premium_start, $getRecord->premium_expire];
|
*
|
||||||
|
* @return int Returns the premium expiration date.
|
||||||
|
*/
|
||||||
|
public function isPremium()
|
||||||
|
{
|
||||||
|
// Get rank IDs from the db
|
||||||
|
$premiumRank = (int) Config::get('premium_rank_id');
|
||||||
|
$defaultRank = (int) Config::get('default_rank_id');
|
||||||
|
|
||||||
|
// Fetch expiration date
|
||||||
|
$expire = $this->premiumInfo()->expire;
|
||||||
|
|
||||||
|
// Check if the user has static premium
|
||||||
|
if (!$expire
|
||||||
|
&& $this->permission(Site::STATIC_PREMIUM)) {
|
||||||
|
$expire = time() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else return the start and expiration date
|
// Check if the user has premium and isn't in the premium rank
|
||||||
return [1, $getRecord->premium_start, $getRecord->premium_expire];
|
if ($expire
|
||||||
|
&& !$this->hasRanks([$premiumRank])) {
|
||||||
|
// Add the premium rank
|
||||||
|
$this->addRanks([$premiumRank]);
|
||||||
|
|
||||||
|
// Set it as default
|
||||||
|
if ($this->mainRankId == $defaultRank) {
|
||||||
|
$this->setMainRank($premiumRank);
|
||||||
|
}
|
||||||
|
} elseif (!$expire
|
||||||
|
&& $this->hasRanks([$premiumRank])) {
|
||||||
|
$this->removeRanks([$premiumRank]);
|
||||||
|
|
||||||
|
if ($this->mainRankId == $premiumRank) {
|
||||||
|
$this->setMainRank($defaultRank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $expire;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function premiumInfo()
|
||||||
|
{
|
||||||
|
// Attempt to retrieve the premium record from the database
|
||||||
|
$check = DB::table('premium')
|
||||||
|
->where('user_id', $this->id)
|
||||||
|
->where('premium_expire', '>', time())
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$return = new stdClass;
|
||||||
|
|
||||||
|
$return->start = $check ? $check[0]->premium_start : 0;
|
||||||
|
$return->expire = $check ? $check[0]->premium_expire : 0;
|
||||||
|
|
||||||
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,22 +47,6 @@ class Users
|
||||||
|
|
||||||
// Check if the session exists and check if the user is activated
|
// Check if the session exists and check if the user is activated
|
||||||
if ($sessionValid == 0 || $user->permission(Site::DEACTIVATED)) {
|
if ($sessionValid == 0 || $user->permission(Site::DEACTIVATED)) {
|
||||||
// Unset User ID
|
|
||||||
setcookie(
|
|
||||||
Config::get('cookie_prefix') . 'id',
|
|
||||||
0,
|
|
||||||
time() - 60,
|
|
||||||
Config::get('cookie_path')
|
|
||||||
);
|
|
||||||
|
|
||||||
// Unset Session ID
|
|
||||||
setcookie(
|
|
||||||
Config::get('cookie_prefix') . 'session',
|
|
||||||
'',
|
|
||||||
time() - 60,
|
|
||||||
Config::get('cookie_path')
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +76,6 @@ class Users
|
||||||
'user_last_online' => time(),
|
'user_last_online' => time(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update the premium meta
|
|
||||||
self::updatePremiumMeta($uid);
|
|
||||||
|
|
||||||
// If everything went through return true
|
// If everything went through return true
|
||||||
return [$uid, $sid];
|
return [$uid, $sid];
|
||||||
}
|
}
|
||||||
|
@ -250,120 +231,4 @@ class Users
|
||||||
// Return the yeahs
|
// Return the yeahs
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all online users.
|
|
||||||
*
|
|
||||||
* @return array Array containing User instances.
|
|
||||||
*/
|
|
||||||
public static function checkAllOnline()
|
|
||||||
{
|
|
||||||
// Assign time - 500 to a variable
|
|
||||||
$time = time() - Config::get('max_online_time');
|
|
||||||
|
|
||||||
$return = [];
|
|
||||||
|
|
||||||
// Get all online users in the past 5 minutes
|
|
||||||
$getAll = DB::table('users')
|
|
||||||
->where('user_last_online', '>', $time)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
foreach ($getAll as $user) {
|
|
||||||
$return[] = User::construct($user->user_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return all the online users
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add premium time to a user.
|
|
||||||
*
|
|
||||||
* @param int $id The user ID.
|
|
||||||
* @param int $seconds The amount of extra seconds.
|
|
||||||
*
|
|
||||||
* @return array|double|int The new expiry date.
|
|
||||||
*/
|
|
||||||
public static function addUserPremium($id, $seconds)
|
|
||||||
{
|
|
||||||
// Check if there's already a record of premium for this user in the database
|
|
||||||
$getUser = DB::table('premium')
|
|
||||||
->where('user_id', $id)
|
|
||||||
->count();
|
|
||||||
|
|
||||||
// Calculate the (new) start and expiration timestamp
|
|
||||||
$start = isset($getUser['premium_start']) ? $getUser['premium_start'] : time();
|
|
||||||
$expire = isset($getUser['premium_expire']) ? $getUser['premium_expire'] + $seconds : time() + $seconds;
|
|
||||||
|
|
||||||
// If the user already exists do an update call, otherwise an insert call
|
|
||||||
if (empty($getUser)) {
|
|
||||||
DB::table('premium')
|
|
||||||
->insert([
|
|
||||||
'user_id' => $id,
|
|
||||||
'premium_start' => $start,
|
|
||||||
'premium_expire' => $expire,
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
DB::table('premium')
|
|
||||||
->where('user_id', $id)
|
|
||||||
->update('premium_expire', $expire);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the expiration timestamp
|
|
||||||
return $expire;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process premium meta data.
|
|
||||||
*
|
|
||||||
* @param int $id The user ID.
|
|
||||||
*/
|
|
||||||
public static function updatePremiumMeta($id)
|
|
||||||
{
|
|
||||||
// Get the ID for the premium user rank from the database
|
|
||||||
$premiumRank = Config::get('premium_rank_id');
|
|
||||||
$excepted = Config::get('restricted_rank_id');
|
|
||||||
|
|
||||||
// Create user object
|
|
||||||
$user = User::construct($id);
|
|
||||||
|
|
||||||
// Run the check
|
|
||||||
$check = $user->isPremium();
|
|
||||||
|
|
||||||
// Check if the user has premium
|
|
||||||
if ($check[0] && !array_key_exists($excepted, $user->ranks)) {
|
|
||||||
// If so add the rank to them
|
|
||||||
$user->addRanks([$premiumRank]);
|
|
||||||
|
|
||||||
// Check if the user's default rank is standard user and update it to premium
|
|
||||||
if ($user->mainRankId == 2) {
|
|
||||||
$user->setMainRank($premiumRank);
|
|
||||||
}
|
|
||||||
} elseif (!$check[0]) {
|
|
||||||
// Remove the expired entry
|
|
||||||
DB::table('premium')
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->delete();
|
|
||||||
|
|
||||||
// Else remove the rank from them
|
|
||||||
$user->removeRanks([$premiumRank]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the newest member's ID.
|
|
||||||
*
|
|
||||||
* @return int The user ID.
|
|
||||||
*/
|
|
||||||
public static function getNewestUserId()
|
|
||||||
{
|
|
||||||
$get = DB::table('users')
|
|
||||||
->where('rank_main', '!=', Config::get('restricted_rank_id'))
|
|
||||||
->where('rank_main', '!=', Config::get('deactive_rank_id'))
|
|
||||||
->orderBy('user_id', 'desc')
|
|
||||||
->limit(1)
|
|
||||||
->get(['user_id']);
|
|
||||||
|
|
||||||
return $get ? $get[0]->user_id : 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,7 @@ class Utils
|
||||||
// Attempt to get country code using PHP's built in geo thing
|
// Attempt to get country code using PHP's built in geo thing
|
||||||
if (function_exists("geoip_country_code_by_name")) {
|
if (function_exists("geoip_country_code_by_name")) {
|
||||||
try {
|
try {
|
||||||
$code = geoip_country_code_by_name(Net::IP());
|
$code = geoip_country_code_by_name(Net::ip());
|
||||||
|
|
||||||
// Check if $code is anything
|
// Check if $code is anything
|
||||||
if ($code) {
|
if ($code) {
|
||||||
|
@ -346,94 +346,4 @@ class Utils
|
||||||
// Return the formatted string
|
// Return the formatted string
|
||||||
return $bytes;
|
return $bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the premium tracker data.
|
|
||||||
*
|
|
||||||
* @return array The premium tracker data.
|
|
||||||
*/
|
|
||||||
public static function getPremiumTrackerData()
|
|
||||||
{
|
|
||||||
// Create data array
|
|
||||||
$data = [];
|
|
||||||
|
|
||||||
// Get database stuff
|
|
||||||
$table = DB::table('premium_log')
|
|
||||||
->orderBy('transaction_id', 'desc')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
// Add raw table data to data array
|
|
||||||
$data['table'] = $table;
|
|
||||||
|
|
||||||
// Create balance entry
|
|
||||||
$data['balance'] = 0.0;
|
|
||||||
|
|
||||||
// users
|
|
||||||
$data['users'] = [];
|
|
||||||
|
|
||||||
// Calculate the thing
|
|
||||||
foreach ($table as $row) {
|
|
||||||
// Calculate balance
|
|
||||||
$data['balance'] = $data['balance'] + $row->transaction_amount;
|
|
||||||
|
|
||||||
// Add userdata to table
|
|
||||||
if (!array_key_exists($row->user_id, $data['users'])) {
|
|
||||||
$data['users'][$row->user_id] = User::construct($row->user_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the data
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new entry to the tracker.
|
|
||||||
*
|
|
||||||
* @param int $id The user ID.
|
|
||||||
* @param float $amount The amount of money.
|
|
||||||
* @param string $comment A little information.
|
|
||||||
*/
|
|
||||||
public static function updatePremiumTracker($id, $amount, $comment)
|
|
||||||
{
|
|
||||||
DB::table('premium_log')
|
|
||||||
->insert([
|
|
||||||
'user_id' => $id,
|
|
||||||
'transaction_amount' => $amount,
|
|
||||||
'transaction_date' => time(),
|
|
||||||
'transaction_comment' => $comment,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up the contents of <code> tags.
|
|
||||||
*
|
|
||||||
* @param string $text Dirty
|
|
||||||
*
|
|
||||||
* @return string Clean
|
|
||||||
*/
|
|
||||||
public static function fixCodeTags($text)
|
|
||||||
{
|
|
||||||
$parts = explode('<code>', $text);
|
|
||||||
$newStr = '';
|
|
||||||
|
|
||||||
if (count($parts) > 1) {
|
|
||||||
foreach ($parts as $p) {
|
|
||||||
$parts2 = explode('</code>', $p);
|
|
||||||
if (count($parts2) > 1) {
|
|
||||||
$code = str_replace('<br />', '', $parts2[0]);
|
|
||||||
$code = str_replace('<br/>', '', $code);
|
|
||||||
$code = str_replace('<br>', '', $code);
|
|
||||||
$code = str_replace('<', '<', $code);
|
|
||||||
$newStr .= '<code>' . $code . '</code>';
|
|
||||||
$newStr .= $parts2[1];
|
|
||||||
} else {
|
|
||||||
$newStr .= $p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$newStr = $text;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $newStr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,9 +106,11 @@ Router::get('/a/{id}', 'FileController@avatar', 'file.avatar');
|
||||||
Router::get('/bg/{id}', 'FileController@background', 'file.background');
|
Router::get('/bg/{id}', 'FileController@background', 'file.background');
|
||||||
|
|
||||||
// Premium
|
// Premium
|
||||||
Router::group(['prefix' => 'support'], function () {
|
Router::group(['prefix' => 'support', 'before' => 'loginCheck'], function () {
|
||||||
Router::get('/', 'PremiumController@index', 'premium.index');
|
Router::get('/', 'PremiumController@index', 'premium.index');
|
||||||
Router::get('/tracker', 'PremiumController@tracker', 'premium.tracker');
|
Router::get('/handle', 'PremiumController@handle', 'premium.handle');
|
||||||
|
Router::get('/complete', 'PremiumController@complete', 'premium.complete');
|
||||||
|
Router::post('/purchase', 'PremiumController@purchase', 'premium.purchase');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
namespace Sakura;
|
namespace Sakura;
|
||||||
|
|
||||||
// Define Sakura version
|
// Define Sakura version
|
||||||
define('SAKURA_VERSION', 20160326);
|
define('SAKURA_VERSION', 20160327);
|
||||||
|
|
||||||
// Define Sakura Path
|
// Define Sakura Path
|
||||||
define('ROOT', __DIR__ . '/');
|
define('ROOT', __DIR__ . '/');
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
<div class="default-avatar-setting user-container-avatar" style="background-image: url({{ route('file.avatar', activePoster.id) }}); box-shadow: 0 0 5px #{% if activePoster.isOnline %}484{% else %}844{% endif %};"></div>
|
<div class="default-avatar-setting user-container-avatar" style="background-image: url({{ route('file.avatar', activePoster.id) }}); box-shadow: 0 0 5px #{% if activePoster.isOnline %}484{% else %}844{% endif %};"></div>
|
||||||
<div class="user-container-info">
|
<div class="user-container-info">
|
||||||
<h1 style="color: {{ activePoster.colour }}; text-shadow: 0 0 7px {% if activePoster.colour != 'inherit' %}{{ activePoster.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;" {% if activePoster.getUsernameHistory %} title="Known as {{ activePoster.getUsernameHistory[0].username_old }} before {{ activePoster.getUsernameHistory[0].change_time|date(sakura.dateFormat) }}." {% endif %}>{{ activePoster.username }}</h1>
|
<h1 style="color: {{ activePoster.colour }}; text-shadow: 0 0 7px {% if activePoster.colour != 'inherit' %}{{ activePoster.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;" {% if activePoster.getUsernameHistory %} title="Known as {{ activePoster.getUsernameHistory[0].username_old }} before {{ activePoster.getUsernameHistory[0].change_time|date(sakura.dateFormat) }}." {% endif %}>{{ activePoster.username }}</h1>
|
||||||
{% if activePoster.isPremium[0] %}<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;" /> {% endif %}<img src="{{ sakura.contentPath }}/images/flags/{{ activePoster.country|lower }}.png" alt="{{ activePoster.country }}" style="vertical-align: middle;" title="{{ activePoster.country(true) }}" /> <span style="font-size: .8em;">{{ activePoster.title }}</span>
|
{% if activePoster.isPremium %}<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;" /> {% endif %}<img src="{{ sakura.contentPath }}/images/flags/{{ activePoster.country|lower }}.png" alt="{{ activePoster.country }}" style="vertical-align: middle;" title="{{ activePoster.country(true) }}" /> <span style="font-size: .8em;">{{ activePoster.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="userdata">
|
<div class="userdata">
|
||||||
<div class="usertitle">{{ post.poster.title }}</div>
|
<div class="usertitle">{{ post.poster.title }}</div>
|
||||||
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not post.poster.isPremium[0] %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ post.poster.country|lower }}.png" alt="{{ post.poster.country(true) }}" />{% if post.poster.id == (thread.posts|first).poster.id %} <img src="{{ sakura.contentPath }}/images/op.png" alt="OP" title="Original Poster" />{% endif %}
|
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not post.poster.isPremium %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ post.poster.country|lower }}.png" alt="{{ post.poster.country(true) }}" />{% if post.poster.id == (thread.posts|first).poster.id %} <img src="{{ sakura.contentPath }}/images/op.png" alt="OP" title="Original Poster" />{% endif %}
|
||||||
{% if session.checkLogin %}
|
{% if session.checkLogin %}
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
{% if (user.id == post.poster.id and forum.permission(constant('Sakura\\Perms\\Forum::EDIT_OWN'), user.id)) or forum.permission(constant('Sakura\\Perms\\Forum::EDIT_ANY'), user.id) %}
|
{% if (user.id == post.poster.id and forum.permission(constant('Sakura\\Perms\\Forum::EDIT_OWN'), user.id)) or forum.permission(constant('Sakura\\Perms\\Forum::EDIT_ANY'), user.id) %}
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
<img src="{{ route('file.avatar', user.id) }}" alt="{{ user.username }}" class="avatar" style="box-shadow: 0 3px 7px #484;" />
|
<img src="{{ route('file.avatar', user.id) }}" alt="{{ user.username }}" class="avatar" style="box-shadow: 0 3px 7px #484;" />
|
||||||
<div class="userdata">
|
<div class="userdata">
|
||||||
<div class="usertitle">{{ user.title }}</div>
|
<div class="usertitle">{{ user.title }}</div>
|
||||||
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not user.isPremium[0] %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ user.country|lower }}.png" alt="{{ user.country(true) }}" />{% if user.id == (thread.posts|first).poster.id %} <img src="{{ sakura.contentPath }}/images/op.png" alt="OP" title="Original Poster" />{% endif %}
|
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not user.isPremium %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ user.country|lower }}.png" alt="{{ user.country(true) }}" />{% if user.id == (thread.posts|first).poster.id %} <img src="{{ sakura.contentPath }}/images/op.png" alt="OP" title="Original Poster" />{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="post-content">
|
<td class="post-content">
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
<div>
|
<div>
|
||||||
<h1>Information</h1>
|
<h1>Information</h1>
|
||||||
<hr class="default" />
|
<hr class="default" />
|
||||||
{{ page.message }}
|
{{ message }}
|
||||||
{% if page.redirect %}<br /><a href="{{ page.redirect }}" class="default">Click here if you aren't being redirected.</a>{% endif %}
|
{% if redirect %}<br /><a href="{{ redirect }}" class="default">Click here if you aren't being redirected.</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -10,8 +10,14 @@
|
||||||
<meta name="msapplication-TileColor" content="#9475b2" />
|
<meta name="msapplication-TileColor" content="#9475b2" />
|
||||||
<meta name="msapplication-TileImage" content="/content/images/icons/ms-icon-144x144.png" />
|
<meta name="msapplication-TileImage" content="/content/images/icons/ms-icon-144x144.png" />
|
||||||
<meta name="theme-color" content="#9475B2" />
|
<meta name="theme-color" content="#9475B2" />
|
||||||
{% if page.redirect %}
|
|
||||||
<meta http-equiv="refresh" content="{{ page.redirectTimeout ? page.redirectTimeout : '3' }}; URL={{ page.redirect }}" />
|
{# want to start moving away from page.etc but older files are a thing #}
|
||||||
|
{% if message is not defined %}{% set message = page.message %}{% endif %}
|
||||||
|
{% if redirect is not defined %}{% set redirect = page.redirect %}{% endif %}
|
||||||
|
{% if redirectTimeout is not defined %}{% set redirectTimeout = page.redirectTimeout %}{% endif %}
|
||||||
|
|
||||||
|
{% if redirect %}
|
||||||
|
<meta http-equiv="refresh" content="{{ redirectTimeout ? redirectTimeout : '3' }}; URL={{ redirect }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<link rel="apple-touch-icon" sizes="57x57" href="/content/images/icons/apple-icon-57x57.png" />
|
<link rel="apple-touch-icon" sizes="57x57" href="/content/images/icons/apple-icon-57x57.png" />
|
||||||
<link rel="apple-touch-icon" sizes="60x60" href="/content/images/icons/apple-icon-60x60.png" />
|
<link rel="apple-touch-icon" sizes="60x60" href="/content/images/icons/apple-icon-60x60.png" />
|
||||||
|
@ -63,7 +69,7 @@
|
||||||
notifyUI({
|
notifyUI({
|
||||||
"title": "An error has occurred!",
|
"title": "An error has occurred!",
|
||||||
"text": "There was a problem while executing the JavaScript code for this page: " + msg + ", URL: " + url + ", Line: " + line + ", Column: " + col + ". Please report this to a developer.",
|
"text": "There was a problem while executing the JavaScript code for this page: " + msg + ", URL: " + url + ", Line: " + line + ", Column: " + col + ". Please report this to a developer.",
|
||||||
"img": "FONT:fa-warning"
|
"image": "FONT:fa-warning"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -6,6 +6,6 @@
|
||||||
<div class="content standalone" style="text-align: center;">
|
<div class="content standalone" style="text-align: center;">
|
||||||
<h1 class="stylised" style="margin: 1em auto;">Thank you for your contribution!</h1>
|
<h1 class="stylised" style="margin: 1em auto;">Thank you for your contribution!</h1>
|
||||||
<h1 class="fa fa-heart stylised" style="font-size: 20em;"></h1>
|
<h1 class="fa fa-heart stylised" style="font-size: 20em;"></h1>
|
||||||
<h3>Your Tenshi will expire on {{ page.expiration|date(sakura.dateFormat) }}.</h3>
|
<h3>Your Tenshi will expire on {{ user.isPremium|date(sakura.dateFormat) }}.</h3>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
<div class="default-avatar-setting new-profile-avatar" style="background-image: url({{ route('file.avatar', profile.id) }}); box-shadow: 0 0 5px #{% if profile.isOnline %}484{% else %}844{% endif %};"></div>
|
<div class="default-avatar-setting new-profile-avatar" style="background-image: url({{ route('file.avatar', profile.id) }}); box-shadow: 0 0 5px #{% if profile.isOnline %}484{% else %}844{% endif %};"></div>
|
||||||
<div class="new-profile-username">
|
<div class="new-profile-username">
|
||||||
<h1 style="color: {{ profile.colour }}; text-shadow: 0 0 7px {% if profile.colour != 'inherit' %}{{ profile.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;" {% if profile.getUsernameHistory %} title="Known as {{ profile.getUsernameHistory[0].username_old }} before {{ profile.getUsernameHistory[0].change_time|date(sakura.dateFormat) }}." {% endif %}>{{ profile.username }}</h1>
|
<h1 style="color: {{ profile.colour }}; text-shadow: 0 0 7px {% if profile.colour != 'inherit' %}{{ profile.colour }}{% else %}#222{% endif %}; padding: 0 0 2px;" {% if profile.getUsernameHistory %} title="Known as {{ profile.getUsernameHistory[0].username_old }} before {{ profile.getUsernameHistory[0].change_time|date(sakura.dateFormat) }}." {% endif %}>{{ profile.username }}</h1>
|
||||||
{% if profile.isPremium[0] %}<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;" /> {% endif %}<img src="{{ sakura.contentPath }}/images/flags/{{ profile.country|lower }}.png" alt="{{ profile.country }}" style="vertical-align: middle;" title="{{ profile.country(true) }}" /> <span style="font-size: .8em;">{{ profile.title }}</span>
|
{% if profile.isPremium %}<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi" style="vertical-align: middle;" /> {% endif %}<img src="{{ sakura.contentPath }}/images/flags/{{ profile.country|lower }}.png" alt="{{ profile.country }}" style="vertical-align: middle;" title="{{ profile.country(true) }}" /> <span style="font-size: .8em;">{{ profile.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="new-profile-dates">
|
<div class="new-profile-dates">
|
||||||
<b>Joined</b> <time>{{ profile.registered|date(sakura.dateFormat) }}</time>
|
<b>Joined</b> <time>{{ profile.registered|date(sakura.dateFormat) }}</time>
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
{% block title %}Support {{ sakura.siteName }}{% endblock %}
|
{% block title %}Support {{ sakura.siteName }}{% endblock %}
|
||||||
|
|
||||||
|
{% set persistentPremium = user.permission(constant('Sakura\\Perms\\Site::STATIC_PREMIUM')) %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if page.fail %}
|
{% if get.fail %}
|
||||||
<div class="headerNotify">
|
<div class="headerNotify">
|
||||||
<h1>The payment failed or was cancelled!</h1>
|
<h1>The payment failed or was cancelled!</h1>
|
||||||
<p>Something went wrong while processing the transaction, your PayPal account wasn't charged.</p>
|
<p>Something went wrong while processing the transaction, your PayPal account wasn't charged.</p>
|
||||||
|
@ -13,15 +15,14 @@
|
||||||
<div class="head">Support {{ sakura.siteName }}</div>
|
<div class="head">Support {{ sakura.siteName }}</div>
|
||||||
<div style="font-size: .9em; margin-bottom: 10px;">
|
<div style="font-size: .9em; margin-bottom: 10px;">
|
||||||
<p>In order to keep the site, its services and improvements on it going I need money but I'm not that big of a fan of asking for money without giving anything special in return thus Tenshi exists. Tenshi is the name for our supporter rank which gives you access to an extra set of features (which are listed further down on this page). With your help we can keep adding new stuff, get new hardware and keep the site awesome!</p>
|
<p>In order to keep the site, its services and improvements on it going I need money but I'm not that big of a fan of asking for money without giving anything special in return thus Tenshi exists. Tenshi is the name for our supporter rank which gives you access to an extra set of features (which are listed further down on this page). With your help we can keep adding new stuff, get new hardware and keep the site awesome!</p>
|
||||||
<h3><a href="{{ route('premium.tracker') }}" class="default">Ever wonder what happens on the financial side of things? View the donation tracker!</a></h3>
|
|
||||||
</div>
|
</div>
|
||||||
{% if page.current[0] %}
|
{% if user.isPremium %}
|
||||||
<div class="sectionHeader">
|
<div class="sectionHeader">
|
||||||
Your current Tenshi tag
|
Your current Tenshi tag
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-bottom: 10px;">
|
<div style="margin-bottom: 10px;">
|
||||||
<h3>{% if page.current[0] == 2 %}Your rank has persistent Tenshi.{% else %}Your Tenshi tag is valid till {{ page.current[2]|date(sakura.dateFormat) }}.{% endif %}</h3>
|
<h3>{% if persistentPremium %}Your rank has persistent Tenshi.{% else %}Your Tenshi tag is valid till {{ user.premiumInfo.expire|date(sakura.dateFormat) }}.{% endif %}</h3>
|
||||||
<progress value="{{ page.current[0] == 2 ? 100 : (100 - (((php.time - page.current[1]) / (page.current[2] - page.current[1])) * 100)) }}" max="100" style="width: 100%"></progress>
|
<progress value="{{ persistentPremium ? 100 : (100 - (((php.time - user.premiumInfo.start) / (user.premiumInfo.expire - user.premiumInfo.start)) * 100)) }}" max="100" style="width: 100%"></progress>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="sectionHeader">
|
<div class="sectionHeader">
|
||||||
|
@ -91,7 +92,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% if session.checkLogin and user.permission(constant('Sakura\\Perms\\Site::OBTAIN_PREMIUM')) %}
|
{% if session.checkLogin and user.permission(constant('Sakura\\Perms\\Site::OBTAIN_PREMIUM')) %}
|
||||||
<div class="slider">
|
<div class="slider">
|
||||||
<input class="inputStyling" type="range" min="1" max="{{ page.amount_max }}" value="1" onchange="document.getElementById('monthsNo').value = this.value; document.getElementById('monthNoBtn').innerHTML = this.value; document.getElementById('monthsTrailingS').innerHTML = (this.value == 1 ? '' : 's'); document.getElementById('totalAmount').innerHTML = (this.value * {{ page.price }}).formatMoney(2);" />
|
<input class="inputStyling" type="range" min="1" max="{{ amountLimit }}" value="1" onchange="document.getElementById('monthsNo').value = this.value; document.getElementById('monthNoBtn').innerHTML = this.value; document.getElementById('monthsTrailingS').innerHTML = (this.value == 1 ? '' : 's'); document.getElementById('totalAmount').innerHTML = (this.value * {{ price }}).formatMoney(2);" />
|
||||||
</div>
|
</div>
|
||||||
<div class="checkout" style="line-height: 28px;">
|
<div class="checkout" style="line-height: 28px;">
|
||||||
<div style="float: left;">
|
<div style="float: left;">
|
||||||
|
@ -109,14 +110,14 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if session.checkLogin and user.permission(constant('Sakura\\Perms\\Site::OBTAIN_PREMIUM')) %}
|
{% if session.checkLogin and user.permission(constant('Sakura\\Perms\\Site::OBTAIN_PREMIUM')) %}
|
||||||
<form action="{{ route('premium.index') }}" method="post" id="purchaseForm" class="hidden">
|
<form action="{{ route('premium.purchase') }}" method="post" id="purchaseForm" class="hidden">
|
||||||
<input type="hidden" name="mode" value="purchase" />
|
<input type="hidden" name="mode" value="purchase" />
|
||||||
<input type="hidden" name="time" value="{{ php.time }}" />
|
<input type="hidden" name="time" value="{{ php.time }}" />
|
||||||
<input type="hidden" name="session" value="{{ php.sessionid }}" />
|
<input type="hidden" name="session" value="{{ php.sessionid }}" />
|
||||||
<input type="hidden" name="months" id="monthsNo" value="1" />
|
<input type="hidden" name="months" id="monthsNo" value="1" />
|
||||||
</form>
|
</form>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.onload = function() { document.getElementById('totalAmount').innerHTML = ({{ page.price }}).formatMoney(2); };
|
window.onload = function() { document.getElementById('totalAmount').innerHTML = ({{ price }}).formatMoney(2); };
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Reference in a new issue