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

@@ -54,8 +54,8 @@ function contact_link(): ?string
function is_https_enabled(): bool
{
// check forwarded protocol
if (is_trusted_proxy() && !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$_SERVER['HTTPS'] = 'on';
if (REVERSE_PROXY_X_HEADERS && !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$_SERVER['HTTPS']='on';
}
return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
}
@@ -80,10 +80,10 @@ function get_memory_limit(): int
global $config;
// thumbnail generation requires lots of memory
$default_limit = 8 * 1024 * 1024; // 8 MB of memory is PHP's default.
$default_limit = 8*1024*1024; // 8 MB of memory is PHP's default.
$shimmie_limit = $config->get_int(MediaConfig::MEM_LIMIT);
if ($shimmie_limit < 3 * 1024 * 1024) {
if ($shimmie_limit < 3*1024*1024) {
// we aren't going to fit, override
$shimmie_limit = $default_limit;
}
@@ -143,43 +143,30 @@ function check_gd_version(): int
*/
function check_im_version(): int
{
$convert_check = exec("convert --version");
$convert_check = exec("convert");
return (empty($convert_check) ? 0 : 1);
}
function is_trusted_proxy(): bool
{
$ra = $_SERVER['REMOTE_ADDR'] ?? "0.0.0.0";
// @phpstan-ignore-next-line - TRUSTED_PROXIES is defined in config
foreach(TRUSTED_PROXIES as $proxy) {
if(ip_in_range($ra, $proxy)) {
return true;
}
}
return false;
}
/**
* Get request IP
*/
function get_remote_addr()
{
return $_SERVER['REMOTE_ADDR'];
}
/**
* Get real IP if behind a reverse proxy
*/
function get_real_ip(): string
function get_real_ip()
{
$ip = $_SERVER['REMOTE_ADDR'];
if(is_trusted_proxy()) {
if (isset($_SERVER['HTTP_X_REAL_IP'])) {
if(filter_var_ex($ip, FILTER_VALIDATE_IP)) {
$ip = $_SERVER['HTTP_X_REAL_IP'];
}
}
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$last_ip = $ips[count($ips) - 1];
if(filter_var_ex($last_ip, FILTER_VALIDATE_IP)) {
$ip = $last_ip;
}
$ip = get_remote_addr();
if (REVERSE_PROXY_X_HEADERS && isset($_SERVER['HTTP_X_REAL_IP'])) {
$ip = $_SERVER['HTTP_X_REAL_IP'];
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
$ip = "0.0.0.0";
}
}
@@ -194,7 +181,7 @@ function get_session_ip(Config $config): string
{
$mask = $config->get_string("session_hash_mask", "255.255.0.0");
$addr = get_real_ip();
$addr = inet_ntop_ex(inet_pton_ex($addr) & inet_pton_ex($mask));
$addr = inet_ntop(inet_pton($addr) & inet_pton($mask));
return $addr;
}
@@ -218,9 +205,9 @@ function format_text(string $string): string
* @param int $splits The number of octet pairs to split the hash into. Caps out at strlen($hash)/2.
* @return string
*/
function warehouse_path(string $base, string $hash, bool $create = true, int $splits = WH_SPLITS): string
function warehouse_path(string $base, string $hash, bool $create=true, int $splits = WH_SPLITS): string
{
$dirs = [DATA_DIR, $base];
$dirs =[DATA_DIR, $base];
$splits = min($splits, strlen($hash) / 2);
for ($i = 0; $i < $splits; $i++) {
$dirs[] = substr($hash, $i * 2, 2);
@@ -241,13 +228,13 @@ function warehouse_path(string $base, string $hash, bool $create = true, int $sp
function data_path(string $filename, bool $create = true): string
{
$filename = join_path("data", $filename);
if ($create && !file_exists(dirname($filename))) {
if ($create&&!file_exists(dirname($filename))) {
mkdir(dirname($filename), 0755, true);
}
return $filename;
}
function load_balance_url(string $tmpl, string $hash, int $n = 0): string
function load_balance_url(string $tmpl, string $hash, int $n=0): string
{
static $flexihashes = [];
$matches = [];
@@ -285,24 +272,16 @@ function load_balance_url(string $tmpl, string $hash, int $n = 0): string
return $tmpl;
}
class FetchException extends \Exception
{
}
/**
* @return array<string, string|string[]>
*/
function fetch_url(string $url, string $mfile): array
function fetch_url(string $url, string $mfile): ?array
{
global $config;
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "curl" && function_exists("curl_init")) {
$ch = curl_init($url);
assert($ch !== false);
$fp = false_throws(fopen($mfile, "w"));
$fp = fopen($mfile, "w");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
# curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_USERAGENT, "Shimmie-".VERSION);
@@ -310,37 +289,37 @@ function fetch_url(string $url, string $mfile): array
$response = curl_exec($ch);
if ($response === false) {
throw new FetchException("cURL failed: ".curl_error($ch));
}
if ($response === true) { // we use CURLOPT_RETURNTRANSFER, so this should never happen
throw new FetchException("cURL failed successfully??");
return null;
}
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header_text = trim(substr($response, 0, $header_size));
$headers = http_parse_headers(implode("\n", false_throws(preg_split('/\R/', $header_text))));
$headers = http_parse_headers(implode("\n", preg_split('/\R/', rtrim(substr($response, 0, $header_size)))));
$body = substr($response, $header_size);
curl_close($ch);
fwrite($fp, $body);
fclose($fp);
} elseif ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "wget") {
return $headers;
}
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "wget") {
$s_url = escapeshellarg($url);
$s_mfile = escapeshellarg($mfile);
system("wget --no-check-certificate $s_url --output-document=$s_mfile");
if(!file_exists($mfile)) {
throw new FetchException("wget failed");
}
$headers = [];
} elseif ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "fopen") {
return file_exists($mfile) ? ["ok"=>"true"] : null;
}
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "fopen") {
$fp_in = @fopen($url, "r");
$fp_out = fopen($mfile, "w");
if (!$fp_in || !$fp_out) {
throw new FetchException("fopen failed");
return null;
}
$length = 0;
while (!feof($fp_in) && $length <= $config->get_int(UploadConfig::SIZE)) {
$data = false_throws(fread($fp_in, 8192));
$data = fread($fp_in, 8192);
$length += strlen($data);
fwrite($fp_out, $data);
}
@@ -348,22 +327,14 @@ function fetch_url(string $url, string $mfile): array
fclose($fp_out);
$headers = http_parse_headers(implode("\n", $http_response_header));
} else {
throw new FetchException("No transload engine configured");
return $headers;
}
if (filesize($mfile) == 0) {
@unlink($mfile);
throw new FetchException("No data found in $url -- perhaps the site has hotlink protection?");
}
return $headers;
return null;
}
/**
* @return string[]
*/
function path_to_tags(string $path): array
function path_to_tags(string $path): string
{
$matches = [];
$tags = [];
@@ -384,7 +355,7 @@ function path_to_tags(string $path): array
$category_to_inherit = "";
foreach (explode(" ", $dir) as $tag) {
$tag = trim($tag);
if ($tag == "") {
if ($tag=="") {
continue;
}
if (substr_compare($tag, ":", -1) === 0) {
@@ -392,7 +363,7 @@ function path_to_tags(string $path): array
// which is for inheriting to tags on the subfolder
$category_to_inherit = $tag;
} else {
if ($category != "" && !str_contains($tag, ":")) {
if ($category!="" && !str_contains($tag, ":")) {
// This indicates that category inheritance is active,
// and we've encountered a tag that does not specify a category.
// So we attach the inherited category to the tag.
@@ -407,12 +378,9 @@ function path_to_tags(string $path): array
$category = $category_to_inherit;
}
return $tags;
return implode(" ", $tags);
}
/**
* @return string[]
*/
function get_dir_contents(string $dir): array
{
assert(!empty($dir));
@@ -421,17 +389,29 @@ function get_dir_contents(string $dir): array
return [];
}
return array_diff(
false_throws(scandir($dir)),
scandir(
$dir
),
['..', '.']
);
}
function remove_empty_dirs(string $dir): bool
{
assert(!empty($dir));
$result = true;
$items = get_dir_contents($dir);
;
if (!is_dir($dir)) {
return false;
}
$items = array_diff(
scandir(
$dir
),
['..', '.']
);
foreach ($items as $item) {
$path = join_path($dir, $item);
if (is_dir($path)) {
@@ -440,21 +420,31 @@ function remove_empty_dirs(string $dir): bool
$result = false;
}
}
if ($result === true) {
if ($result===true) {
$result = rmdir($dir);
}
return $result;
}
/**
* @return string[]
*/
function get_files_recursively(string $dir): array
{
$things = get_dir_contents($dir);
assert(!empty($dir));
if (!is_dir($dir)) {
return [];
}
$things = array_diff(
scandir(
$dir
),
['..', '.']
);
$output = [];
foreach ($things as $thing) {
$path = join_path($dir, $thing);
if (is_file($path)) {
@@ -469,8 +459,6 @@ function get_files_recursively(string $dir): array
/**
* Returns amount of files & total size of dir.
*
* @return array{"path": string, "total_files": int, "total_mb": string}
*/
function scan_dir(string $path): array
{
@@ -532,11 +520,6 @@ function get_debug_info(): string
return $debug;
}
/**
* Collects some debug information (execution time, memory usage, queries, etc)
*
* @return array<string, mixed>
*/
function get_debug_info_arr(): array
{
global $cache, $config, $_shm_event_count, $database, $_shm_load_start;
@@ -550,7 +533,7 @@ function get_debug_info_arr(): array
return [
"time" => round(ftime() - $_shm_load_start, 2),
"dbtime" => round($database->dbtime, 2),
"mem_mb" => round(((memory_get_peak_usage(true) + 512) / 1024) / 1024, 2),
"mem_mb" => round(((memory_get_peak_usage(true)+512)/1024)/1024, 2),
"files" => count(get_included_files()),
"query_count" => $database->query_count,
// "query_log" => $database->queries,
@@ -566,9 +549,6 @@ function get_debug_info_arr(): array
* Request initialisation stuff *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* @param string[] $files
*/
function require_all(array $files): void
{
foreach ($files as $filename) {
@@ -576,7 +556,7 @@ function require_all(array $files): void
}
}
function _load_core_files(): void
function _load_core_files()
{
require_all(array_merge(
zglob("core/*.php"),
@@ -585,20 +565,11 @@ function _load_core_files(): void
));
}
function _load_extension_files(): void
{
ExtensionInfo::load_all_extension_info();
Extension::determine_enabled_extensions();
require_all(zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/main.php"));
}
function _load_theme_files(): void
function _load_theme_files()
{
$theme = get_theme();
require_once('themes/'.$theme.'/page.class.php');
require_once('themes/'.$theme.'/themelet.class.php');
require_all(zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/theme.php"));
require_all(zglob('themes/'.$theme.'/{'.Extension::get_enabled_extensions_as_string().'}.theme.php'));
$files = _get_themelet_files($theme);
require_all($files);
}
function _set_up_shimmie_environment(): void
@@ -620,8 +591,20 @@ function _set_up_shimmie_environment(): void
// The trace system has a certain amount of memory consumption every time it is used,
// so to prevent running out of memory during complex operations code that uses it should
// check if tracer output is enabled before making use of it.
// @phpstan-ignore-next-line - TRACE_FILE is defined in config
$tracer_enabled = !is_null('TRACE_FILE');
$tracer_enabled = constant('TRACE_FILE')!==null;
}
function _get_themelet_files(string $_theme): array
{
$base_themelets = [];
$base_themelets[] = 'themes/'.$_theme.'/page.class.php';
$base_themelets[] = 'themes/'.$_theme.'/themelet.class.php';
$ext_themelets = zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/theme.php");
$custom_themelets = zglob('themes/'.$_theme.'/{'.Extension::get_enabled_extensions_as_string().'}.theme.php');
return array_merge($base_themelets, $ext_themelets, $custom_themelets);
}
@@ -633,6 +616,8 @@ function _fatal_error(\Exception $e): void
$version = VERSION;
$message = $e->getMessage();
$phpver = phpversion();
$query = is_subclass_of($e, "Shimmie2\SCoreException") ? $e->query : null;
$code = is_subclass_of($e, "Shimmie2\SCoreException") ? $e->http_code : 500;
//$hash = exec("git rev-parse HEAD");
//$h_hash = $hash ? "<p><b>Hash:</b> $hash" : "";
@@ -644,29 +629,19 @@ function _fatal_error(\Exception $e): void
foreach ($t as $n => $f) {
$c = $f['class'] ?? '';
$t = $f['type'] ?? '';
$i = $f['file'] ?? 'unknown file';
$l = $f['line'] ?? -1;
$a = implode(", ", array_map("Shimmie2\stringer", $f['args'] ?? []));
print("$n: {$i}({$l}): {$c}{$t}{$f['function']}({$a})\n");
print("$n: {$f['file']}({$f['line']}): {$c}{$t}{$f['function']}({$a})\n");
}
print("Message: $message\n");
if (is_a($e, DatabaseException::class)) {
print("Query: {$e->query}\n");
print("Args: ".var_export($e->args, true)."\n");
if ($query) {
print("Query: {$query}\n");
}
print("Version: $version (on $phpver)\n");
} else {
$query = is_a($e, DatabaseException::class) ? $e->query : null;
$code = is_a($e, SCoreException::class) ? $e->http_code : 500;
$q = "";
if(is_a($e, DatabaseException::class)) {
$q .= "<p><b>Query:</b> " . html_escape($query);
$q .= "<p><b>Args:</b> " . html_escape(var_export($e->args, true));
}
$q = $query ? "" : "<p><b>Query:</b> " . html_escape($query);
if ($code >= 500) {
error_log("Shimmie Error: $message (Query: $query)\n{$e->getTraceAsString()}");
}
@@ -702,7 +677,7 @@ function _get_user(): User
}
}
}
if (is_null($my_user) && $page->get_cookie("user") && $page->get_cookie("session")) {
if ($page->get_cookie("user") && $page->get_cookie("session")) {
$my_user = User::by_session($page->get_cookie("user"), $page->get_cookie("session"));
}
if (is_null($my_user)) {
@@ -713,6 +688,11 @@ function _get_user(): User
return $my_user;
}
function _get_query(): string
{
return (@$_POST["q"] ?: @$_GET["q"]) ?: "/";
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* HTML Generation *
@@ -737,7 +717,7 @@ function show_ip(string $ip, string $ban_reason): string
/**
* Make a form tag with relevant auth token and stuff
*/
function make_form(string $target, string $method = "POST", bool $multipart = false, string $form_id = "", string $onsubmit = ""): string
function make_form(string $target, string $method="POST", bool $multipart=false, string $form_id="", string $onsubmit=""): string
{
global $user;
if ($method == "GET") {
@@ -759,7 +739,7 @@ function make_form(string $target, string $method = "POST", bool $multipart = fa
}
const BYTE_DENOMINATIONS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
function human_filesize(int $bytes, int $decimals = 2): string
function human_filesize(int $bytes, $decimals = 2): string
{
$factor = floor((strlen(strval($bytes)) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @BYTE_DENOMINATIONS[$factor];
@@ -779,12 +759,3 @@ function generate_key(int $length = 20): string
return $randomString;
}
function shm_tempnam(string $prefix = ""): string
{
if(!is_dir("data/temp")) {
mkdir("data/temp");
}
$temp = false_throws(realpath("data/temp"));
return false_throws(tempnam($temp, $prefix));
}