usersCtx->getBans()->countActiveBans($assetUser)) // allow staff viewing profile to still see banned user assets // should change the Referer check with some query param only applied when needed return $this->authInfo->getPerms('user')->check(Perm::U_USERS_MANAGE) && parse_url($request->getHeaderFirstLine('Referer'), PHP_URL_PATH) === $this->urls->format('user-profile'); return true; } #[HttpGet('/assets/avatar')] #[HttpGet('/assets/avatar/([0-9]+)(?:\.[a-z]+)?')] #[URLInfo('user-avatar', '/assets/avatar/', ['res' => ''])] public function getAvatar($response, $request, string $userId = '') { $assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/no-avatar.png', MSZ_PUBLIC); try { $userInfo = $this->usersCtx->getUserInfo($userId); if(!$this->canViewAsset($request, $userInfo)) { $assetInfo = new StaticUserImageAsset(MSZ_PUBLIC . '/images/banned-avatar.png', MSZ_PUBLIC); } else { $userAssetInfo = new UserAvatarAsset($userInfo); if($userAssetInfo->isPresent()) $assetInfo = $userAssetInfo; } } catch(RuntimeException $ex) { } catch(InvalidArgumentException $ex) {} $this->serveAsset($response, $request, $assetInfo); } #[HttpGet('/assets/profile-background')] #[HttpGet('/assets/profile-background/([0-9]+)(?:\.[a-z]+)?')] #[URLInfo('user-background', '/assets/profile-background/')] public function getProfileBackground($response, $request, string $userId = '') { try { $userInfo = $this->usersCtx->getUserInfo($userId); } catch(RuntimeException $ex) { } catch(InvalidArgumentException $ex) {} if(!empty($userInfo)) { $userAssetInfo = new UserBackgroundAsset($userInfo); if($userAssetInfo->isPresent() && $this->canViewAsset($request, $userInfo)) $assetInfo = $userAssetInfo; } if(!isset($assetInfo)) { // circumvent the default error page $response->setContent('Not Found'); return 404; } $this->serveAsset($response, $request, $assetInfo); } #[HttpGet('/user-assets.php')] public function getUserAssets($response, $request) { $userId = (string)$request->getParam('u', FILTER_SANITIZE_NUMBER_INT); $mode = (string)$request->getParam('m'); if($mode === 'avatar') return $this->getAvatar($response, $request, $userId); if($mode === 'background') return $this->getProfileBackground($response, $request, $userId); // circumvent the default error page $response->setContent('Not Found'); return 404; } private function serveAsset($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); } }