From e80d235fe9b32c1161d100f2c82d8deda2e31e4a Mon Sep 17 00:00:00 2001 From: Shish Date: Tue, 20 Feb 2024 00:22:25 +0000 Subject: [PATCH] [core] use Safe library, reduce StdLibEx --- composer.json | 6 +- composer.lock | 198 +++++++++++++++++++++++++++++++- core/basepage.php | 2 +- core/dbengine.php | 8 +- core/extension.php | 6 +- core/imageboard/image.php | 9 ++ core/polyfills.php | 6 +- core/stdlib_ex.php | 64 +---------- core/tests/ImageTest.php | 2 +- core/tests/StdLibExTest.php | 4 +- core/util.php | 14 +-- ext/alias_editor/main.php | 2 +- ext/artists/test.php | 2 +- ext/auto_tagger/main.php | 4 +- ext/autocomplete/main.php | 2 +- ext/blotter/theme.php | 6 +- ext/browser_search/main.php | 4 +- ext/bulk_add_csv/main.php | 2 +- ext/bulk_import_export/main.php | 4 +- ext/comment/main.php | 4 +- ext/cron_uploader/main.php | 4 +- ext/emoticons_list/main.php | 2 +- ext/eokm/main.php | 2 +- ext/et/main.php | 12 +- ext/favorites/main.php | 2 +- ext/featured/main.php | 2 +- ext/forum/main.php | 2 +- ext/graphql/main.php | 10 +- ext/handle_archive/main.php | 2 +- ext/handle_cbz/main.php | 2 +- ext/handle_ico/main.php | 8 +- ext/handle_svg/main.php | 8 +- ext/home/main.php | 2 +- ext/image/main.php | 99 ++++++++-------- ext/image_hash_ban/test.php | 7 +- ext/log_logstash/main.php | 2 +- ext/media/main.php | 11 +- ext/mime/mime_type.php | 4 +- ext/not_a_tag/test.php | 2 +- ext/notes/main.php | 16 +-- ext/notes/theme.php | 2 +- ext/numeric_score/main.php | 6 +- ext/numeric_score/theme.php | 4 +- ext/ouroboros_api/main.php | 10 +- ext/pools/main.php | 4 +- ext/post_lock/test.php | 10 +- ext/post_owner/test.php | 2 +- ext/post_source/main.php | 2 +- ext/post_source/test.php | 2 +- ext/post_tags/test.php | 4 +- ext/private_image/main.php | 10 +- ext/rating/main.php | 2 +- ext/rating/test.php | 14 +-- ext/regen_thumb/main.php | 2 +- ext/relationships/main.php | 4 +- ext/relationships/test.php | 44 +++---- ext/relationships/theme.php | 2 +- ext/replace_file/main.php | 13 +-- ext/replace_file/test.php | 8 +- ext/replace_file/theme.php | 2 +- ext/resize/main.php | 35 +++--- ext/rotate/main.php | 29 +++-- ext/rss_comments/main.php | 2 +- ext/rss_images/main.php | 2 +- ext/s3/main.php | 4 +- ext/setup/main.php | 9 +- ext/sitemap/main.php | 6 +- ext/static_files/main.php | 2 +- ext/tag_editcloud/main.php | 2 +- ext/tag_history/main.php | 5 +- ext/tag_history/test.php | 2 +- ext/tag_list/main.php | 6 +- ext/transcode/main.php | 20 ++-- ext/transcode_video/main.php | 18 ++- ext/upload/main.php | 4 +- ext/upload/test.php | 2 +- ext/view/main.php | 17 +-- ext/view/test.php | 11 +- tests/phpstan.neon | 2 + 79 files changed, 491 insertions(+), 382 deletions(-) diff --git a/composer.json b/composer.json index a525e48b..ede6c514 100644 --- a/composer.json +++ b/composer.json @@ -52,14 +52,16 @@ "sabre/cache": "^2.0.1", "naroga/redis-cache": "dev-master", "aws/aws-sdk-php": "^3.294", - "symfony/console": "6.4.x-dev" + "symfony/console": "6.4.x-dev", + "thecodingmachine/safe": "2.5.0" }, "require-dev" : { "phpunit/phpunit" : "10.5.3", "friendsofphp/php-cs-fixer" : "3.41.1", "scrutinizer/ocular": "1.9", - "phpstan/phpstan": "1.10.50" + "phpstan/phpstan": "1.10.50", + "thecodingmachine/phpstan-safe-rule": "^1.2" }, "suggest": { "ext-memcache": "memcache caching", diff --git a/composer.lock b/composer.lock index b7c1cc65..100f0fe2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cc4804abf9dc372f6dc18abd353bb0e2", + "content-hash": "81a9e4f6ce3456d5fb11270463967752", "packages": [ { "name": "aws/aws-crt-php", @@ -2302,6 +2302,145 @@ ], "time": "2024-01-19T13:57:07+00:00" }, + { + "name": "thecodingmachine/safe", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "reference": "3115ecd6b4391662b4931daac4eba6b07a2ac1f0", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "files": [ + "deprecated/apc.php", + "deprecated/array.php", + "deprecated/datetime.php", + "deprecated/libevent.php", + "deprecated/misc.php", + "deprecated/password.php", + "deprecated/mssql.php", + "deprecated/stats.php", + "deprecated/strings.php", + "lib/special_cases.php", + "deprecated/mysqli.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "deprecated/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v2.5.0" + }, + "time": "2023-04-05T11:54:14+00:00" + }, { "name": "webonyx/graphql-php", "version": "v15.8.1", @@ -5688,6 +5827,63 @@ ], "time": "2023-02-16T10:14:28+00:00" }, + { + "name": "thecodingmachine/phpstan-safe-rule", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/phpstan-safe-rule.git", + "reference": "8a7b88e0d54f209a488095085f183e9174c40e1e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/phpstan-safe-rule/zipball/8a7b88e0d54f209a488095085f183e9174c40e1e", + "reference": "8a7b88e0d54f209a488095085f183e9174c40e1e", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "phpstan/phpstan": "^1.0", + "thecodingmachine/safe": "^1.0 || ^2.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^7.5.2 || ^8.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + }, + "phpstan": { + "includes": [ + "phpstan-safe-rule.neon" + ] + } + }, + "autoload": { + "psr-4": { + "TheCodingMachine\\Safe\\PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David NĂ©grier", + "email": "d.negrier@thecodingmachine.com" + } + ], + "description": "A PHPStan rule to detect safety issues. Must be used in conjunction with thecodingmachine/safe", + "support": { + "issues": "https://github.com/thecodingmachine/phpstan-safe-rule/issues", + "source": "https://github.com/thecodingmachine/phpstan-safe-rule/tree/v1.2.0" + }, + "time": "2022-01-17T10:12:29+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.2", diff --git a/core/basepage.php b/core/basepage.php index 9580c135..b8ffffc9 100644 --- a/core/basepage.php +++ b/core/basepage.php @@ -308,7 +308,7 @@ class BasePage assert($this->file, "file should not be null with PageMode::FILE"); // https://gist.github.com/codler/3906826 - $size = filesize_ex($this->file); // File size + $size = \Safe\filesize($this->file); // File size $length = $size; // Content length $start = 0; // Start byte $end = $size - 1; // End byte diff --git a/core/dbengine.php b/core/dbengine.php index e71c18b5..6376bd5b 100644 --- a/core/dbengine.php +++ b/core/dbengine.php @@ -72,7 +72,7 @@ class MySQL extends DBEngine public function get_version(PDO $db): string { - return false_throws($db->query('select version()'))->fetch()[0]; + return $db->execute('select version()')->fetch()[0]; } } @@ -121,14 +121,14 @@ class PostgreSQL extends DBEngine public function get_version(PDO $db): string { - return false_throws($db->query('select version()'))->fetch()[0]; + return $db->execute('select version()')->fetch()[0]; } } // shimmie functions for export to sqlite function _unix_timestamp(string $date): int { - return strtotime_ex($date); + return \Safe\strtotime($date); } function _now(): string { @@ -228,6 +228,6 @@ class SQLite extends DBEngine public function get_version(PDO $db): string { - return false_throws($db->query('select sqlite_version()'))->fetch()[0]; + return $db->execute('select sqlite_version()')->fetch()[0]; } } diff --git a/core/extension.php b/core/extension.php index 0521cc7e..30b9fd71 100644 --- a/core/extension.php +++ b/core/extension.php @@ -334,7 +334,7 @@ abstract class DataHandlerExtension extends Extension throw new UploadException("Invalid or corrupted file"); } - $existing = Image::by_hash(md5_file_ex($event->tmpname)); + $existing = Image::by_hash(\Safe\md5_file($event->tmpname)); if (!is_null($existing)) { if ($config->get_string(ImageConfig::UPLOAD_COLLISION_HANDLER) == ImageConfig::COLLISION_MERGE) { // Right now tags are the only thing that get merged, so @@ -355,8 +355,8 @@ abstract class DataHandlerExtension extends Extension assert(is_readable($filename)); $image = new Image(); $image->tmp_file = $filename; - $image->filesize = filesize_ex($filename); - $image->hash = md5_file_ex($filename); + $image->filesize = \Safe\filesize($filename); + $image->hash = \Safe\md5_file($filename); $image->filename = (($pos = strpos($event->metadata['filename'], '?')) !== false) ? substr($event->metadata['filename'], 0, $pos) : $event->metadata['filename']; $image->set_mime(MimeType::get_for_file($filename, get_file_ext($event->metadata["filename"]) ?? null)); if (empty($image->get_mime())) { diff --git a/core/imageboard/image.php b/core/imageboard/image.php index 49457c4f..113b8ef4 100644 --- a/core/imageboard/image.php +++ b/core/imageboard/image.php @@ -175,6 +175,15 @@ class Image implements \ArrayAccess return ($row ? new Image($row) : null); } + public static function by_id_ex(int $post_id): Image + { + $maybe_post = static::by_id($post_id); + if(!is_null($maybe_post)) { + return $maybe_post; + } + throw new ImageNotFound("Image $post_id not found"); + } + public static function by_hash(string $hash): ?Image { global $database; diff --git a/core/polyfills.php b/core/polyfills.php index e078c1e7..6e5bc820 100644 --- a/core/polyfills.php +++ b/core/polyfills.php @@ -579,8 +579,8 @@ function parse_to_milliseconds(string $input): int */ 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', \Safe\strtotime($date)); + $hum = date('F j, Y; H:i', \Safe\strtotime($date)); return ($html ? "" : $hum); } @@ -677,7 +677,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", \Safe\strtotime(trim($value))); } elseif (in_array('string', $flags)) { if (in_array('trim', $flags)) { $value = trim($value); diff --git a/core/stdlib_ex.php b/core/stdlib_ex.php index 516d0ea0..3f9514ac 100644 --- a/core/stdlib_ex.php +++ b/core/stdlib_ex.php @@ -17,64 +17,7 @@ function false_throws(mixed $x, ?callable $errorgen = null): mixed return $x; } -/** - * @template T - * @param T|null $x - * @return T - */ -function null_throws(mixed $x, ?callable $errorgen = null): mixed -{ - if($x === null) { - $msg = "Unexpected null"; - if($errorgen) { - $msg = $errorgen(); - } - throw new \Exception($msg); - } - return $x; -} - -/** - * @param int<1,max> $depth - */ -function json_encode_ex(mixed $value, int|null $flags = 0, int $depth = 512): string -{ - return false_throws(json_encode($value, $flags, $depth), "json_last_error_msg"); -} - -function strtotime_ex(string $time, int|null $now = null): int -{ - return false_throws(strtotime($time, $now)); -} - -function md5_file_ex(string $filename, bool|null $raw_output = false): string -{ - return false_throws(md5_file($filename, $raw_output)); -} - -/** - * @return string[] - */ -function glob_ex(string $pattern, int|null $flags = 0): array -{ - return false_throws(glob($pattern, $flags)); -} - -function file_get_contents_ex(string $filename): string -{ - return false_throws(file_get_contents($filename)); -} - -function filesize_ex(string $filename): int -{ - return false_throws(filesize($filename)); -} - -function inet_ntop_ex(string $in_addr): string -{ - return false_throws(inet_ntop($in_addr)); -} - +# https://github.com/thecodingmachine/safe/pull/428 function inet_pton_ex(string $ip_address): string { return false_throws(inet_pton($ip_address)); @@ -85,11 +28,6 @@ function dir_ex(string $directory): \Directory return false_throws(dir($directory)); } -function exec_ex(string $command): string -{ - return false_throws(exec($command)); -} - function filter_var_ex(mixed $variable, int $filter = FILTER_DEFAULT, mixed $options = null): mixed { return false_throws(filter_var($variable, $filter, $options)); diff --git a/core/tests/ImageTest.php b/core/tests/ImageTest.php index 8c860a9a..523dae3b 100644 --- a/core/tests/ImageTest.php +++ b/core/tests/ImageTest.php @@ -12,7 +12,7 @@ class ImageTest extends ShimmiePHPUnitTestCase { $this->log_in_as_user(); $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "question? colon:thing exclamation!"); - $image = Image::by_id($image_id_1); + $image = Image::by_id_ex($image_id_1); $this->assertNull($image->source); } } diff --git a/core/tests/StdLibExTest.php b/core/tests/StdLibExTest.php index c6a3476c..004cd568 100644 --- a/core/tests/StdLibExTest.php +++ b/core/tests/StdLibExTest.php @@ -10,14 +10,14 @@ class StdLibExTest extends ShimmiePHPUnitTestCase { $this->assertEquals( '{"a":1,"b":2,"c":3,"d":4,"e":5}', - json_encode_ex(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]) + \Safe\json_encode(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]) ); } public function testJsonEncodeError(): void { $e = $this->assertException(\Exception::class, function () { - json_encode_ex("\xB1\x31"); + \Safe\json_encode("\xB1\x31"); }); $this->assertEquals( "Malformed UTF-8 characters, possibly incorrectly encoded", diff --git a/core/util.php b/core/util.php index ce23f913..56338e0f 100644 --- a/core/util.php +++ b/core/util.php @@ -194,7 +194,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 = \Safe\inet_ntop(inet_pton_ex($addr) & inet_pton_ex($mask)); return $addr; } @@ -299,7 +299,7 @@ function fetch_url(string $url, string $mfile): array 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 = \Safe\fopen($mfile, "w"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); # curl_setopt($ch, CURLOPT_VERBOSE, 1); @@ -318,7 +318,7 @@ function fetch_url(string $url, string $mfile): array $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", \Safe\preg_split('/\R/', $header_text))); $body = substr($response, $header_size); curl_close($ch); @@ -340,7 +340,7 @@ function fetch_url(string $url, string $mfile): array } $length = 0; while (!feof($fp_in) && $length <= $config->get_int(UploadConfig::SIZE)) { - $data = false_throws(fread($fp_in, 8192)); + $data = \Safe\fread($fp_in, 8192); $length += strlen($data); fwrite($fp_out, $data); } @@ -421,7 +421,7 @@ function get_dir_contents(string $dir): array return []; } return array_diff( - false_throws(scandir($dir)), + \Safe\scandir($dir), ['..', '.'] ); } @@ -783,6 +783,6 @@ 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)); + $temp = \Safe\realpath("data/temp"); + return \Safe\tempnam($temp, $prefix); } diff --git a/ext/alias_editor/main.php b/ext/alias_editor/main.php index bb184935..1957ff66 100644 --- a/ext/alias_editor/main.php +++ b/ext/alias_editor/main.php @@ -97,7 +97,7 @@ class AliasEditor extends Extension if ($event->page_matches("alias/import", method: "POST", permission: Permissions::MANAGE_ALIAS_LIST)) { if (count($_FILES) > 0) { $tmp = $_FILES['alias_file']['tmp_name']; - $contents = file_get_contents_ex($tmp); + $contents = \Safe\file_get_contents($tmp); $this->add_alias_csv($contents); log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many? $page->set_mode(PageMode::REDIRECT); diff --git a/ext/artists/test.php b/ext/artists/test.php index 36bdaed8..2154a092 100644 --- a/ext/artists/test.php +++ b/ext/artists/test.php @@ -11,7 +11,7 @@ class ArtistsTest extends ShimmiePHPUnitTestCase global $user; $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); send_event(new AuthorSetEvent($image, $user, "bob")); diff --git a/ext/auto_tagger/main.php b/ext/auto_tagger/main.php index 71e4173a..eca01d14 100644 --- a/ext/auto_tagger/main.php +++ b/ext/auto_tagger/main.php @@ -103,7 +103,7 @@ class AutoTagger extends Extension if ($event->page_matches("auto_tag/import", method: "POST", permission: Permissions::MANAGE_AUTO_TAG)) { if (count($_FILES) > 0) { $tmp = $_FILES['auto_tag_file']['tmp_name']; - $contents = file_get_contents_ex($tmp); + $contents = \Safe\file_get_contents($tmp); $count = $this->add_auto_tag_csv($contents); log_info(AutoTaggerInfo::KEY, "Imported $count auto-tag definitions from file from file", "Imported $count auto-tag definitions"); $page->set_mode(PageMode::REDIRECT); @@ -243,7 +243,7 @@ class AutoTagger extends Extension $image_ids = $database->get_col_iterable("SELECT image_id FROM image_tags WHERE tag_id = :tag_id", ["tag_id" => $tag_id]); foreach ($image_ids as $image_id) { $image_id = (int) $image_id; - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); send_event(new TagSetEvent($image, $image->get_tag_array())); } } diff --git a/ext/autocomplete/main.php b/ext/autocomplete/main.php index 830e9bc2..f57e85fe 100644 --- a/ext/autocomplete/main.php +++ b/ext/autocomplete/main.php @@ -23,7 +23,7 @@ class AutoComplete extends Extension $page->set_mode(PageMode::DATA); $page->set_mime(MimeType::JSON); - $page->set_data(json_encode_ex($res)); + $page->set_data(\Safe\json_encode($res)); } } diff --git a/ext/blotter/theme.php b/ext/blotter/theme.php index 504ed843..5c076b71 100644 --- a/ext/blotter/theme.php +++ b/ext/blotter/theme.php @@ -140,7 +140,7 @@ class BlotterTheme extends Themelet $i_close = ""; //$id = $entries[$i]['id']; $messy_date = $entries[$i]['entry_date']; - $clean_date = date("y/m/d", strtotime_ex($messy_date)); + $clean_date = date("y/m/d", \Safe\strtotime($messy_date)); $entry_text = $entries[$i]['entry_text']; if ($entries[$i]['important'] == 'Y') { $i_open = ""; @@ -170,7 +170,7 @@ class BlotterTheme extends Themelet $i_close = ""; //$id = $entry['id']; $messy_date = $entry['entry_date']; - $clean_date = date("m/d/y", strtotime_ex($messy_date)); + $clean_date = date("m/d/y", \Safe\strtotime($messy_date)); $entry_text = $entry['entry_text']; if ($entry['important'] == 'Y') { $i_open = ""; @@ -191,7 +191,7 @@ class BlotterTheme extends Themelet $out_text = "No blotter entries yet."; $in_text = "Empty."; } else { - $clean_date = date("m/d/y", strtotime_ex($entries[0]['entry_date'])); + $clean_date = date("m/d/y", \Safe\strtotime($entries[0]['entry_date'])); $out_text = "Blotter updated: {$clean_date}"; $in_text = "
    $entries_list
