Added ImageDownloadingEvent that allows extensions to stop a user from viewing an image or perform other operations on the image before the image is downloaded to the user

This commit is contained in:
Matthew Barbour 2020-06-16 18:40:13 -05:00 committed by Shish
parent 40b80bca93
commit 9b5d963aa3
8 changed files with 130 additions and 14 deletions

View File

@ -99,9 +99,9 @@ class Approval extends Extension
public function onDisplayingImage(DisplayingImageEvent $event) public function onDisplayingImage(DisplayingImageEvent $event)
{ {
global $user, $page, $config; global $page;
if ($config->get_bool(ApprovalConfig::IMAGES) && $event->image->approved===false && !$user->can(Permissions::APPROVE_IMAGE)) { if (!$this->check_permissions(($event->image))) {
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list")); $page->set_redirect(make_link("post/list"));
} }
@ -187,6 +187,26 @@ class Approval extends Extension
); );
} }
private function check_permissions(Image $image): bool
{
global $user, $config;
if ($config->get_bool(ApprovalConfig::IMAGES) && $image->approved===false && !$user->can(Permissions::APPROVE_IMAGE)) {
return false;
}
return true;
}
public function onImageDownloading(ImageDownloadingEvent $event)
{
/**
* Deny images upon insufficient permissions.
**/
if (!$this->check_permissions($event->image)) {
throw new SCoreException("Access denied");
}
}
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event) public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{ {
global $user, $config; global $user, $config;

16
ext/download/events.php Normal file
View File

@ -0,0 +1,16 @@
<?php
class ImageDownloadingEvent extends Event
{
public $image;
public $mime;
public $path;
public $file_modified = false;
public function __construct(Image $image, String $path, string $mime)
{
$this->image = $image;
$this->path = $path;
$this->mime = $mime;
}
}

14
ext/download/info.php Normal file
View File

@ -0,0 +1,14 @@
<?php
class DownloadInfo extends ExtensionInfo
{
public const KEY = "download";
public $key = self::KEY;
public $name = "Download";
public $authors = ["Matthew Barbour"=>"matthew@darkholme.net"];
public $license = self::LICENSE_WTFPL;
public $description = "System-wide download functions";
public $core = true;
public $visibility = self::VISIBLE_HIDDEN;
}

26
ext/download/main.php Normal file
View File

@ -0,0 +1,26 @@
<?php
require_once "events.php";
class Download extends Extension
{
public function get_priority(): int
{
// Set near the end to give everything else a chance to process
return 99;
}
public function onImageDownloading(ImageDownloadingEvent $event)
{
global $page;
$page->set_mime($event->mime);
$page->set_mode(PageMode::FILE);
$page->set_file($event->path, $event->file_modified);
$event->stop_processing = true;
}
}

View File

@ -271,10 +271,9 @@ class ImageIO extends Extension
private function send_file(int $image_id, string $type) private function send_file(int $image_id, string $type)
{ {
global $config; global $config, $page;
$image = Image::by_id($image_id);
global $page; $image = Image::by_id($image_id);
if (!is_null($image)) { if (!is_null($image)) {
if ($type == "thumb") { if ($type == "thumb") {
$ext = $config->get_string(ImageConfig::THUMB_TYPE); $ext = $config->get_string(ImageConfig::THUMB_TYPE);
@ -285,7 +284,6 @@ class ImageIO extends Extension
$page->set_type($image->get_mime_type()); $page->set_type($image->get_mime_type());
$file = $image->get_image_filename(); $file = $image->get_image_filename();
} }
if (!file_exists($file)) { if (!file_exists($file)) {
http_response_code(404); http_response_code(404);
die(); die();
@ -319,6 +317,8 @@ class ImageIO extends Extension
} }
$page->add_http_header('Expires: ' . $expires); $page->add_http_header('Expires: ' . $expires);
} }
send_event(new ImageDownloadingEvent($image, $file, $mime));
} else { } else {
$page->set_title("Not Found"); $page->set_title("Not Found");
$page->set_heading("Not Found"); $page->set_heading("Not Found");

View File

@ -28,9 +28,9 @@ class RandomImage extends Extension
} }
if ($action === "download") { if ($action === "download") {
$page->set_mode(PageMode::DATA); if (!is_null($image)) {
$page->set_type($image->get_mime_type()); send_event(new ImageDownloadingEvent($image, $image->get_image_filename(), $image->get_mime_type()));
$page->set_data(file_get_contents($image->get_image_filename())); }
} elseif ($action === "view") { } elseif ($action === "view") {
send_event(new DisplayingImageEvent($image)); send_event(new DisplayingImageEvent($image));
} elseif ($action === "widget") { } elseif ($action === "widget") {

View File

@ -115,11 +115,32 @@ class Ratings extends Extension
} }
} }
private function check_permissions(Image $image): bool
{
global $user;
$user_view_level = Ratings::get_user_class_privs($user);
if (!in_array($image->rating, $user_view_level)) {
return false;
}
return true;
}
public function onInitUserConfig(InitUserConfigEvent $event) public function onInitUserConfig(InitUserConfigEvent $event)
{ {
$event->user_config->set_default_array(RatingsConfig::USER_DEFAULTS, self::get_user_class_privs($event->user)); $event->user_config->set_default_array(RatingsConfig::USER_DEFAULTS, self::get_user_class_privs($event->user));
} }
public function onImageDownloading(ImageDownloadingEvent $event)
{
/**
* Deny images upon insufficient permissions.
**/
if (!$this->check_permissions($event->image)) {
throw new SCoreException("Access denied");
}
}
public function onUserOptionsBuilding(UserOptionsBuildingEvent $event) public function onUserOptionsBuilding(UserOptionsBuildingEvent $event)
{ {
global $user; global $user;
@ -159,12 +180,11 @@ class Ratings extends Extension
public function onDisplayingImage(DisplayingImageEvent $event) public function onDisplayingImage(DisplayingImageEvent $event)
{ {
global $user, $page; global $page;
/** /**
* Deny images upon insufficient permissions. * Deny images upon insufficient permissions.
**/ **/
$user_view_level = Ratings::get_user_class_privs($user); if (!$this->check_permissions($event->image)) {
if (!in_array($event->image->rating, $user_view_level)) {
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list")); $page->set_redirect(make_link("post/list"));
} }

View File

@ -41,11 +41,31 @@ class Trash extends Extension
} }
} }
private function check_permissions(Image $image): bool
{
global $user;
if ($image->trash===true && !$user->can(Permissions::VIEW_TRASH)) {
return false;
}
return true;
}
public function onImageDownloading(ImageDownloadingEvent $event)
{
/**
* Deny images upon insufficient permissions.
**/
if (!$this->check_permissions($event->image)) {
throw new SCoreException("Access denied");
}
}
public function onDisplayingImage(DisplayingImageEvent $event) public function onDisplayingImage(DisplayingImageEvent $event)
{ {
global $user, $page; global $page;
if ($event->image->trash===true && !$user->can(Permissions::VIEW_TRASH)) { if (!$this->check_permissions(($event->image))) {
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list")); $page->set_redirect(make_link("post/list"));
} }