$v) {
$s[$k] = htmlescape($v);
}
return $s;
}
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
function strtrim(string $str, int $len, bool &$trimmed): string {
if (mb_strlen($str) > $len) {
$str = mb_substr($str, 0, $len);
$trimmed = true;
} else {
$trimmed = false;
}
return $str;
}
function sizeString(int $size): string {
$ks = array('B', 'KiB', 'MiB', 'GiB');
foreach ($ks as $i => $k) {
if ($size < pow(1024, $i + 1)) {
if ($i == 0)
return $size . ' ' . $k;
return round($size / pow(1024, $i), 2).' '.$k;
}
}
return $size;
}
function extension(string $name): string {
$expl = explode('.', $name);
return end($expl);
}
/**
* @param string $filename
* @return resource|bool
*/
function imageopen(string $filename) {
$size = getimagesize($filename);
$types = [
1 => 'gif',
2 => 'jpeg',
3 => 'png'
];
if (!$size || !isset($types[$size[2]]))
return null;
return call_user_func('imagecreatefrom'.$types[$size[2]], $filename);
}
function detect_image_type(string $filename) {
$size = getimagesize($filename);
$types = [
1 => 'gif',
2 => 'jpg',
3 => 'png'
];
if (!$size || !isset($types[$size[2]]))
return false;
return $types[$size[2]];
}
function transliterate(string $string): string {
$roman = array(
'Sch', 'sch', 'Yo', 'Zh', 'Kh', 'Ts', 'Ch', 'Sh', 'Yu', 'ya', 'yo',
'zh', 'kh', 'ts', 'ch', 'sh', 'yu', 'ya', 'A', 'B', 'V', 'G', 'D', 'E',
'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F',
'', 'Y', '', 'E', 'a', 'b', 'v', 'g', 'd', 'e', 'z', 'i', 'y', 'k',
'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', '', 'y', '', 'e'
);
$cyrillic = array(
'Щ', 'щ', 'Ё', 'Ж', 'Х', 'Ц', 'Ч', 'Ш', 'Ю', 'я', 'ё', 'ж', 'х', 'ц',
'ч', 'ш', 'ю', 'я', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'З', 'И', 'Й', 'К',
'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Ь', 'Ы', 'Ъ', 'Э',
'а', 'б', 'в', 'г', 'д', 'е', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о',
'п', 'р', 'с', 'т', 'у', 'ф', 'ь', 'ы', 'ъ', 'э'
);
return str_replace($cyrillic, $roman, $string);
}
/**
* @param resource $img
* @param ?int $w
* @param ?int $h
* @param ?int[] $transparent_color
*/
function imageresize(&$img, ?int $w = null, ?int $h = null, ?array $transparent_color = null) {
assert(is_int($w) || is_int($h));
$curw = imagesx($img);
$curh = imagesy($img);
if (!is_int($w) && is_int($h)) {
$w = round($curw / ($curw / $w));
} else if (is_int($w) && !is_int($h)) {
$h = round($curh / ($curh / $h));
}
$img2 = imagecreatetruecolor($w, $h);
if (is_array($transparent_color)) {
list($r, $g, $b) = $transparent_color;
$col = imagecolorallocate($img2, $r, $g, $b);
imagefilledrectangle($img2, 0, 0, $w, $h, $col);
} else {
imagealphablending($img2, false);
imagesavealpha($img2, true);
imagefilledrectangle($img2, 0, 0, $w, $h, imagecolorallocatealpha($img2, 255, 255, 255, 127));
}
imagecopyresampled($img2, $img, 0, 0, 0, 0, $w, $h, $curw, $curh);
imagedestroy($img);
$img = $img2;
}
function rrmdir(string $dir, bool $dont_delete_dir = false): bool {
if (!is_dir($dir)) {
logError('rrmdir: '.$dir.' is not a directory');
return false;
}
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != '.' && $object != '..') {
if (is_dir($dir.'/'.$object)) {
rrmdir($dir.'/'.$object);
} else {
unlink($dir.'/'.$object);
}
}
}
if (!$dont_delete_dir)
rmdir($dir);
return true;
}
function ip2ulong(string $ip): int {
return sprintf("%u", ip2long($ip));
}
function ulong2ip(int $ip): string {
$long = 4294967295 - ($ip - 1);
return long2ip(-$long);
}
function from_camel_case(string $s): string {
$buf = '';
$len = strlen($s);
for ($i = 0; $i < $len; $i++) {
if (!ctype_upper($s[$i])) {
$buf .= $s[$i];
} else {
$buf .= '_'.strtolower($s[$i]);
}
}
return $buf;
}
function to_camel_case(string $input, string $separator = '_'): string {
return lcfirst(str_replace($separator, '', ucwords($input, $separator)));
}
function str_replace_once(string $needle, string $replace, string $haystack) {
$pos = strpos($haystack, $needle);
if ($pos !== false)
$haystack = substr_replace($haystack, $replace, $pos, strlen($needle));
return $haystack;
}
function strgen(int $len): string {
$buf = '';
for ($i = 0; $i < $len; $i++) {
$j = mt_rand(0, 61);
if ($j >= 36) {
$j += 13;
} else if ($j >= 10) {
$j += 7;
}
$buf .= chr(48 + $j);
}
return $buf;
}
function sanitize_filename(string $name): string {
$name = mb_strtolower($name);
$name = transliterate($name);
$name = preg_replace('/[^\w\d\-_\s.]/', '', $name);
$name = preg_replace('/\s+/', '_', $name);
return $name;
}
function glob_escape(string $pattern): string {
if (strpos($pattern, '[') !== false || strpos($pattern, ']') !== false) {
$placeholder = uniqid();
$replaces = array( $placeholder.'[', $placeholder.']', );
$pattern = str_replace( array('[', ']', ), $replaces, $pattern);
$pattern = str_replace( $replaces, array('[[]', '[]]', ), $pattern);
}
return $pattern;
}
/**
* Does not support flag GLOB_BRACE
*
* @param string $pattern
* @param int $flags
* @return array
*/
function glob_recursive(string $pattern, int $flags = 0): array {
$files = glob(glob_escape($pattern), $flags);
foreach (glob(glob_escape(dirname($pattern)).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
}
return $files;
}
function setperm(string $file): void {
global $config;
// chgrp
$gid = filegroup($file);
if ($gid != $config['group']) {
if (!chgrp($file, $config['group'])) {
logError(__FUNCTION__.": chgrp() failed on $file");
}
}
// chmod
$perms = fileperms($file);
$need_perms = is_dir($file) ? $config['dirs_mode'] : $config['files_mode'];
if (($perms & $need_perms) !== $need_perms) {
if (!chmod($file, $need_perms)) {
logError(__FUNCTION__.": chmod() failed on $file");
}
}
}
function salt_password(string $pwd): string {
global $config;
return hash('sha256', "{$pwd}|{$config['password_salt']}");
}
function exectime(?string $format = null) {
$time = round(microtime(true) - START_TIME, 4);
if (!is_null($format))
$time = sprintf($format, $time);
return $time;
}
function fullURL(string $url): string {
global $config;
return 'https://'.$config['domain'].$url;
}
function getDb(): SQLiteConnection|MySQLConnection|null {
global $config;
static $link = null;
if (!is_null($link))
return $link;
switch ($config['db']['type']) {
case 'mysql':
$link = new MySQLConnection(
$config['db']['host'],
$config['db']['user'],
$config['db']['password'],
$config['db']['database']);
if (!$link->connect()) {
if (PHP_SAPI != 'cli') {
header('HTTP/1.1 503 Service Temporarily Unavailable');
header('Status: 503 Service Temporarily Unavailable');
header('Retry-After: 300');
die('database connection failed');
} else {
fwrite(STDERR, 'database connection failed');
exit(1);
}
}
break;
case 'sqlite':
$link = new SQLiteConnection($config['db']['path']);
break;
default:
logError('invalid database type');
break;
}
return $link;
}