"; } diff --git a/ext/browser_search/main.php b/ext/browser_search/main.php index 88a632d2..74a5e971 100644 --- a/ext/browser_search/main.php +++ b/ext/browser_search/main.php @@ -28,7 +28,7 @@ class BrowserSearch extends Extension $search_title = $config->get_string(SetupConfig::TITLE); $search_form_url = search_link(['{searchTerms}']); $suggenton_url = make_link('browser_search/')."{searchTerms}"; - $icon_b64 = base64_encode(file_get_contents_ex("ext/static_files/static/favicon.ico")); + $icon_b64 = base64_encode(\Safe\file_get_contents("ext/static_files/static/favicon.ico")); // Now for the XML $xml = " @@ -71,7 +71,7 @@ class BrowserSearch extends Extension // And to do stuff with it. We want our output to look like: // ["shimmie",["shimmies","shimmy","shimmie","21 shimmies","hip shimmies","skea shimmies"],[],[]] $page->set_mode(PageMode::DATA); - $page->set_data(json_encode_ex([$tag_search, $tags, [], []])); + $page->set_data(\Safe\json_encode([$tag_search, $tags, [], []])); } } diff --git a/ext/bulk_add_csv/main.php b/ext/bulk_add_csv/main.php index 1c6dd51a..ec668da6 100644 --- a/ext/bulk_add_csv/main.php +++ b/ext/bulk_add_csv/main.php @@ -86,7 +86,7 @@ class BulkAddCSV extends Extension $linenum = 1; $list = ""; - $csvhandle = false_throws(fopen($csvfile, "r")); + $csvhandle = \Safe\fopen($csvfile, "r"); while (($csvdata = fgetcsv($csvhandle, 0, ",")) !== false) { if (count($csvdata) != 5) { diff --git a/ext/bulk_import_export/main.php b/ext/bulk_import_export/main.php index f3b41fae..0b614024 100644 --- a/ext/bulk_import_export/main.php +++ b/ext/bulk_import_export/main.php @@ -126,7 +126,7 @@ class BulkImportExport extends DataHandlerExtension $zip->addFile($img_loc, $image->hash); } - $json_data = json_encode_ex($json_data, JSON_PRETTY_PRINT); + $json_data = \Safe\json_encode($json_data, JSON_PRETTY_PRINT); $zip->addFromString(self::EXPORT_INFO_FILE_NAME, $json_data); $zip->close(); @@ -163,7 +163,7 @@ class BulkImportExport extends DataHandlerExtension $info = $zip->getStream(self::EXPORT_INFO_FILE_NAME); if ($info !== false) { try { - $json_string = false_throws(stream_get_contents($info)); + $json_string = \Safe\stream_get_contents($info); $json_data = json_decode($json_string); return $json_data; } finally { diff --git a/ext/comment/main.php b/ext/comment/main.php index cbfb87e3..0069864c 100644 --- a/ext/comment/main.php +++ b/ext/comment/main.php @@ -320,7 +320,7 @@ class CommentList extends Extension public function onUserPageBuilding(UserPageBuildingEvent $event): void { - $i_days_old = ((time() - strtotime_ex($event->display_user->join_date)) / 86400) + 1; + $i_days_old = ((time() - \Safe\strtotime($event->display_user->join_date)) / 86400) + 1; $i_comment_count = Comment::count_comments_by_user($event->display_user); $h_comment_rate = sprintf("%.1f", ($i_comment_count / $i_days_old)); $event->add_stats("Comments made: $i_comment_count, $h_comment_rate per day"); @@ -597,7 +597,7 @@ class CommentList extends Extension } // advanced sanity checks - elseif (strlen($comment) / strlen(false_throws(gzcompress($comment))) > 10) { + elseif (strlen($comment) / strlen(\Safe\gzcompress($comment)) > 10) { throw new CommentPostingException("Comment too repetitive~"); } elseif ($user->is_anonymous() && ($_POST['hash'] != $this->get_hash())) { $page->add_cookie("nocache", "Anonymous Commenter", time() + 60 * 60 * 24, "/"); diff --git a/ext/cron_uploader/main.php b/ext/cron_uploader/main.php index bcfb0f3a..5970c559 100644 --- a/ext/cron_uploader/main.php +++ b/ext/cron_uploader/main.php @@ -231,7 +231,7 @@ class CronUploader extends Extension $running = false; - $lockfile = false_throws(fopen($this->get_lock_file(), "w")); + $lockfile = \Safe\fopen($this->get_lock_file(), "w"); try { if (!flock($lockfile, LOCK_EX | LOCK_NB)) { $running = true; @@ -339,7 +339,7 @@ class CronUploader extends Extension throw new PermissionDenied("User does not have permission to run cron upload"); } - $lockfile = false_throws(fopen($this->get_lock_file(), "w")); + $lockfile = \Safe\fopen($this->get_lock_file(), "w"); if (!flock($lockfile, LOCK_EX | LOCK_NB)) { throw new ServerError("Cron upload process is already running"); } diff --git a/ext/emoticons_list/main.php b/ext/emoticons_list/main.php index a0dd7271..b3d12a38 100644 --- a/ext/emoticons_list/main.php +++ b/ext/emoticons_list/main.php @@ -15,7 +15,7 @@ class EmoticonList extends Extension public function onPageRequest(PageRequestEvent $event): void { if ($event->page_matches("emote/list")) { - $this->theme->display_emotes(glob_ex("ext/emoticons/default/*")); + $this->theme->display_emotes(\Safe\glob("ext/emoticons/default/*")); } } } diff --git a/ext/eokm/main.php b/ext/eokm/main.php index dd1e9f52..0ad5b266 100644 --- a/ext/eokm/main.php +++ b/ext/eokm/main.php @@ -18,7 +18,7 @@ class Eokm extends Extension $password = $config->get_string("eokm_password"); if ($username && $password) { - $ch = false_throws(curl_init("https://api.eokmhashdb.nl/v1/check/md5")); + $ch = \Safe\curl_init("https://api.eokmhashdb.nl/v1/check/md5"); // curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/xml', $additionalHeaders)); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $password); diff --git a/ext/et/main.php b/ext/et/main.php index 54e4e252..7dac4f15 100644 --- a/ext/et/main.php +++ b/ext/et/main.php @@ -77,8 +77,8 @@ class ET extends Extension $ver .= "+"; } - $disk_total = false_throws(disk_total_space("./")); - $disk_free = false_throws(disk_free_space("./")); + $disk_total = \Safe\disk_total_space("./"); + $disk_free = \Safe\disk_free_space("./"); $info = [ "about" => [ 'title' => $config->get_string(SetupConfig::TITLE), @@ -120,9 +120,9 @@ class ET extends Extension if (file_exists(".git")) { try { - $commitHash = trim(exec_ex('git log --pretty="%h" -n1 HEAD')); - $commitBranch = trim(exec_ex('git rev-parse --abbrev-ref HEAD')); - $commitOrigin = trim(exec_ex('git config --get remote.origin.url')); + $commitHash = trim(\Safe\exec('git log --pretty="%h" -n1 HEAD')); + $commitBranch = trim(\Safe\exec('git rev-parse --abbrev-ref HEAD')); + $commitOrigin = trim(\Safe\exec('git config --get remote.origin.url')); $commitOrigin = preg_replace("#//.*@#", "//xxx@", $commitOrigin); $info['versions']['shimmie'] .= $commitHash; $info['versions']['origin'] = "$commitOrigin ($commitBranch)"; @@ -148,7 +148,7 @@ class ET extends Extension foreach ($info as $title => $section) { $data .= "$title:\n"; foreach ($section as $k => $v) { - $data .= " $k: " . json_encode_ex($v, JSON_UNESCAPED_SLASHES) . "\n"; + $data .= " $k: " . \Safe\json_encode($v, JSON_UNESCAPED_SLASHES) . "\n"; } $data .= "\n"; } diff --git a/ext/favorites/main.php b/ext/favorites/main.php index 877c7c21..afdd58c3 100644 --- a/ext/favorites/main.php +++ b/ext/favorites/main.php @@ -84,7 +84,7 @@ class Favorites extends Extension public function onUserPageBuilding(UserPageBuildingEvent $event): void { $i_favorites_count = Search::count_images(["favorited_by={$event->display_user->name}"]); - $i_days_old = ((time() - strtotime_ex($event->display_user->join_date)) / 86400) + 1; + $i_days_old = ((time() - \Safe\strtotime($event->display_user->join_date)) / 86400) + 1; $h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old)); $favorites_link = search_link(["favorited_by={$event->display_user->name}"]); $event->add_stats("Posts favorited: $i_favorites_count, $h_favorites_rate per day"); diff --git a/ext/featured/main.php b/ext/featured/main.php index a7c6a470..8f684a52 100644 --- a/ext/featured/main.php +++ b/ext/featured/main.php @@ -30,7 +30,7 @@ class Featured extends Extension if (!is_null($image)) { $page->set_mode(PageMode::DATA); $page->set_mime($image->get_mime()); - $page->set_data(file_get_contents_ex($image->get_image_filename())); + $page->set_data(\Safe\file_get_contents($image->get_image_filename())); } } if ($event->page_matches("featured_image/view")) { diff --git a/ext/forum/main.php b/ext/forum/main.php index c908f01f..ec7a8c96 100644 --- a/ext/forum/main.php +++ b/ext/forum/main.php @@ -82,7 +82,7 @@ class Forum extends Extension $threads_count = $database->get_one("SELECT COUNT(*) FROM forum_threads WHERE user_id=:user_id", ['user_id' => $event->display_user->id]); $posts_count = $database->get_one("SELECT COUNT(*) FROM forum_posts WHERE user_id=:user_id", ['user_id' => $event->display_user->id]); - $days_old = ((time() - strtotime_ex($event->display_user->join_date)) / 86400) + 1; + $days_old = ((time() - \Safe\strtotime($event->display_user->join_date)) / 86400) + 1; $threads_rate = sprintf("%.1f", ($threads_count / $days_old)); $posts_rate = sprintf("%.1f", ($posts_count / $days_old)); diff --git a/ext/graphql/main.php b/ext/graphql/main.php index 1db6ab1a..bc394af0 100644 --- a/ext/graphql/main.php +++ b/ext/graphql/main.php @@ -29,14 +29,14 @@ class MetadataInput public static function update_post_metadata(int $post_id, MetadataInput $metadata): Image { global $user; - $image = Image::by_id($post_id); + $image = Image::by_id_ex($post_id); if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) { send_event(new ImageInfoSetEvent($image, [ 'tags' => $metadata->tags, 'source' => $metadata->source, ])); } - return Image::by_id($post_id); + return Image::by_id_ex($post_id); } } @@ -108,13 +108,13 @@ class GraphQL extends Extension // sleep(1); $page->set_mode(PageMode::DATA); $page->set_mime("application/json"); - $page->set_data(json_encode_ex($body, JSON_UNESCAPED_UNICODE)); + $page->set_data(\Safe\json_encode($body, JSON_UNESCAPED_UNICODE)); } if ($event->page_matches("graphql_upload")) { $this->cors(); $page->set_mode(PageMode::DATA); $page->set_mime("application/json"); - $page->set_data(json_encode_ex(self::handle_uploads())); + $page->set_data(\Safe\json_encode(self::handle_uploads())); } } @@ -203,7 +203,7 @@ class GraphQL extends Extension $body['stats'] = get_debug_info_arr(); $body['stats']['graphql_schema_time'] = round($t2 - $t1, 2); $body['stats']['graphql_execute_time'] = round($t3 - $t2, 2); - echo json_encode_ex($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + echo \Safe\json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); return Command::SUCCESS; }); $event->app->register('graphql:schema') diff --git a/ext/handle_archive/main.php b/ext/handle_archive/main.php index 5d1fa85a..d940f862 100644 --- a/ext/handle_archive/main.php +++ b/ext/handle_archive/main.php @@ -41,7 +41,7 @@ class ArchiveFileHandler extends DataHandlerExtension $page->flash($r->name." failed: ".$r->error); } if(is_a($r, UploadSuccess::class)) { - $event->images[] = Image::by_id($r->image_id); + $event->images[] = Image::by_id_ex($r->image_id); } } } finally { diff --git a/ext/handle_cbz/main.php b/ext/handle_cbz/main.php index c160d52b..cbcfa832 100644 --- a/ext/handle_cbz/main.php +++ b/ext/handle_cbz/main.php @@ -39,7 +39,7 @@ class CBZFileHandler extends DataHandlerExtension protected function check_contents(string $tmpname): bool { - $fp = false_throws(fopen($tmpname, "r")); + $fp = \Safe\fopen($tmpname, "r"); $head = fread($fp, 4); fclose($fp); return $head == "PK\x03\x04"; diff --git a/ext/handle_ico/main.php b/ext/handle_ico/main.php index 145857a7..969d369f 100644 --- a/ext/handle_ico/main.php +++ b/ext/handle_ico/main.php @@ -15,10 +15,10 @@ class IcoFileHandler extends DataHandlerExtension $event->image->audio = false; $event->image->image = ($event->image->get_mime() != MimeType::ANI); - $fp = false_throws(fopen($event->image->get_image_filename(), "r")); + $fp = \Safe\fopen($event->image->get_image_filename(), "r"); try { fseek($fp, 6); // skip header - $subheader = false_throws(unpack("Cwidth/Cheight/Ccolours/Cnull/Splanes/Sbpp/Lsize/loffset", false_throws(fread($fp, 16)))); + $subheader = \Safe\unpack("Cwidth/Cheight/Ccolours/Cnull/Splanes/Sbpp/Lsize/loffset", \Safe\fread($fp, 16)); $width = $subheader['width']; $height = $subheader['height']; $event->image->width = $width == 0 ? 256 : $width; @@ -41,8 +41,8 @@ class IcoFileHandler extends DataHandlerExtension protected function check_contents(string $tmpname): bool { - $fp = false_throws(fopen($tmpname, "r")); - $header = false_throws(unpack("Snull/Stype/Scount", false_throws(fread($fp, 6)))); + $fp = \Safe\fopen($tmpname, "r"); + $header = \Safe\unpack("Snull/Stype/Scount", \Safe\fread($fp, 6)); fclose($fp); return ($header['null'] == 0 && ($header['type'] == 0 || $header['type'] == 1)); } diff --git a/ext/handle_svg/main.php b/ext/handle_svg/main.php index 6af7e031..b9eafe23 100644 --- a/ext/handle_svg/main.php +++ b/ext/handle_svg/main.php @@ -18,7 +18,7 @@ class SVGFileHandler extends DataHandlerExtension global $page; if ($event->page_matches("get_svg/{id}")) { $id = $event->get_iarg('id'); - $image = Image::by_id($id); + $image = Image::by_id_ex($id); $hash = $image->hash; $page->set_mime(MimeType::SVG); @@ -26,7 +26,7 @@ class SVGFileHandler extends DataHandlerExtension $sanitizer = new Sanitizer(); $sanitizer->removeRemoteReferences(true); - $dirtySVG = file_get_contents_ex(warehouse_path(Image::IMAGE_DIR, $hash)); + $dirtySVG = \Safe\file_get_contents(warehouse_path(Image::IMAGE_DIR, $hash)); $cleanSVG = $sanitizer->sanitize($dirtySVG); $page->set_data($cleanSVG); } @@ -41,7 +41,7 @@ class SVGFileHandler extends DataHandlerExtension // then sanitise it before touching it $sanitizer = new Sanitizer(); $sanitizer->removeRemoteReferences(true); - $dirtySVG = file_get_contents_ex($event->tmpname); + $dirtySVG = \Safe\file_get_contents($event->tmpname); $cleanSVG = false_throws($sanitizer->sanitize($dirtySVG)); $event->hash = md5($cleanSVG); $new_tmpname = shm_tempnam("svg"); @@ -103,7 +103,7 @@ class MiniSVGParser { $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, [$this, "startElement"], [$this, "endElement"]); - $this->valid = bool_escape(xml_parse($xml_parser, file_get_contents_ex($file), true)); + $this->valid = bool_escape(xml_parse($xml_parser, \Safe\file_get_contents($file), true)); xml_parser_free($xml_parser); } diff --git a/ext/home/main.php b/ext/home/main.php index 7731205d..c1fcb2ef 100644 --- a/ext/home/main.php +++ b/ext/home/main.php @@ -28,7 +28,7 @@ class Home extends Extension $counters = []; $counters["None"] = "none"; $counters["Text-only"] = "text-only"; - foreach (glob_ex("ext/home/counters/*") as $counter_dirname) { + foreach (\Safe\glob("ext/home/counters/*") as $counter_dirname) { $name = str_replace("ext/home/counters/", "", $counter_dirname); $counters[ucfirst($name)] = $name; } diff --git a/ext/image/main.php b/ext/image/main.php index 05de0ede..21700213 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -131,7 +131,7 @@ class ImageIO extends Extension ->setDescription('Delete a specific post') ->setCode(function (InputInterface $input, OutputInterface $output): int { $post_id = (int)$input->getArgument('id'); - $image = Image::by_id($post_id); + $image = Image::by_id_ex($post_id); send_event(new ImageDeletionEvent($image)); return Command::SUCCESS; }); @@ -152,7 +152,7 @@ class ImageIO extends Extension { $u_name = url_escape($event->display_user->name); $i_image_count = Search::count_images(["user={$event->display_user->name}"]); - $i_days_old = ((time() - strtotime_ex($event->display_user->join_date)) / 86400) + 1; + $i_days_old = ((time() - \Safe\strtotime($event->display_user->join_date)) / 86400) + 1; $h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old)); $images_link = search_link(["user=$u_name"]); $event->add_stats("Posts uploaded: $i_image_count, $h_image_rate per day"); @@ -226,60 +226,51 @@ class ImageIO extends Extension { global $config, $page; - $image = Image::by_id($image_id); - if (!is_null($image)) { - if ($type == "thumb") { - $mime = $config->get_string(ImageConfig::THUMB_MIME); - $file = $image->get_thumb_filename(); - } else { - $mime = $image->get_mime(); - $file = $image->get_image_filename(); - } - if (!file_exists($file)) { - http_response_code(404); - die(); - } + $image = Image::by_id_ex($image_id); - $page->set_mime($mime); - - - if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { - $if_modified_since = preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]); - } else { - $if_modified_since = ""; - } - $gmdate_mod = gmdate('D, d M Y H:i:s', false_throws(filemtime($file))) . ' GMT'; - - if ($if_modified_since == $gmdate_mod) { - $page->set_mode(PageMode::DATA); - $page->set_code(304); - $page->set_data(""); - } else { - $page->set_mode(PageMode::FILE); - $page->add_http_header("Last-Modified: $gmdate_mod"); - if ($type != "thumb") { - $page->set_filename($image->get_nice_image_name(), 'inline'); - } - - $page->set_file($file); - - if ($config->get_int(ImageConfig::EXPIRES)) { - $expires = date(DATE_RFC1123, time() + $config->get_int(ImageConfig::EXPIRES)); - } else { - $expires = 'Fri, 2 Sep 2101 12:42:42 GMT'; // War was beginning - } - $page->add_http_header('Expires: ' . $expires); - } - - send_event(new ImageDownloadingEvent($image, $file, $mime, $params)); + if ($type == "thumb") { + $mime = $config->get_string(ImageConfig::THUMB_MIME); + $file = $image->get_thumb_filename(); } else { - $page->set_title("Not Found"); - $page->set_heading("Not Found"); - $page->add_block(new Block("Navigation", "Index", "left", 0)); - $page->add_block(new Block( - "Post not in database", - "The requested image was not found in the database" - )); + $mime = $image->get_mime(); + $file = $image->get_image_filename(); } + if (!file_exists($file)) { + http_response_code(404); + die(); + } + + $page->set_mime($mime); + + + if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) { + $if_modified_since = preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]); + } else { + $if_modified_since = ""; + } + $gmdate_mod = gmdate('D, d M Y H:i:s', \Safe\filemtime($file)) . ' GMT'; + + if ($if_modified_since == $gmdate_mod) { + $page->set_mode(PageMode::DATA); + $page->set_code(304); + $page->set_data(""); + } else { + $page->set_mode(PageMode::FILE); + $page->add_http_header("Last-Modified: $gmdate_mod"); + if ($type != "thumb") { + $page->set_filename($image->get_nice_image_name(), 'inline'); + } + + $page->set_file($file); + + if ($config->get_int(ImageConfig::EXPIRES)) { + $expires = date(DATE_RFC1123, time() + $config->get_int(ImageConfig::EXPIRES)); + } else { + $expires = 'Fri, 2 Sep 2101 12:42:42 GMT'; // War was beginning + } + $page->add_http_header('Expires: ' . $expires); + } + + send_event(new ImageDownloadingEvent($image, $file, $mime, $params)); } } diff --git a/ext/image_hash_ban/test.php b/ext/image_hash_ban/test.php index 9ad35fde..e791b4a6 100644 --- a/ext/image_hash_ban/test.php +++ b/ext/image_hash_ban/test.php @@ -26,11 +26,12 @@ class ImageBanTest extends ShimmiePHPUnitTestCase // Ban & delete send_event(new AddImageHashBanEvent($this->hash, "test hash ban")); - send_event(new ImageDeletionEvent(Image::by_id($image_id), true)); + send_event(new ImageDeletionEvent(Image::by_id_ex($image_id), true)); // Check deleted - $page = $this->get_page("post/view/$image_id"); - $this->assertEquals(404, $page->code); + $this->assertException(ImageNotFound::class, function () use ($image_id) { + $this->get_page("post/view/$image_id"); + }); // Can't repost $this->assertException(UploadException::class, function () { diff --git a/ext/log_logstash/main.php b/ext/log_logstash/main.php index 33cc2c69..cdc53214 100644 --- a/ext/log_logstash/main.php +++ b/ext/log_logstash/main.php @@ -59,7 +59,7 @@ class LogLogstash extends Extension if (!$fp) { return; } - fwrite($fp, json_encode_ex($data)); + fwrite($fp, \Safe\json_encode($data)); fclose($fp); } catch (\Exception $e) { // we can't log that logging is broken diff --git a/ext/media/main.php b/ext/media/main.php index e932002c..aeacad12 100644 --- a/ext/media/main.php +++ b/ext/media/main.php @@ -79,7 +79,7 @@ class Media extends Extension global $page, $user; if ($event->page_matches("media_rescan/{image_id}", method: "POST", permission: Permissions::RESCAN_MEDIA)) { - $image = Image::by_id($event->get_iarg('image_id')); + $image = Image::by_id_ex($event->get_iarg('image_id')); send_event(new MediaCheckPropertiesEvent($image)); $image->save_to_db(); @@ -702,7 +702,7 @@ class Media extends Extension $new_width = $width; } - $image = imagecreatefromstring(file_get_contents_ex($image_filename)); + $image = imagecreatefromstring(\Safe\file_get_contents($image_filename)); if ($image === false) { throw new MediaException("Could not load image: " . $image_filename); } @@ -850,7 +850,12 @@ class Media extends Extension "-y", "-i", escapeshellarg($filename), "-vstats" ])); - $output = null_throws(false_throws(shell_exec($cmd . " 2>&1"))); + // \Safe\shell_exec is a little broken + // https://github.com/thecodingmachine/safe/issues/281 + $output = shell_exec($cmd . " 2>&1"); + if(is_null($output) || $output === false) { + throw new MediaException("Failed to execute command: $cmd"); + } // error_log("Getting size with `$cmd`"); $regex_sizes = "/Video: .* ([0-9]{1,4})x([0-9]{1,4})/"; diff --git a/ext/mime/mime_type.php b/ext/mime/mime_type.php index 198eae7f..05623bc0 100644 --- a/ext/mime/mime_type.php +++ b/ext/mime/mime_type.php @@ -159,7 +159,7 @@ class MimeType */ private static function compare_file_bytes(string $file_name, array $comparison): bool { - $size = filesize_ex($file_name); + $size = \Safe\filesize($file_name); $cc = count($comparison); if ($size < $cc) { // Can't match because it's too small @@ -168,7 +168,7 @@ class MimeType if (($fh = @fopen($file_name, 'rb'))) { try { - $chunk = false_throws(unpack("C*", false_throws(fread($fh, $cc)))); + $chunk = \Safe\unpack("C*", \Safe\fread($fh, $cc)); for ($i = 0; $i < $cc; $i++) { $byte = $comparison[$i]; diff --git a/ext/not_a_tag/test.php b/ext/not_a_tag/test.php index eae7fd44..d0939b82 100644 --- a/ext/not_a_tag/test.php +++ b/ext/not_a_tag/test.php @@ -14,7 +14,7 @@ class NotATagTest extends ShimmiePHPUnitTestCase $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); // Original $this->get_page("post/view/$image_id"); diff --git a/ext/notes/main.php b/ext/notes/main.php index 94fcf1f0..21b362ef 100644 --- a/ext/notes/main.php +++ b/ext/notes/main.php @@ -119,7 +119,7 @@ class Notes extends Extension $page->set_mode(PageMode::DATA); if (!$user->can(Permissions::NOTES_CREATE)) { $note_id = $this->add_new_note(); - $page->set_data(json_encode_ex([ + $page->set_data(\Safe\json_encode([ 'status' => 'success', 'note_id' => $note_id, ])); @@ -129,14 +129,14 @@ class Notes extends Extension $page->set_mode(PageMode::DATA); if (!$user->can(Permissions::NOTES_EDIT)) { $this->update_note(); - $page->set_data(json_encode_ex(['status' => 'success'])); + $page->set_data(\Safe\json_encode(['status' => 'success'])); } } if ($event->page_matches("note/delete_note")) { $page->set_mode(PageMode::DATA); if ($user->can(Permissions::NOTES_ADMIN)) { $this->delete_note(); - $page->set_data(json_encode_ex(['status' => 'success'])); + $page->set_data(\Safe\json_encode(['status' => 'success'])); } } if ($event->page_matches("note/nuke_notes")) { @@ -243,7 +243,7 @@ class Notes extends Extension { global $database, $user; - $note = json_decode(file_get_contents_ex('php://input'), true); + $note = json_decode(\Safe\file_get_contents('php://input'), true); $database->execute( " @@ -304,7 +304,7 @@ class Notes extends Extension { global $database; - $note = json_decode(file_get_contents_ex('php://input'), true); + $note = json_decode(\Safe\file_get_contents('php://input'), true); // validate parameters if (empty($note['note'])) { @@ -323,7 +323,7 @@ class Notes extends Extension { global $user, $database; - $note = json_decode(file_get_contents_ex('php://input'), true); + $note = json_decode(\Safe\file_get_contents('php://input'), true); $database->execute(" UPDATE notes SET enable = :enable WHERE image_id = :image_id AND id = :id @@ -367,7 +367,7 @@ class Notes extends Extension $images = []; foreach ($image_ids as $id) { - $images[] = Image::by_id($id); + $images[] = Image::by_id_ex($id); } $this->theme->display_note_list($images, $pageNumber + 1, $totalPages); @@ -393,7 +393,7 @@ class Notes extends Extension $images = []; while ($row = $result->fetch()) { - $images[] = Image::by_id($row["image_id"]); + $images[] = Image::by_id_ex($row["image_id"]); } $this->theme->display_note_requests($images, $pageNumber + 1, $totalPages); diff --git a/ext/notes/theme.php b/ext/notes/theme.php index a0ec94af..169c0444 100644 --- a/ext/notes/theme.php +++ b/ext/notes/theme.php @@ -62,7 +62,7 @@ class NotesTheme extends Themelet ]; } $page->add_html_header(""); diff --git a/ext/numeric_score/main.php b/ext/numeric_score/main.php index 4a54b879..97aa6137 100644 --- a/ext/numeric_score/main.php +++ b/ext/numeric_score/main.php @@ -20,7 +20,7 @@ class NumericScoreVote #[Field] public function post(): Image { - return Image::by_id($this->image_id); + return Image::by_id_ex($this->image_id); } #[Field] @@ -205,13 +205,13 @@ class NumericScore extends Extension if ($event->page_matches("popular_by_day")) { $sql .= " AND EXTRACT(MONTH FROM posted) = :month AND EXTRACT(DAY FROM posted) = :day"; $args = array_merge($args, ["month" => $month, "day" => $day]); - $current = date("F jS, Y", strtotime_ex($totaldate)). + $current = date("F jS, Y", \Safe\strtotime($totaldate)). $name = "day"; $fmt = "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d"; } elseif ($event->page_matches("popular_by_month")) { $sql .= " AND EXTRACT(MONTH FROM posted) = :month"; $args = array_merge($args, ["month" => $month]); - $current = date("F Y", strtotime_ex($totaldate)); + $current = date("F Y", \Safe\strtotime($totaldate)); $name = "month"; $fmt = "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m"; } elseif ($event->page_matches("popular_by_year")) { diff --git a/ext/numeric_score/theme.php b/ext/numeric_score/theme.php index 5d181c33..a8a04d6f 100644 --- a/ext/numeric_score/theme.php +++ b/ext/numeric_score/theme.php @@ -73,8 +73,8 @@ class NumericScoreTheme extends Themelet $pop_images .= $this->build_thumb_html($image)."\n"; } - $b_dte = make_link("popular_by_$name", date($fmt, strtotime_ex("-1 $name", strtotime_ex($totaldate)))); - $f_dte = make_link("popular_by_$name", date($fmt, strtotime_ex("+1 $name", strtotime_ex($totaldate)))); + $b_dte = make_link("popular_by_$name", date($fmt, \Safe\strtotime("-1 $name", \Safe\strtotime($totaldate)))); + $f_dte = make_link("popular_by_$name", date($fmt, \Safe\strtotime("+1 $name", \Safe\strtotime($totaldate)))); $html = "\n". "

