2020-07-06 17:09:56 +00:00
< ? php
include_once '_utils.php' ;
define ( 'FMF_UF_SCROLLBEYOND' , 1 );
2021-05-05 15:52:04 +00:00
//define('FMF_UF_NEWSTYLE', 2);
2020-07-06 17:09:56 +00:00
function get_user_id ( string $username , string $email ) : int {
global $pdo ;
$checkUser = $pdo -> prepare ( 'SELECT `user_id` FROM `fmf_users` WHERE LOWER(`user_login`) = LOWER(:login) OR LOWER(`user_email`) = LOWER(:email)' );
$checkUser -> bindValue ( 'login' , $username );
$checkUser -> bindValue ( 'email' , $email );
$checkUser -> execute ();
return ( int ) $checkUser -> fetchColumn ();
}
function get_user_for_login ( string $nameOrMail ) : array {
global $pdo ;
$getUser = $pdo -> prepare ( 'SELECT `user_id`, `user_login`, `user_password`, `user_email_verification` FROM `fmf_users` WHERE LOWER(`user_login`) = LOWER(:login) OR LOWER(`user_email`) = LOWER(:email)' );
$getUser -> bindValue ( 'login' , $nameOrMail );
$getUser -> bindValue ( 'email' , $nameOrMail );
$user = $getUser -> execute () ? $getUser -> fetch ( PDO :: FETCH_ASSOC ) : false ;
return $user ? $user : [];
}
function user_info ( ? int $user , bool $fresh = false ) : array {
global $pdo ;
static $cache = [];
if ( $user < 1 )
return [];
if ( ! $fresh && ! empty ( $cache [ $user ]))
return $cache [ $user ];
$getUserInfo = $pdo -> prepare ( 'SELECT *, UNIX_TIMESTAMP(`user_created`) AS `user_created`, UNIX_TIMESTAMP(`user_banned`) AS `user_banned`, MD5(LOWER(TRIM(`user_email`))) AS `gravatar_hash` FROM `fmf_users` WHERE `user_id` = :user' );
$getUserInfo -> bindValue ( 'user' , $user );
$userInfo = $getUserInfo -> execute () ? $getUserInfo -> fetch ( PDO :: FETCH_ASSOC ) : false ;
return $cache [ $user ] = ( $userInfo ? $userInfo : []);
}
function user_has_flag ( int $user , int $flag , bool $strict = false ) : bool {
$userInfo = user_info ( $user );
if ( empty ( $userInfo ))
return false ;
$flags = ( $userInfo [ 'user_flags' ] & $flag );
return $strict ? ( $flags === $flag ) : ( $flags > 0 );
}
function create_user ( string $username , string $email , string $password , string $ipAddr , bool $verified = false ) : array {
global $pdo ;
$verification = $verified ? null : bin2hex ( random_bytes ( 16 ));
$createUser = $pdo -> prepare ( 'INSERT INTO `fmf_users` (`user_login`, `user_password`, `user_email`, `user_email_verification`, `user_ip_created`) VALUES (:login, :password, :email, :verification, INET6_ATON(:ip))' );
$createUser -> bindValue ( 'login' , $username );
$createUser -> bindValue ( 'password' , password_hash ( $password , PASSWORD_DEFAULT ));
$createUser -> bindValue ( 'email' , $email );
$createUser -> bindValue ( 'verification' , $verification );
$createUser -> bindValue ( 'ip' , $ipAddr );
$createUser -> execute ();
return [
'user_id' => ( int ) $pdo -> lastInsertId (),
'verification' => $verification ,
];
}
function validate_username ( string $username ) : ? string {
if ( $username !== trim ( $username ))
return 'Your username may not start or end with spaces.' ;
$usernameLength = strlen ( $username );
if ( $usernameLength < 3 )
return 'Your username must be longer than 3 characters.' ;
if ( $usernameLength > 16 )
return 'Your username may not be longer than 16 characters.' ;
if ( ! preg_match ( '#^[A-Za-z0-9-_]+$#u' , $username ))
return 'Your username may only contains alphanumeric characters, dashes and underscores (A-Z, a-z, 0-9, -, _).' ;
return null ;
}
function validate_email ( string $email ) : ? string {
if ( filter_var ( $email , FILTER_VALIDATE_EMAIL ) === false )
return 'Your e-mail address is not correctly formatted.' ;
$domain = mb_substr ( mb_strstr ( $email , '@' ), 1 );
if ( ! checkdnsrr ( $domain , 'MX' ) && ! checkdnsrr ( $domain , 'A' ))
return 'Your e-mail address domain does not have valid DNS records.' ;
return null ;
}
function validate_password ( string $password ) : ? string {
if ( unique_chars ( $password ) < 10 )
return 'Your password is too weak.' ;
return null ;
}
function activate_user ( string $code ) : void {
global $pdo ;
if ( strlen ( $code ) !== 32 )
return ;
$verify = $pdo -> prepare ( 'UPDATE `fmf_users` SET `user_email_verification` = NULL WHERE `user_email_verification` = :code' );
$verify -> bindValue ( 'code' , $code );
$verify -> execute ();
}
function create_session ( int $userId ) : string {
global $pdo ;
if ( $userId < 1 )
return '' ;
$sessionKey = bin2hex ( random_bytes ( 32 ));
$createSession = $pdo -> prepare ( 'INSERT INTO `fmf_sessions` (`user_id`, `sess_key`) VALUES (:user, :key)' );
$createSession -> bindValue ( 'user' , $userId );
$createSession -> bindValue ( 'key' , $sessionKey );
$createSession -> execute ();
return $sessionKey ;
}
function purge_old_sessions () : void {
global $pdo ;
$pdo -> exec ( 'DELETE FROM `fmf_sessions` WHERE `sess_created` + INTERVAL 1 MONTH <= NOW()' );
}
function session_activate ( ? string $key ) : void {
global $pdo ;
if ( empty ( $key ) || strlen ( $key ) !== 64 )
return ;
$verify = $pdo -> prepare ( 'SELECT `user_id` FROM `fmf_sessions` WHERE `sess_key` = :key AND `sess_created` + INTERVAL 1 MONTH > NOW()' );
$verify -> bindValue ( 'key' , $key );
$userId = $verify -> execute () ? $verify -> fetchColumn () : 0 ;
if ( $userId < 1 )
return ;
$GLOBALS [ 'fmf_user_id' ] = ( int ) $userId ;
}
function session_active () : bool {
return ! empty ( $GLOBALS [ 'fmf_user_id' ]) && is_int ( $GLOBALS [ 'fmf_user_id' ]) && $GLOBALS [ 'fmf_user_id' ] > 0 ;
}
function logout_token () : string {
$sessionKey = $_COOKIE [ 'fmfauth' ] ? ? '' ;
if ( strlen ( $sessionKey ) !== 64 || ! ctype_xdigit ( $sessionKey ))
return bin2hex ( random_bytes ( 4 ));
$offset = hexdec ( $sessionKey [ 0 ]) * 2 ;
$offset = hexdec ( $sessionKey [ $offset ]) * 2 ;
$offset = hexdec ( $sessionKey [ $offset ]) * 2 ;
return substr ( $sessionKey , $offset , 8 );
}
function destroy_session ( string $token ) : void {
global $pdo ;
$delete = $pdo -> prepare ( 'DELETE FROM `fmf_sessions` WHERE `sess_key` = :key' );
$delete -> bindValue ( 'key' , $token );
$delete -> execute ();
}
2021-05-05 15:31:51 +00:00
function destroy_user_sessions ( int $userId ) : void {
global $pdo ;
$delete = $pdo -> prepare ( 'DELETE FROM `fmf_sessions` WHERE `user_id` = :user' );
$delete -> bindValue ( 'user' , $userId );
$delete -> execute ();
}
function destroy_current_user_sessions () : void {
destroy_user_sessions ( current_user_id ());
}
2020-07-06 17:09:56 +00:00
function current_user_id () : int {
return session_active () ? $GLOBALS [ 'fmf_user_id' ] : 0 ;
}
function verify_password ( string $pass , ? int $user = null ) : bool {
global $pdo ;
$user = $user ? ? current_user_id ();
if ( $user < 1 )
return false ;
$getHash = $pdo -> prepare ( 'SELECT `user_password` FROM `fmf_users` WHERE `user_id` = :user' );
$getHash -> bindValue ( 'user' , $user );
$hash = $getHash -> execute () ? $getHash -> fetchColumn () : '' ;
if ( empty ( $hash ))
return false ;
return password_verify ( $pass , $hash );
}
function user_set_password ( int $user , string $password ) : void {
global $pdo ;
2021-05-05 15:52:04 +00:00
2020-07-06 17:09:56 +00:00
if ( $user < 1 )
return ;
$password = password_hash ( $password , PASSWORD_DEFAULT );
$update = $pdo -> prepare ( 'UPDATE `fmf_users` SET `user_password` = :pass WHERE `user_id` = :user' );
$update -> bindValue ( 'pass' , $password );
$update -> bindValue ( 'user' , $user );
$update -> execute ();
}
function user_set_email ( int $user , string $email , bool $verified = false ) : ? string {
global $pdo ;
2021-05-05 15:52:04 +00:00
2020-07-06 17:09:56 +00:00
if ( $user < 1 )
return null ;
$verification = $verified ? null : bin2hex ( random_bytes ( 16 ));
$update = $pdo -> prepare ( 'UPDATE `fmf_users` SET `user_email` = LOWER(:mail), `user_email_verification` = :verf WHERE `user_id` = :user' );
$update -> bindValue ( 'mail' , $email );
$update -> bindValue ( 'verf' , $verification );
$update -> bindValue ( 'user' , $user );
$update -> execute ();
return $verification ;
}
function user_gravatar ( ? int $user , int $res = 80 ) : string {
$authorInfo = user_info ( $user );
return '//www.gravatar.com/avatar/' . ( $authorInfo [ 'gravatar_hash' ] ? ? str_repeat ( '0' , 32 )) . '?s=' . $res . '&r=g&d=identicon' ;
}