2015-04-01 17:34:36 +00:00
< ? php
/*
* Main Class
*/
2015-08-23 22:08:36 +00:00
2015-04-01 17:34:36 +00:00
namespace Sakura ;
2015-06-04 12:41:55 +00:00
use Parsedown ;
use PHPMailer ;
2015-09-14 20:51:23 +00:00
class Main
{
2015-04-18 18:32:41 +00:00
// Constructor
2015-09-14 20:51:23 +00:00
public static function init ( $config )
{
2015-04-01 17:34:36 +00:00
2015-04-18 18:32:41 +00:00
// Configuration Management and local configuration
Configuration :: init ( $config );
2015-04-01 17:34:36 +00:00
2015-04-18 18:32:41 +00:00
// Database
2015-05-29 19:27:45 +00:00
Database :: init ( Configuration :: getLocalConfig ( 'database' , 'driver' ));
2015-04-01 17:34:36 +00:00
// "Dynamic" Configuration
Configuration :: initDB ();
// Create new session
Session :: init ();
}
2015-04-01 17:45:05 +00:00
// Parse markdown
2015-09-14 20:51:23 +00:00
public static function mdParse ( $text )
{
2015-04-01 17:45:05 +00:00
2015-08-23 22:08:36 +00:00
return ( new Parsedown ()) -> text ( $text );
2015-04-01 17:45:05 +00:00
}
2015-07-30 18:51:24 +00:00
// Get bbcodes
2015-09-14 20:51:23 +00:00
public static function getBBcodes ()
{
2015-07-30 18:51:24 +00:00
return Database :: fetch ( 'bbcodes' );
}
2015-06-21 13:41:07 +00:00
// Parse bbcodes
2015-09-14 20:51:23 +00:00
public static function bbParse ( $text )
{
2015-06-21 13:41:07 +00:00
// Get bbcode regex from the database
$bbcodes = Database :: fetch ( 'bbcodes' );
// Split the regex
2015-09-14 20:51:23 +00:00
$regex = array_map ( function ( $arr ) {
2015-06-21 13:41:07 +00:00
return $arr [ 'regex' ];
}, $bbcodes );
// Split the replacement
2015-09-14 20:51:23 +00:00
$replace = array_map ( function ( $arr ) {
2015-06-21 13:41:07 +00:00
return $arr [ 'replace' ];
}, $bbcodes );
// Do the replacement
$text = preg_replace ( $regex , $replace , $text );
// Return the parsed text
return $text ;
}
2015-07-30 18:51:24 +00:00
// Get emoticons
2015-09-14 20:51:23 +00:00
public static function getEmotes ()
{
2015-07-30 18:51:24 +00:00
return Database :: fetch ( 'emoticons' );
}
2015-07-05 15:03:58 +00:00
// Parsing emoticons
2015-09-14 20:51:23 +00:00
public static function parseEmotes ( $text )
{
2015-07-05 15:03:58 +00:00
// Get emoticons from the database
$emotes = Database :: fetch ( 'emoticons' );
// Do the replacements
2015-09-14 20:51:23 +00:00
foreach ( $emotes as $emote ) {
$text = str_replace ( $emote [ 'emote_string' ], '<img src="' . $emote [ 'emote_path' ] . '" class="emoticon" alt="' . $emote [ 'emote_string' ] . '" />' , $text );
2015-08-09 20:50:03 +00:00
}
2015-07-05 15:03:58 +00:00
// Return the parsed text
return $text ;
}
2015-04-01 17:34:36 +00:00
// Verify ReCAPTCHA
2015-09-14 20:51:23 +00:00
public static function verifyCaptcha ( $response )
{
2015-04-01 17:34:36 +00:00
// Attempt to get the response
2015-09-14 20:51:23 +00:00
$resp = @ file_get_contents ( 'https://www.google.com/recaptcha/api/siteverify?secret=' . Configuration :: getConfig ( 'recaptcha_private' ) . '&response=' . $response );
2015-04-01 17:34:36 +00:00
// In the highly unlikely case that it failed to get anything forge a false
2015-09-14 20:51:23 +00:00
if ( ! $resp ) {
2015-06-04 12:41:55 +00:00
return false ;
2015-08-09 20:50:03 +00:00
}
2015-04-01 17:34:36 +00:00
// Decode the response JSON from the servers
$resp = json_decode ( $resp , true );
// Return shit
return $resp ;
}
2015-04-18 18:32:41 +00:00
// Error Handler
2015-09-14 20:51:23 +00:00
public static function errorHandler ( $errno , $errstr , $errfile , $errline )
{
2015-04-01 17:34:36 +00:00
2015-09-06 01:04:55 +00:00
// Remove ROOT path from the error string and file location
2015-09-14 20:51:23 +00:00
$errstr = str_replace ( ROOT , '' , $errstr );
$errfile = str_replace ( ROOT , '' , $errfile );
2015-09-06 01:04:55 +00:00
// Attempt to log the error to the database
2015-09-14 20:51:23 +00:00
if ( Database :: $database !== null ) {
2015-09-06 01:04:55 +00:00
// Encode backtrace data
$backtrace = base64_encode ( json_encode ( debug_backtrace ()));
// Check if this error has already been logged in the past
2015-09-14 20:51:23 +00:00
if ( $past = Database :: fetch ( 'error_log' , false , [ 'backtrace' => [ $backtrace , '=' , true ], 'error_string' => [ $errstr , '=' ]])) {
2015-09-06 01:04:55 +00:00
// If so assign the errid
$errid = $past [ 'id' ];
} else {
// Create an error ID
$errid = substr ( md5 ( microtime ()), rand ( 0 , 22 ), 10 );
// Log the error
Database :: insert ( 'error_log' , [
2015-09-14 20:51:23 +00:00
'id' => $errid ,
'timestamp' => date ( " r " ),
'revision' => SAKURA_VERSION ,
'error_type' => $errno ,
'error_line' => $errline ,
'error_string' => $errstr ,
'error_file' => $errfile ,
'backtrace' => $backtrace ,
2015-09-06 01:04:55 +00:00
]);
}
}
2015-04-01 17:34:36 +00:00
2015-04-18 18:32:41 +00:00
switch ( $errno ) {
case E_ERROR :
case E_USER_ERROR :
$error = '<b>FATAL ERROR</b>: ' . $errstr . ' on line ' . $errline . ' in ' . $errfile ;
2015-04-01 17:34:36 +00:00
break ;
2015-04-18 18:32:41 +00:00
case E_WARNING :
case E_USER_WARNING :
$error = '<b>WARNING</b>: ' . $errstr . ' on line ' . $errline . ' in ' . $errfile ;
2015-04-01 17:34:36 +00:00
break ;
2015-04-18 18:32:41 +00:00
case E_NOTICE :
case E_USER_NOTICE :
$error = '<b>NOTICE</b>: ' . $errstr . ' on line ' . $errline . ' in ' . $errfile ;
2015-04-01 17:34:36 +00:00
break ;
2015-04-18 18:32:41 +00:00
default :
$error = '<b>Unknown error type</b> [' . $errno . ']: ' . $errstr . ' on line ' . $errline . ' in ' . $errfile ;
}
2015-04-01 17:34:36 +00:00
2015-04-18 18:32:41 +00:00
// Truncate all previous outputs
ob_clean ();
2015-05-29 19:27:45 +00:00
ob_end_clean ();
2015-04-01 17:34:36 +00:00
2015-09-06 01:04:55 +00:00
// Build page
$errorPage = ' <! DOCTYPE html >
< html >
< head >
< meta charset = " utf-8 " />
< title > Sakura Internal Error </ title >
< style type = " text/css " >
body { margin : 0 ; padding : 0 ; background : #EEE; color: #000; font: 12px/20px Verdana, Arial, Helvetica, sans-serif; }
h1 , h2 { font - weight : 100 ; background : #CAA; padding: 8px 5px 10px; margin: 0; font-style: italic; font-family: serif; }
h1 { border - radius : 8 px 8 px 0 0 ; }
h2 { margin : 0 - 10 px ; }
. container { border : 1 px solid #CAA; margin: 10px auto; background: #FFF; box-shadow: 2px 2px 1em #888; max-width: 1024px; border-radius: 10px; }
. container . inner { padding : 0 px 10 px ; }
. container . inner . error { background : #555; color: #EEE; border-left: 5px solid #C22; padding: 4px 6px; text-shadow: 0px 1px 1px #888; white-space: pre-wrap; word-wrap: break-word; margin: 12px 0; border-radius: 5px; box-shadow: inset 0 0 1em #333; }
. container . footer { border - top : 1 px solid #CAA; font-size: x-small; padding: 0px 5px 1px; }
a { color : #77E; text-decoration: none; }
a : hover { text - decoration : underline ; }
a : active { color : #E77; }
</ style >
</ head >
< body >
< div class = " container " >
< h1 > An error occurred while executing the script .</ h1 >
< div class = " inner " >
< p > To prevent potential security risks or data loss Sakura has stopped execution of the script .</ p > ' ;
2015-09-14 20:51:23 +00:00
if ( isset ( $errid )) {
$errorPage .= ' < p > The error and surrounding data has been logged .</ p >
< h2 > ' . (SAKURA_STABLE ? ' Report the following text to a staff member ' : ' Logged as ') . ' </ h2 >< pre class = " error " > ' . $errid . ' </ pre > ' ;
} else {
$errorPage .= '<p>Sakura was not able to log this error which could mean that there was an error with the database connection. If you\'re the system administrator check the database credentials and make sure the server is running and if you\'re not please let the system administrator know about this error if it occurs again.</p>' ;
}
2015-09-06 01:04:55 +00:00
2015-09-14 20:51:23 +00:00
if ( ! SAKURA_STABLE ) {
$errorPage .= ' < h2 > Summary </ h2 >
< pre class = " error " > ' . $error . ' </ pre >
2015-09-06 01:04:55 +00:00
< h2 > Backtraces </ h2 > ' ;
2015-09-14 20:51:23 +00:00
foreach ( debug_backtrace ( DEBUG_BACKTRACE_IGNORE_ARGS ) as $num => $trace ) {
$errorPage .= '<h3>#' . $num . '</h3><pre class="error">' ;
2015-09-06 01:04:55 +00:00
2015-09-14 20:51:23 +00:00
foreach ( $trace as $key => $val ) {
$errorPage .= str_pad ( '[' . $key . ']' , 12 ) . '=> ' . ( is_array ( $val ) || is_object ( $val ) ? json_encode ( $val ) : $val ) . " \r \n " ;
}
2015-09-06 01:04:55 +00:00
2015-09-14 20:51:23 +00:00
$errorPage .= '</pre>' ;
}
2015-09-06 01:04:55 +00:00
}
2015-09-14 20:51:23 +00:00
$errorPage .= ' </ div >
2015-09-06 01:04:55 +00:00
< div class = " footer " >
2015-09-14 20:51:23 +00:00
Sakura r ' . SAKURA_VERSION . ' .
2015-09-06 01:04:55 +00:00
</ div >
</ div >
</ body >
</ html > ' ;
2015-04-18 18:32:41 +00:00
// Die and display error message
2015-09-06 01:04:55 +00:00
die ( $errorPage );
2015-04-01 17:34:36 +00:00
2015-04-18 18:32:41 +00:00
}
2015-04-01 17:34:36 +00:00
2015-04-18 18:26:52 +00:00
// Send emails
2015-09-14 20:51:23 +00:00
public static function sendMail ( $to , $subject , $body )
{
2015-04-18 18:26:52 +00:00
// Initialise PHPMailer
2015-06-04 12:41:55 +00:00
$mail = new PHPMailer ();
2015-04-18 18:26:52 +00:00
// Set to SMTP
$mail -> IsSMTP ();
// Set the SMTP server host
$mail -> Host = Configuration :: getConfig ( 'smtp_server' );
// Do we require authentication?
$mail -> SMTPAuth = Configuration :: getConfig ( 'smtp_auth' );
// Do we encrypt as well?
$mail -> SMTPSecure = Configuration :: getConfig ( 'smtp_secure' );
// Set the port to the SMTP server
$mail -> Port = Configuration :: getConfig ( 'smtp_port' );
// If authentication is required log in as well
2015-09-14 20:51:23 +00:00
if ( Configuration :: getConfig ( 'smtp_auth' )) {
2015-04-18 18:26:52 +00:00
$mail -> Username = Configuration :: getConfig ( 'smtp_username' );
$mail -> Password = base64_decode ( Configuration :: getConfig ( 'smtp_password' ));
}
// Add a reply-to header
$mail -> AddReplyTo ( Configuration :: getConfig ( 'smtp_replyto_mail' ), Configuration :: getConfig ( 'smtp_replyto_name' ));
// Set a from address as well
$mail -> SetFrom ( Configuration :: getConfig ( 'smtp_from_email' ), Configuration :: getConfig ( 'smtp_from_name' ));
// Set the addressee
2015-09-14 20:51:23 +00:00
foreach ( $to as $email => $name ) {
2015-04-18 18:26:52 +00:00
$mail -> AddBCC ( $email , $name );
2015-09-05 16:11:04 +00:00
}
2015-04-18 18:26:52 +00:00
// Subject line
$mail -> Subject = $subject ;
// Set the mail type to HTML
$mail -> isHTML ( true );
// Set email contents
2015-09-14 20:51:23 +00:00
$htmlMail = file_get_contents ( ROOT . '_sakura/templates/htmlEmail.tpl' );
2015-04-18 18:26:52 +00:00
// Replace template tags
2015-09-14 20:51:23 +00:00
$htmlMail = str_replace ( '{{ sitename }}' , Configuration :: getConfig ( 'sitename' ), $htmlMail );
$htmlMail = str_replace ( '{{ siteurl }}' , '//' . Configuration :: getConfig ( 'url_main' ), $htmlMail );
$htmlMail = str_replace ( '{{ contents }}' , self :: mdParse ( $body ), $htmlMail );
2015-04-18 18:26:52 +00:00
// Set HTML body
$mail -> Body = $htmlMail ;
// Set fallback body
$mail -> AltBody = $body ;
// Send the message
$send = $mail -> Send ();
// Clear the addressee list
$mail -> ClearAddresses ();
// If we got an error return the error
2015-09-14 20:51:23 +00:00
if ( ! $send ) {
2015-09-05 16:11:04 +00:00
2015-04-18 18:26:52 +00:00
return $mail -> ErrorInfo ;
2015-09-05 16:11:04 +00:00
}
2015-04-18 18:26:52 +00:00
// Else just return whatever
return $send ;
}
2015-04-01 17:34:36 +00:00
// Cleaning strings
2015-09-14 20:51:23 +00:00
public static function cleanString ( $string , $lower = false , $noSpecial = false )
{
2015-04-01 17:34:36 +00:00
2015-04-27 00:41:59 +00:00
// Run common sanitisation function over string
2015-06-29 12:40:00 +00:00
$string = htmlentities ( $string , ENT_NOQUOTES | ENT_HTML401 , Configuration :: getConfig ( 'charset' ));
2015-04-18 18:32:41 +00:00
$string = stripslashes ( $string );
$string = strip_tags ( $string );
2015-04-27 00:41:59 +00:00
// If set also make the string lowercase
2015-09-14 20:51:23 +00:00
if ( $lower ) {
2015-04-01 17:34:36 +00:00
$string = strtolower ( $string );
2015-09-05 16:11:04 +00:00
}
2015-04-27 00:41:59 +00:00
// If set remove all characters that aren't a-z or 0-9
2015-09-14 20:51:23 +00:00
if ( $noSpecial ) {
2015-04-27 00:41:59 +00:00
$string = preg_replace ( '/[^a-z0-9]/' , '' , $string );
2015-09-05 16:11:04 +00:00
}
2015-04-27 00:41:59 +00:00
// Return clean string
2015-04-18 18:32:41 +00:00
return $string ;
2015-04-01 17:34:36 +00:00
}
// Loading info pages
2015-09-14 20:51:23 +00:00
public static function loadInfoPage ( $id )
{
2015-04-01 17:34:36 +00:00
// Get contents from the database
$infopage = Database :: fetch ( 'infopages' , false , [ 'shorthand' => [ $id , '=' ]]);
2015-04-01 17:45:05 +00:00
// Return the data if there is any else just return false
return count ( $infopage ) ? $infopage : false ;
2015-04-01 17:34:36 +00:00
}
2015-04-14 14:27:37 +00:00
// Validate MX records
2015-09-14 20:51:23 +00:00
public static function checkMXRecord ( $email )
{
2015-04-14 14:27:37 +00:00
2015-04-19 13:00:32 +00:00
// Get the domain from the e-mail address
$domain = substr ( strstr ( $email , '@' ), 1 );
2015-04-14 14:27:37 +00:00
// Check the MX record
$record = checkdnsrr ( $domain , 'MX' );
// Return the record data
return $record ;
}
// Check IP version
2015-09-14 20:51:23 +00:00
public static function ipVersion ( $ip )
{
2015-04-14 14:27:37 +00:00
// Check if var is IP
2015-09-14 20:51:23 +00:00
if ( filter_var ( $ip , FILTER_VALIDATE_IP )) {
2015-04-14 14:27:37 +00:00
// IPv4
2015-09-14 20:51:23 +00:00
if ( filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 )) {
2015-04-14 14:27:37 +00:00
return 4 ;
2015-09-05 16:11:04 +00:00
}
2015-04-14 14:27:37 +00:00
// IPv6
2015-09-14 20:51:23 +00:00
if ( filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 )) {
2015-04-14 14:27:37 +00:00
return 6 ;
2015-09-05 16:11:04 +00:00
}
2015-04-14 14:27:37 +00:00
}
// Not an IP or unknown type
return 0 ;
}
// Convert inet_pton to string with bits
2015-09-14 20:51:23 +00:00
public static function inetToBits ( $inet )
{
2015-04-14 14:27:37 +00:00
// Unpack string
$unpacked = unpack ( 'A16' , $inet );
// Split the string
$unpacked = str_split ( $unpacked [ 1 ]);
// Define variable
$binaryIP = null ;
// "Build" binary IP
2015-09-14 20:51:23 +00:00
foreach ( $unpacked as $char ) {
2015-04-14 14:27:37 +00:00
$binaryIP .= str_pad ( decbin ( ord ( $char )), 8 , '0' , STR_PAD_LEFT );
2015-09-05 16:11:04 +00:00
}
2015-04-14 14:27:37 +00:00
// Return IP
return $binaryIP ;
}
// Match IP subnets
2015-09-14 20:51:23 +00:00
public static function matchSubnet ( $ip , $range )
{
2015-04-14 14:27:37 +00:00
// Use the proper IP type
2015-09-14 20:51:23 +00:00
switch ( self :: ipVersion ( $ip )) {
2015-04-14 14:27:37 +00:00
case 4 :
// Break the range up in parts
list ( $subnet , $bits ) = explode ( '/' , $range );
// Convert IP and Subnet to long
2015-09-14 20:51:23 +00:00
$ip = ip2long ( $ip );
2015-04-14 14:27:37 +00:00
$subnet = ip2long ( $subnet );
2015-09-14 20:51:23 +00:00
$mask = - 1 << ( 32 - $bits );
2015-04-14 14:27:37 +00:00
// 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
2015-09-14 20:51:23 +00:00
$subnet = inet_pton ( $subnet );
$binarySubnet = self :: inetToBits ( $subnet );
2015-04-14 14:27:37 +00:00
// Convert IPv6 to packed address and convert it to binary as well
2015-09-14 20:51:23 +00:00
$ip = inet_pton ( $ip );
$binaryIP = self :: inetToBits ( $ip );
2015-04-14 14:27:37 +00:00
// Return bits of the strings according to the bits
2015-09-14 20:51:23 +00:00
$ipBits = substr ( $binaryIP , 0 , $bits );
2015-04-14 14:27:37 +00:00
$subnetBits = substr ( $binarySubnet , 0 , $bits );
return ( $ipBits === $subnetBits );
default :
return 0 ;
}
}
// Check if IP is a CloudFlare IP
2015-09-14 20:51:23 +00:00
public static function checkCFIP ( $ip )
{
2015-04-14 14:27:37 +00:00
// Get CloudFlare Subnet list
2015-09-14 20:51:23 +00:00
$cfhosts = file_get_contents ( ROOT . '_sakura/' . Configuration :: getLocalConfig ( 'data' , 'cfipv' . ( self :: ipVersion ( $ip ))));
2015-04-14 14:27:37 +00:00
// 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
2015-09-14 20:51:23 +00:00
foreach ( $cfhosts as $subnet ) {
2015-09-07 20:53:47 +00:00
// Check if the subnet isn't empty (git newline prevention)
2015-09-14 20:51:23 +00:00
if ( strlen ( $subnet ) < 1 ) {
2015-09-07 20:53:47 +00:00
continue ;
}
2015-04-14 14:27:37 +00:00
// Return true if found
2015-09-14 20:51:23 +00:00
if ( self :: matchSubnet ( $ip , $subnet )) {
2015-04-14 14:27:37 +00:00
return true ;
2015-09-05 16:11:04 +00:00
}
2015-04-14 14:27:37 +00:00
}
// Return false if fails
return false ;
}
// Gets IP of current visitor
2015-09-14 20:51:23 +00:00
public static function getRemoteIP ()
{
2015-04-14 14:27:37 +00:00
// Assign REMOTE_ADDR to a variables
$ip = $_SERVER [ 'REMOTE_ADDR' ];
// Check if the IP is a CloudFlare IP
2015-09-14 20:51:23 +00:00
if ( self :: checkCFIP ( $ip )) {
2015-04-14 14:27:37 +00:00
// If it is check if the CloudFlare IP header is set and if it is assign it to the ip variable
2015-09-14 20:51:23 +00:00
if ( isset ( $_SERVER [ 'HTTP_CF_CONNECTING_IP' ])) {
2015-04-14 14:27:37 +00:00
$ip = $_SERVER [ 'HTTP_CF_CONNECTING_IP' ];
2015-09-05 16:11:04 +00:00
}
2015-04-14 14:27:37 +00:00
}
// Return the correct IP
return $ip ;
}
2015-09-03 19:44:14 +00:00
// Get country code from CloudFlare header (which just returns XX if not found)
2015-09-14 20:51:23 +00:00
public static function getCountryCode ()
{
2015-04-18 18:26:52 +00:00
2015-04-27 17:04:27 +00:00
// Check if the required header is set and return it
2015-09-14 20:51:23 +00:00
if ( isset ( $_SERVER [ 'HTTP_CF_IPCOUNTRY' ])) {
2015-04-27 17:04:27 +00:00
return $_SERVER [ 'HTTP_CF_IPCOUNTRY' ];
2015-09-05 16:11:04 +00:00
}
2015-09-03 19:44:14 +00:00
// Return XX as a fallback
return 'XX' ;
2015-04-18 18:26:52 +00:00
}
2015-04-19 13:00:32 +00:00
// Create a new action code
2015-09-14 20:51:23 +00:00
public static function newActionCode ( $action , $userid , $instruct )
{
2015-04-19 13:00:32 +00:00
// Make sure the user we're working with exists
2015-09-14 20:51:23 +00:00
if ( Users :: getUser ( $userid )[ 'id' ] == 0 ) {
2015-04-19 13:00:32 +00:00
return false ;
2015-09-05 16:11:04 +00:00
}
2015-04-19 13:00:32 +00:00
// Convert the instruction array to a JSON
$instruct = json_encode ( $instruct );
// Generate a key
$key = sha1 ( date ( " r " ) . time () . $userid . $action . rand ( 0 , 9999 ));
// Insert the key into the database
Database :: insert ( 'actioncodes' , [
2015-09-14 20:51:23 +00:00
'action' => $action ,
'userid' => $userid ,
'actkey' => $key ,
'instruction' => $instruct ,
2015-04-19 13:00:32 +00:00
]);
// Return the key
return $key ;
}
// Use an action code
2015-09-14 20:51:23 +00:00
public static function useActionCode ( $action , $key , $uid = 0 )
{
2015-04-19 13:00:32 +00:00
// Retrieve the row from the database
$keyRow = Database :: fetch ( 'actioncodes' , false , [
2015-09-14 20:51:23 +00:00
'actkey' => [ $key , '=' ],
'action' => [ $action , '=' ],
2015-04-19 13:00:32 +00:00
]);
// Check if the code exists
2015-09-14 20:51:23 +00:00
if ( count ( $keyRow ) <= 1 ) {
2015-04-19 13:00:32 +00:00
return [ 0 , 'INVALID_CODE' ];
2015-09-05 16:11:04 +00:00
}
2015-04-19 13:00:32 +00:00
// Check if the code was intended for the user that's using this code
2015-09-14 20:51:23 +00:00
if ( $keyRow [ 'userid' ] != 0 ) {
if ( $keyRow [ 'userid' ] != $uid ) {
2015-04-19 13:00:32 +00:00
return [ 0 , 'INVALID_USER' ];
2015-09-05 16:11:04 +00:00
}
2015-04-19 13:00:32 +00:00
}
// Remove the key from the database
Database :: delete ( 'actioncodes' , [
2015-09-14 20:51:23 +00:00
'id' => [ $keyRow [ 'id' ], '=' ],
2015-04-19 13:00:32 +00:00
]);
// Return success
return [ 1 , 'SUCCESS' , $keyRow [ 'instruction' ]];
}
2015-04-24 17:48:56 +00:00
// Calculate password entropy
2015-09-14 20:51:23 +00:00
public static function pwdEntropy ( $pw )
{
2015-04-24 17:48:56 +00:00
// Decode utf-8 chars
$pw = utf8_decode ( $pw );
// Count the amount of unique characters in the password string and calculate the entropy
return count ( count_chars ( $pw , 1 )) * log ( 256 , 2 );
}
2015-04-27 00:41:59 +00:00
// Get country name from ISO 3166 code
2015-09-14 20:51:23 +00:00
public static function getCountryName ( $code )
{
2015-04-27 00:41:59 +00:00
// Parse JSON file
2015-09-14 20:51:23 +00:00
$iso3166 = json_decode ( utf8_encode ( file_get_contents ( ROOT . '_sakura/' . Configuration :: getLocalConfig ( 'data' , 'iso3166' ))), true );
2015-04-27 00:41:59 +00:00
// Check if key exists
2015-09-14 20:51:23 +00:00
if ( array_key_exists ( $code , $iso3166 )) {
2015-04-27 00:41:59 +00:00
return $iso3166 [ $code ]; // If entry found return the full name
2015-09-05 16:11:04 +00:00
}
2015-09-14 20:51:23 +00:00
// Else return unknown
return 'Unknown' ;
2015-04-27 00:41:59 +00:00
}
2015-04-30 14:12:49 +00:00
// Get FAQ data
2015-09-14 20:51:23 +00:00
public static function getFaqData ()
{
2015-04-30 14:12:49 +00:00
// Do database call
$faq = Database :: fetch ( 'faq' , true , null , [ 'id' ]);
// Return FAQ data
return $faq ;
}
2015-05-23 03:31:42 +00:00
// Get log type string
2015-09-14 20:51:23 +00:00
public static function getLogStringFromType ( $type )
{
2015-05-23 03:31:42 +00:00
// Query the database
$return = Database :: fetch ( 'logtypes' , false , [ 'id' => [ $type , '=' ]]);
// Check if type exists and else return a unformattable string
2015-09-14 20:51:23 +00:00
if ( count ( $return ) < 2 ) {
2015-05-23 03:31:42 +00:00
return 'Unknown action.' ;
2015-09-05 16:11:04 +00:00
}
2015-05-23 03:31:42 +00:00
// Return the string
return $return [ 'string' ];
}
// Get formatted logs
2015-09-14 20:51:23 +00:00
public static function getUserLogs ( $uid = 0 )
{
2015-05-23 03:31:42 +00:00
// 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 = array ();
// Iterate over entries
2015-09-14 20:51:23 +00:00
foreach ( $logsDB as $log ) {
2015-05-23 03:31:42 +00:00
// Store usable data
$logs [ $log [ 'id' ]] = [
2015-09-14 20:51:23 +00:00
'user' => $_USER = Users :: getUser ( $log [ 'uid' ]),
'rank' => Users :: getRank ( $_USER [ 'rank_main' ]),
'string' => vsprintf ( self :: getLogStringFromType ( $log [ 'action' ]), json_decode ( $log [ 'attribs' ], true )),
2015-05-23 03:31:42 +00:00
];
}
// Return new logs
return $logs ;
}
2015-06-04 12:41:55 +00:00
// Indent JSON
2015-09-14 20:51:23 +00:00
public static function jsonPretty ( $json )
{
2015-06-04 12:41:55 +00:00
// Defines
$tab = ' ' ;
$out = '' ;
$lvl = 0 ;
$str = false ;
$obj = json_decode ( $json );
// Validate the object
2015-09-14 20:51:23 +00:00
if ( $obj === false ) {
2015-06-04 12:41:55 +00:00
return false ;
2015-09-14 20:51:23 +00:00
}
2015-06-04 12:41:55 +00:00
// Re-encode the json and get the length
$json = json_encode ( $obj );
$len = strlen ( $json );
// Go over the entries
2015-09-14 20:51:23 +00:00
for ( $c = 0 ; $c < $len ; $c ++ ) {
2015-06-04 12:41:55 +00:00
// Get the current character
$char = $json [ $c ];
2015-09-14 20:51:23 +00:00
switch ( $char ) {
2015-06-04 12:41:55 +00:00
case '[' :
case '{' :
2015-09-14 20:51:23 +00:00
if ( $str ) {
2015-06-04 12:41:55 +00:00
$out .= $char ;
} else {
2015-09-14 20:51:23 +00:00
$out .= $char . " \r \n " . str_repeat ( $tab , $lvl + 1 );
2015-06-04 12:41:55 +00:00
$lvl ++ ;
}
break ;
case ']' :
case '}' :
2015-09-14 20:51:23 +00:00
if ( $str ) {
2015-06-04 12:41:55 +00:00
$out .= $char ;
} else {
$lvl -- ;
2015-09-14 20:51:23 +00:00
$out .= " \r \n " . str_repeat ( $tab , $lvl ) . $char ;
2015-06-04 12:41:55 +00:00
}
break ;
case ',' :
2015-09-14 20:51:23 +00:00
if ( $str ) {
2015-06-04 12:41:55 +00:00
$out .= $char ;
} else {
2015-09-14 20:51:23 +00:00
$out .= " , \r \n " . str_repeat ( $tab , $lvl );
2015-06-04 12:41:55 +00:00
}
break ;
case ':' :
2015-09-14 20:51:23 +00:00
if ( $str ) {
2015-06-04 12:41:55 +00:00
$out .= $char ;
} else {
$out .= " : " ;
}
break ;
default :
$out .= $char ;
break ;
}
}
2015-05-24 22:06:53 +00:00
2015-06-04 12:41:55 +00:00
// Return the indented JSON
return $out ;
2015-05-24 22:06:53 +00:00
}
2015-07-05 00:03:15 +00:00
// Time elapsed
2015-09-14 20:51:23 +00:00
public static function timeElapsed ( $timestamp , $append = ' ago' , $none = 'Just now' )
{
2015-07-05 00:03:15 +00:00
// Subtract the entered timestamp from the current timestamp
$time = time () - $timestamp ;
// If the new timestamp is below 1 return a standard string
2015-09-14 20:51:23 +00:00
if ( $time < 1 ) {
2015-09-08 21:57:33 +00:00
return $none ;
}
2015-07-05 00:03:15 +00:00
// Array containing time "types"
$times = [
365 * 24 * 60 * 60 => 'year' ,
2015-09-14 20:51:23 +00:00
30 * 24 * 60 * 60 => 'month' ,
24 * 60 * 60 => 'day' ,
60 * 60 => 'hour' ,
60 => 'minute' ,
1 => 'second' ,
2015-07-05 00:03:15 +00:00
];
2015-09-14 20:51:23 +00:00
foreach ( $times as $secs => $str ) {
2015-07-05 00:03:15 +00:00
// Do a devision to check if the given timestamp fits in the current "type"
$calc = $time / $secs ;
2015-09-14 20:51:23 +00:00
if ( $calc >= 1 ) {
2015-07-05 00:03:15 +00:00
// Round the number
$round = round ( $calc );
// Return the string
2015-09-14 20:51:23 +00:00
return $round . ' ' . $times [ $secs ] . ( $round == 1 ? '' : 's' ) . $append ;
2015-08-23 22:08:36 +00:00
}
2015-07-05 00:03:15 +00:00
}
}
2015-08-09 18:26:01 +00:00
// Get the byte symbol from a value
2015-09-14 20:51:23 +00:00
public static function getByteSymbol ( $bytes )
{
2015-08-09 18:26:01 +00:00
// Return nothing if the input was 0
2015-09-14 20:51:23 +00:00
if ( ! $bytes ) {
2015-08-09 18:26:01 +00:00
return ;
2015-09-14 20:51:23 +00:00
}
2015-08-09 18:26:01 +00:00
// Array with byte symbols
$symbols = [ 'B' , 'KiB' , 'MiB' , 'GiB' , 'TiB' , 'PiB' , 'EiB' , 'ZiB' , 'YiB' ];
// Calculate byte entity
$exp = floor ( log ( $bytes ) / log ( 1024 ));
// Format the things
2015-09-14 20:51:23 +00:00
$bytes = sprintf ( " %.2f " . $symbols [ $exp ], ( $bytes / pow ( 1024 , floor ( $exp ))));
2015-08-09 18:26:01 +00:00
// Return the formatted string
return $bytes ;
}
2015-09-03 19:44:14 +00:00
// Get Premium tracker data
2015-09-14 20:51:23 +00:00
public static function getPremiumTrackerData ()
{
2015-09-03 19:44:14 +00:00
// Create data array
$data = [];
// Get database stuff
$table = Database :: fetch ( 'premium_log' , true , null , [ 'id' , true ]);
// Add raw table data to data array
$data [ 'table' ] = $table ;
// Create balance entry
$data [ 'balance' ] = 0.0 ;
// Create users entry
$data [ 'users' ] = [];
// Calculate the thing
2015-09-14 20:51:23 +00:00
foreach ( $table as $row ) {
2015-09-03 19:44:14 +00:00
// Calculate balance
$data [ 'balance' ] = $data [ 'balance' ] + $row [ 'amount' ];
// Add userdata to table
2015-09-14 20:51:23 +00:00
if ( ! array_key_exists ( $row [ 'uid' ], $data [ 'users' ])) {
2015-09-03 19:44:14 +00:00
$data [ 'users' ][ $row [ 'uid' ]] = new User ( $row [ 'uid' ]);
}
}
// Return the data
return $data ;
}
// Update donation tracker
2015-09-14 20:51:23 +00:00
public static function updatePremiumTracker ( $id , $amount , $comment )
{
2015-09-03 19:44:14 +00:00
Database :: insert ( 'premium_log' , [
2015-09-14 20:51:23 +00:00
'uid' => $id ,
'amount' => $amount ,
'date' => time (),
'comment' => $comment ,
2015-09-03 19:44:14 +00:00
]);
}
2015-04-01 17:34:36 +00:00
}