\n". diff --git a/ext/ouroboros_api/main.php b/ext/ouroboros_api/main.php index e74d156d..91fb848b 100644 --- a/ext/ouroboros_api/main.php +++ b/ext/ouroboros_api/main.php @@ -69,7 +69,7 @@ class _SafeOuroborosImage // meta $this->change = intval($img->id); //DaFug is this even supposed to do? ChangeID? // Should be JSON specific, just strip this when converting to XML - $this->created_at = ['n' => 123456789, 's' => strtotime_ex($img->posted), 'json_class' => 'Time']; + $this->created_at = ['n' => 123456789, 's' => \Safe\strtotime($img->posted), 'json_class' => 'Time']; $this->id = intval($img->id); $this->parent_id = null; @@ -409,7 +409,7 @@ class OuroborosAPI extends Extension protected function postShow(int $id = null): void { if (!is_null($id)) { - $post = new _SafeOuroborosImage(Image::by_id($id)); + $post = new _SafeOuroborosImage(Image::by_id_ex($id)); $this->sendData('post', [$post]); } else { $this->sendResponse(424, 'ID is mandatory'); @@ -514,7 +514,7 @@ class OuroborosAPI extends Extension $response['location'] = $response['reason']; unset($response['reason']); } - $response = json_encode_ex($response); + $response = \Safe\json_encode($response); } elseif ($this->type == 'xml') { // Seriously, XML sucks... $xml = new \XMLWriter(); @@ -543,7 +543,7 @@ class OuroborosAPI extends Extension global $page; $response = ''; if ($this->type == 'json') { - $response = json_encode_ex($data); + $response = \Safe\json_encode($data); } elseif ($this->type == 'xml') { $xml = new \XMLWriter(); $xml->openMemory(); @@ -572,7 +572,7 @@ class OuroborosAPI extends Extension private function createItemXML(\XMLWriter $xml, string $type, _SafeOuroborosTag|_SafeOuroborosImage $item): void { $xml->startElement($type); - foreach (json_decode(json_encode_ex($item)) as $key => $val) { + foreach (json_decode(\Safe\json_encode($item)) as $key => $val) { if ($key == 'created_at' && $type == 'post') { $xml->writeAttribute($key, $val['s']); } else { diff --git a/ext/pools/main.php b/ext/pools/main.php index 341e5ab8..6ff10135 100644 --- a/ext/pools/main.php +++ b/ext/pools/main.php @@ -281,7 +281,7 @@ class Pools extends Extension $result = $database->execute("SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC", ["pid" => $pool_id]); $images = []; while ($row = $result->fetch()) { - $images[] = Image::by_id((int) $row["image_id"]); + $images[] = Image::by_id_ex((int) $row["image_id"]); } $this->theme->edit_pool($page, $pool, $images); } @@ -831,7 +831,7 @@ class Pools extends Extension $images = []; foreach ($result as $singleResult) { - $images[] = Image::by_id((int) $singleResult["image_id"]); + $images[] = Image::by_id_ex((int) $singleResult["image_id"]); } $this->theme->view_pool($pool, $images, $pageNumber + 1, $totalPages); diff --git a/ext/post_lock/test.php b/ext/post_lock/test.php index ba0eb2ee..e451651c 100644 --- a/ext/post_lock/test.php +++ b/ext/post_lock/test.php @@ -14,24 +14,24 @@ class PostLockTest extends ShimmiePHPUnitTestCase // admin can lock $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent(Image::by_id($image_id), ["locked" => "on"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["locked" => "on"])); // user can't edit locked post $this->log_in_as_user(); $this->assertException(PermissionDenied::class, function () use ($image_id) { - send_event(new ImageInfoSetEvent(Image::by_id($image_id), ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["source" => "http://example.com"])); }); // admin can edit locked post $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent(Image::by_id($image_id), ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["source" => "http://example.com"])); // admin can unlock $this->log_in_as_admin(); - send_event(new ImageInfoSetEvent(Image::by_id($image_id), [])); // "locked" is not set + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), [])); // "locked" is not set // user can edit un-locked post $this->log_in_as_user(); - send_event(new ImageInfoSetEvent(Image::by_id($image_id), ["source" => "http://example.com"])); + send_event(new ImageInfoSetEvent(Image::by_id_ex($image_id), ["source" => "http://example.com"])); } } diff --git a/ext/post_owner/test.php b/ext/post_owner/test.php index 741d08b0..35c14c2e 100644 --- a/ext/post_owner/test.php +++ b/ext/post_owner/test.php @@ -10,7 +10,7 @@ class PostOwnerTest extends ShimmiePHPUnitTestCase { $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); $this->log_in_as_admin(); send_event(new ImageInfoSetEvent($image, ["owner" => self::$admin_name])); diff --git a/ext/post_source/main.php b/ext/post_source/main.php index 88cd2d78..cdc42085 100644 --- a/ext/post_source/main.php +++ b/ext/post_source/main.php @@ -73,7 +73,7 @@ class PostSource extends Extension { if (preg_match("/^source[=|:](.*)$/i", $event->term, $matches)) { $source = ($matches[1] !== "none" ? $matches[1] : null); - send_event(new SourceSetEvent(Image::by_id($event->image_id), $source)); + send_event(new SourceSetEvent(Image::by_id_ex($event->image_id), $source)); } } diff --git a/ext/post_source/test.php b/ext/post_source/test.php index 8622d738..19fd0f7f 100644 --- a/ext/post_source/test.php +++ b/ext/post_source/test.php @@ -10,7 +10,7 @@ class PostSourceTest extends ShimmiePHPUnitTestCase { $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); send_event(new ImageInfoSetEvent($image, ["source" => "example.com"])); send_event(new ImageInfoSetEvent($image, ["source" => "http://example.com"])); diff --git a/ext/post_tags/test.php b/ext/post_tags/test.php index 1ffb8eea..583af312 100644 --- a/ext/post_tags/test.php +++ b/ext/post_tags/test.php @@ -10,7 +10,7 @@ class PostTagsTest extends ShimmiePHPUnitTestCase { $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); // Original $this->get_page("post/view/$image_id"); @@ -26,7 +26,7 @@ class PostTagsTest extends ShimmiePHPUnitTestCase { $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); $e = $this->assertException(TagSetException::class, function () use ($image) { send_event(new TagSetEvent($image, [])); diff --git a/ext/private_image/main.php b/ext/private_image/main.php index 0b8e9877..c4533fe7 100644 --- a/ext/private_image/main.php +++ b/ext/private_image/main.php @@ -45,10 +45,7 @@ class PrivateImage extends Extension if ($event->page_matches("privatize_image/{image_id}", method: "POST", permission: Permissions::SET_PRIVATE_IMAGE)) { $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - if ($image == null) { - throw new ImageNotFound("Post not found."); - } + $image = Image::by_id_ex($image_id); if ($image->owner_id != $user->can(Permissions::SET_OTHERS_PRIVATE_IMAGES)) { throw new PermissionDenied("Cannot set another user's image to private."); } @@ -60,10 +57,7 @@ class PrivateImage extends Extension if ($event->page_matches("publicize_image/{image_id}", method: "POST")) { $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - if ($image == null) { - throw new ImageNotFound("Post not found."); - } + $image = Image::by_id_ex($image_id); if ($image->owner_id != $user->can(Permissions::SET_OTHERS_PRIVATE_IMAGES)) { throw new PermissionDenied("Cannot set another user's image to public."); } diff --git a/ext/rating/main.php b/ext/rating/main.php index b9f45049..6627a136 100644 --- a/ext/rating/main.php +++ b/ext/rating/main.php @@ -292,7 +292,7 @@ class Ratings extends Extension $ratings = array_intersect(str_split($ratings), Ratings::get_user_class_privs($user)); $rating = $ratings[0]; - $image = Image::by_id($event->image_id); + $image = Image::by_id_ex($event->image_id); send_event(new RatingSetEvent($image, $rating)); } } diff --git a/ext/rating/test.php b/ext/rating/test.php index 7d4f744d..eff467d3 100644 --- a/ext/rating/test.php +++ b/ext/rating/test.php @@ -10,7 +10,7 @@ class RatingsTest extends ShimmiePHPUnitTestCase { $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); send_event(new RatingSetEvent($image, "s")); # search for it in various ways @@ -31,7 +31,7 @@ class RatingsTest extends ShimmiePHPUnitTestCase $config->set_array("ext_rating_anonymous_privs", ["s", "q"]); $this->log_in_as_user(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); send_event(new RatingSetEvent($image, "e")); # the explicit image shouldn't show up in anon's searches @@ -46,10 +46,10 @@ class RatingsTest extends ShimmiePHPUnitTestCase // post a safe image and an explicit image $this->log_in_as_user(); $image_id_e = $this->post_image("tests/bedroom_workshop.jpg", "pbx"); - $image_e = Image::by_id($image_id_e); + $image_e = Image::by_id_ex($image_id_e); send_event(new RatingSetEvent($image_e, "e")); $image_id_s = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image_s = Image::by_id($image_id_s); + $image_s = Image::by_id_ex($image_id_s); send_event(new RatingSetEvent($image_s, "s")); // user is allowed to see all @@ -84,13 +84,13 @@ class RatingsTest extends ShimmiePHPUnitTestCase $this->log_in_as_user(); $image_id_s = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); - $image_s = Image::by_id($image_id_s); + $image_s = Image::by_id_ex($image_id_s); send_event(new RatingSetEvent($image_s, "s")); $image_id_q = $this->post_image("tests/favicon.png", "favicon"); - $image_q = Image::by_id($image_id_q); + $image_q = Image::by_id_ex($image_id_q); send_event(new RatingSetEvent($image_q, "q")); $image_id_e = $this->post_image("tests/bedroom_workshop.jpg", "bedroom"); - $image_e = Image::by_id($image_id_e); + $image_e = Image::by_id_ex($image_id_e); send_event(new RatingSetEvent($image_e, "e")); $config->set_array("ext_rating_user_privs", ["s", "q"]); diff --git a/ext/regen_thumb/main.php b/ext/regen_thumb/main.php index 5d523ee5..70538f75 100644 --- a/ext/regen_thumb/main.php +++ b/ext/regen_thumb/main.php @@ -22,7 +22,7 @@ class RegenThumb extends Extension global $page, $user; if ($event->page_matches("regen_thumb/one/{image_id}", method: "POST", permission: Permissions::DELETE_IMAGE)) { - $image = Image::by_id($event->get_iarg('image_id')); + $image = Image::by_id_ex($event->get_iarg('image_id')); $this->regenerate_thumbnail($image); diff --git a/ext/relationships/main.php b/ext/relationships/main.php index d5f6c136..a12cdb46 100644 --- a/ext/relationships/main.php +++ b/ext/relationships/main.php @@ -216,7 +216,7 @@ class Relationships extends Extension { global $database; - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); $count = $database->get_one( "SELECT COUNT(*) FROM images WHERE id!=:id AND parent_id=:pid", @@ -233,7 +233,7 @@ class Relationships extends Extension { global $database; - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); $sibling_ids = $database->get_col( "SELECT id FROM images WHERE id!=:id AND parent_id=:pid", diff --git a/ext/relationships/test.php b/ext/relationships/test.php index cfaa82ae..7b2ecb1f 100644 --- a/ext/relationships/test.php +++ b/ext/relationships/test.php @@ -23,9 +23,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "pbx"); $image_id_3 = $this->post_image("tests/favicon.png", "pbx"); - $image_1 = null_throws(Image::by_id($image_id_1)); - $image_2 = null_throws(Image::by_id($image_id_2)); - $image_3 = null_throws(Image::by_id($image_id_3)); + $image_1 = Image::by_id_ex($image_id_1); + $image_2 = Image::by_id_ex($image_id_2); + $image_3 = Image::by_id_ex($image_id_3); $this->assertNull($image_1['parent_id']); $this->assertNull($image_2['parent_id']); @@ -48,9 +48,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase send_event(new ImageRelationshipSetEvent($image_2->id, $image_1->id)); // refresh data from database - $image_1 = null_throws(Image::by_id($image_1->id)); - $image_2 = null_throws(Image::by_id($image_2->id)); - $image_3 = null_throws(Image::by_id($image_3->id)); + $image_1 = Image::by_id_ex($image_1->id); + $image_2 = Image::by_id_ex($image_2->id); + $image_3 = Image::by_id_ex($image_3->id); $this->assertNull($image_1['parent_id']); $this->assertEquals($image_1->id, $image_2['parent_id']); @@ -72,9 +72,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase send_event(new ImageRelationshipSetEvent($image_2->id, $image_3->id)); // refresh data from database - $image_1 = null_throws(Image::by_id($image_1->id)); - $image_2 = null_throws(Image::by_id($image_2->id)); - $image_3 = null_throws(Image::by_id($image_3->id)); + $image_1 = Image::by_id_ex($image_1->id); + $image_2 = Image::by_id_ex($image_2->id); + $image_3 = Image::by_id_ex($image_3->id); $this->assertNull($image_1['parent_id']); $this->assertEquals($image_3->id, $image_2['parent_id']); @@ -112,9 +112,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase // FIXME: send_event(new ImageRelationshipSetEvent($image_2->id, null)); // refresh data from database - $image_1 = null_throws(Image::by_id($image_1->id)); - $image_2 = null_throws(Image::by_id($image_2->id)); - $image_3 = null_throws(Image::by_id($image_3->id)); + $image_1 = Image::by_id_ex($image_1->id); + $image_2 = Image::by_id_ex($image_2->id); + $image_3 = Image::by_id_ex($image_3->id); $this->assertNull($image_1['parent_id']); $this->assertNull($image_2['parent_id']); @@ -138,9 +138,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "pbx"); $image_id_3 = $this->post_image("tests/favicon.png", "pbx"); - $image_1 = null_throws(Image::by_id($image_id_1)); - $image_2 = null_throws(Image::by_id($image_id_2)); - $image_3 = null_throws(Image::by_id($image_id_3)); + $image_1 = Image::by_id_ex($image_id_1); + $image_2 = Image::by_id_ex($image_id_2); + $image_3 = Image::by_id_ex($image_id_3); $this->assertNull($image_1['parent_id']); $this->assertNull($image_2['parent_id']); @@ -163,9 +163,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase send_event(new TagSetEvent($image_2, ["pbx", "parent:{$image_1->id}"])); // refresh data from database - $image_1 = null_throws(Image::by_id($image_1->id)); - $image_2 = null_throws(Image::by_id($image_2->id)); - $image_3 = null_throws(Image::by_id($image_3->id)); + $image_1 = Image::by_id_ex($image_1->id); + $image_2 = Image::by_id_ex($image_2->id); + $image_3 = Image::by_id_ex($image_3->id); $this->assertEquals(["pbx"], $image_2->get_tag_array()); $this->assertNull($image_1['parent_id']); @@ -189,9 +189,9 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase send_event(new TagSetEvent($image_3, ["pbx", "child:{$image_1->id}"])); // refresh data from database - $image_1 = null_throws(Image::by_id($image_1->id)); - $image_2 = null_throws(Image::by_id($image_2->id)); - $image_3 = null_throws(Image::by_id($image_3->id)); + $image_1 = Image::by_id_ex($image_1->id); + $image_2 = Image::by_id_ex($image_2->id); + $image_3 = Image::by_id_ex($image_3->id); $this->assertEquals(["pbx"], $image_3->get_tag_array()); $this->assertEquals($image_3->id, $image_1['parent_id']); @@ -216,7 +216,7 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase send_event(new TagSetEvent($image_2, ["pbx", "parent:none"])); // refresh data from database - $image_2 = Image::by_id($image_2->id); + $image_2 = Image::by_id_ex($image_2->id); // check it was unset $this->assertEquals(["pbx"], $image_2->get_tag_array()); diff --git a/ext/relationships/theme.php b/ext/relationships/theme.php index 16d64f28..6cf7c39b 100644 --- a/ext/relationships/theme.php +++ b/ext/relationships/theme.php @@ -100,7 +100,7 @@ class RelationshipsTheme extends Themelet private function get_parent_thumbnail_html(Image $image): HTMLElement { $parent_id = $image['parent_id']; - $parent_image = Image::by_id($parent_id); + $parent_image = Image::by_id_ex($parent_id); return $this->build_thumb_html($parent_image); } diff --git a/ext/replace_file/main.php b/ext/replace_file/main.php index d29be4d7..d139bad2 100644 --- a/ext/replace_file/main.php +++ b/ext/replace_file/main.php @@ -15,20 +15,13 @@ class ReplaceFile extends Extension if ($event->page_matches("replace/{image_id}", method: "GET", permission: Permissions::REPLACE_IMAGE)) { $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - if (is_null($image)) { - throw new UploadException("Can not replace Post: No post with ID $image_id"); - } - + $image = Image::by_id_ex($image_id); $this->theme->display_replace_page($page, $image_id); } if ($event->page_matches("replace/{image_id}", method: "POST", permission: Permissions::REPLACE_IMAGE)) { $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - if (is_null($image)) { - throw new UploadException("Can not replace Post: No post with ID $image_id"); - } + $image = Image::by_id_ex($image_id); if(empty($event->get_POST("url")) && count($_FILES) == 0) { $page->set_mode(PageMode::REDIRECT); @@ -85,7 +78,7 @@ class ReplaceFile extends Extension // update metadata and save metadata to DB $event->image->hash = $event->new_hash; - $event->image->filesize = filesize_ex($target); + $event->image->filesize = \Safe\filesize($target); $event->image->set_mime(MimeType::get_for_file($target)); send_event(new MediaCheckPropertiesEvent($image)); $image->save_to_db(); diff --git a/ext/replace_file/test.php b/ext/replace_file/test.php index aecd08be..21249d54 100644 --- a/ext/replace_file/test.php +++ b/ext/replace_file/test.php @@ -22,8 +22,8 @@ class ReplaceFileTest extends ShimmiePHPUnitTestCase $image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot"); // check that the image is original - $image = Image::by_id($image_id); - $old_hash = md5_file_ex("tests/pbx_screenshot.jpg"); + $image = Image::by_id_ex($image_id); + $old_hash = \Safe\md5_file("tests/pbx_screenshot.jpg"); //$this->assertEquals("pbx_screenshot.jpg", $image->filename); $this->assertEquals("image/jpeg", $image->get_mime()); $this->assertEquals(19774, $image->filesize); @@ -34,7 +34,7 @@ class ReplaceFileTest extends ShimmiePHPUnitTestCase // create a copy because the file is deleted after upload $tmpfile = shm_tempnam("test"); copy("tests/favicon.png", $tmpfile); - $new_hash = md5_file_ex($tmpfile); + $new_hash = \Safe\md5_file($tmpfile); $_FILES = [ 'data' => [ 'name' => 'favicon.png', @@ -52,7 +52,7 @@ class ReplaceFileTest extends ShimmiePHPUnitTestCase $this->assertEquals(1, $database->get_one("SELECT COUNT(*) FROM images")); // check that the image was replaced - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); // $this->assertEquals("favicon.png", $image->filename); // TODO should we update filename? $this->assertEquals("image/png", $image->get_mime()); $this->assertEquals(246, $image->filesize); diff --git a/ext/replace_file/theme.php b/ext/replace_file/theme.php index b385d249..f0df2d8d 100644 --- a/ext/replace_file/theme.php +++ b/ext/replace_file/theme.php @@ -25,7 +25,7 @@ class ReplaceFileTheme extends Themelet $max_size = $config->get_int(UploadConfig::SIZE); $max_kb = to_shorthand_int($max_size); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); $thumbnail = $this->build_thumb_html($image); $form = SHM_FORM("replace/".$image_id, multipart: true); diff --git a/ext/resize/main.php b/ext/resize/main.php index 75abb138..4dc9a754 100644 --- a/ext/resize/main.php +++ b/ext/resize/main.php @@ -112,12 +112,11 @@ class ResizeImage extends Extension $isanigif = 0; if ($image_obj->get_mime() == MimeType::GIF) { $image_filename = warehouse_path(Image::IMAGE_DIR, $image_obj->hash); - if (($fh = @fopen($image_filename, 'rb'))) { - //check if gif is animated (via https://www.php.net/manual/en/function.imagecreatefromgif.php#104473) - while (!feof($fh) && $isanigif < 2) { - $chunk = false_throws(fread($fh, 1024 * 100)); - $isanigif += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches); - } + $fh = \Safe\fopen($image_filename, 'rb'); + //check if gif is animated (via https://www.php.net/manual/en/function.imagecreatefromgif.php#104473) + while (!feof($fh) && $isanigif < 2) { + $chunk = \Safe\fread($fh, 1024 * 100); + $isanigif += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches); } } if ($isanigif == 0) { @@ -125,7 +124,7 @@ class ResizeImage extends Extension //Need to generate thumbnail again... //This only seems to be an issue if one of the sizes was set to 0. - $image_obj = Image::by_id($image_obj->id); //Must be a better way to grab the new hash than setting this again.. + $image_obj = Image::by_id_ex($image_obj->id); //Must be a better way to grab the new hash than setting this again.. send_event(new ThumbnailGenerationEvent($image_obj, true)); log_info("resize", ">>{$image_obj->id} has been resized to: ".$width."x".$height); @@ -141,18 +140,14 @@ class ResizeImage extends Extension if ($event->page_matches("resize/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) { // Try to get the image ID $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - if (is_null($image)) { - $this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id"); - } else { - /* Check if options were given to resize an image. */ - $width = int_escape($event->get_POST('resize_width')); - $height = int_escape($event->get_POST('resize_height')); - if ($width || $height) { - $this->resize_image($image, $width, $height); - $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(make_link("post/view/".$image_id)); - } + $image = Image::by_id_ex($image_id); + /* Check if options were given to resize an image. */ + $width = int_escape($event->get_POST('resize_width')); + $height = int_escape($event->get_POST('resize_height')); + if ($width || $height) { + $this->resize_image($image, $width, $height); + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(make_link("post/view/".$image_id)); } } } @@ -233,7 +228,7 @@ class ResizeImage extends Extension $hash = $image_obj->hash; $image_filename = warehouse_path(Image::IMAGE_DIR, $hash); - $info = false_throws(getimagesize($image_filename)); + $info = \Safe\getimagesize($image_filename); if (($image_obj->width != $info[0]) || ($image_obj->height != $info[1])) { throw new ImageResizeException("The current image size does not match what is set in the database! - Aborting Resize."); } diff --git a/ext/rotate/main.php b/ext/rotate/main.php index 517b7f3e..e0d147c0 100644 --- a/ext/rotate/main.php +++ b/ext/rotate/main.php @@ -59,18 +59,14 @@ class RotateImage extends Extension if ($event->page_matches("rotate/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) { // Try to get the image ID $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - if (is_null($image)) { - $this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id"); - } else { - /* Check if options were given to rotate an image. */ - $deg = int_escape($event->req_POST('rotate_deg')); + $image = Image::by_id_ex($image_id); + /* Check if options were given to rotate an image. */ + $deg = int_escape($event->req_POST('rotate_deg')); - /* Attempt to rotate the image */ - $this->rotate_image($image_id, $deg); - $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(make_link("post/view/".$image_id)); - } + /* Attempt to rotate the image */ + $this->rotate_image($image_id, $deg); + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(make_link("post/view/".$image_id)); } } @@ -83,7 +79,7 @@ class RotateImage extends Extension throw new ImageRotateException("Invalid options for rotation angle. ($deg)"); } - $image_obj = Image::by_id($image_id); + $image_obj = Image::by_id_ex($image_id); $hash = $image_obj->hash; $image_filename = warehouse_path(Image::IMAGE_DIR, $hash); @@ -91,8 +87,11 @@ class RotateImage extends Extension throw new ImageRotateException("$image_filename does not exist."); } - $info = false_throws(getimagesize($image_filename)); + $info = \Safe\getimagesize($image_filename); + // we need to fully-enable phpstan-safe-rules to get the + // full type hint + // @phpstan-ignore-next-line $memory_use = Media::calc_memory_use($info); $memory_limit = get_memory_limit(); @@ -102,7 +101,7 @@ class RotateImage extends Extension /* Attempt to load the image */ - $image = imagecreatefromstring(file_get_contents_ex($image_filename)); + $image = imagecreatefromstring(\Safe\file_get_contents($image_filename)); if ($image == false) { throw new ImageRotateException("Could not load image: ".$image_filename); } @@ -154,7 +153,7 @@ class RotateImage extends Extension throw new ImageRotateException("Could not save image: ".$tmp_filename); } - $new_hash = md5_file_ex($tmp_filename); + $new_hash = \Safe\md5_file($tmp_filename); /* Move the new image into the main storage location */ $target = warehouse_path(Image::IMAGE_DIR, $new_hash); if (!@copy($tmp_filename, $target)) { diff --git a/ext/rss_comments/main.php b/ext/rss_comments/main.php index 312818d0..e274a15c 100644 --- a/ext/rss_comments/main.php +++ b/ext/rss_comments/main.php @@ -40,7 +40,7 @@ class RSSComments extends Extension $comment_id = $comment['comment_id']; $link = make_http(make_link("post/view/$image_id")); $owner = html_escape($comment['user_name']); - $posted = date(DATE_RSS, strtotime_ex($comment['posted'])); + $posted = date(DATE_RSS, \Safe\strtotime($comment['posted'])); $comment = html_escape($comment['comment']); $content = html_escape("$owner: $comment"); diff --git a/ext/rss_images/main.php b/ext/rss_images/main.php index 5e08c7ab..774ba440 100644 --- a/ext/rss_images/main.php +++ b/ext/rss_images/main.php @@ -112,7 +112,7 @@ class RSSImages extends Extension $tags = html_escape($image->get_tag_list()); $thumb_url = $image->get_thumb_link(); $image_url = $image->get_image_link(); - $posted = date(DATE_RSS, strtotime_ex($image->posted)); + $posted = date(DATE_RSS, \Safe\strtotime($image->posted)); $content = html_escape( "
" . "

