misuzu/src/Http/Handlers/AssetsHandler.php
flash 1d552e907b Added new banning system.
it actually works and isn't confusing this time around!
2023-07-26 18:19:48 +00:00

98 lines
3.5 KiB
PHP

<?php
namespace Misuzu\Http\Handlers;
use RuntimeException;
use Misuzu\GitInfo;
use Misuzu\Users\User;
use Misuzu\Users\Assets\StaticUserImageAsset;
use Misuzu\Users\Assets\UserImageAssetInterface;
use Misuzu\Users\Assets\UserAssetScalableInterface;
final class AssetsHandler extends Handler {
private function canViewAsset($request, User $assetUser): bool {
return !$this->context->hasActiveBan($assetUser) || (
User::hasCurrent()
&& parse_url($request->getHeaderFirstLine('Referer'), PHP_URL_PATH) === url('user-profile')
&& perms_check_user(MSZ_PERMS_USER, User::getCurrent()->getId(), MSZ_PERM_USER_MANAGE_USERS)
);
}
private function serveUserAsset($response, $request, UserImageAssetInterface $assetInfo): void {
$contentType = $assetInfo->getMimeType();
$publicPath = $assetInfo->getPublicPath();
$fileName = $assetInfo->getFileName();
if($assetInfo instanceof UserAssetScalableInterface) {
$dimensions = (int)($request->getParam('res', FILTER_SANITIZE_NUMBER_INT) ?? $request->getParam('r', FILTER_SANITIZE_NUMBER_INT));
if($dimensions > 0) {
$assetInfo->ensureScaledExists($dimensions);
$contentType = $assetInfo->getScaledMimeType($dimensions);
$publicPath = $assetInfo->getPublicScaledPath($dimensions);
$fileName = $assetInfo->getScaledFileName($dimensions);
}
}
$response->accelRedirect($publicPath);
$response->setContentType($contentType);
$response->setFileName($fileName, false);
}
public function serveAvatar($response, $request, string $fileName) {
$userId = (int)pathinfo($fileName, PATHINFO_FILENAME);
$type = pathinfo($fileName, PATHINFO_EXTENSION);
if($type !== '' && $type !== 'png')
return 404;
$assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/no-avatar.png', MSZ_PUBLIC);
try {
$userInfo = User::byId($userId);
if(!$this->canViewAsset($request, $userInfo)) {
$assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/banned-avatar.png', MSZ_PUBLIC);
} elseif($userInfo->hasAvatar()) {
$assetInfo = $userInfo->getAvatarInfo();
}
} catch(RuntimeException $ex) {}
$this->serveUserAsset($response, $request, $assetInfo);
}
public function serveProfileBackground($response, $request, string $fileName) {
$userId = (int)pathinfo($fileName, PATHINFO_FILENAME);
$type = pathinfo($fileName, PATHINFO_EXTENSION);
if($type !== '' && $type !== 'png')
return 404;
try {
$userInfo = User::byId($userId);
} catch(RuntimeException $ex) {}
if(empty($userInfo) || !$userInfo->hasBackground() || !$this->canViewAsset($request, $userInfo)) {
$response->setContent('');
return 404;
}
$this->serveUserAsset($response, $request, $userInfo->getBackgroundInfo());
}
public function serveLegacy($response, $request) {
$assetUserId = $request->getParam('u', FILTER_SANITIZE_NUMBER_INT);
switch($request->getParam('m')) {
case 'avatar':
$this->serveAvatar($response, $request, $assetUserId);
return;
case 'background':
$this->serveProfileBackground($response, $request, $assetUserId);
return;
}
$response->setContent('');
return 404;
}
}