Files
LittleBeast/util.php
2025-12-12 20:19:29 +09:00

274 lines
9.3 KiB
PHP

<?php
enum LogType {
case ActivityPub;
case Mailer;
case MySQL;
case Csv;
}
class Result {
public bool $isSuccess;
public ?string $message;
public function __construct(bool $isSuccess, ?string $message = null) {
$this->isSuccess = $isSuccess;
$this->message = $message;
}
public static function Success(?string $message = null): self {
return new self(true, $message);
}
public static function Error(string $message): self {
return new self(false, $message);
}
}
function uuid(): string {
$data = random_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
function kys(mixed $arg): void {
if (gettype($arg) == 'boolean') $arg = $arg === true ? 'true' : 'false';
if (gettype($arg) == 'array' || gettype($arg) == 'object') {
foreach ($arg as $a) { if (gettype($a) == 'boolean') $a = $a === true ? 'true' : 'false'; }
}
echo '<style>html { color: #fcfcfc; background-color: #232023; } body { margin: 0; }</style>';
echo '<header style="padding: 10px 0; display: flex; justify-content: space-evenly; background-color: #550f75; margin-bottom: 20px; position: sticky; top: 0;"><div><b>K</b>ILL</div> <div><b>Y</b>OUR</div> <div><b>S</b>ELF</div></header>';
echo '<pre>';
print_r($arg);
echo '<pre>';
die();
}
function ffs(): void {
echo '<style>html { color: #fcfcfc; background-color: #232023; } body { margin: 0; }</style>';
echo '<header style="padding: 10px 0; display: flex; justify-content: space-evenly; background-color: #b61729; margin-bottom: 20px; position: sticky; top: 0;"><div><b>F</b>OR</div> <div><b>F</b>UCKS</div> <div><b>S</b>AKE</div></header>';
$stack = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 50);
$st = [];
unset($stack[0]);
$i = 0;
echo '<pre>';
print_r($stack);
echo '<pre>';
foreach ($stack as $s) {
if (isset($s['file'])) $st[$i]['file'] = $s['file'].(isset($s['line']) ? ':'.$s['line'] : '');
else $st[$i]['file'] = '';
if (isset($s['function'])) $st[$i]['func'] = (isset($s['class']) ? $s['class'].(isset($s['type']) ? $s['type'] : '::') : '').$s['function'];
else $st[$i]['func'] = '';
if (isset($s['object'])) $st[$i]['objs'] = $s['object'];
else $st[$i]['objs'] = new \stdClass;
if (isset($s['args'])) $st[$i]['args'] = $s['args'];
else $st[$i]['args'] = [];
$i++;
}
unset($stack[$i]);
foreach ($st as $s) {
echo '<div>';
echo '<b>ファイル:</b>';
echo $s['file'].'<br />';
echo '<b>関数:</b>';
echo $s['func'].'<br />';
echo '<b>オブジェクト:</b>';
echo print_r($s['objs']).'<br />';
echo '<b>その他:</b>';
echo print_r($s['args']).'<br />';
echo '</div>';
}
die();
}
function base58btc_encode(string $bin): string {
$a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
$base = 58;
$num = \gmp_import($bin, 1, GMP_LSW_FIRST | GMP_NATIVE_ENDIAN);
$res = '';
if (\gmp_cmp($num, 0) == 0) return '1';
while (\gmp_cmp($num, 0) > 0) {
$mod = \gmp_intval(\gmp_mod($num, $base));
$res = $a[$mod].$res;
$num = \gmp_div_q($num, $base);
}
$bytes = str_split($bin);
foreach ($bytes as $byte) {
if (ord($byte) === 0) {
$res = '1'.$res;
} else {
break;
}
}
return $res;
}
function logger(LogType $section, mixed $arg): void {
if (LOGGING_ENABLED) {
$logfile = ROOT.'/log/';
if ($section == LogType::ActivityPub) $logfile .= 'ap_log.txt';
else if ($section == LogType::Mailer) $logfile .= 'mail_log.txt';
else if ($section == LogType::MySQL) $logfile .= 'mysql_log.txt';
else if ($section == LogType::Csv) $logfile .= 'csv_log.txt';
file_put_contents($logfile, $arg."\n", FILE_APPEND);
}
}
function to_money($amount, $lang) {
$amount = floatval($amount);
switch (strtolower($lang)) {
case 'ja':
if ($amount >= 100000000) {
$oku = $amount / 100000000;
return $oku.'億円';
} else if ($amount >= 10000) {
$man = $amount / 10000;
return $man.'万円';
}
return number_format($amount, 0).'円';
case 'en':
if ($amount >= 1000000000) {
$billion = $amount / 1000000000;
return '¥ '.$billion.' billion';
} else if ($amount >= 1000000) {
$million = $amount / 1000000;
return '¥ '.$million.' million';
} else if ($amount >= 1000) {
$thousand = $amount / 1000;
return '¥ '.$thousand.' thousand';
}
return '¥ '.number_format($amount, 0);
default:
return '¥ '.number_format($amount, 0);
}
}
function randstr(): string {
$len = random_int(1, 20);
return bin2hex(random_bytes($len));
}
function assert_null(mixed $assertion, Throwable|string|null $description = null): bool {
if (ini_get('zend.assertions') < 1) trigger_error('assert機能性が無効です。有効するには、php.iniで「zend.assertions = 1」に設定して下さい。', E_USER_WARNING);
if (is_null($assertion)) return true;
assert(false, $description ?? 'Assertion failed: value is not null');
return false;
}
function assert_not_null(mixed $assertion, Throwable|string|null $description = null): bool {
if (ini_get('zend.assertions') < 1) trigger_error('assert機能性が無効です。有効するには、php.iniで「zend.assertions = 1」に設定して下さい。', E_USER_WARNING);
if (!is_null($assertion)) return true;
assert(false, $description ?? 'Assertion failed: value is null');
return false;
}
function assert_unless_success(Result $assertion, Throwable|string|null $description = null): bool {
if (ini_get('zend.assertions') < 1) trigger_error('assert機能性が無効です。有効するには、php.iniで「zend.assertions = 1」に設定して下さい。', E_USER_WARNING);
if ($assertion->isSuccess) return true;
assert(false, $description ?? $assertion->message ?? 'Assertion failed: Result is not successful');
return false;
}
function getcookie(string $name): string|null {
return $_COOKIE[$name] ?? null;
}
function namecolor(\stdClass $userData): string {
$ban = "#888888";
$male = "#97ACEF";
$female = "#F185C9";
$ungender = "#7C60B0";
$gender = 'color: '.($userData->gender === 0 ? $male : ($userData->gender === 1 ? $female : $ungender)).';';
$style = $userData->namecolor ?: ($userData->role >= 0 ? $gender : $ban);
$showname = $userData->displayname ?: $userData->username;
$color = "<span style=\"{$style}\">{$showname}</span>";
if ($userData->role === 1) $color .= "<span style=\"font-size: x-small; background: #10c074; border: 1px solid #fcfcfc; border-radius: 10px; padding: 0 0.5em;\">✓</span>";
$suffix = $userData->gender === 0 ? 'くん' : ($userData->gender === 1 ? 'ちゃん' : 'さん');
return $color.$suffix;
}
function make_csrf_token(?bool $force = false): string {
if (null !== getcookie('csrf_token') && !$force) return getcookie('csrf_token');
$token = bin2hex(random_bytes(32));
setcookie('csrf_token', $token, [
'expires' => time() + 300, // 5分
'path' => '/',
'domain' => $_SERVER['SERVER_NAME'],
'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
'httponly' => true,
'samesite' => 'Strict'
]);
return $token;
}
function verify_csrf_token(string $token): bool {
return null !== getcookie('csrf_token') && hash_equals(getcookie('csrf_token'), $token);
}
function count_special_chars(string $str): int {
$count = 0;
$len = strlen($str);
for ($i = 0; $i < $len; ++$i) {
if (str_contains('!', $str[$i])) ++$count;
if (str_contains('"', $str[$i])) ++$count;
if (str_contains('#', $str[$i])) ++$count;
if (str_contains('$', $str[$i])) ++$count;
if (str_contains('%', $str[$i])) ++$count;
if (str_contains('&', $str[$i])) ++$count;
if (str_contains('\'', $str[$i])) ++$count;
if (str_contains('(', $str[$i])) ++$count;
if (str_contains(')', $str[$i])) ++$count;
if (str_contains('-', $str[$i])) ++$count;
if (str_contains('=', $str[$i])) ++$count;
if (str_contains('^', $str[$i])) ++$count;
if (str_contains('~', $str[$i])) ++$count;
if (str_contains('\\', $str[$i])) ++$count;
if (str_contains('|', $str[$i])) ++$count;
if (str_contains('[', $str[$i])) ++$count;
if (str_contains(']', $str[$i])) ++$count;
if (str_contains(':', $str[$i])) ++$count;
if (str_contains('@', $str[$i])) ++$count;
if (str_contains('`', $str[$i])) ++$count;
if (str_contains('*', $str[$i])) ++$count;
if (str_contains('{', $str[$i])) ++$count;
if (str_contains('}', $str[$i])) ++$count;
if (str_contains(';', $str[$i])) ++$count;
if (str_contains('+', $str[$i])) ++$count;
if (str_contains(',', $str[$i])) ++$count;
if (str_contains('<', $str[$i])) ++$count;
if (str_contains('.', $str[$i])) ++$count;
if (str_contains('>', $str[$i])) ++$count;
if (str_contains('/', $str[$i])) ++$count;
if (str_contains('?', $str[$i])) ++$count;
if (str_contains('_', $str[$i])) ++$count;
}
return $count;
}
function countmatch(string $str): bool {
$len = strlen($str);
$numUpper = preg_match_all('/[A-Z]/', $str) ?? 0;
$numLower = preg_match_all('/[a-z]/', $str) ?? 0;
$numDigit = preg_match_all('/[0-9]/', $str) ?? 0;
$numSymbol = count_special_chars($str);
$sum = $numUpper + $numLower + $numDigit + $numSymbol;
return $len == $sum;
}