" . $this->theme->build_thumb_html($image) . "

" . diff --git a/ext/s3/main.php b/ext/s3/main.php index 84afea2d..6668a61b 100644 --- a/ext/s3/main.php +++ b/ext/s3/main.php @@ -131,7 +131,7 @@ class S3 extends Extension global $config, $page, $user; if ($event->page_matches("s3/sync/{image_id}", method: "POST", permission: Permissions::DELETE_IMAGE)) { $id = $event->get_iarg('image_id'); - $this->sync_post(Image::by_id($id)); + $this->sync_post(Image::by_id_ex($id)); log_info("s3", "Manual resync for >>$id", "File re-sync'ed"); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("post/view/$id")); @@ -237,7 +237,7 @@ class S3 extends Extension $client->putObject([ 'Bucket' => $image_bucket, 'Key' => $key, - 'Body' => file_get_contents_ex($image->get_image_filename()), + 'Body' => \Safe\file_get_contents($image->get_image_filename()), 'ACL' => 'public-read', 'ContentType' => $image->get_mime(), 'ContentDisposition' => "inline; filename=\"$friendly\"", diff --git a/ext/setup/main.php b/ext/setup/main.php index bb8d2f37..78352f24 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -326,7 +326,7 @@ class Setup extends Extension if ($event->page_starts_with("nicedebug")) { $page->set_mode(PageMode::DATA); - $page->set_data(json_encode_ex([ + $page->set_data(\Safe\json_encode([ "args" => $event->args, ])); } @@ -354,9 +354,12 @@ class Setup extends Extension public function onSetupBuilding(SetupBuildingEvent $event): void { $themes = []; - foreach (glob_ex("themes/*") as $theme_dirname) { + foreach (\Safe\glob("themes/*") as $theme_dirname) { $name = str_replace("themes/", "", $theme_dirname); $human = str_replace("_", " ", $name); + // while phpstan-safe-rule isn't enabled, phpstan can't tell + // that \Safe\glob() returns string[] + // @phpstan-ignore-next-line $human = ucwords($human); $themes[$human] = $name; } @@ -405,7 +408,7 @@ class Setup extends Extension } } log_warning("setup", "Configuration updated"); - foreach (glob_ex("data/cache/*.css") as $css_cache) { + foreach (\Safe\glob("data/cache/*.css") as $css_cache) { unlink($css_cache); } log_warning("setup", "Cache cleared"); diff --git a/ext/sitemap/main.php b/ext/sitemap/main.php index c8c82dda..5310d43a 100644 --- a/ext/sitemap/main.php +++ b/ext/sitemap/main.php @@ -29,7 +29,7 @@ class XMLSitemap extends Extension file_put_contents($cache_path, $xml); } - $xml = file_get_contents_ex($cache_path); + $xml = \Safe\file_get_contents($cache_path); $page->set_mode(PageMode::DATA); $page->set_mime(MimeType::XML_APPLICATION); $page->set_data($xml); @@ -67,7 +67,7 @@ class XMLSitemap extends Extension "post/view/$image->id", "weekly", "0.8", - date("Y-m-d", strtotime_ex($image->posted)) + date("Y-m-d", \Safe\strtotime($image->posted)) ); } @@ -87,7 +87,7 @@ class XMLSitemap extends Extension "post/view/$image->id", "monthly", "0.6", - date("Y-m-d", strtotime_ex($image->posted)) + date("Y-m-d", \Safe\strtotime($image->posted)) ); } diff --git a/ext/static_files/main.php b/ext/static_files/main.php index f7311d93..0f05d73f 100644 --- a/ext/static_files/main.php +++ b/ext/static_files/main.php @@ -48,7 +48,7 @@ class StaticFiles extends Extension $page->add_http_header("Cache-control: public, max-age=600"); $page->add_http_header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 600) . ' GMT'); $page->set_mode(PageMode::DATA); - $page->set_data(file_get_contents_ex($filename)); + $page->set_data(\Safe\file_get_contents($filename)); $page->set_mime(MimeType::get_for_file($filename)); } } diff --git a/ext/tag_editcloud/main.php b/ext/tag_editcloud/main.php index edeb3773..f65c1d05 100644 --- a/ext/tag_editcloud/main.php +++ b/ext/tag_editcloud/main.php @@ -163,7 +163,7 @@ class TagEditCloud extends Extension } $size = sprintf("%.2f", max($row['scaled'], 0.5)); - $js = html_escape('tageditcloud_toggle_tag(this,'.json_encode_ex($full_tag).')'); //Ugly, but it works + $js = html_escape('tageditcloud_toggle_tag(this,'.\Safe\json_encode($full_tag).')'); //Ugly, but it works if (in_array($row['tag'], $image->get_tag_array())) { if ($used_first) { diff --git a/ext/tag_history/main.php b/ext/tag_history/main.php index 7f9fb246..1af6c08d 100644 --- a/ext/tag_history/main.php +++ b/ext/tag_history/main.php @@ -205,10 +205,7 @@ class TagHistory extends Extension $stored_image_id = (int)$result['image_id']; $stored_tags = $result['tags']; - $image = Image::by_id($stored_image_id); - if (!$image instanceof Image) { - throw new ImageNotFound("Error: cannot find any image with the ID = ". $stored_image_id); - } + $image = Image::by_id_ex($stored_image_id); log_debug("tag_history", 'Reverting tags of >>'.$stored_image_id.' to ['.$stored_tags.']'); // all should be ok so we can revert by firing the SetUserTags event. diff --git a/ext/tag_history/test.php b/ext/tag_history/test.php index 4c3fc084..aeca8b2a 100644 --- a/ext/tag_history/test.php +++ b/ext/tag_history/test.php @@ -10,7 +10,7 @@ class TagHistoryTest extends ShimmiePHPUnitTestCase { $this->log_in_as_admin(); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "old_tag"); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); // Original $this->get_page("post/view/$image_id"); diff --git a/ext/tag_list/main.php b/ext/tag_list/main.php index 5d6e3687..8e92e985 100644 --- a/ext/tag_list/main.php +++ b/ext/tag_list/main.php @@ -235,7 +235,7 @@ class TagList extends Extension md5("tc" . $tags_min . $starts_with . VERSION) ); if (file_exists($cache_key)) { - return file_get_contents_ex($cache_key); + return \Safe\file_get_contents($cache_key); } $tag_data = $database->get_all(" @@ -288,7 +288,7 @@ class TagList extends Extension md5("ta" . $tags_min . $starts_with . VERSION) ); if (file_exists($cache_key)) { - return file_get_contents_ex($cache_key); + return \Safe\file_get_contents($cache_key); } $tag_data = $database->get_pairs(" @@ -368,7 +368,7 @@ class TagList extends Extension md5("tp" . $tags_min . VERSION) ); if (file_exists($cache_key)) { - return file_get_contents_ex($cache_key); + return \Safe\file_get_contents($cache_key); } $tag_data = $database->get_all(" diff --git a/ext/transcode/main.php b/ext/transcode/main.php index ed6f6e5c..068aa983 100644 --- a/ext/transcode/main.php +++ b/ext/transcode/main.php @@ -209,17 +209,13 @@ class TranscodeImage extends Extension if ($event->page_matches("transcode/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) { $image_id = $event->get_iarg('image_id'); - $image_obj = Image::by_id($image_id); - if (is_null($image_obj)) { - $this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id"); - } else { - try { - $this->transcode_and_replace_image($image_obj, $event->req_POST('transcode_mime')); - $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(make_link("post/view/".$image_id)); - } catch (ImageTranscodeException $e) { - $this->theme->display_transcode_error($page, "Error Transcoding", $e->getMessage()); - } + $image_obj = Image::by_id_ex($image_id); + try { + $this->transcode_and_replace_image($image_obj, $event->req_POST('transcode_mime')); + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(make_link("post/view/".$image_id)); + } catch (ImageTranscodeException $e) { + $this->theme->display_transcode_error($page, "Error Transcoding", $e->getMessage()); } } } @@ -382,7 +378,7 @@ class TranscodeImage extends Extension $tmp_name = shm_tempnam("transcode"); - $image = false_throws(imagecreatefromstring(file_get_contents_ex($source_name))); + $image = false_throws(imagecreatefromstring(\Safe\file_get_contents($source_name))); try { $result = false; switch ($target_mime) { diff --git a/ext/transcode_video/main.php b/ext/transcode_video/main.php index 64229dd7..20355777 100644 --- a/ext/transcode_video/main.php +++ b/ext/transcode_video/main.php @@ -103,17 +103,13 @@ class TranscodeVideo extends Extension if ($event->page_matches("transcode_video/{image_id}", method: "POST", permission: Permissions::EDIT_FILES)) { $image_id = $event->get_iarg('image_id'); - $image_obj = Image::by_id($image_id); - if (is_null($image_obj)) { - $this->theme->display_error(404, "Post not found", "No post in the database has the ID #$image_id"); - } else { - try { - $this->transcode_and_replace_video($image_obj, $event->req_POST('transcode_format')); - $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(make_link("post/view/".$image_id)); - } catch (VideoTranscodeException $e) { - $this->theme->display_transcode_error($page, "Error Transcoding", $e->getMessage()); - } + $image_obj = Image::by_id_ex($image_id); + try { + $this->transcode_and_replace_video($image_obj, $event->req_POST('transcode_format')); + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(make_link("post/view/".$image_id)); + } catch (VideoTranscodeException $e) { + $this->theme->display_transcode_error($page, "Error Transcoding", $e->getMessage()); } } } diff --git a/ext/upload/main.php b/ext/upload/main.php index b2d620d4..c77509a6 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -45,8 +45,8 @@ class DataUploadEvent extends Event { assert(is_readable($tmpname)); $this->tmpname = $tmpname; - $this->hash = md5_file_ex($tmpname); - $this->size = filesize_ex($tmpname); + $this->hash = \Safe\md5_file($tmpname); + $this->size = \Safe\filesize($tmpname); $mime = $mime ?? MimeType::get_for_file($tmpname, get_file_ext($this->metadata["filename"]) ?? null); if (empty($mime)) { throw new UploadException("Could not determine mime type"); diff --git a/ext/upload/test.php b/ext/upload/test.php index c2093263..70f5b038 100644 --- a/ext/upload/test.php +++ b/ext/upload/test.php @@ -80,7 +80,7 @@ class UploadTest extends ShimmiePHPUnitTestCase public function testRejectHuge(): void { // FIXME: huge.dat is rejected for other reasons; manual testing shows that this works - file_put_contents("data/huge.jpg", file_get_contents_ex("tests/pbx_screenshot.jpg") . str_repeat("U", 1024 * 1024 * 3)); + file_put_contents("data/huge.jpg", \Safe\file_get_contents("tests/pbx_screenshot.jpg") . str_repeat("U", 1024 * 1024 * 3)); $e = $this->assertException(UploadException::class, function () { $this->post_image("data/huge.jpg", "test"); }); diff --git a/ext/view/main.php b/ext/view/main.php index ba8c4983..7b10f19a 100644 --- a/ext/view/main.php +++ b/ext/view/main.php @@ -34,11 +34,7 @@ class ViewPost extends Extension $query = null; } - $image = Image::by_id($image_id); - if (is_null($image)) { - $this->theme->display_error(404, "Post not found", "Post $image_id could not be found"); - return; - } + $image = Image::by_id_ex($image_id); if ($event->page_matches("post/next/{image_id}")) { $image = $image->get_next($search_terms); @@ -64,16 +60,11 @@ class ViewPost extends Extension } $image_id = $event->get_iarg('image_id'); - $image = Image::by_id($image_id); - - if (!is_null($image)) { - send_event(new DisplayingImageEvent($image)); - } else { - $this->theme->display_error(404, "Post not found", "No post in the database has the ID #$image_id"); - } + $image = Image::by_id_ex($image_id); + send_event(new DisplayingImageEvent($image)); } elseif ($event->page_matches("post/set", method: "POST")) { $image_id = int_escape($event->req_POST('image_id')); - $image = Image::by_id($image_id); + $image = Image::by_id_ex($image_id); if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) { // currently all post metadata is string => string - in the future // we might want to have a more complex type system, but for now diff --git a/ext/view/test.php b/ext/view/test.php index cbb1e3c0..0d0d86ea 100644 --- a/ext/view/test.php +++ b/ext/view/test.php @@ -90,10 +90,11 @@ class ViewPostTest extends ShimmiePHPUnitTestCase $image_id_1 = $this->post_image("tests/favicon.png", "test"); $idp1 = $image_id_1 + 1; - $this->get_page("post/view/$idp1"); - $this->assert_title('Post not found'); - - $this->get_page('post/view/-1'); - $this->assert_title('Post not found'); + $this->assertException(ImageNotFound::class, function () use ($idp1) { + $this->get_page("post/view/$idp1"); + }); + $this->assertException(ImageNotFound::class, function () { + $this->get_page('post/view/-1'); + }); } } diff --git a/tests/phpstan.neon b/tests/phpstan.neon index 644b3d7c..d80d46f1 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -15,3 +15,5 @@ parameters: - STATSD_HOST - TRACE_FILE - UNITTEST +#includes: +# - ../vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon