A bunch of half implemented shit, also r20160207
This commit is contained in:
parent
58776ee047
commit
ed00e852d8
17 changed files with 250 additions and 330 deletions
|
@ -1,14 +0,0 @@
|
|||
103.21.244.0/22
|
||||
103.22.200.0/22
|
||||
103.31.4.0/22
|
||||
104.16.0.0/12
|
||||
108.162.192.0/18
|
||||
141.101.64.0/18
|
||||
162.158.0.0/15
|
||||
172.64.0.0/13
|
||||
173.245.48.0/20
|
||||
188.114.96.0/20
|
||||
190.93.240.0/20
|
||||
197.234.240.0/22
|
||||
198.41.128.0/17
|
||||
199.27.128.0/21
|
|
@ -1,5 +0,0 @@
|
|||
2400:cb00::/32
|
||||
2405:8100::/32
|
||||
2405:b500::/32
|
||||
2606:4700::/32
|
||||
2803:f800::/32
|
|
@ -33,12 +33,6 @@ prefix = sakura_
|
|||
|
||||
; Data files relative to the root directory
|
||||
[data]
|
||||
; File containing CloudFlare IPv4 CIDRs
|
||||
cfipv4 = config/cloudflare.ipv4
|
||||
|
||||
; File containing CloudFlare IPv6 CIDRs
|
||||
cfipv6 = config/cloudflare.ipv6
|
||||
|
||||
; JSON file containing WHOIS servers
|
||||
whoisservers = config/whois.json
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ class Meta
|
|||
Template::vars([
|
||||
'page' => [
|
||||
'title' => 'Frequently Asked Questions',
|
||||
'questions' => Utils::getFaqData(),
|
||||
'questions' => Database::fetch('faq', true, null, ['faq_id']),
|
||||
],
|
||||
]);
|
||||
|
||||
|
@ -117,7 +117,7 @@ class Meta
|
|||
$id = strtolower($id);
|
||||
|
||||
// Get info page data from the database
|
||||
if ($ipData = Utils::loadInfoPage($id)) {
|
||||
if ($ipData = Database::fetch('infopages', false, ['page_shorthand' => [$id, '=']])) {
|
||||
// Assign new proper variable
|
||||
$renderData['page'] = [
|
||||
'id' => $id,
|
||||
|
|
|
@ -12,6 +12,7 @@ use Sakura\Database;
|
|||
use Sakura\User;
|
||||
use Sakura\BBcode;
|
||||
use Sakura\Config;
|
||||
use Sakura\Net;
|
||||
|
||||
/**
|
||||
* Used to serve, create and update posts.
|
||||
|
@ -212,7 +213,7 @@ class Post
|
|||
'topic_id' => $thread->id,
|
||||
'forum_id' => $thread->forum,
|
||||
'poster_id' => $this->poster->id,
|
||||
'poster_ip' => Utils::getRemoteIP(),
|
||||
'poster_ip' => Net::pton(Net::IP()),
|
||||
'post_time' => $this->time,
|
||||
'post_subject' => $this->subject,
|
||||
'post_text' => $this->text,
|
||||
|
|
212
libraries/Net.php
Normal file
212
libraries/Net.php
Normal file
|
@ -0,0 +1,212 @@
|
|||
<?php
|
||||
/**
|
||||
* Holds the everything networking.
|
||||
*
|
||||
* @package Sakura
|
||||
*/
|
||||
|
||||
namespace Sakura;
|
||||
|
||||
/**
|
||||
* Networking methods.
|
||||
*
|
||||
* @package Sakura
|
||||
* @author Julian van de Groep <me@flash.moe>
|
||||
*/
|
||||
class Net {
|
||||
/**
|
||||
* Returns the connecting IP.
|
||||
*
|
||||
* @return string The IP.
|
||||
*/
|
||||
public static function IP()
|
||||
{
|
||||
return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the version of an IP.
|
||||
*
|
||||
* @param string $ipAddr The IP.
|
||||
*
|
||||
* @return int Either 0, 4 or 6.
|
||||
*/
|
||||
public static function detectIPVersion($ipAddr)
|
||||
{
|
||||
// Check if var is IP
|
||||
if (filter_var($ipAddr, FILTER_VALIDATE_IP)) {
|
||||
// v4
|
||||
if (filter_var($ipAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// v6
|
||||
if (filter_var($ipAddr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
// Not an IP or unknown type
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a printable IP address into an unpacked binary string.
|
||||
*
|
||||
* @param string $ip Printable IP string.
|
||||
*
|
||||
* @throws \Exception Thrown if an invalid IP is supplied.
|
||||
*
|
||||
* @return string Unpacked IP address.
|
||||
*/
|
||||
public static function pton($ip)
|
||||
{
|
||||
// Detect the IP version
|
||||
$ipv = self::detectIPVersion($ip);
|
||||
|
||||
// Check for IPv4 first since that's most common
|
||||
if ($ipv === 4) {
|
||||
return current(unpack("A4", inet_pton($ip)));
|
||||
}
|
||||
|
||||
// Then attempt IPv6
|
||||
if ($ipv === 6) {
|
||||
return current(unpack("A16", inet_pton($ip)));
|
||||
}
|
||||
|
||||
// Throw an exception if an invalid IP was supplied
|
||||
throw new \Exception("Invalid IP address supplied.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a binary unpacked IP to a printable packed IP.
|
||||
*
|
||||
* @param string $bin The unpacked IP.
|
||||
*
|
||||
* @throws \Exception Thrown if the unpacked IP is invalid.
|
||||
*
|
||||
* @return string The packed IP.
|
||||
*/
|
||||
public static function ntop($bin)
|
||||
{
|
||||
// Get the length of the binary string
|
||||
$len = strlen($bin);
|
||||
|
||||
// Throw an exception if it's not 4 or 16 bytes
|
||||
if ($len !== 4 && $len !== 16) {
|
||||
throw new \Exception("Could not handle this IP type.");
|
||||
}
|
||||
|
||||
// Finally pack the IP
|
||||
return inet_ntop(pack("A{$len}", $bin));
|
||||
}
|
||||
|
||||
public static function matchCIDR($ip, $range)
|
||||
{
|
||||
// Break the range up in parts
|
||||
list($net, $mask) = explode('/', $range);
|
||||
|
||||
// Check IP version
|
||||
$ipv = self::detectIPVersion($ip);
|
||||
$rangev = self::detectIPVersion($net);
|
||||
|
||||
// Return false if it's not a valid IP
|
||||
if ($ipv !== $rangev && !$ipv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// v4
|
||||
if ($ipv === 4) {
|
||||
return self::matchCIDRv4($ip, $net, $mask);
|
||||
}
|
||||
|
||||
// v6
|
||||
if ($ipv === 6) {
|
||||
return self::matchCIDRv6($ip, $net, $mask);
|
||||
}
|
||||
|
||||
// Return false by default
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match an IPv4 CIDR
|
||||
*
|
||||
* @param string $ip The IP address to match.
|
||||
* @param string $net The Net address to match.
|
||||
* @param string $mask The Mask to match.
|
||||
*
|
||||
* @return bool Returns true if it matches.
|
||||
*/
|
||||
private static function matchCIDRv4($ip, $net, $mask)
|
||||
{
|
||||
// Convert IP and Net address to long
|
||||
$ip = ip2long($ip);
|
||||
$net = ip2long($net);
|
||||
|
||||
// Generate mask
|
||||
$mask = -1 << (32 - $mask);
|
||||
|
||||
// Do the check
|
||||
return ($ip & $mask) === $net;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an IPv6 mask to a byte array
|
||||
*
|
||||
* @param int $mask The mask.
|
||||
*
|
||||
* @return string The byte array.
|
||||
*/
|
||||
private static function maskToByteArray($mask)
|
||||
{
|
||||
// Generate an address from the mask
|
||||
$addr = str_repeat("f", $mask / 4);
|
||||
|
||||
// Append uneven bit
|
||||
switch ($mask % 4) {
|
||||
case 1:
|
||||
$addr .= '8';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$addr .= 'c';
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$addr .= 'e';
|
||||
break;
|
||||
}
|
||||
|
||||
// Pad the address with zeroes
|
||||
$addr = str_pad($addr, 32, '0');
|
||||
|
||||
// Pack the address
|
||||
$addr = pack('H*', $addr);
|
||||
|
||||
// Return the packed address
|
||||
return $addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match an IPv6 CIDR
|
||||
*
|
||||
* @param string $ip The IP address to match.
|
||||
* @param string $net The Net address to match.
|
||||
* @param int $mask The net mask.
|
||||
*
|
||||
* @return bool Returns true if it's a successful match.
|
||||
*/
|
||||
private static function matchCIDRv6($ip, $net, $mask)
|
||||
{
|
||||
// Pack the IP and Net addresses
|
||||
$ip = inet_pton($ip);
|
||||
$net = inet_pton($net);
|
||||
|
||||
// Convert the mask to a byte array
|
||||
$mask = self::maskToByteArray($mask);
|
||||
|
||||
// Compare them
|
||||
return ($ip & $mask) === $net;
|
||||
}
|
||||
}
|
|
@ -145,8 +145,10 @@ class Router
|
|||
try {
|
||||
try {
|
||||
return self::$dispatcher->dispatch($method, $url);
|
||||
} catch (HttpMethodNotAllowedException $e) {}
|
||||
} catch (HttpRouteNotFoundException $e) {}
|
||||
} catch (HttpMethodNotAllowedException $e) {
|
||||
}
|
||||
} catch (HttpRouteNotFoundException $e) {
|
||||
}
|
||||
|
||||
// Default to the not found page
|
||||
return Template::render('global/notfound');
|
||||
|
|
|
@ -95,7 +95,7 @@ class Session
|
|||
// Insert the session into the database
|
||||
Database::insert('sessions', [
|
||||
'user_id' => $this->userId,
|
||||
'user_ip' => Utils::getRemoteIP(),
|
||||
'user_ip' => Net::pton(Net::IP()),
|
||||
'user_agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
|
||||
'session_key' => $session,
|
||||
'session_start' => time(),
|
||||
|
@ -132,13 +132,13 @@ class Session
|
|||
}
|
||||
|
||||
// IP Check
|
||||
$ipCheck = Config::get('session_check');
|
||||
$ipCheck = false;// Config::get('session_check');
|
||||
|
||||
// Origin checking
|
||||
if ($ipCheck) {
|
||||
// Split both IPs up
|
||||
$sessionIP = explode('.', $session['user_ip']);
|
||||
$userIP = explode('.', Utils::getRemoteIP());
|
||||
$userIP = explode('.', Net::IP());
|
||||
|
||||
// Take 1 off the ipCheck variable so it's equal to the array keys
|
||||
$ipCheck = $ipCheck - 1;
|
||||
|
|
|
@ -267,8 +267,8 @@ class User
|
|||
'password_iter' => $password[1],
|
||||
'email' => $emailClean,
|
||||
'rank_main' => 0,
|
||||
'register_ip' => Utils::getRemoteIP(),
|
||||
'last_ip' => Utils::getRemoteIP(),
|
||||
'register_ip' => Net::pton(Net::IP()),
|
||||
'last_ip' => Net::pton(Net::IP()),
|
||||
'user_registered' => time(),
|
||||
'user_last_online' => 0,
|
||||
'user_country' => Utils::getCountryCode(),
|
||||
|
|
|
@ -120,7 +120,7 @@ class Users
|
|||
|
||||
// Check if we haven't hit the rate limit
|
||||
$rates = Database::fetch('login_attempts', true, [
|
||||
'attempt_ip' => [Utils::getRemoteIP(), '='],
|
||||
'attempt_ip' => [Net::pton(Net::IP()), '='],
|
||||
'attempt_timestamp' => [time() - 1800, '>'],
|
||||
'attempt_success' => [0, '='],
|
||||
]);
|
||||
|
|
|
@ -17,16 +17,6 @@ use PHPMailer;
|
|||
*/
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* Get the emoticons.
|
||||
*
|
||||
* @return array Array containing emoticons.
|
||||
*/
|
||||
public static function getEmotes()
|
||||
{
|
||||
return Database::fetch('emoticons');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the emoticons.
|
||||
*
|
||||
|
@ -36,9 +26,8 @@ class Utils
|
|||
*/
|
||||
public static function parseEmotes($text)
|
||||
{
|
||||
|
||||
// Get emoticons from the database
|
||||
$emotes = self::getEmotes();
|
||||
$emotes = Database::fetch('emoticons');
|
||||
|
||||
// Do the replacements
|
||||
foreach ($emotes as $emote) {
|
||||
|
@ -62,7 +51,6 @@ class Utils
|
|||
*/
|
||||
public static function verifyCaptcha($response)
|
||||
{
|
||||
|
||||
// Attempt to get the response
|
||||
$resp = @file_get_contents(
|
||||
'https://www.google.com/recaptcha/api/siteverify?secret='
|
||||
|
@ -93,7 +81,6 @@ class Utils
|
|||
*/
|
||||
public static function errorHandler($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
|
||||
// Remove ROOT path from the error string and file location
|
||||
$errstr = str_replace(ROOT, '', $errstr);
|
||||
$errfile = str_replace(ROOT, '', $errfile);
|
||||
|
@ -254,7 +241,6 @@ class Utils
|
|||
*/
|
||||
public static function sendMail($to, $subject, $body)
|
||||
{
|
||||
|
||||
// Initialise PHPMailer
|
||||
$mail = new PHPMailer();
|
||||
|
||||
|
@ -323,7 +309,6 @@ class Utils
|
|||
*/
|
||||
public static function cleanString($string, $lower = false, $noSpecial = false, $replaceSpecial = '')
|
||||
{
|
||||
|
||||
// Run common sanitisation function over string
|
||||
$string = htmlentities($string, ENT_NOQUOTES | ENT_HTML401, Config::get('charset'));
|
||||
$string = stripslashes($string);
|
||||
|
@ -343,23 +328,6 @@ class Utils
|
|||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load contents of an infopage.
|
||||
*
|
||||
* @param string $id ID of the info page.
|
||||
*
|
||||
* @return array|bool Contents of the info page.
|
||||
*/
|
||||
public static function loadInfoPage($id)
|
||||
{
|
||||
|
||||
// Get contents from the database
|
||||
$infopage = Database::fetch('infopages', false, ['page_shorthand' => [$id, '=']]);
|
||||
|
||||
// Return the data if there is any else just return false
|
||||
return count($infopage) ? $infopage : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate MX records.
|
||||
*
|
||||
|
@ -369,7 +337,6 @@ class Utils
|
|||
*/
|
||||
public static function checkMXRecord($email)
|
||||
{
|
||||
|
||||
// Get the domain from the e-mail address
|
||||
$domain = substr(strstr($email, '@'), 1);
|
||||
|
||||
|
@ -380,174 +347,6 @@ class Utils
|
|||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the version of an IP.
|
||||
*
|
||||
* @param string $ip The IP.
|
||||
*
|
||||
* @return int Either 0, 4 or 6.
|
||||
*/
|
||||
public static function ipVersion($ip)
|
||||
{
|
||||
|
||||
// Check if var is IP
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP)) {
|
||||
// IPv4
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// IPv6
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
// Not an IP or unknown type
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack an IPv6
|
||||
*
|
||||
* @param mixed $inet IP address.
|
||||
*
|
||||
* @return null|string The unpacked IP.
|
||||
*/
|
||||
public static function inetToBits($inet)
|
||||
{
|
||||
|
||||
// Unpack string
|
||||
$unpacked = unpack('A16', $inet);
|
||||
|
||||
// Split the string
|
||||
$unpacked = str_split($unpacked[1]);
|
||||
|
||||
// Define variable
|
||||
$binaryIP = null;
|
||||
|
||||
// "Build" binary IP
|
||||
foreach ($unpacked as $char) {
|
||||
$binaryIP .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
// Return IP
|
||||
return $binaryIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match a subnet.
|
||||
*
|
||||
* @param string $ip the IP.
|
||||
* @param string $range The range.
|
||||
*
|
||||
* @return bool|int Success.
|
||||
*/
|
||||
public static function matchSubnet($ip, $range)
|
||||
{
|
||||
|
||||
// Use the proper IP type
|
||||
switch (self::ipVersion($ip)) {
|
||||
case 4:
|
||||
// Break the range up in parts
|
||||
list($subnet, $bits) = explode('/', $range);
|
||||
|
||||
// Convert IP and Subnet to long
|
||||
$ip = ip2long($ip);
|
||||
$subnet = ip2long($subnet);
|
||||
$mask = -1 << (32 - $bits);
|
||||
|
||||
// In case the supplied subnet wasn't correctly aligned
|
||||
$subnet &= $mask;
|
||||
|
||||
// Return true if IP is in subnet
|
||||
return ($ip & $mask) == $subnet;
|
||||
|
||||
case 6:
|
||||
// Break the range up in parts
|
||||
list($subnet, $bits) = explode('/', $range);
|
||||
|
||||
// Convert subnet to packed address and convert it to binary
|
||||
$subnet = inet_pton($subnet);
|
||||
$binarySubnet = self::inetToBits($subnet);
|
||||
|
||||
// Convert IPv6 to packed address and convert it to binary as well
|
||||
$ip = inet_pton($ip);
|
||||
$binaryIP = self::inetToBits($ip);
|
||||
|
||||
// Return bits of the strings according to the bits
|
||||
$ipBits = substr($binaryIP, 0, $bits);
|
||||
$subnetBits = substr($binarySubnet, 0, $bits);
|
||||
|
||||
return ($ipBits === $subnetBits);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IP originates from CloudFlare.
|
||||
*
|
||||
* @param string $ip The IP.
|
||||
*
|
||||
* @return bool Success.
|
||||
*/
|
||||
public static function checkCFIP($ip)
|
||||
{
|
||||
|
||||
// Get CloudFlare Subnet list
|
||||
$cfhosts = file_get_contents(
|
||||
ROOT . Config::local('data', 'cfipv' . (self::ipVersion($ip)))
|
||||
);
|
||||
|
||||
// Replace \r\n with \n
|
||||
$cfhosts = str_replace("\r\n", "\n", $cfhosts);
|
||||
|
||||
// Explode the file into an array
|
||||
$cfhosts = explode("\n", $cfhosts);
|
||||
|
||||
// Check if IP is in a CloudFlare subnet
|
||||
foreach ($cfhosts as $subnet) {
|
||||
// Check if the subnet isn't empty (git newline prevention)
|
||||
if (strlen($subnet) < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Return true if found
|
||||
if (self::matchSubnet($ip, $subnet)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return false if fails
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IP of a visitor.
|
||||
*
|
||||
* @return string The IP.
|
||||
*/
|
||||
public static function getRemoteIP()
|
||||
{
|
||||
|
||||
// Assign REMOTE_ADDR to a variables
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
// Check if the IP is a CloudFlare IP
|
||||
if (self::checkCFIP($ip)) {
|
||||
// If 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'])) {
|
||||
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
|
||||
}
|
||||
}
|
||||
|
||||
// Return the correct IP
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the country code of a visitor.
|
||||
*
|
||||
|
@ -557,7 +356,7 @@ class Utils
|
|||
{
|
||||
// Attempt to get country code using PHP's built in geo thing
|
||||
if (function_exists("geoip_country_code_by_name")) {
|
||||
$code = geoip_country_code_by_name(self::getRemoteIP());
|
||||
$code = geoip_country_code_by_name(Net::IP());
|
||||
|
||||
// Check if $code is anything
|
||||
if ($code) {
|
||||
|
@ -583,7 +382,6 @@ class Utils
|
|||
*/
|
||||
public static function pwdEntropy($pw)
|
||||
{
|
||||
|
||||
// Decode utf-8 chars
|
||||
$pw = utf8_decode($pw);
|
||||
|
||||
|
@ -600,7 +398,6 @@ class Utils
|
|||
*/
|
||||
public static function getCountryName($code)
|
||||
{
|
||||
|
||||
// Parse JSON file
|
||||
$iso3166 = json_decode(
|
||||
utf8_encode(
|
||||
|
@ -620,72 +417,6 @@ class Utils
|
|||
return 'Unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FAQ table data (why is this a function).
|
||||
*
|
||||
* @return array FAQ data.
|
||||
*/
|
||||
public static function getFaqData()
|
||||
{
|
||||
|
||||
// Do database call
|
||||
$faq = Database::fetch('faq', true, null, ['faq_id']);
|
||||
|
||||
// Return FAQ data
|
||||
return $faq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of log in text (unused and will probably be removwed).
|
||||
* @param mixed $type
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getLogStringFromType($type)
|
||||
{
|
||||
|
||||
// Query the database
|
||||
$return = Database::fetch('logtypes', false, ['id' => [$type, '=']]);
|
||||
|
||||
// Check if type exists and else return a unformattable string
|
||||
if (count($return) < 2) {
|
||||
return 'Unknown action.';
|
||||
}
|
||||
|
||||
// Return the string
|
||||
return $return['string'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user's logs (unused, probably removed in future).
|
||||
* @param mixed $uid
|
||||
* @return array
|
||||
*/
|
||||
public static function getUserLogs($uid = 0)
|
||||
{
|
||||
|
||||
// Check if a user is specified
|
||||
$conditions = ($uid ? ['uid' => [$uid, '=']] : null);
|
||||
|
||||
// Get data from database
|
||||
$logsDB = Database::fetch('logs', true, $conditions, ['id', true]);
|
||||
|
||||
// Storage array
|
||||
$logs = [];
|
||||
|
||||
// Iterate over entries
|
||||
foreach ($logsDB as $log) {
|
||||
// Store usable data
|
||||
$logs[$log['id']] = [
|
||||
'user' => $_USER = Users::getUser($log['uid']),
|
||||
'rank' => Users::getRank($_USER['rank_main']),
|
||||
'string' => vsprintf(self::getLogStringFromType($log['action']), json_decode($log['attribs'], true)),
|
||||
];
|
||||
}
|
||||
|
||||
// Return new logs
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the byte symbol for a unit from bytes.
|
||||
*
|
||||
|
@ -695,7 +426,6 @@ class Utils
|
|||
*/
|
||||
public static function getByteSymbol($bytes)
|
||||
{
|
||||
|
||||
// Return nothing if the input was 0
|
||||
if (!$bytes) {
|
||||
return;
|
||||
|
@ -721,7 +451,6 @@ class Utils
|
|||
*/
|
||||
public static function getPremiumTrackerData()
|
||||
{
|
||||
|
||||
// Create data array
|
||||
$data = [];
|
||||
|
||||
|
@ -762,12 +491,10 @@ class Utils
|
|||
public static function updatePremiumTracker($id, $amount, $comment)
|
||||
{
|
||||
Database::insert('premium_log', [
|
||||
|
||||
'user_id' => $id,
|
||||
'transaction_amount' => $amount,
|
||||
'transaction_date' => time(),
|
||||
'transaction_comment' => $comment,
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ if (isset($_REQUEST['mode'])) {
|
|||
Database::insert('login_attempts', [
|
||||
'attempt_success' => $login[0],
|
||||
'attempt_timestamp' => time(),
|
||||
'attempt_ip' => Utils::getRemoteIP(),
|
||||
'attempt_ip' => Net::pton(Net::IP()),
|
||||
'user_id' => isset($login[2]) ? $login[2] : 0,
|
||||
]);
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ if (Users::checkLogin()) {
|
|||
}
|
||||
|
||||
// Check if a user has already registered from the current IP address
|
||||
if (count($regUserIP = Users::getUsersByIP(Utils::getRemoteIP()))) {
|
||||
if (count($regUserIP = Users::getUsersByIP(Net::pton(Net::IP())))) {
|
||||
$renderData['auth']['blockRegister'] = [
|
||||
|
||||
'do' => true,
|
||||
|
|
|
@ -118,12 +118,13 @@ var Sakura = (function () {
|
|||
}
|
||||
// Times array
|
||||
var times = {
|
||||
31536000: 'year',
|
||||
2592000: 'month',
|
||||
86400: 'day',
|
||||
3600: 'hour',
|
||||
60: 'minute',
|
||||
1: 'second'
|
||||
31536000: ['year', 'a'],
|
||||
2592000: ['month', 'a'],
|
||||
604800: ['week', 'a'],
|
||||
86400: ['day', 'a'],
|
||||
3600: ['hour', 'an'],
|
||||
60: ['minute', 'a'],
|
||||
1: ['second', 'a']
|
||||
};
|
||||
//
|
||||
var timeKeys = Object.keys(times).reverse();
|
||||
|
@ -136,7 +137,7 @@ var Sakura = (function () {
|
|||
// Round the number
|
||||
var display = Math.floor(calc);
|
||||
// Return the formatted string
|
||||
return display + " " + times[timeKeys[i]] + (display === 1 ? '' : 's') + append;
|
||||
return (display === 1 ? times[timeKeys[i]][1] : display) + " " + times[timeKeys[i]][0] + (display === 1 ? '' : 's') + append;
|
||||
}
|
||||
}
|
||||
// If everything fails just return none
|
||||
|
|
|
@ -141,12 +141,13 @@ class Sakura {
|
|||
|
||||
// Times array
|
||||
var times: Object = {
|
||||
31536000: 'year',
|
||||
2592000: 'month',
|
||||
86400: 'day',
|
||||
3600: 'hour',
|
||||
60: 'minute',
|
||||
1: 'second'
|
||||
31536000: ['year', 'a'],
|
||||
2592000: ['month', 'a'],
|
||||
604800: ['week', 'a'],
|
||||
86400: ['day', 'a'],
|
||||
3600: ['hour', 'an'],
|
||||
60: ['minute', 'a'],
|
||||
1: ['second', 'a']
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -163,7 +164,7 @@ class Sakura {
|
|||
var display: number = Math.floor(calc);
|
||||
|
||||
// Return the formatted string
|
||||
return display + " " + times[timeKeys[i]] + (display === 1 ? '' : 's') + append;
|
||||
return (display === 1 ? times[timeKeys[i]][1] : display) + " " + times[timeKeys[i]][0] + (display === 1 ? '' : 's') + append;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
namespace Sakura;
|
||||
|
||||
// Include components
|
||||
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php';
|
||||
require_once __DIR__ . '/../sakura.php';
|
||||
|
||||
// Handle requests
|
||||
echo Router::handle($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
|
||||
|
|
|
@ -69,7 +69,7 @@ $mode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) ? 't' : (isset($_GET['p'])
|
|||
|
||||
// Include emotes and bbcodes
|
||||
$posting = [
|
||||
'emoticons' => Utils::getEmotes(),
|
||||
'emoticons' => Database::fetch('emoticons'),
|
||||
];
|
||||
|
||||
// Check if we're in reply mode
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Sakura;
|
||||
|
||||
// Define Sakura version
|
||||
define('SAKURA_VERSION', '20160205');
|
||||
define('SAKURA_VERSION', '20160207');
|
||||
define('SAKURA_VLABEL', 'Amethyst');
|
||||
define('SAKURA_COLOUR', '#9966CC');
|
||||
|
||||
|
@ -45,6 +45,7 @@ require_once ROOT . 'libraries/CSRF.php';
|
|||
require_once ROOT . 'libraries/Database.php';
|
||||
require_once ROOT . 'libraries/File.php';
|
||||
require_once ROOT . 'libraries/Hashing.php';
|
||||
require_once ROOT . 'libraries/Net.php';
|
||||
require_once ROOT . 'libraries/News.php';
|
||||
require_once ROOT . 'libraries/Payments.php';
|
||||
require_once ROOT . 'libraries/Perms.php';
|
||||
|
|
Reference in a new issue