[core] use Safe library, reduce StdLibEx

This commit is contained in:
Shish 2024-02-20 00:22:25 +00:00 committed by Shish
parent c0bc11ee0c
commit e80d235fe9
79 changed files with 491 additions and 382 deletions

View file

@ -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",

198
composer.lock generated
View file

@ -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",

View file

@ -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

View file

@ -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];
}
}

View file

@ -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())) {

View file

@ -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;

View file

@ -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 ? "<time datetime='$cpu'>$hum</time>" : $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);

View file

@ -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));

View file

@ -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);
}
}

View file

@ -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",

View file

@ -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);
}

View file

@ -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);

View file

@ -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"));

View file

@ -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()));
}
}

View file

@ -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));
}
}

View file

@ -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 = "<span style='color: #$i_color;'>";
@ -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 = "<span style='color: #$i_color'>";
@ -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 = "<ul>$entries_list</ul>";
}

View file

@ -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, [], []]));
}
}

View file

@ -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) {

View file

@ -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 {

View file

@ -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, "/");

View file

@ -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");
}

View file

@ -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/*"));
}
}
}

View file

@ -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);

View file

@ -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";
}

View file

@ -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("<a href='$favorites_link'>Posts favorited</a>: $i_favorites_count, $h_favorites_rate per day");

View file

@ -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")) {

View file

@ -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));

View file

@ -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')

View file

@ -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 {

View file

@ -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";

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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("<a href='$images_link'>Posts uploaded</a>: $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", "<a href='" . make_link() . "'>Index</a>", "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));
}
}

View file

@ -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 () {

View file

@ -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

View file

@ -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})/";

View file

@ -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];

View file

@ -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");

View file

@ -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);

View file

@ -62,7 +62,7 @@ class NotesTheme extends Themelet
];
}
$page->add_html_header("<script type='text/javascript'>
window.notes = ".json_encode_ex($to_json).";
window.notes = ".\Safe\json_encode($to_json).";
window.notes_image_id = $image_id;
window.notes_admin = ".($adminOptions ? "true" : "false").";
</script>");

View file

@ -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")) {

View file

@ -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".
"<h3 style='text-align: center;'>\n".

View file

@ -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 {

View file

@ -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);

View file

@ -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"]));
}
}

View file

@ -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]));

View file

@ -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));
}
}

View file

@ -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"]));

View file

@ -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, []));

View file

@ -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.");
}

View file

@ -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));
}
}

View file

@ -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"]);

View file

@ -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);

View file

@ -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",

View file

@ -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());

View file

@ -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);
}

View file

@ -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();

View file

@ -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);

View file

@ -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);

View file

@ -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.");
}

View file

@ -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)) {

View file

@ -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");

View file

@ -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(
"<div>" .
"<p>" . $this->theme->build_thumb_html($image) . "</p>" .

View file

@ -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\"",

View file

@ -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");

View file

@ -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))
);
}

View file

@ -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));
}
}

View file

@ -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) {

View file

@ -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.

View file

@ -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");

View file

@ -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("

View file

@ -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) {

View file

@ -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());
}
}
}

View file

@ -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");

View file

@ -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");
});

View file

@ -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

View file

@ -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');
});
}
}

View file

@ -15,3 +15,5 @@ parameters:
- STATSD_HOST
- TRACE_FILE
- UNITTEST
#includes:
# - ../vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon