Moved user asset loading into the router.
This commit is contained in:
parent
0e885f6311
commit
fa80803dd2
6 changed files with 105 additions and 71 deletions
|
@ -16,7 +16,11 @@ Router::addRoutes(
|
|||
Route::get('/', 'index', 'Home'),
|
||||
|
||||
// Assets
|
||||
Route::get('/assets/([a-zA-Z0-9\-]+)\.(css|js)', 'view', 'Assets'),
|
||||
Route::group('/assets', 'Assets')->addChildren(
|
||||
Route::get('/([a-zA-Z0-9\-]+)\.(css|js)', 'serveComponent'),
|
||||
Route::get('/avatar/([0-9]+)(?:\.png)?', 'serveAvatar'),
|
||||
Route::get('/profile-background/([0-9]+)(?:\.png)?', 'serveProfileBackground'),
|
||||
),
|
||||
|
||||
// Info
|
||||
Route::get('/info', 'index', 'Info'),
|
||||
|
@ -71,6 +75,7 @@ Router::addRoutes(
|
|||
Route::get('/news/feed.php', 'legacy', 'News'),
|
||||
Route::get('/news/feed.php/rss', 'legacy', 'News'),
|
||||
Route::get('/news/feed.php/atom', 'legacy', 'News'),
|
||||
Route::get('/user-assets.php', 'serveLegacy', 'Assets'),
|
||||
);
|
||||
|
||||
$response = Router::handle($request);
|
||||
|
@ -90,7 +95,7 @@ foreach($response->getHeaders() as $name => $lines) {
|
|||
|
||||
$responseBody = $response->getBody();
|
||||
|
||||
if($responseStatus >= 400 && $responseStatus <= 599 && ($responseBody === null || $responseBody->getSize() < 1))
|
||||
if($responseStatus >= 400 && $responseStatus <= 599 && $responseBody === null)
|
||||
echo render_error($responseStatus);
|
||||
else
|
||||
echo (string)$responseBody;
|
||||
|
|
|
@ -1,66 +1,2 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
use Misuzu\Users\User;
|
||||
use Misuzu\Users\UserNotFoundException;
|
||||
use Misuzu\Users\Assets\StaticUserImageAsset;
|
||||
use Misuzu\Users\Assets\UserAssetScalableInterface;
|
||||
|
||||
$assetMode = (string)filter_input(INPUT_GET, 'm', FILTER_SANITIZE_STRING);
|
||||
$assetUserId = (int)filter_input(INPUT_GET, 'u', FILTER_SANITIZE_NUMBER_INT);
|
||||
$assetDims = filter_input(INPUT_GET, 'r', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
$misuzuBypassLockdown = $assetMode === 'avatar';
|
||||
|
||||
require_once '../misuzu.php';
|
||||
|
||||
try {
|
||||
$assetUser = User::byId($assetUserId);
|
||||
} catch(UserNotFoundException $ex) {}
|
||||
|
||||
$assetVisible = !isset($assetUser) || !$assetUser->isBanned() || (
|
||||
parse_url($_SERVER['HTTP_REFERER'] ?? '', PHP_URL_PATH) === url('user-profile')
|
||||
&& User::hasCurrent() && perms_check_user(MSZ_PERMS_USER, User::getCurrent()->getId(), MSZ_PERM_USER_MANAGE_USERS)
|
||||
);
|
||||
|
||||
switch($assetMode) {
|
||||
case 'avatar':
|
||||
if(!$assetVisible) {
|
||||
$assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/banned-avatar.png', MSZ_PUBLIC);
|
||||
break;
|
||||
}
|
||||
|
||||
$assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/no-avatar.png', MSZ_PUBLIC);
|
||||
|
||||
if(!isset($assetUser) || !$assetUser->hasAvatar())
|
||||
break;
|
||||
|
||||
$assetInfo = $assetUser->getAvatarInfo();
|
||||
break;
|
||||
|
||||
case 'background':
|
||||
if(!$assetVisible || !isset($assetUser) || !$assetUser->hasBackground())
|
||||
break;
|
||||
$assetInfo = $assetUser->getBackgroundInfo();
|
||||
break;
|
||||
}
|
||||
|
||||
if(!isset($assetInfo) || !$assetInfo->isPresent()) {
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
$contentType = $assetInfo->getMimeType();
|
||||
$publicPath = $assetInfo->getPublicPath();
|
||||
$fileName = $assetInfo->getFileName();
|
||||
|
||||
if($assetDims > 0 && $assetInfo instanceof UserAssetScalableInterface) {
|
||||
$assetInfo->ensureScaledExists($assetDims);
|
||||
|
||||
$publicPath = $assetInfo->getPublicScaledPath($assetDims);
|
||||
$fileName = $assetInfo->getScaledFileName($assetDims);
|
||||
}
|
||||
|
||||
header(sprintf('X-Accel-Redirect: %s', $publicPath));
|
||||
header(sprintf('Content-Type: %s', $contentType));
|
||||
header(sprintf('Content-Disposition: inline; filename="%s"', $fileName));
|
||||
require_once __DIR__ . '/index.php';
|
||||
|
|
|
@ -4,6 +4,11 @@ namespace Misuzu\Http\Handlers;
|
|||
use HttpResponse;
|
||||
use HttpRequest;
|
||||
use Misuzu\GitInfo;
|
||||
use Misuzu\Users\User;
|
||||
use Misuzu\Users\UserNotFoundException;
|
||||
use Misuzu\Users\Assets\StaticUserImageAsset;
|
||||
use Misuzu\Users\Assets\UserImageAssetInterface;
|
||||
use Misuzu\Users\Assets\UserAssetScalableInterface;
|
||||
|
||||
final class AssetsHandler extends Handler {
|
||||
private const TYPES = [
|
||||
|
@ -44,7 +49,7 @@ final class AssetsHandler extends Handler {
|
|||
return $str;
|
||||
}
|
||||
|
||||
public static function view(HttpResponse $response, HttpRequest $request, string $name, string $type) {
|
||||
public function serveComponent(HttpResponse $response, HttpRequest $request, string $name, string $type) {
|
||||
$entityTag = sprintf('W/"%s.%s/%s"', $name, $type, GitInfo::hash());
|
||||
|
||||
if(!MSZ_DEBUG && $name === 'debug')
|
||||
|
@ -64,4 +69,78 @@ final class AssetsHandler extends Handler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function canViewAsset(HttpRequest $request, User $assetUser): bool {
|
||||
return !$assetUser->isBanned() || (
|
||||
User::hasCurrent()
|
||||
&& parse_url($request->getHeaderLine('Referer'), PHP_URL_PATH) === url('user-profile')
|
||||
&& perms_check_user(MSZ_PERMS_USER, User::getCurrent()->getId(), MSZ_PERM_USER_MANAGE_USERS)
|
||||
);
|
||||
}
|
||||
|
||||
private function serveUserAsset(HttpResponse $response, HttpRequest $request, UserImageAssetInterface $assetInfo): void {
|
||||
$contentType = $assetInfo->getMimeType();
|
||||
$publicPath = $assetInfo->getPublicPath();
|
||||
$fileName = $assetInfo->getFileName();
|
||||
|
||||
if($assetInfo instanceof UserAssetScalableInterface) {
|
||||
$dimensions = (int)($request->getQueryParam('res', FILTER_SANITIZE_NUMBER_INT) ?? $request->getQueryParam('r', FILTER_SANITIZE_NUMBER_INT));
|
||||
|
||||
if($dimensions > 0) {
|
||||
$assetInfo->ensureScaledExists($dimensions);
|
||||
$contentType = $assetInfo->getScaledMimeType($dimensions);
|
||||
$publicPath = $assetInfo->getPublicScaledPath($dimensions);
|
||||
$fileName = $assetInfo->getScaledFileName($dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
$response->setHeader('X-Accel-Redirect', $publicPath);
|
||||
$response->setHeader('Content-Type', $contentType);
|
||||
$response->setHeader('Content-Disposition', sprintf('inline; filename="%s"', $fileName));
|
||||
}
|
||||
|
||||
public function serveAvatar(HttpResponse $response, HttpRequest $request, int $userId) {
|
||||
$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(UserNotFoundException $ex) {}
|
||||
|
||||
$this->serveUserAsset($response, $request, $assetInfo);
|
||||
}
|
||||
|
||||
public function serveProfileBackground(HttpResponse $response, HttpRequest $request, int $userId) {
|
||||
try {
|
||||
$userInfo = User::byId($userId);
|
||||
} catch(UserNotFoundException $ex) {}
|
||||
|
||||
if(empty($userInfo) || !$userInfo->hasBackground() || !$this->canViewAsset($request, $userInfo)) {
|
||||
$response->setText('');
|
||||
return 404;
|
||||
}
|
||||
|
||||
$this->serveUserAsset($response, $request, $userInfo->getBackgroundInfo());
|
||||
}
|
||||
|
||||
public function serveLegacy(HttpResponse $response, HttpRequest $request) {
|
||||
$assetUserId = (int)$request->getQueryParam('u', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
switch($request->getQueryParam('m')) {
|
||||
case 'avatar':
|
||||
$this->serveAvatar($response, $request, $assetUserId);
|
||||
return;
|
||||
case 'background':
|
||||
$this->serveProfileBackground($response, $request, $assetUserId);
|
||||
return;
|
||||
}
|
||||
|
||||
$response->setText('');
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,4 +9,6 @@ interface UserAssetScalableInterface {
|
|||
public function ensureScaledExists(int $dims): void;
|
||||
public function getPublicScaledPath(int $dims): string;
|
||||
public function getScaledFileName(int $dims): string;
|
||||
public function getScaledFileExtension(int $dims): string;
|
||||
public function getScaledMimeType(int $dims): string;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,19 @@ class UserAvatarAsset extends UserImageAsset implements UserAssetScalableInterfa
|
|||
return sprintf('avatar-%1$d.%2$s', $this->getUser()->getId(), $this->getFileExtension());
|
||||
}
|
||||
public function getScaledFileName(int $dims): string {
|
||||
return sprintf('avatar-%1$d-%3$dx%3$d.%2$s', $this->getUser()->getId(), $this->getFileExtension(), self::clampDimensions($dims));
|
||||
return sprintf('avatar-%1$d-%3$dx%3$d.%2$s', $this->getUser()->getId(), $this->getScaledFileExtension($dims), self::clampDimensions($dims));
|
||||
}
|
||||
|
||||
public function getScaledMimeType(int $dims): string {
|
||||
if(!$this->isScaledPresent($dims))
|
||||
return '';
|
||||
return mime_content_type($this->getScaledPath($dims));
|
||||
}
|
||||
public function getScaledFileExtension(int $dims): string {
|
||||
$imageSize = getimagesize($this->getScaledPath($dims));
|
||||
if($imageSize === null)
|
||||
return 'img';
|
||||
return self::TYPES_EXT[$imageSize[2]] ?? 'img';
|
||||
}
|
||||
|
||||
public function getRelativePath(): string {
|
||||
|
|
|
@ -74,8 +74,8 @@ define('MSZ_URLS', [
|
|||
'user-profile-edit' => ['/profile.php', ['u' => '<user>', 'edit' => '1']],
|
||||
'user-account-standing' => ['/profile.php', ['u' => '<user>'], 'account-standing'],
|
||||
|
||||
'user-avatar' => ['/user-assets.php', ['u' => '<user>', 'm' => 'avatar', 'r' => '<res>']],
|
||||
'user-background' => ['/user-assets.php', ['u' => '<user>', 'm' => 'background']],
|
||||
'user-avatar' => ['/assets/avatar/<user>', ['res' => '<res>']],
|
||||
'user-background' => ['/assets/profile-background/<user>'],
|
||||
|
||||
'user-relation-create' => ['/relations.php', ['u' => '<user>', 'm' => '<type>', 'csrf' => '{csrf}']],
|
||||
'user-relation-none' => ['/relations.php', ['u' => '<user>', 'm' => '[\Misuzu\Users\UserRelation::TYPE_NONE]', 'csrf' => '{csrf}']],
|
||||
|
|
Loading…
Reference in a new issue