Revert "Merge tag 'v2.10.6'"

This reverts commit 122ea4ab9e, reversing
changes made to c54a11e250.
This commit is contained in:
2024-02-16 23:06:09 -06:00
parent 122ea4ab9e
commit 6c08ee9675
521 changed files with 12363 additions and 14503 deletions

View File

@ -10,9 +10,6 @@ namespace Shimmie2;
/**
* Return the unique elements of an array, case insensitively
*
* @param array<string> $array
* @return list<string>
*/
function array_iunique(array $array): array
{
@ -39,11 +36,7 @@ function array_iunique(array $array): array
*/
function ip_in_range(string $IP, string $CIDR): bool
{
$parts = explode("/", $CIDR);
if(count($parts) == 1) {
$parts[1] = "32";
}
list($net, $mask) = $parts;
list($net, $mask) = explode("/", $CIDR);
$ip_net = ip2long($net);
$ip_mask = ~((1 << (32 - (int)$mask)) - 1);
@ -57,16 +50,42 @@ function ip_in_range(string $IP, string $CIDR): bool
/**
* Delete an entire file heirachy
*
* from a patch by Christian Walde; only intended for use in the
* "extension manager" extension, but it seems to fit better here
*/
function deltree(string $dir): void
function deltree(string $f): void
{
$di = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::KEY_AS_PATHNAME);
$ri = new \RecursiveIteratorIterator($di, \RecursiveIteratorIterator::CHILD_FIRST);
/** @var \SplFileInfo $file */
foreach ($ri as $filename => $file) {
$file->isDir() ? rmdir($filename) : unlink($filename);
//Because Windows (I know, bad excuse)
if (PHP_OS === 'WINNT') {
$real = realpath($f);
$path = realpath('./').'\\'.str_replace('/', '\\', $f);
if ($path != $real) {
rmdir($path);
} else {
foreach (glob($f.'/*') as $sf) {
if (is_dir($sf) && !is_link($sf)) {
deltree($sf);
} else {
unlink($sf);
}
}
rmdir($f);
}
} else {
if (is_link($f)) {
unlink($f);
} elseif (is_dir($f)) {
foreach (glob($f.'/*') as $sf) {
if (is_dir($sf) && !is_link($sf)) {
deltree($sf);
} else {
unlink($sf);
}
}
rmdir($f);
}
}
rmdir($dir);
}
/**
@ -79,13 +98,9 @@ function full_copy(string $source, string $target): void
if (is_dir($source)) {
@mkdir($target);
$d = dir_ex($source);
$d = dir($source);
while (true) {
$entry = $d->read();
if ($entry === false) {
break;
}
while (false !== ($entry = $d->read())) {
if ($entry == '.' || $entry == '..') {
continue;
}
@ -105,10 +120,8 @@ function full_copy(string $source, string $target): void
/**
* Return a list of all the regular files in a directory and subdirectories
*
* @return string[]
*/
function list_files(string $base, string $_sub_dir = ""): array
function list_files(string $base, string $_sub_dir=""): array
{
assert(is_dir($base));
@ -116,7 +129,7 @@ function list_files(string $base, string $_sub_dir = ""): array
$files = [];
$dir = opendir("$base/$_sub_dir");
if ($dir === false) {
if ($dir===false) {
throw new SCoreException("Unable to open directory $base/$_sub_dir");
}
try {
@ -159,16 +172,12 @@ function flush_output(): void
function stream_file(string $file, int $start, int $end): void
{
$fp = fopen($file, 'r');
if(!$fp) {
throw new \Exception("Failed to open $file");
}
try {
fseek($fp, $start);
$buffer = 1024 * 1024;
while (!feof($fp) && ($p = ftell($fp)) <= $end) {
if ($p + $buffer > $end) {
$buffer = $end - $p + 1;
assert($buffer >= 0);
}
echo fread($fp, $buffer);
flush_output();
@ -188,13 +197,13 @@ function stream_file(string $file, int $start, int $end): void
# http://www.php.net/manual/en/function.http-parse-headers.php#112917
if (!function_exists('http_parse_headers')) {
/**
* @return array<string, string|string[]>
* #return string[]
*/
function http_parse_headers(string $raw_headers): array
{
$headers = [];
$headers = []; // $headers = [];
foreach (explode("\n", $raw_headers) as $h) {
foreach (explode("\n", $raw_headers) as $i => $h) {
$h = explode(':', $h, 2);
if (isset($h[1])) {
@ -216,8 +225,6 @@ if (!function_exists('http_parse_headers')) {
/**
* HTTP Headers can sometimes be lowercase which will cause issues.
* In cases like these, we need to make sure to check for them if the camelcase version does not exist.
*
* @param array<string, mixed> $headers
*/
function find_header(array $headers, string $name): ?string
{
@ -240,22 +247,20 @@ function find_header(array $headers, string $name): ?string
if (!function_exists('mb_strlen')) {
// TODO: we should warn the admin that they are missing multibyte support
/** @noinspection PhpUnusedParameterInspection */
function mb_strlen(string $str, string $encoding): int
function mb_strlen($str, $encoding): int
{
return strlen($str);
}
function mb_internal_encoding(string $encoding): void
function mb_internal_encoding($encoding): void
{
}
function mb_strtolower(string $str): string
function mb_strtolower($str): string
{
return strtolower($str);
}
}
/**
* @return class-string[]
*/
/** @noinspection PhpUnhandledExceptionInspection */
function get_subclasses_of(string $parent): array
{
$result = [];
@ -270,8 +275,6 @@ function get_subclasses_of(string $parent): array
/**
* Like glob, with support for matching very long patterns with braces.
*
* @return string[]
*/
function zglob(string $pattern): array
{
@ -293,6 +296,52 @@ function zglob(string $pattern): array
}
}
/**
* Figure out the path to the shimmie install directory.
*
* eg if shimmie is visible at https://foo.com/gallery, this
* function should return /gallery
*
* PHP really, really sucks.
*/
function get_base_href(): string
{
if (defined("BASE_HREF") && !empty(BASE_HREF)) {
return BASE_HREF;
}
$possible_vars = ['SCRIPT_NAME', 'PHP_SELF', 'PATH_INFO', 'ORIG_PATH_INFO'];
$ok_var = null;
foreach ($possible_vars as $var) {
if (isset($_SERVER[$var]) && substr($_SERVER[$var], -4) === '.php') {
$ok_var = $_SERVER[$var];
break;
}
}
assert(!empty($ok_var));
$dir = dirname($ok_var);
$dir = str_replace("\\", "/", $dir);
$dir = str_replace("//", "/", $dir);
$dir = rtrim($dir, "/");
return $dir;
}
/**
* The opposite of the standard library's parse_url
*/
function unparse_url(array $parsed_url): string
{
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
$host = $parsed_url['host'] ?? '';
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
$user = $parsed_url['user'] ?? '';
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
$pass = ($user || $pass) ? "$pass@" : '';
$path = $parsed_url['path'] ?? '';
$query = !empty($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$fragment = !empty($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return "$scheme$user$pass$host$port$path$query$fragment";
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Input / Output Sanitising *
@ -347,7 +396,7 @@ function url_escape(?string $input): string
/**
* Turn all manner of HTML / INI / JS / DB booleans into a PHP one
*/
function bool_escape(mixed $input): bool
function bool_escape($input): bool
{
/*
Sometimes, I don't like PHP -- this, is one of those times...
@ -390,7 +439,7 @@ function no_escape(string $input): string
* Given a 1-indexed numeric-ish thing, return a zero-indexed
* number between 0 and $max
*/
function page_number(string $input, ?int $max = null): int
function page_number(string $input, ?int $max=null): int
{
if (!is_numeric($input)) {
$pageNumber = 0;
@ -401,23 +450,10 @@ function page_number(string $input, ?int $max = null): int
} else {
$pageNumber = $input - 1;
}
return (int)$pageNumber;
return $pageNumber;
}
function is_numberish(string $s): bool
{
return is_numeric($s);
}
/**
* Because apparently phpstan thinks that if $i is an int, type(-$i) == int|float
*/
function negative_int(int $i): int
{
return -$i;
}
function clamp(int $val, ?int $min = null, ?int $max = null): int
function clamp(int $val, ?int $min=null, ?int $max=null): int
{
if (!is_null($min) && $val < $min) {
$val = $min;
@ -435,7 +471,7 @@ function clamp(int $val, ?int $min = null, ?int $max = null): int
* Original PHP code by Chirp Internet: www.chirp.com.au
* Please acknowledge use of this code by including this header.
*/
function truncate(string $string, int $limit, string $break = " ", string $pad = "..."): string
function truncate(string $string, int $limit, string $break=" ", string $pad="..."): string
{
// return with no change if string is shorter than $limit
if (strlen($string) <= $limit) {
@ -492,17 +528,17 @@ function to_shorthand_int(int $int): string
{
assert($int >= 0);
return match (true) {
$int >= pow(1024, 4) * 10 => sprintf("%.0fTB", $int / pow(1024, 4)),
$int >= pow(1024, 4) => sprintf("%.1fTB", $int / pow(1024, 4)),
$int >= pow(1024, 3) * 10 => sprintf("%.0fGB", $int / pow(1024, 3)),
$int >= pow(1024, 3) => sprintf("%.1fGB", $int / pow(1024, 3)),
$int >= pow(1024, 2) * 10 => sprintf("%.0fMB", $int / pow(1024, 2)),
$int >= pow(1024, 2) => sprintf("%.1fMB", $int / pow(1024, 2)),
$int >= pow(1024, 1) * 10 => sprintf("%.0fKB", $int / pow(1024, 1)),
$int >= pow(1024, 1) => sprintf("%.1fKB", $int / pow(1024, 1)),
default => (string)$int,
};
if ($int >= pow(1024, 4)) {
return sprintf("%.1fTB", $int / pow(1024, 4));
} elseif ($int >= pow(1024, 3)) {
return sprintf("%.1fGB", $int / pow(1024, 3));
} elseif ($int >= pow(1024, 2)) {
return sprintf("%.1fMB", $int / pow(1024, 2));
} elseif ($int >= 1024) {
return sprintf("%.1fKB", $int / 1024);
} else {
return (string)$int;
}
}
abstract class TIME_UNITS
{
@ -513,12 +549,12 @@ abstract class TIME_UNITS
public const DAYS = "d";
public const YEARS = "y";
public const CONVERSION = [
self::MILLISECONDS => 1000,
self::SECONDS => 60,
self::MINUTES => 60,
self::HOURS => 24,
self::DAYS => 365,
self::YEARS => PHP_INT_MAX
self::MILLISECONDS=>1000,
self::SECONDS=>60,
self::MINUTES=>60,
self::HOURS=>24,
self::DAYS=>365,
self::YEARS=>PHP_INT_MAX
];
}
function format_milliseconds(int $input, string $min_unit = TIME_UNITS::SECONDS): string
@ -529,17 +565,17 @@ function format_milliseconds(int $input, string $min_unit = TIME_UNITS::SECONDS)
$found = false;
foreach (TIME_UNITS::CONVERSION as $unit => $conversion) {
foreach (TIME_UNITS::CONVERSION as $unit=>$conversion) {
$count = $remainder % $conversion;
$remainder = floor($remainder / $conversion);
if ($found || $unit == $min_unit) {
if ($found||$unit==$min_unit) {
$found = true;
} else {
continue;
}
if ($count == 0 && $remainder < 1) {
if ($count==0&&$remainder<1) {
break;
}
$output = "$count".$unit." ".$output;
@ -560,7 +596,7 @@ function parse_to_milliseconds(string $input): int
$output += $length;
}
} else {
foreach (TIME_UNITS::CONVERSION as $unit => $conversion) {
foreach (TIME_UNITS::CONVERSION as $unit=>$conversion) {
if (preg_match('/([0-9]+)'.$unit.'/i', $input, $match)) {
$length = $match[1];
if (is_numeric($length)) {
@ -577,10 +613,10 @@ function parse_to_milliseconds(string $input): int
/**
* Turn a date into a time, a date, an "X minutes ago...", etc
*/
function autodate(string $date, bool $html = true): string
function autodate(string $date, bool $html=true): string
{
$cpu = date('c', strtotime_ex($date));
$hum = date('F j, Y; H:i', strtotime_ex($date));
$cpu = date('c', strtotime($date));
$hum = date('F j, Y; H:i', strtotime($date));
return ($html ? "<time datetime='$cpu'>$hum</time>" : $hum);
}
@ -613,10 +649,6 @@ function isValidDate(string $date): bool
return false;
}
/**
* @param array<string, string> $inputs
* @return array<string, mixed>
*/
function validate_input(array $inputs): array
{
$outputs = [];
@ -649,7 +681,6 @@ function validate_input(array $inputs): array
}
$outputs[$key] = $id;
} elseif (in_array('user_name', $flags)) {
// @phpstan-ignore-next-line - phpstan thinks $value can never be empty?
if (strlen($value) < 1) {
throw new InvalidInput("Username must be at least 1 character");
} elseif (!preg_match('/^[a-zA-Z0-9-_]+$/', $value)) {
@ -660,7 +691,8 @@ function validate_input(array $inputs): array
}
$outputs[$key] = $value;
} elseif (in_array('user_class', $flags)) {
if (!array_key_exists($value, UserClass::$known_classes)) {
global $_shm_user_classes;
if (!array_key_exists($value, $_shm_user_classes)) {
throw new InvalidInput("Invalid user class: ".html_escape($value));
}
$outputs[$key] = $value;
@ -677,7 +709,7 @@ function validate_input(array $inputs): array
} elseif (in_array('bool', $flags)) {
$outputs[$key] = bool_escape($value);
} elseif (in_array('date', $flags)) {
$outputs[$key] = date("Y-m-d H:i:s", strtotime_ex(trim($value)));
$outputs[$key] = date("Y-m-d H:i:s", strtotime(trim($value)));
} elseif (in_array('string', $flags)) {
if (in_array('trim', $flags)) {
$value = trim($value);
@ -736,12 +768,6 @@ function join_path(string ...$paths): string
/**
* Perform callback on each item returned by an iterator.
*
* @template T
* @template U
* @param callable(U):T $callback
* @param \iterator<U> $iter
* @return \Generator<T>
*/
function iterator_map(callable $callback, \iterator $iter): \Generator
{
@ -752,26 +778,20 @@ function iterator_map(callable $callback, \iterator $iter): \Generator
/**
* Perform callback on each item returned by an iterator and combine the result into an array.
*
* @template T
* @template U
* @param callable(U):T $callback
* @param \iterator<U> $iter
* @return array<T>
*/
function iterator_map_to_array(callable $callback, \iterator $iter): array
{
return iterator_to_array(iterator_map($callback, $iter));
}
function stringer(mixed $s): string
function stringer($s): string
{
if (is_array($s)) {
if (isset($s[0])) {
return "[" . implode(", ", array_map("Shimmie2\stringer", $s)) . "]";
} else {
$pairs = [];
foreach ($s as $k => $v) {
foreach ($s as $k=>$v) {
$pairs[] = "\"$k\"=>" . stringer($v);
}
return "[" . implode(", ", $pairs) . "]";
@ -794,24 +814,3 @@ function stringer(mixed $s): string
}
return "<Unstringable>";
}
/**
* If a value is in the cache, return it; otherwise, call the callback
* to generate it and store it in the cache.
*
* @template T
* @param string $key
* @param callable():T $callback
* @param int|null $ttl
* @return T
*/
function cache_get_or_set(string $key, callable $callback, ?int $ttl = null): mixed
{
global $cache;
$value = $cache->get($key);
if ($value === null) {
$value = $callback();
$cache->set($key, $value, $ttl);
}
return $value;
}