2020-12-26 01:42:23 +08:00
< ? php
2022-03-20 22:14:00 +08:00
2020-12-26 01:42:23 +08:00
function get_global_sp_state ()
{
static $global_promotion_state ;
2022-08-26 17:35:49 +08:00
$cacheKey = \App\Models\Setting :: TORRENT_GLOBAL_STATE_CACHE_KEY ;
2022-07-23 23:35:43 +08:00
if ( ! $global_promotion_state ) {
2022-07-30 15:06:51 +08:00
$row = \Nexus\Database\NexusDB :: remember ( $cacheKey , 600 , function () use ( $cacheKey ) {
2022-08-26 17:35:49 +08:00
return \Nexus\Database\NexusDB :: getOne ( 'torrents_state' , 1 );
2022-07-30 15:06:51 +08:00
});
2022-07-30 15:42:07 +08:00
if ( is_array ( $row ) && isset ( $row [ 'deadline' ]) && $row [ 'deadline' ] < date ( 'Y-m-d H:i:s' )) {
2022-07-30 15:06:51 +08:00
//expired
$global_promotion_state = \App\Models\Torrent :: PROMOTION_NORMAL ;
2022-08-26 17:35:49 +08:00
} elseif ( is_array ( $row ) && isset ( $row [ 'begin' ]) && $row [ 'begin' ] > date ( 'Y-m-d H:i:s' )) {
//Not begin
$global_promotion_state = \App\Models\Torrent :: PROMOTION_NORMAL ;
2022-07-30 15:42:07 +08:00
} elseif ( is_array ( $row )) {
2022-07-30 15:06:51 +08:00
$global_promotion_state = $row [ " global_sp_state " ];
2022-07-30 15:42:07 +08:00
} else {
$global_promotion_state = $row ;
2022-07-30 15:06:51 +08:00
}
2020-12-26 01:42:23 +08:00
}
return $global_promotion_state ;
}
// IP Validation
function validip ( $ip )
{
if ( ! ip2long ( $ip )) //IPv6
return true ;
if ( ! empty ( $ip ) && $ip == long2ip ( ip2long ( $ip )))
{
// reserved IANA IPv4 addresses
// http://www.iana.org/assignments/ipv4-address-space
$reserved_ips = array (
array ( '192.0.2.0' , '192.0.2.255' ),
array ( '192.168.0.0' , '192.168.255.255' ),
array ( '255.255.255.0' , '255.255.255.255' )
);
foreach ( $reserved_ips as $r )
{
$min = ip2long ( $r [ 0 ]);
$max = ip2long ( $r [ 1 ]);
if (( ip2long ( $ip ) >= $min ) && ( ip2long ( $ip ) <= $max )) return false ;
}
return true ;
}
else return false ;
}
2024-01-23 01:36:58 +08:00
function getip ( $real = true ) {
2020-12-26 01:42:23 +08:00
if ( isset ( $_SERVER )) {
if ( isset ( $_SERVER [ 'HTTP_X_FORWARDED_FOR' ]) && validip ( $_SERVER [ 'HTTP_X_FORWARDED_FOR' ])) {
$ip = $_SERVER [ 'HTTP_X_FORWARDED_FOR' ];
} elseif ( isset ( $_SERVER [ 'HTTP_CLIENT_IP' ]) && validip ( $_SERVER [ 'HTTP_CLIENT_IP' ])) {
$ip = $_SERVER [ 'HTTP_CLIENT_IP' ];
} else {
2021-05-31 21:04:49 +08:00
$ip = $_SERVER [ 'REMOTE_ADDR' ] ? ? '' ;
2020-12-26 01:42:23 +08:00
}
} else {
if ( getenv ( 'HTTP_X_FORWARDED_FOR' ) && validip ( getenv ( 'HTTP_X_FORWARDED_FOR' ))) {
$ip = getenv ( 'HTTP_X_FORWARDED_FOR' );
} elseif ( getenv ( 'HTTP_CLIENT_IP' ) && validip ( getenv ( 'HTTP_CLIENT_IP' ))) {
$ip = getenv ( 'HTTP_CLIENT_IP' );
} else {
2021-05-31 21:04:49 +08:00
$ip = getenv ( 'REMOTE_ADDR' ) ? ? '' ;
2020-12-26 01:42:23 +08:00
}
}
2024-03-01 23:45:13 +08:00
$ip = trim ( trim ( $ip ), " , " );
if ( $real && str_contains ( $ip , " , " )) {
2024-01-23 01:34:06 +08:00
return strstr ( $ip , " , " , true );
}
2020-12-26 01:42:23 +08:00
return $ip ;
}
function sql_query ( $query )
{
2021-01-12 21:14:02 +08:00
$begin = microtime ( true );
2020-12-26 01:42:23 +08:00
global $query_name ;
2020-12-29 21:49:37 +08:00
$result = mysql_query ( $query );
2021-01-15 22:13:46 +08:00
$end = microtime ( true );
2020-12-29 21:49:37 +08:00
$query_name [] = [
'query' => $query ,
2021-01-15 22:13:46 +08:00
'time' => sprintf ( '%.3f ms' , ( $end - $begin ) * 1000 ),
2020-12-29 21:49:37 +08:00
];
return $result ;
2020-12-26 01:42:23 +08:00
}
function sqlesc ( $value ) {
2021-01-11 22:00:46 +08:00
if ( is_null ( $value )) {
2021-01-20 20:06:48 +08:00
return 'null' ;
2021-01-11 22:00:46 +08:00
}
$value = " ' " . mysql_real_escape_string ( $value ) . " ' " ;
2020-12-26 01:42:23 +08:00
return $value ;
}
function hash_pad ( $hash ) {
return str_pad ( $hash , 20 );
}
function hash_where ( $name , $hash ) {
2023-03-04 13:26:20 +08:00
// $shhash = preg_replace('/ *$/s', "", $hash);
2021-06-13 20:53:14 +08:00
// return "($name = " . sqlesc($hash) . " OR $name = " . sqlesc($shhash) . ")";
2023-03-04 13:26:20 +08:00
// return sprintf("$name in (%s, %s)", sqlesc($hash), sqlesc($shhash));
return " $name = " . sqlesc ( $hash );
2020-12-26 01:42:23 +08:00
}
2021-01-12 21:14:02 +08:00
2021-05-11 01:41:58 +08:00
//no need any more...
/*
2021-01-12 21:14:02 +08:00
function strip_magic_quotes ( $arr )
{
foreach ( $arr as $k => $v )
{
if ( is_array ( $v ))
{
$arr [ $k ] = strip_magic_quotes ( $v );
} else {
$arr [ $k ] = stripslashes ( $v );
}
}
return $arr ;
}
if ( function_exists ( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc ())
{
if ( ! empty ( $_GET )) {
$_GET = strip_magic_quotes ( $_GET );
}
if ( ! empty ( $_POST )) {
$_POST = strip_magic_quotes ( $_POST );
}
if ( ! empty ( $_COOKIE )) {
$_COOKIE = strip_magic_quotes ( $_COOKIE );
}
}
2021-05-11 01:41:58 +08:00
*/
2021-01-12 21:14:02 +08:00
function get_langfolder_list ()
{
//do not access db for speed up, or for flexibility
return array ( " en " , " chs " , " cht " , " ko " , " ja " );
}
function printLine ( $line , $exist = false )
{
echo " [ " . date ( 'Y-m-d H:i:s' ) . " ] $line <br /> " ;
if ( $exist ) {
exit ( 0 );
}
}
2021-04-02 19:48:41 +08:00
function nexus_dd ( $vars )
2021-01-12 21:14:02 +08:00
{
2021-04-02 19:48:41 +08:00
echo '<pre>' ;
array_map ( function ( $var ) {
var_dump ( $var );
}, func_get_args ());
echo '</pre>' ;
exit ( 0 );
2021-01-12 21:14:02 +08:00
}
2021-04-26 20:37:17 +08:00
/**
* write log , use in both pure nexus and inside laravel
*
* @ param $log
* @ param string $level
*/
2022-03-26 04:27:04 +08:00
function do_log ( $log , $level = 'info' , $echo = false )
2021-01-12 21:14:02 +08:00
{
2022-03-20 22:14:00 +08:00
static $env , $setLogLevel ;
2021-06-09 15:11:02 +08:00
if ( is_null ( $setLogLevel )) {
$setLogLevel = nexus_env ( 'LOG_LEVEL' , 'debug' );
}
2022-03-20 22:14:00 +08:00
if ( is_null ( $env )) {
$env = nexus_env ( 'APP_ENV' , 'production' );
}
2022-03-18 19:59:27 +08:00
$logLevels = [ 'debug' , 'info' , 'notice' , 'warning' , 'error' , 'critical' , 'alert' , 'emergency' ];
2021-06-09 15:11:02 +08:00
$setLogLevelKey = array_search ( $setLogLevel , $logLevels );
$currentLogLevelKey = array_search ( $level , $logLevels );
if ( $currentLogLevelKey === false ) {
2022-03-18 19:59:27 +08:00
$level = 'error' ;
2021-06-09 15:11:02 +08:00
$log = " [ERROR_LOG_LEVEL] $log " ;
$currentLogLevelKey = array_search ( $level , $logLevels );
}
if ( $currentLogLevelKey < $setLogLevelKey ) {
return ;
}
2021-01-30 13:53:15 +08:00
$logFile = getLogFile ();
2021-04-26 20:37:17 +08:00
if (( $fd = fopen ( $logFile , 'a' )) === false ) {
2022-06-20 19:16:37 +08:00
$log .= " --------Can not open $logFile " ;
$fd = fopen ( sys_get_temp_dir () . '/nexus.log' , 'a' );
2021-01-12 21:14:02 +08:00
}
2022-04-06 21:32:57 +08:00
$uid = 0 ;
2022-03-20 22:14:00 +08:00
if ( IN_NEXUS ) {
global $CURUSER ;
$user = $CURUSER ;
$uid = $user [ 'id' ] ? ? 0 ;
$passkey = $user [ 'passkey' ] ? ? $_REQUEST [ 'passkey' ] ? ? $_REQUEST [ 'authkey' ] ? ? '' ;
2021-05-31 21:04:49 +08:00
} else {
2022-04-06 21:32:57 +08:00
try {
$user = \Illuminate\Support\Facades\Auth :: user ();
$uid = $user -> id ? ? 0 ;
$passkey = $user -> passkey ? ? request ( 'passkey' , request ( 'authkey' , '' ));
} catch ( \Throwable $exception ) {
$passkey = " !IN_NEXUS: " . $exception -> getMessage ();
}
2021-04-26 20:37:17 +08:00
}
$backtrace = debug_backtrace ( DEBUG_BACKTRACE_IGNORE_ARGS , 2 );
$content = sprintf (
2021-05-31 21:04:49 +08:00
" [%s] [%s] [%s] [%s] [%s] [%s] %s.%s %s:%s %s%s%s %s%s " ,
2021-04-26 20:37:17 +08:00
date ( 'Y-m-d H:i:s' ),
2022-03-20 22:14:00 +08:00
nexus () ? nexus () -> getRequestId () : 'NO_REQUEST_ID' ,
nexus () ? nexus () -> getLogSequence () : 0 ,
sprintf ( '%.3f' , microtime ( true ) - ( nexus () ? nexus () -> getStartTimestamp () : 0 )),
2021-04-26 20:37:17 +08:00
$uid ,
$passkey ,
2023-07-17 02:02:45 +08:00
$env , strtoupper ( $level ),
2021-04-26 20:37:17 +08:00
$backtrace [ 0 ][ 'file' ] ? ? '' ,
$backtrace [ 0 ][ 'line' ] ? ? '' ,
$backtrace [ 1 ][ 'class' ] ? ? '' ,
$backtrace [ 1 ][ 'type' ] ? ? '' ,
$backtrace [ 1 ][ 'function' ] ? ? '' ,
$log ,
PHP_EOL
);
fwrite ( $fd , $content );
fclose ( $fd );
2022-03-26 04:27:04 +08:00
if ( is_bool ( $echo ) && $echo ) {
echo $content . PHP_EOL ;
}
2022-03-20 22:14:00 +08:00
if ( nexus ()) {
nexus () -> incrementLogSequence ();
}
2021-01-12 21:14:02 +08:00
}
2023-03-13 17:41:03 +08:00
function getLogFile ( $append = '' )
2021-01-30 13:53:15 +08:00
{
2023-03-13 17:41:03 +08:00
static $logFiles = [];
if ( isset ( $logFiles [ $append ])) {
return $logFiles [ $append ];
2021-01-30 13:53:15 +08:00
}
2022-04-06 21:32:57 +08:00
$config = nexus_config ( 'nexus' );
2025-04-17 01:39:40 +07:00
if ( ! empty ( $config [ 'log_file' ]) && in_array ( $config [ 'log_files' ], [ " /dev/stdout " , " /dev/stderr " ])) {
return $logFiles [ $append ] = $config [ 'log_files' ];
}
2022-06-20 18:26:38 +08:00
$path = getenv ( 'NEXUS_LOG_DIR' , true );
$fromEnv = true ;
if ( $path === false ) {
$fromEnv = false ;
$path = sys_get_temp_dir ();
}
2022-06-20 19:16:37 +08:00
$logFile = rtrim ( $path , '/' ) . '/nexus.log' ;
2022-06-20 18:26:38 +08:00
if ( ! $fromEnv && ! empty ( $config [ 'log_file' ])) {
2021-01-30 13:53:15 +08:00
$logFile = $config [ 'log_file' ];
}
$lastDotPos = strrpos ( $logFile , '.' );
if ( $lastDotPos !== false ) {
$prefix = substr ( $logFile , 0 , $lastDotPos );
$suffix = substr ( $logFile , $lastDotPos );
} else {
$prefix = $logFile ;
$suffix = '' ;
}
2023-03-13 17:41:03 +08:00
$name = $prefix ;
if ( $append ) {
$name .= " - $append " ;
}
2025-01-19 14:37:00 +08:00
if ( isRunningInConsole ()) {
2025-01-19 19:09:16 +08:00
$scriptUserInfo = posix_getpwuid ( posix_getuid ());
$name .= sprintf ( " -cli-%s " , $scriptUserInfo [ 'name' ]);
2025-01-19 14:37:00 +08:00
}
2023-03-13 17:41:03 +08:00
$logFile = sprintf ( '%s-%s%s' , $name , date ( 'Y-m-d' ), $suffix );
return $logFiles [ $append ] = $logFile ;
2021-01-30 13:53:15 +08:00
}
2021-04-02 19:48:41 +08:00
function nexus_config ( $key , $default = null )
2021-01-12 21:14:02 +08:00
{
2022-05-03 23:58:27 +08:00
if ( ! IN_NEXUS ) {
return config ( $key , $default );
}
2021-04-02 19:48:41 +08:00
static $configs ;
if ( is_null ( $configs )) {
//get all configuration from config file
// $files = glob(ROOT_PATH . 'config/*.php');
$files = [
ROOT_PATH . 'config/nexus.php' ,
2022-05-03 23:58:27 +08:00
ROOT_PATH . 'config/emoji.php' ,
2021-04-02 19:48:41 +08:00
];
foreach ( $files as $file ) {
$basename = basename ( $file );
if ( $basename == 'allconfig.php' ) {
//exclude the NexusPHP default config file
continue ;
}
$values = require $file ;
$configPrefix = strstr ( $basename , '.php' , true );
$configs [ $configPrefix ] = $values ;
}
}
return arr_get ( $configs , $key , $default );
2021-01-12 21:14:02 +08:00
}
2021-04-02 19:48:41 +08:00
2021-01-12 21:14:02 +08:00
/**
* get setting for given name and prefix
*
* @ date 2021 / 1 / 11
* @ param null $name
2022-04-04 17:26:26 +08:00
* @ param null $default
* @ return mixed
2021-01-12 21:14:02 +08:00
*/
2022-04-04 17:26:26 +08:00
function get_setting ( $name = null , $default = null ) : mixed
2021-01-12 21:14:02 +08:00
{
static $settings ;
if ( is_null ( $settings )) {
2022-04-22 01:00:59 +08:00
$settings = \Nexus\Database\NexusDB :: remember ( " nexus_settings_in_nexus " , 600 , function () {
2022-03-28 15:58:12 +08:00
//get all settings from database
2022-04-04 17:26:26 +08:00
return \App\Models\Setting :: getFromDb ();
2022-03-28 15:58:12 +08:00
});
2021-01-12 21:14:02 +08:00
}
2021-01-14 20:44:24 +08:00
if ( is_null ( $name )) {
return $settings ;
}
2022-04-04 17:26:26 +08:00
return arr_get ( $settings , $name , $default );
2021-01-12 21:14:02 +08:00
}
2022-04-04 17:26:26 +08:00
function get_setting_from_db ( $name = null , $default = null )
{
static $final ;
if ( is_null ( $final )) {
$final = \App\Models\Setting :: getFromDb ();
}
if ( is_null ( $name )) {
return $final ;
}
return arr_get ( $final , $name , $default );
}
2021-04-02 19:48:41 +08:00
function nexus_env ( $key = null , $default = null )
2021-01-12 21:14:02 +08:00
{
2021-04-02 19:48:41 +08:00
static $env ;
if ( is_null ( $env )) {
2022-03-18 19:59:27 +08:00
$envFile = dirname ( __DIR__ ) . '/.env' ;
2021-04-02 19:48:41 +08:00
$env = readEnvFile ( $envFile );
2021-01-21 20:42:22 +08:00
}
2021-04-02 19:48:41 +08:00
if ( is_null ( $key )) {
return $env ;
}
return $env [ $key ] ? ? $default ;
2021-01-12 21:14:02 +08:00
}
2021-01-21 20:42:22 +08:00
function readEnvFile ( $envFile )
{
if ( ! file_exists ( $envFile )) {
2021-04-30 19:16:51 +08:00
if ( php_sapi_name () == 'cli' ) {
2021-05-02 17:24:05 +08:00
return [];
2021-04-30 19:16:51 +08:00
}
2021-04-02 19:48:41 +08:00
throw new \RuntimeException ( " env file : $envFile is not exists in the root path. " );
2021-01-21 20:42:22 +08:00
}
$env = [];
$fp = fopen ( $envFile , 'r' );
if ( $fp === false ) {
throw new \RuntimeException ( " .env file: $envFile is not readable. " );
}
while (( $line = fgets ( $fp )) !== false ) {
$line = trim ( $line );
if ( empty ( $line )) {
continue ;
}
$pos = strpos ( $line , '=' );
if ( $pos <= 0 ) {
continue ;
}
if ( mb_substr ( $line , 0 , 1 , 'utf-8' ) == '#' ) {
continue ;
}
$lineKey = normalize_env ( mb_substr ( $line , 0 , $pos , 'utf-8' ));
$lineValue = normalize_env ( mb_substr ( $line , $pos + 1 , null , 'utf-8' ));
$env [ $lineKey ] = $lineValue ;
}
return $env ;
}
2021-01-12 21:14:02 +08:00
function normalize_env ( $value )
{
$value = trim ( $value );
$toStrip = [ '\'' , '"' ];
if ( in_array ( mb_substr ( $value , 0 , 1 , 'utf-8' ), $toStrip )) {
$value = mb_substr ( $value , 1 , null , 'utf-8' );
}
if ( in_array ( mb_substr ( $value , - 1 , null , 'utf-8' ), $toStrip )) {
$value = mb_substr ( $value , 0 , - 1 , 'utf-8' );
}
switch ( strtolower ( $value )) {
case 'true' :
return true ;
case 'false' :
return false ;
case 'null' :
return null ;
default :
return $value ;
}
}
2021-01-14 20:44:24 +08:00
/**
* Get an item from an array using " dot " notation .
*
2021-01-15 01:12:44 +08:00
* reference to Laravel
2021-01-14 20:44:24 +08:00
*
* @ date 2021 / 1 / 14
* @ param $array
* @ param $key
* @ param null $default
* @ return mixed | null
*/
2021-01-12 21:14:02 +08:00
function arr_get ( $array , $key , $default = null )
{
if ( strpos ( $key , '.' ) === false ) {
return $array [ $key ] ? ? $default ;
}
foreach ( explode ( '.' , $key ) as $segment ) {
if ( isset ( $array [ $segment ])) {
$array = $array [ $segment ];
} else {
return $default ;
}
}
return $array ;
}
2021-01-13 19:32:26 +08:00
2021-01-14 20:44:24 +08:00
/**
* From Laravel
*
* Set an array item to a given value using " dot " notation .
*
* If no key is given to the method , the entire array will be replaced .
*
* @ param array $array
* @ param string | null $key
* @ param mixed $value
* @ return array
*/
2021-01-13 19:32:26 +08:00
function arr_set ( & $array , $key , $value )
{
2021-01-14 20:44:24 +08:00
if ( is_null ( $key )) {
return $array = $value ;
}
$keys = explode ( '.' , $key );
foreach ( $keys as $i => $key ) {
if ( count ( $keys ) === 1 ) {
break ;
2021-01-14 02:27:55 +08:00
}
2021-01-14 20:44:24 +08:00
unset ( $keys [ $i ]);
// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if ( ! isset ( $array [ $key ]) || ! is_array ( $array [ $key ])) {
$array [ $key ] = [];
2021-01-14 02:27:55 +08:00
}
2021-01-14 20:44:24 +08:00
$array = & $array [ $key ];
2021-01-14 02:27:55 +08:00
}
2021-01-14 20:44:24 +08:00
$array [ array_shift ( $keys )] = $value ;
2021-01-14 02:27:55 +08:00
return $array ;
2021-01-13 19:32:26 +08:00
}
2021-01-22 01:58:28 +08:00
2022-04-07 00:54:05 +08:00
function isHttps () : bool
2021-02-28 02:47:13 +08:00
{
2024-04-01 21:39:43 +08:00
if ( isRunningInConsole ()) {
$securityLogin = get_setting ( " security.securelogin " );
if ( $securityLogin != " no " ) {
return true ;
}
return false ;
}
return nexus () -> getRequestSchema () == 'https' ;
2021-02-28 02:47:13 +08:00
}
2021-01-22 01:58:28 +08:00
2024-04-01 21:39:43 +08:00
function getSchemeAndHttpHost ( bool $fromConfig = false )
2021-01-22 01:58:28 +08:00
{
2024-04-01 21:39:43 +08:00
if ( isRunningInConsole () || $fromConfig ) {
$host = get_setting ( " basic.BASEURL " );
} else {
$host = nexus () -> getRequestHost ();
2021-06-01 23:33:28 +08:00
}
2021-02-28 02:47:13 +08:00
$isHttps = isHttps ();
2021-01-22 01:58:28 +08:00
$protocol = $isHttps ? 'https' : 'http' ;
2022-04-07 19:08:02 +08:00
return " $protocol :// " . $host ;
2021-01-22 01:58:28 +08:00
}
function getBaseUrl ()
{
2021-02-03 18:41:53 +08:00
$url = getSchemeAndHttpHost ();
2025-04-17 01:39:40 +07:00
if ( ! isRunningInConsole ()) {
$requestUri = $_SERVER [ 'REQUEST_URI' ];
$pos = strpos ( $requestUri , '?' );
if ( $pos !== false ) {
$url .= substr ( $requestUri , 0 , $pos );
} else {
$url .= $requestUri ;
}
2021-01-22 01:58:28 +08:00
}
2021-02-28 02:47:13 +08:00
return trim ( $url , '/' );
2021-01-22 01:58:28 +08:00
}
2021-04-02 19:48:41 +08:00
2021-04-21 00:07:32 +08:00
function nexus_json_encode ( $data )
{
return json_encode ( $data , JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
}
2021-04-02 19:48:41 +08:00
function api ( ... $args )
{
2021-05-14 20:41:43 +08:00
if ( func_num_args () < 3 ) {
2021-04-02 19:48:41 +08:00
//参数少于3个时, 默认为错误状态。
$ret = - 1 ;
$msg = isset ( $args [ 0 ]) ? $args [ 0 ] : 'ERROR' ;
$data = isset ( $args [ 1 ]) ? $args [ 1 ] : [];
} else {
$ret = $args [ 0 ];
$msg = $args [ 1 ];
$data = $args [ 2 ];
}
2025-04-17 01:39:40 +07:00
if ( $data instanceof \Illuminate\Http\Resources\Json\JsonResource ) {
2022-03-20 22:14:00 +08:00
$data = $data -> response () -> getData ( true );
2021-04-02 19:48:41 +08:00
}
2025-04-17 01:39:40 +07:00
// dd($data);
2022-08-16 18:31:04 +08:00
$time = ( float ) number_format ( microtime ( true ) - nexus () -> getStartTimestamp (), 3 );
$count = null ;
$resultKey = 'ret' ;
$msgKey = 'msg' ;
$format = $_REQUEST [ '__format' ] ? ? '' ;
2022-09-08 19:14:01 +08:00
if ( in_array ( $format , [ 'layui-table' , 'data-table' ])) {
2022-08-16 18:31:04 +08:00
$resultKey = 'code' ;
$count = $data [ 'meta' ][ 'total' ] ? ? 0 ;
if ( isset ( $data [ 'data' ])) {
$data = $data [ 'data' ];
}
}
$results = [
$resultKey => ( int ) $ret ,
$msgKey => ( string ) $msg ,
2021-04-02 19:48:41 +08:00
'data' => $data ,
2022-08-16 18:31:04 +08:00
'time' => $time ,
2022-03-20 22:14:00 +08:00
'rid' => nexus () -> getRequestId (),
2021-04-02 19:48:41 +08:00
];
2022-08-16 18:31:04 +08:00
if ( $format == 'layui-table' ) {
$results [ 'count' ] = $count ;
}
2022-09-08 19:14:01 +08:00
if ( $format == 'data-table' ) {
$results [ 'draw' ] = intval ( $_REQUEST [ 'draw' ] ? ? 1 );
$results [ 'recordsTotal' ] = $count ;
$results [ 'recordsFiltered' ] = $count ;
}
2022-08-16 18:31:04 +08:00
return $results ;
2021-04-02 19:48:41 +08:00
}
function success ( ... $args )
{
$ret = 0 ;
$msg = 'OK' ;
$data = [];
$argumentCount = func_num_args ();
if ( $argumentCount == 1 ) {
$data = $args [ 0 ];
} elseif ( $argumentCount == 2 ) {
$msg = $args [ 0 ];
$data = $args [ 1 ];
}
return api ( $ret , $msg , $data );
}
function fail ( ... $args )
{
$ret = - 1 ;
$msg = 'ERROR' ;
$data = [];
$argumentCount = func_num_args ();
if ( $argumentCount == 1 ) {
$data = $args [ 0 ];
} elseif ( $argumentCount == 2 ) {
$msg = $args [ 0 ];
$data = $args [ 1 ];
}
return api ( $ret , $msg , $data );
}
2021-04-26 20:37:17 +08:00
function last_query ( $all = false )
{
2021-06-10 21:07:20 +08:00
static $connection , $pdo ;
if ( is_null ( $connection )) {
if ( IN_NEXUS ) {
$connection = \Illuminate\Database\Capsule\Manager :: connection ( \Nexus\Database\NexusDB :: ELOQUENT_CONNECTION_NAME );
} else {
$connection = \Illuminate\Support\Facades\DB :: connection ( config ( 'database.default' ));
}
$pdo = $connection -> getPdo ();
}
$queries = $connection -> getQueryLog ();
if ( ! $all ) {
$queries = [ last ( $queries )];
}
$queryFormatted = [];
foreach ( $queries as $query ) {
$sqlWithPlaceholders = str_replace ([ '%' , '?' ], [ '%%' , '%s' ], $query [ 'query' ]);
$bindings = $query [ 'bindings' ];
$realSql = $sqlWithPlaceholders ;
if ( count ( $bindings ) > 0 ) {
$realSql = vsprintf ( $sqlWithPlaceholders , array_map ([ $pdo , 'quote' ], $bindings ));
}
$queryFormatted [] = $realSql ;
2021-04-26 20:37:17 +08:00
}
if ( $all ) {
2021-06-10 21:07:20 +08:00
return nexus_json_encode ( $queryFormatted );
2021-04-26 20:37:17 +08:00
}
2021-06-10 21:07:20 +08:00
return $queryFormatted [ 0 ];
2021-04-26 20:37:17 +08:00
}
2021-05-18 02:37:39 +08:00
function format_datetime ( $datetime , $format = 'Y-m-d H:i' )
2021-04-26 20:37:17 +08:00
{
2022-06-17 00:29:26 +08:00
if ( empty ( $datetime )) {
2025-04-17 01:39:40 +07:00
return null ;
2022-06-17 00:29:26 +08:00
}
2022-06-08 20:47:34 +08:00
try {
$carbonTime = \Carbon\Carbon :: parse ( $datetime );
2022-06-08 23:10:32 +08:00
return $carbonTime -> format ( $format );
2022-06-08 20:47:34 +08:00
} catch ( \Exception ) {
do_log ( " Invalid datetime: $datetime " , 'error' );
return $datetime ;
2021-04-26 20:37:17 +08:00
}
}
2021-04-27 02:44:44 +08:00
2021-04-29 02:52:22 +08:00
function nexus_trans ( $key , $replace = [], $locale = null )
2021-04-27 02:44:44 +08:00
{
2022-08-10 17:38:05 +08:00
return \Nexus\Nexus :: trans ( $key , $replace , $locale );
2021-04-27 02:44:44 +08:00
}
2021-06-01 23:33:28 +08:00
function isRunningInConsole () : bool
{
2022-04-01 23:13:42 +08:00
return ! RUNNING_IN_OCTANE && php_sapi_name () == 'cli' ;
2021-06-01 23:33:28 +08:00
}
2021-06-09 02:23:09 +08:00
2022-05-14 15:19:10 +08:00
function isRunningOnWindows () : bool
{
return ! RUNNING_IN_OCTANE && strtoupper ( substr ( PHP_OS , 0 , 3 )) === 'WIN' ;
}
function command_exists ( $command ) : bool
{
return ! ( trim ( exec ( " command -v $command " )) == '' );
}
2022-04-01 23:13:42 +08:00
function get_tracker_schema_and_host ( $combine = false ) : array | string
2021-06-09 02:23:09 +08:00
{
global $https_announce_urls , $announce_urls ;
$httpsAnnounceUrls = array_filter ( $https_announce_urls );
$log = " cookie: " . json_encode ( $_COOKIE ) . " , https_announce_urls: " . json_encode ( $httpsAnnounceUrls );
2022-04-07 19:08:02 +08:00
if (
( isset ( $_COOKIE [ " c_secure_tracker_ssl " ]) && $_COOKIE [ " c_secure_tracker_ssl " ] == base64 ( " yeah " ))
|| ! empty ( $httpsAnnounceUrls )
|| isHttps ()
) {
$log .= " , c_secure_tracker_ssl = base64('yeah'): " . base64 ( " yeah " ) . " , or not empty https_announce_urls, or isHttps() " ;
2021-06-09 02:23:09 +08:00
$tracker_ssl = true ;
} else {
$tracker_ssl = false ;
}
$log .= " , tracker_ssl: $tracker_ssl " ;
if ( $tracker_ssl == true ){
$ssl_torrent = " https:// " ;
if ( $https_announce_urls [ 0 ] != " " ) {
$log .= " , https_announce_urls not empty, use it " ;
$base_announce_url = $https_announce_urls [ 0 ];
} else {
$log .= " , https_announce_urls empty, use announce_urls[0] " ;
$base_announce_url = $announce_urls [ 0 ];
}
2022-04-01 23:13:42 +08:00
} else {
2021-06-09 02:23:09 +08:00
$ssl_torrent = " http:// " ;
$base_announce_url = $announce_urls [ 0 ];
}
do_log ( $log );
2022-04-01 23:13:42 +08:00
if ( $combine ) {
return $ssl_torrent . $base_announce_url ;
}
2021-06-10 00:50:17 +08:00
return compact ( 'ssl_torrent' , 'base_announce_url' );
2021-06-09 02:23:09 +08:00
}
2021-06-21 02:01:26 +08:00
2022-04-01 23:13:42 +08:00
2021-06-21 02:01:26 +08:00
function get_hr_ratio ( $uped , $downed )
{
if ( $downed > 0 ) {
$ratio = $uped / $downed ;
$color = get_ratio_color ( $ratio );
if ( $ratio > 10000 ) $ratio = 'Inf.' ;
else
$ratio = number_format ( $ratio , 3 );
if ( $color )
$ratio = " <font color= \" " . $color . " \" > " . $ratio . " </font> " ;
} elseif ( $uped > 0 )
$ratio = 'Inf.' ;
else
$ratio = " --- " ;
return $ratio ;
}
2022-03-20 22:14:00 +08:00
2022-04-25 14:52:59 +08:00
function get_row_count ( $table , $suffix = " " )
{
$r = sql_query ( " SELECT COUNT(*) FROM $table $suffix " ) or sqlerr ( __FILE__ , __LINE__ );
$a = mysql_fetch_row ( $r );
return $a [ 0 ];
}
2022-08-22 21:39:20 +08:00
function get_user_row ( $id )
{
global $Cache , $CURUSER ;
2022-12-19 19:17:22 +08:00
static $userRows = [];
2022-08-22 21:39:20 +08:00
static $curuserRowUpdated = false ;
2022-08-23 01:02:54 +08:00
static $neededColumns = array (
'id' , 'noad' , 'class' , 'enabled' , 'privacy' , 'avatar' , 'signature' , 'uploaded' , 'downloaded' , 'last_access' , 'username' , 'donor' ,
'donoruntil' , 'leechwarn' , 'warned' , 'title' , 'downloadpos' , 'parked' , 'clientselect' , 'showclienterror' ,
);
2022-12-19 19:17:22 +08:00
if ( isset ( $userRows [ $id ])) return $userRows [ $id ];
2022-08-22 21:39:20 +08:00
$cacheKey = 'user_' . $id . '_content' ;
2022-08-24 00:19:19 +08:00
$row = \Nexus\Database\NexusDB :: remember ( $cacheKey , 3600 , function () use ( $id , $neededColumns ) {
2022-08-22 21:39:20 +08:00
$user = \App\Models\User :: query () -> with ([ 'wearing_medals' ]) -> find ( $id , $neededColumns );
2022-08-23 01:02:54 +08:00
if ( ! $user ) {
return null ;
}
$arr = $user -> toArray ();
2022-08-24 00:19:19 +08:00
//Rainbow ID
2022-08-23 01:02:54 +08:00
$userRep = new \App\Repositories\UserRepository ();
$metas = $userRep -> listMetas ( $id , \App\Models\UserMeta :: META_KEY_PERSONALIZED_USERNAME );
if ( $metas -> isNotEmpty ()) {
$arr [ '__is_rainbow' ] = 1 ;
} else {
$arr [ '__is_rainbow' ] = 0 ;
2022-08-22 21:39:20 +08:00
}
2022-09-25 16:33:52 +08:00
$arr [ '__is_donor' ] = is_donor ( $arr );
2022-08-24 00:19:19 +08:00
return apply_filter ( " user_row " , $arr );
2022-08-22 21:39:20 +08:00
});
// if ($CURUSER && $id == $CURUSER['id']) {
// $row = array();
// foreach($neededColumns as $column) {
// $row[$column] = $CURUSER[$column];
// }
// if (!$curuserRowUpdated) {
// $Cache->cache_value('user_'.$CURUSER['id'].'_content', $row, 900);
// $curuserRowUpdated = true;
// }
// } elseif (!$row = $Cache->get_value('user_'.$id.'_content')){
// $res = sql_query("SELECT ".implode(',', $neededColumns)." FROM users WHERE id = ".sqlesc($id)) or sqlerr(__FILE__,__LINE__);
// $row = mysql_fetch_array($res);
// $Cache->cache_value('user_'.$id.'_content', $row, 900);
// }
if ( ! $row )
return false ;
2022-12-19 19:17:22 +08:00
else return $userRows [ $id ] = $row ;
2022-08-22 21:39:20 +08:00
}
function get_user_class ()
{
if ( IN_NEXUS ) {
global $CURUSER ;
return $CURUSER [ " class " ] ? ? '' ;
}
return auth () -> user () -> class ;
}
function get_user_id ()
{
if ( IN_NEXUS ) {
global $CURUSER ;
return $CURUSER [ " id " ] ? ? 0 ;
}
return auth () -> user () -> id ? ? 0 ;
}
2024-10-10 03:05:34 +08:00
function get_user_passkey ()
{
if ( IN_NEXUS ) {
global $CURUSER ;
return $CURUSER [ " passkey " ] ? ? " " ;
}
return auth () -> user () -> passkey ? ? " " ;
}
2023-11-14 02:13:21 +08:00
function get_pure_username ()
{
if ( IN_NEXUS ) {
global $CURUSER ;
return $CURUSER [ " username " ] ? ? " " ;
}
return auth () -> user () -> username ? ? " " ;
}
2022-03-20 22:14:00 +08:00
function nexus ()
{
return \Nexus\Nexus :: instance ();
}
2022-03-30 15:37:11 +08:00
function site_info ()
{
$setting = \App\Models\Setting :: get ( 'basic' );
$siteInfo = [
'site_name' => $setting [ 'SITENAME' ],
'base_url' => getSchemeAndHttpHost (),
];
return $siteInfo ;
}
2022-04-18 19:07:35 +08:00
function isIPV4 ( $ip )
{
return filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV4 );
}
function isIPV6 ( $ip )
{
return filter_var ( $ip , FILTER_VALIDATE_IP , FILTER_FLAG_IPV6 );
}
2022-06-03 03:42:53 +08:00
function add_filter ( $name , $function , $priority = 10 , $argc = 1 )
{
global $hook ;
$hook -> addFilter ( $name , $function , $priority , $argc );
}
2022-06-08 14:15:59 +08:00
function apply_filter ( $name , ... $args )
2022-06-03 03:42:53 +08:00
{
global $hook ;
2022-08-20 19:11:28 +08:00
// do_log("[APPLY_FILTER]: $name");
2022-06-08 14:15:59 +08:00
return $hook -> applyFilter ( ... func_get_args ());
2022-06-03 03:42:53 +08:00
}
function add_action ( $name , $function , $priority = 10 , $argc = 1 )
{
global $hook ;
$hook -> addAction ( $name , $function , $priority , $argc );
}
function do_action ( $name , ... $args )
{
global $hook ;
2022-08-20 19:11:28 +08:00
// do_log("[DO_ACTION]: $name");
2022-06-08 14:15:59 +08:00
return $hook -> doAction ( ... func_get_args ());
2022-06-03 03:42:53 +08:00
}
2024-11-22 01:37:57 +08:00
function isIPSeedBoxFromASN ( $ip , $exceptionWhenYes = false ) : bool
2024-11-19 01:16:54 +08:00
{
2025-01-21 13:24:10 +08:00
$redis = \Nexus\Database\NexusDB :: redis ();
$key = " nexus_asn " ;
$notFoundCacheValue = " __NOT_FOUND__ " ;
2024-11-19 01:16:54 +08:00
try {
static $reader ;
$database = nexus_env ( 'GEOIP2_ASN_DATABASE' );
if ( ! file_exists ( $database ) || ! is_readable ( $database )) {
do_log ( " GEOIP2_ASN_DATABASE: $database not exists or not readable " , " debug " );
return false ;
}
if ( is_null ( $reader )) {
$reader = new \GeoIp2\Database\Reader ( $database );
}
$asnObj = $reader -> asn ( $ip );
$asn = $asnObj -> autonomousSystemNumber ;
if ( $asn <= 0 ) {
return false ;
}
2025-01-21 13:24:10 +08:00
$cacheResult = $redis -> hGet ( $key , $asn );
if ( $cacheResult !== false ) {
if ( $cacheResult === $notFoundCacheValue ) {
return false ;
} else {
return true ;
}
}
2024-11-19 01:16:54 +08:00
$row = \Nexus\Database\NexusDB :: getOne ( " seed_box_records " , " asn = $asn " , " id " );
2025-01-21 13:24:10 +08:00
if ( ! empty ( $row )) {
$redis -> hSet ( $key , $asn , $row [ 'id' ]);
} else {
$redis -> hSet ( $key , $asn , $notFoundCacheValue );
}
2024-11-19 01:16:54 +08:00
} catch ( \Throwable $throwable ) {
2025-01-21 13:24:10 +08:00
do_log ( " ip: $ip , " . $throwable -> getMessage ());
$redis -> hSet ( $key , $asn , $notFoundCacheValue );
2024-11-19 01:16:54 +08:00
}
2024-11-22 01:37:57 +08:00
$result = ! empty ( $row );
if ( $result && $exceptionWhenYes ) {
throw new \App\Exceptions\SeedBoxYesException ( $row [ 'id' ]);
}
return $result ;
2024-11-19 01:16:54 +08:00
}
2024-11-22 01:37:57 +08:00
function isIPSeedBox ( $ip , $uid , $withoutCache = false , $exceptionWhenYes = false ) : bool
2022-07-23 15:05:32 +08:00
{
2022-07-29 03:34:55 +08:00
$key = " nexus_is_ip_seed_box:ip: $ip :uid: $uid " ;
$cacheData = \Nexus\Database\NexusDB :: cache_get ( $key );
2022-07-30 15:06:51 +08:00
if ( in_array ( $cacheData , [ 0 , 1 , '0' , '1' ], true ) && ! $withoutCache ) {
do_log ( " $key , get result from cache: $cacheData ( " . gettype ( $cacheData ) . " ) " );
2022-07-29 03:34:55 +08:00
return ( bool ) $cacheData ;
2022-07-23 15:05:32 +08:00
}
2024-11-19 01:16:54 +08:00
//check from asn
2024-11-22 01:37:57 +08:00
$res = isIPSeedBoxFromASN ( $ip , $exceptionWhenYes );
2024-11-19 01:16:54 +08:00
if ( ! empty ( $res )) {
\Nexus\Database\NexusDB :: cache_put ( $key , 1 , 300 );
do_log ( " $key , get result from asn, true " );
return true ;
}
2022-07-23 15:05:32 +08:00
$ipObject = \PhpIP\IP :: create ( $ip );
$ipNumeric = $ipObject -> numeric ();
$ipVersion = $ipObject -> getVersion ();
2023-01-31 18:23:20 +08:00
//check allow list first, not consider specific user
$checkSeedBoxAllowedSql = sprintf (
2024-11-19 01:16:54 +08:00
'select id from seed_box_records where `ip_begin_numeric` <= "%s" and `ip_end_numeric` >= "%s" and `version` = %s and `status` = %s and `is_allowed` = 1 and asn = 0 limit 1' ,
2023-01-31 18:23:20 +08:00
$ipNumeric , $ipNumeric , $ipVersion , \App\Models\SeedBoxRecord :: STATUS_ALLOWED
);
$res = \Nexus\Database\NexusDB :: select ( $checkSeedBoxAllowedSql );
if ( ! empty ( $res )) {
2024-11-19 01:16:54 +08:00
\Nexus\Database\NexusDB :: cache_put ( $key , 0 , 300 );
2023-01-31 18:23:20 +08:00
do_log ( " $key , get result from database, is_allowed = 1, false " );
return false ;
}
2022-07-23 15:05:32 +08:00
$checkSeedBoxAdminSql = sprintf (
2024-11-19 01:16:54 +08:00
'select id from seed_box_records where `ip_begin_numeric` <= "%s" and `ip_end_numeric` >= "%s" and `type` = %s and `version` = %s and `status` = %s and `is_allowed` = 0 and asn = 0 limit 1' ,
2022-07-23 15:05:32 +08:00
$ipNumeric , $ipNumeric , \App\Models\SeedBoxRecord :: TYPE_ADMIN , $ipVersion , \App\Models\SeedBoxRecord :: STATUS_ALLOWED
);
$res = \Nexus\Database\NexusDB :: select ( $checkSeedBoxAdminSql );
if ( ! empty ( $res )) {
2022-07-30 15:06:51 +08:00
\Nexus\Database\NexusDB :: cache_put ( $key , 1 , 300 );
2022-07-29 03:34:55 +08:00
do_log ( " $key , get result from admin, true " );
2024-11-22 01:37:57 +08:00
if ( $exceptionWhenYes ) {
throw new \App\Exceptions\SeedBoxYesException ( $res [ 0 ][ 'id' ]);
}
2022-07-23 15:05:32 +08:00
return true ;
}
if ( $uid !== null ) {
$checkSeedBoxUserSql = sprintf (
2024-11-19 01:16:54 +08:00
'select id from seed_box_records where `ip_begin_numeric` <= "%s" and `ip_end_numeric` >= "%s" and `uid` = %s and `type` = %s and `version` = %s and `status` = %s and `is_allowed` = 0 and asn = 0 limit 1' ,
2022-07-23 15:05:32 +08:00
$ipNumeric , $ipNumeric , $uid , \App\Models\SeedBoxRecord :: TYPE_USER , $ipVersion , \App\Models\SeedBoxRecord :: STATUS_ALLOWED
);
$res = \Nexus\Database\NexusDB :: select ( $checkSeedBoxUserSql );
if ( ! empty ( $res )) {
2022-07-30 15:06:51 +08:00
\Nexus\Database\NexusDB :: cache_put ( $key , 1 , 300 );
2022-07-29 03:34:55 +08:00
do_log ( " $key , get result from user, true " );
2024-11-22 01:37:57 +08:00
if ( $exceptionWhenYes ) {
throw new \App\Exceptions\SeedBoxYesException ( $res [ 0 ][ 'id' ]);
}
2022-07-23 15:05:32 +08:00
return true ;
}
}
2022-07-30 15:06:51 +08:00
\Nexus\Database\NexusDB :: cache_put ( $key , 0 , 300 );
2022-07-29 03:34:55 +08:00
do_log ( " $key , no result, false " );
2022-07-23 15:05:32 +08:00
return false ;
}
2022-07-23 23:35:43 +08:00
function getDataTraffic ( array $torrent , array $queries , array $user , $peer , $snatch , $promotionInfo )
{
if ( ! isset ( $user [ '__is_donor' ])) {
throw new \InvalidArgumentException ( " user no '__is_donor' field " );
}
$log = sprintf (
2022-10-12 19:37:02 +08:00
" torrent: %s, owner: %s, user: %s, peerUploaded: %s, peerDownloaded: %s, queriesUploaded: %s, queriesDownloaded: %s " ,
$torrent [ 'id' ], $torrent [ 'owner' ], $user [ 'id' ], $peer [ 'uploaded' ] ? ? '' , $peer [ 'downloaded' ] ? ? '' , $queries [ 'uploaded' ], $queries [ 'downloaded' ]
2022-07-23 23:35:43 +08:00
);
if ( ! empty ( $peer )) {
$realUploaded = max ( bcsub ( $queries [ 'uploaded' ], $peer [ 'uploaded' ]), 0 );
$realDownloaded = max ( bcsub ( $queries [ 'downloaded' ], $peer [ 'downloaded' ]), 0 );
$log .= " , [PEER_EXISTS], realUploaded: $realUploaded , realDownloaded: $realDownloaded , [SP_STATE] " ;
$spStateGlobal = get_global_sp_state ();
$spStateNormal = \App\Models\Torrent :: PROMOTION_NORMAL ;
if ( ! empty ( $promotionInfo ) && isset ( $promotionInfo [ '__ignore_global_sp_state' ])) {
$log .= ', use promotionInfo' ;
$spStateReal = $promotionInfo [ 'sp_state' ];
} elseif ( $spStateGlobal != $spStateNormal ) {
$log .= " , use global " ;
$spStateReal = $spStateGlobal ;
} else {
$log .= " , use torrent individual " ;
$spStateReal = $torrent [ 'sp_state' ];
}
if ( ! isset ( \App\Models\Torrent :: $promotionTypes [ $spStateReal ])) {
$log .= " , spStateReal = $spStateReal , invalid, reset to: $spStateNormal " ;
$spStateReal = $spStateNormal ;
}
$uploaderRatio = get_setting ( 'torrent.uploaderdouble' );
$log .= " , uploaderRatio: $uploaderRatio " ;
2024-10-29 23:41:06 +08:00
if ( $torrent [ 'owner' ] == $user [ 'id' ] && $uploaderRatio != 1 ) {
2022-07-23 23:35:43 +08:00
//uploader, use the bigger one
$upRatio = max ( $uploaderRatio , \App\Models\Torrent :: $promotionTypes [ $spStateReal ][ 'up_multiplier' ]);
2024-10-29 23:41:06 +08:00
$log .= " , [IS_UPLOADER] && uploaderRatio != 1, upRatio: $upRatio " ;
2022-07-23 23:35:43 +08:00
} else {
$upRatio = \App\Models\Torrent :: $promotionTypes [ $spStateReal ][ 'up_multiplier' ];
2024-10-29 23:41:06 +08:00
$log .= " , [IS_NOT_UPLOADER] || uploaderRatio == 1, upRatio: $upRatio " ;
2022-07-23 23:35:43 +08:00
}
/**
* VIP do not calculate downloaded
* @ since 1.7 . 13
*/
if ( $user [ 'class' ] == \App\Models\User :: CLASS_VIP ) {
$downRatio = 0 ;
$log .= " , [IS_VIP], downRatio: $downRatio " ;
} else {
$downRatio = \App\Models\Torrent :: $promotionTypes [ $spStateReal ][ 'down_multiplier' ];
$log .= " , [IS_NOT_VIP], downRatio: $downRatio " ;
}
} else {
$realUploaded = $queries [ 'uploaded' ];
$realDownloaded = $queries [ 'downloaded' ];
/**
* If peer not exits , user increment = 0 ;
*/
$upRatio = 0 ;
$downRatio = 0 ;
$log .= " , [PEER_NOT_EXISTS], realUploaded: $realUploaded , realDownloaded: $realDownloaded , upRatio: $upRatio , downRatio: $downRatio " ;
}
$uploadedIncrementForUser = $realUploaded * $upRatio ;
$downloadedIncrementForUser = $realDownloaded * $downRatio ;
$log .= " , uploadedIncrementForUser: $uploadedIncrementForUser , downloadedIncrementForUser: $downloadedIncrementForUser " ;
/**
* check seed box rule
*/
$isSeedBoxRuleEnabled = get_setting ( 'seed_box.enabled' ) == 'yes' ;
$log .= " , isSeedBoxRuleEnabled: $isSeedBoxRuleEnabled , user class: { $user [ 'class' ] } , __is_donor: { $user [ '__is_donor' ] } " ;
2022-10-12 19:37:02 +08:00
if ( $isSeedBoxRuleEnabled && $torrent [ 'owner' ] != $user [ 'id' ] && ! ( $user [ 'class' ] >= \App\Models\User :: CLASS_VIP || $user [ '__is_donor' ])) {
2022-07-23 23:35:43 +08:00
$isIPSeedBox = isIPSeedBox ( $queries [ 'ip' ], $user [ 'id' ]);
$log .= " , isIPSeedBox: $isIPSeedBox " ;
if ( $isIPSeedBox ) {
$isSeedBoxNoPromotion = get_setting ( 'seed_box.no_promotion' ) == 'yes' ;
$log .= " , isSeedBoxNoPromotion: $isSeedBoxNoPromotion " ;
if ( $isSeedBoxNoPromotion ) {
$uploadedIncrementForUser = $realUploaded ;
$downloadedIncrementForUser = $realDownloaded ;
$log .= " , isIPSeedBox && isSeedBoxNoPromotion, increment for user = real " ;
}
$maxUploadedTimes = get_setting ( 'seed_box.max_uploaded' );
2022-10-02 21:14:11 +08:00
$maxUploadedDurationSeconds = get_setting ( 'seed_box.max_uploaded_duration' , 0 ) * 3600 ;
$torrentTTL = time () - strtotime ( $torrent [ 'added' ]);
$timeRangeValid = ( $maxUploadedDurationSeconds == 0 ) || ( $torrentTTL < $maxUploadedDurationSeconds );
$log .= " , maxUploadedTimes: $maxUploadedTimes , maxUploadedDurationSeconds: $maxUploadedDurationSeconds , timeRangeValid: $timeRangeValid " ;
if ( $maxUploadedTimes > 0 && $timeRangeValid ) {
$log .= " , [LIMIT_UPLOADED] " ;
if ( ! empty ( $snatch ) && isset ( $torrent [ 'size' ]) && $snatch [ 'uploaded' ] >= $torrent [ 'size' ] * $maxUploadedTimes ) {
$log .= " , snatchUploaded( { $snatch [ 'uploaded' ] } ) >= torrentSize( { $torrent [ 'size' ] } ) * times( $maxUploadedTimes ), uploadedIncrementForUser = 0 " ;
$uploadedIncrementForUser = 0 ;
} else {
$log .= " , snatchUploaded( { $snatch [ 'uploaded' ] } ) < torrentSize( { $torrent [ 'size' ] } ) * times( $maxUploadedTimes ), uploadedIncrementForUser do not change to 0 " ;
}
} else {
$log .= " , [NOT_LIMIT_UPLOADED] " ;
2022-07-23 23:35:43 +08:00
}
}
}
$result = [
'uploaded_increment' => $realUploaded ,
'uploaded_increment_for_user' => $uploadedIncrementForUser ,
'downloaded_increment' => $realDownloaded ,
'downloaded_increment_for_user' => $downloadedIncrementForUser ,
];
do_log ( " $log , result: " . json_encode ( $result ), 'info' );
return $result ;
}
2022-08-10 17:38:05 +08:00
function clear_user_cache ( $uid , $passkey = '' )
{
2022-11-09 21:56:03 +08:00
do_log ( " clear_user_cache, uid: $uid , passkey: $passkey " );
2022-08-10 17:38:05 +08:00
\Nexus\Database\NexusDB :: cache_del ( " user_ { $uid } _content " );
2022-08-22 21:07:06 +08:00
\Nexus\Database\NexusDB :: cache_del ( " user_ { $uid } _roles " );
2022-08-24 00:19:19 +08:00
\Nexus\Database\NexusDB :: cache_del ( " announce_user_passkey_ $uid " ); //announce.php
2022-08-24 13:36:14 +08:00
\Nexus\Database\NexusDB :: cache_del ( \App\Models\Setting :: DIRECT_PERMISSION_CACHE_KEY_PREFIX . $uid );
2023-05-30 03:02:49 +08:00
\Nexus\Database\NexusDB :: cache_del ( " user_role_ids: $uid " );
\Nexus\Database\NexusDB :: cache_del ( " direct_permissions: $uid " );
2022-08-10 17:38:05 +08:00
if ( $passkey ) {
2022-08-24 00:19:19 +08:00
\Nexus\Database\NexusDB :: cache_del ( 'user_passkey_' . $passkey . '_content' ); //announce.php
2022-08-10 17:38:05 +08:00
}
2024-12-24 22:22:02 +08:00
$userInfo = \App\Models\User :: query () -> find ( $uid , \App\Models\User :: $commonFields );
if ( $userInfo ) {
fire_event ( " user_updated " , $userInfo );
}
2022-08-10 17:38:05 +08:00
}
2022-08-19 15:30:16 +08:00
2022-10-01 01:58:18 +08:00
function clear_setting_cache ()
2022-08-19 15:30:16 +08:00
{
2022-11-09 21:56:03 +08:00
do_log ( " clear_setting_cache " );
2022-08-19 15:30:16 +08:00
\Nexus\Database\NexusDB :: cache_del ( 'nexus_settings_in_laravel' );
\Nexus\Database\NexusDB :: cache_del ( 'nexus_settings_in_nexus' );
2024-05-01 00:16:45 +08:00
\Nexus\Database\NexusDB :: cache_del ( 'setting_protected_forum' );
2024-03-20 14:24:44 +08:00
$channel = nexus_env ( " CHANNEL_NAME_SETTING " );
if ( ! empty ( $channel )) {
\Nexus\Database\NexusDB :: redis () -> publish ( $channel , " update " );
}
2022-11-05 18:43:49 +08:00
}
2022-08-24 00:19:19 +08:00
2022-11-05 18:43:49 +08:00
/**
2023-01-04 19:35:06 +08:00
* @ see functions . php :: get_category_row (), genrelist ()
2022-11-05 18:43:49 +08:00
*/
function clear_category_cache ()
{
2022-11-09 21:56:03 +08:00
do_log ( " clear_category_cache " );
2022-11-05 18:43:49 +08:00
\Nexus\Database\NexusDB :: cache_del ( 'category_content' );
2023-01-04 19:35:06 +08:00
$searchBoxList = \App\Models\SearchBox :: query () -> get ([ 'id' ]);
foreach ( $searchBoxList as $item ) {
\Nexus\Database\NexusDB :: cache_del ( " category_list_mode_ { $item -> id } " );
}
2022-08-19 15:30:16 +08:00
}
2022-11-09 21:56:03 +08:00
/**
* @ see functions . php :: searchbox_item_list ()
*/
function clear_taxonomy_cache ( $table )
{
do_log ( " clear_taxonomy_cache: $table " );
$list = \App\Models\SearchBox :: query () -> get ([ 'id' ]);
foreach ( $list as $item ) {
\Nexus\Database\NexusDB :: cache_del ( " { $table } _list_mode_ { $item -> id } " );
}
\Nexus\Database\NexusDB :: cache_del ( " { $table } _list_mode_0 " );
}
2022-08-22 21:07:06 +08:00
function clear_staff_message_cache ()
{
do_log ( " clear_staff_message_cache " );
\App\Repositories\MessageRepository :: updateStaffMessageCountCache ( false );
}
2022-11-09 21:56:03 +08:00
/**
* @ see functions . php :: get_searchbox_value ()
*/
2022-11-06 16:12:15 +08:00
function clear_search_box_cache ()
2022-09-14 19:05:29 +08:00
{
2022-11-06 16:12:15 +08:00
do_log ( " clear_search_box_cache " );
\Nexus\Database\NexusDB :: cache_del ( " search_box_content " );
2022-09-14 19:05:29 +08:00
}
2023-02-06 14:25:05 +08:00
/**
* @ see functions . php :: get_category_icon_row ()
*/
function clear_icon_cache ()
{
do_log ( " clear_icon_cache " );
\Nexus\Database\NexusDB :: cache_del ( " category_icon_content " );
}
2023-02-08 13:33:25 +08:00
function clear_inbox_count_cache ( $uid )
{
do_log ( " clear_inbox_count_cache " );
foreach ( \Illuminate\Support\Arr :: wrap ( $uid ) as $id ) {
\Nexus\Database\NexusDB :: cache_del ( 'user_' . $id . '_inbox_count' );
\Nexus\Database\NexusDB :: cache_del ( 'user_' . $id . '_unread_message_count' );
}
}
2023-03-06 14:53:18 +08:00
function clear_agent_allow_deny_cache ()
{
do_log ( " clear_agent_allow_deny_cache " );
2023-04-29 03:46:14 +08:00
$allowCacheKey = nexus_env ( " CACHE_KEY_AGENT_ALLOW " , " all_agent_allows " );
$denyCacheKey = nexus_env ( " CACHE_KEY_AGENT_DENY " , " all_agent_denies " );
foreach ([ " " , " :php " , " :go " ] as $suffix ) {
\Nexus\Database\NexusDB :: cache_del ( $allowCacheKey . $suffix );
\Nexus\Database\NexusDB :: cache_del ( $denyCacheKey . $suffix );
}
2023-03-06 14:53:18 +08:00
}
2023-02-08 13:33:25 +08:00
2022-08-24 14:31:34 +08:00
function user_can ( $permission , $fail = false , $uid = 0 ) : bool
2022-08-19 15:30:16 +08:00
{
2022-08-22 21:07:06 +08:00
$log = " permission: $permission , fail: $fail , user: $uid " ;
static $userCanCached = [];
2022-08-24 00:57:26 +08:00
static $sequence = 0 ;
2022-08-19 15:30:16 +08:00
if ( $uid == 0 ) {
$uid = get_user_id ();
2022-08-22 21:07:06 +08:00
$log .= " , set current uid: $uid " ;
2022-08-19 15:30:16 +08:00
}
2023-05-08 03:18:07 +08:00
if ( $uid <= 0 ) {
if ( $fail ) {
goto FAIL ;
}
2022-08-24 01:09:05 +08:00
do_log ( " $log , unauthenticated, false " );
return false ;
2022-08-19 15:30:16 +08:00
}
2022-08-22 21:07:06 +08:00
if ( ! $fail && isset ( $userCanCached [ $permission ][ $uid ])) {
return $userCanCached [ $permission ][ $uid ];
}
2022-08-24 14:31:34 +08:00
$userInfo = get_user_row ( $uid );
$class = $userInfo [ 'class' ];
2022-08-24 00:19:19 +08:00
$log .= " , userClass: $class " ;
if ( $class == \App\Models\User :: CLASS_STAFF_LEADER ) {
2022-08-20 19:11:28 +08:00
do_log ( " $log , CLASS_STAFF_LEADER, true " );
2022-08-22 21:07:06 +08:00
$userCanCached [ $permission ][ $uid ] = true ;
2022-08-20 19:11:28 +08:00
return true ;
}
2022-08-24 13:36:14 +08:00
$userAllPermissions = \App\Repositories\ToolRepository :: listUserAllPermissions ( $uid );
2022-08-24 00:19:19 +08:00
$result = isset ( $userAllPermissions [ $permission ]);
2022-08-24 00:57:26 +08:00
if ( $sequence == 0 ) {
$sequence ++ ;
$log .= " , userAllPermissions: " . json_encode ( $userAllPermissions );
}
$log .= " , result: $result " ;
2022-08-20 19:11:28 +08:00
if ( ! $fail || $result ) {
2022-08-20 21:07:29 +08:00
do_log ( $log );
2022-08-22 21:07:06 +08:00
$userCanCached [ $permission ][ $uid ] = $result ;
2022-08-19 15:30:16 +08:00
return $result ;
}
2023-05-08 03:18:07 +08:00
FAIL :
2022-08-20 21:07:29 +08:00
do_log ( " $log , [FAIL] " );
2022-08-20 19:11:28 +08:00
if ( IN_NEXUS && ! IN_TRACKER ) {
global $lang_functions ;
2022-08-22 21:07:06 +08:00
$requireClass = get_setting ( " authority. $permission " );
if ( isset ( \App\Models\User :: $classes [ $requireClass ])) {
2022-08-20 19:11:28 +08:00
stderr ( $lang_functions [ 'std_sorry' ], $lang_functions [ 'std_permission_denied_only' ] . get_user_class_name ( $requireClass , false , true , true ) . $lang_functions [ 'std_or_above_can_view' ], false );
} else {
stderr ( $lang_functions [ 'std_error' ], $lang_functions [ 'std_permission_denied' ]);
}
2022-08-19 15:30:16 +08:00
}
2022-08-20 21:07:29 +08:00
throw new \App\Exceptions\InsufficientPermissionException ();
2022-08-19 15:30:16 +08:00
}
2022-09-25 16:33:52 +08:00
2023-05-08 03:18:07 +08:00
2022-09-25 16:33:52 +08:00
function is_donor ( array $userInfo ) : bool
{
return $userInfo [ 'donor' ] == 'yes' && ( $userInfo [ 'donoruntil' ] === null || $userInfo [ 'donoruntil' ] == '0000-00-00 00:00:00' || $userInfo [ 'donoruntil' ] >= date ( 'Y-m-d H:i:s' ));
}
2022-11-06 16:12:15 +08:00
/**
2025-01-19 14:37:00 +08:00
* @ deprecated
2022-11-06 16:12:15 +08:00
* @ param $authkey
* @ return false | int | mixed | string | null
* @ throws \App\Exceptions\NexusException
* @ see download . php
*/
function get_passkey_by_authkey ( $authkey )
{
return \Nexus\Database\NexusDB :: remember ( " authkey2passkey: $authkey " , 3600 * 24 , function () use ( $authkey ) {
$arr = explode ( '|' , $authkey );
if ( count ( $arr ) != 3 ) {
throw new \InvalidArgumentException ( " Invalid authkey: $authkey , format error " );
}
$uid = $arr [ 1 ];
$torrentRep = new \App\Repositories\TorrentRepository ();
2023-03-04 00:52:08 +08:00
$decrypted = $torrentRep -> checkTrackerReportAuthKey ( $authkey );
2022-11-06 16:12:15 +08:00
if ( empty ( $decrypted )) {
throw new \InvalidArgumentException ( " Invalid authkey: $authkey " );
}
$userInfo = \Nexus\Database\NexusDB :: remember ( " announce_user_passkey_ $uid " , 3600 , function () use ( $uid ) {
return \App\Models\User :: query () -> where ( 'id' , $uid ) -> first ([ 'id' , 'passkey' ]);
});
return $userInfo -> passkey ;
});
}
2023-01-07 16:27:27 +08:00
2023-01-31 16:38:21 +08:00
function executeCommand ( $command , $format = 'string' , $artisan = false , $exception = true ) : string | array
2023-01-07 16:27:27 +08:00
{
$append = " 2>&1 " ;
if ( ! str_ends_with ( $command , $append )) {
$command .= $append ;
}
2023-01-31 16:38:21 +08:00
if ( $artisan ) {
2023-02-11 19:22:21 +08:00
$phpPath = nexus_env ( 'PHP_PATH' ) ? : 'php' ;
2023-01-31 16:38:21 +08:00
$webRoot = rtrim ( ROOT_PATH , '/' );
$command = " $phpPath $webRoot /artisan $command " ;
}
2023-01-07 16:27:27 +08:00
do_log ( " command: $command " );
$result = exec ( $command , $output , $result_code );
$outputString = implode ( " \n " , $output );
2024-02-23 02:38:42 +08:00
$log = sprintf ( 'result_code: %s, result: %s, output: %s' , $result_code , $result , $outputString );
if ( $result_code != 0 ) {
do_log ( $log , " error " );
if ( $exception ) {
throw new \RuntimeException ( $outputString );
}
} else {
do_log ( $log );
2023-01-07 16:27:27 +08:00
}
return $format == 'string' ? $outputString : $output ;
}
2023-01-31 16:38:21 +08:00
2023-03-13 17:41:03 +08:00
function has_role_work_seeding ( $uid )
{
2023-04-09 16:33:36 +08:00
$result = apply_filter ( 'user_has_role_work_seeding' , false , $uid );
do_log ( " uid: $uid , result: $result " );
return $result ;
2023-03-13 17:41:03 +08:00
}
2023-07-19 02:32:02 +08:00
function is_danger_url ( $url ) : bool
{
$dangerScriptsPattern = " /(logout|login|ajax|announce|scrape|adduser|modtask|take.*) \ .php/i " ;
$match = preg_match ( $dangerScriptsPattern , $url );
if ( $match > 0 ) {
return true ;
}
return false ;
}
2023-09-20 01:14:08 +08:00
function get_snatch_info ( $torrentId , $userId )
{
return mysql_fetch_assoc ( sql_query ( sprintf ( 'select * from snatched where torrentid = %s and userid = %s order by id desc limit 1' , $torrentId , $userId )));
}
2024-03-16 15:26:12 +08:00
2024-10-10 21:04:35 +08:00
/**
* 完整的 Laravel 事件 , 在 php 端有监听者的需要触发 . 同样会执行 publish_model_event ()
*/
2024-04-26 03:21:35 +08:00
function fire_event ( string $name , \Illuminate\Database\Eloquent\Model $model , \Illuminate\Database\Eloquent\Model $oldModel = null ) : void
2024-03-16 15:26:12 +08:00
{
2025-04-17 01:39:40 +07:00
if ( ! isset ( \App\Enums\ModelEventEnum :: $eventMaps [ $name ])) {
throw new \InvalidArgumentException ( " Event $name is not a valid event enumeration " );
}
if ( IN_NEXUS ) {
$prefix = " fire_event: " ;
$idKey = $prefix . \Illuminate\Support\Str :: random ();
$idKeyOld = " " ;
\Nexus\Database\NexusDB :: cache_put ( $idKey , serialize ( $model ), 3600 * 24 * 30 );
if ( $oldModel ) {
$idKeyOld = $prefix . \Illuminate\Support\Str :: random ();
\Nexus\Database\NexusDB :: cache_put ( $idKeyOld , serialize ( $oldModel ), 3600 * 24 * 30 );
}
executeCommand ( " event:fire --name= $name --idKey= $idKey --idKeyOld= $idKeyOld " , " string " , true , false );
} else {
$eventClass = \App\Enums\ModelEventEnum :: $eventMaps [ $name ][ 'event' ];
$params = [ $model ];
if ( $oldModel ) {
$params [] = $oldModel ;
}
call_user_func_array ([ $eventClass , " dispatch " ], $params );
publish_model_event ( $name , $model -> id );
2024-04-26 03:21:35 +08:00
}
2024-03-16 15:26:12 +08:00
}
2024-10-10 21:04:35 +08:00
/**
* 仅仅是往 redis 发布事件 , php 端无监听者仅在其他平台有需要的触发这个即可 , 较轻量
*/
function publish_model_event ( string $event , int $id ) : void
{
$channel = nexus_env ( " CHANNEL_NAME_MODEL_EVENT " );
if ( ! empty ( $channel )) {
\Nexus\Database\NexusDB :: redis () -> publish ( $channel , json_encode ([ " event " => $event , " id " => $id ]));
} else {
do_log ( " event: $event , id: $id , channel: $channel , channel is empty! " , " error " );
}
}
2024-11-03 15:29:21 +08:00
function convertNamespaceToSnake ( string $str ) : string
{
return str_replace ([ " \\ " , " :: " ], [ " _ " , " . " ], $str );
}
2024-11-22 01:37:57 +08:00
function get_user_locale ( int $uid ) : string
{
$sql = " select language.site_lang_folder from useers inner join language on users.lang = language.id where users.id = $uid limit 1 " ;
$result = \Nexus\Database\NexusDB :: select ( $sql );
2024-11-22 01:42:06 +08:00
if ( empty ( $result ) || empty ( $result [ 0 ][ 'site_lang_folder' ])) {
2024-11-22 01:37:57 +08:00
return " en " ;
}
2024-11-22 01:42:06 +08:00
return \App\Http\Middleware\Locale :: $languageMaps [ $result [ 0 ][ 'site_lang_folder' ]] ? ? 'en' ;
2024-11-22 01:37:57 +08:00
}
2024-12-29 22:16:41 +08:00
function send_admin_success_notification ( string $msg = " " ) : void {
\Filament\Notifications\Notification :: make () -> success () -> title ( $msg ? : " Success! " ) -> send ();
}
function send_admin_fail_notification ( string $msg = " " ) : void {
\Filament\Notifications\Notification :: make () -> danger () -> title ( $msg ? : " Fail! " ) -> send ();
}
2025-03-29 14:32:31 +07:00
function ability ( \App\Enums\Permission\PermissionEnum $permission ) : string {
return sprintf ( " ability:%s " , $permission -> value );
}
2025-04-05 15:38:40 +07:00
function get_challenge_key ( string $challenge ) : string {
return " challenge: " . $challenge ;
}
function get_user_from_cookie ( array $cookie , $isArray = true ) : array | \App\Models\User | null {
$log = " cookie: " . json_encode ( $cookie );
if ( empty ( $_COOKIE [ " c_secure_pass " ])) {
do_log ( " $log , param not enough " );
return null ;
}
list ( $tokenJson , $signature ) = explode ( '.' , base64_decode ( $_COOKIE [ " c_secure_pass " ]));
if ( empty ( $tokenJson ) || empty ( $signature )) {
do_log ( " $log , no tokenJson or signature " );
return null ;
}
$tokenData = json_decode ( $tokenJson , true );
if ( ! isset ( $tokenData [ 'user_id' ])) {
do_log ( " $log , no user_id " );
return null ;
}
if ( ! isset ( $tokenData [ 'expires' ]) || $tokenData [ 'expires' ] < time ()) {
do_log ( " $log , signature expired " );
return null ;
}
$id = $tokenData [ 'user_id' ];
$log .= " , uid = $id " ;
if ( $isArray ) {
$res = sql_query ( " SELECT * FROM users WHERE users.id = " . sqlesc ( $id ) . " AND users.enabled='yes' AND users.status = 'confirmed' LIMIT 1 " );
$row = mysql_fetch_array ( $res );
if ( ! $row ) {
do_log ( " $log , user not exists " );
return null ;
}
$authKey = $row [ " auth_key " ];
unset ( $row [ 'auth_key' ], $row [ 'passhash' ]);
} else {
$row = \App\Models\User :: query () -> find ( $id );
if ( ! $row ) {
do_log ( " $log , user not exists " );
return null ;
}
try {
$row -> checkIsNormal ();
} catch ( \Exception $e ) {
do_log ( " $log , " . $e -> getMessage ());
return null ;
}
$authKey = $row -> auth_key ;
}
$expectedSignature = hash_hmac ( 'sha256' , $tokenJson , $authKey );
if ( ! hash_equals ( $expectedSignature , $signature )) {
do_log ( " $log , !hash_equals, expectedSignature: $expectedSignature , actualSignature: $signature " );
return null ;
}
return $row ;
}
function render_password_hash_js ( string $formId , string $passwordOriginalClass , string $passwordHashedName , bool $passwordRequired , string $passwordConfirmClass = " password_confirmation " , string $usernameName = " username " ) : void {
$tipTooShort = nexus_trans ( 'signup.password_too_short' );
$tipTooLong = nexus_trans ( 'signup.password_too_long' );
$tipEqualUsername = nexus_trans ( 'signup.password_equals_username' );
$tipNotMatch = nexus_trans ( 'signup.passwords_unmatched' );
$passwordValidateJS = " " ;
if ( $passwordRequired ) {
$passwordValidateJS = <<< JS
if ( password . length < 6 ) {
layer . alert ( " $tipTooShort " )
return
}
if ( password . length > 40 ) {
layer . alert ( " $tipTooLong " )
return
}
JS ;
}
$formVar = " jqForm " . md5 ( $formId );
$js = <<< JS
var $formVar = jQuery ( " # { $formId } " );
$formVar . on ( " click " , " input[type=button] " , function () {
let jqUsername = $formVar . find ( " [name= { $usernameName } ] " )
let jqPassword = $formVar . find ( " . { $passwordOriginalClass } " )
let jqPasswordConfirm = $formVar . find ( " . { $passwordConfirmClass } " )
let password = jqPassword . val ()
$passwordValidateJS
if ( jqUsername . length > 0 && jqUsername . val () === password ) {
layer . alert ( " $tipEqualUsername " )
return
}
if ( jqPasswordConfirm . length > 0 && password !== jqPasswordConfirm . val ()) {
layer . alert ( " $tipNotMatch " )
return
}
if ( password !== " " ) {
sha256 ( password ) . then (( passwordHashed ) => {
$formVar . find ( " input[name= { $passwordHashedName } ] " ) . val ( passwordHashed )
$formVar . submit ()
})
} else {
$formVar . submit ()
}
})
JS ;
\Nexus\Nexus :: js ( $js , 'footer' , false );
}
function render_password_challenge_js ( string $formId , string $usernameName , string $passwordOriginalClass ) : void {
$formVar = " jqForm " . md5 ( $formId );
$js = <<< JS
var $formVar = jQuery ( " # { $formId } " );
$formVar . on ( " click " , " input[type=button] " , function () {
let useChallengeResponseAuthentication = $formVar . find ( " input[name=response] " ) . length > 0
if ( ! useChallengeResponseAuthentication ) {
return $formVar . submit ()
}
let jqUsername = $formVar . find ( " [name= { $usernameName } ] " )
let jqPassword = $formVar . find ( " . { $passwordOriginalClass } " )
let username = jqUsername . val ()
let password = jqPassword . val ()
login ( username , password , $formVar )
})
async function login ( username , password , jqForm ) {
try {
jQuery ( 'body' ) . loading ({ stoppable : false });
const challengeResponse = await fetch ( '/api/challenge' , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json'
},
body : JSON . stringify ({ username : username })
});
jQuery ( 'body' ) . loading ( 'stop' );
const challengeData = await challengeResponse . json ();
if ( challengeData . ret !== 0 ) {
layer . alert ( challengeData . msg )
return
}
const clientHashedPassword = await sha256 ( password );
const serverSideHash = await sha256 ( challengeData . data . secret + clientHashedPassword );
const clientResponse = await hmacSha256 ( challengeData . data . challenge , serverSideHash );
jqForm . find ( " input[name=response] " ) . val ( clientResponse )
jqForm . submit ()
} catch ( error ) {
console . error ( error );
layer . alert ( error . toString ())
}
}
JS ;
\Nexus\Nexus :: js ( " vendor/jquery-loading/jquery.loading.min.js " , 'footer' , true );
\Nexus\Nexus :: js ( $js , 'footer' , false );
}