Add DownloadAttachment class to handle file downloads and permissions validation
This commit is contained in:
parent
e23d3280ee
commit
ebcda77d9c
1 changed files with 101 additions and 0 deletions
101
src/FederationServer/Methods/DownloadAttachment.php
Normal file
101
src/FederationServer/Methods/DownloadAttachment.php
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace FederationServer\Methods;
|
||||
|
||||
use FederationServer\Classes\Configuration;
|
||||
use FederationServer\Classes\Managers\EvidenceManager;
|
||||
use FederationServer\Classes\Managers\FileAttachmentManager;
|
||||
use FederationServer\Classes\RequestHandler;
|
||||
use FederationServer\Classes\Validate;
|
||||
use FederationServer\Exceptions\RequestException;
|
||||
use FederationServer\FederationServer;
|
||||
use Throwable;
|
||||
|
||||
class DownloadAttachment extends RequestHandler
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function handleRequest(): void
|
||||
{
|
||||
if(!preg_match('#^/attachment/([a-fA-F0-9\-]{36,})$#', FederationServer::getPath(), $matches))
|
||||
{
|
||||
throw new RequestException('Attachment UUID required', 405);
|
||||
}
|
||||
|
||||
$uuid = $matches[1];
|
||||
if(!$uuid || !Validate::uuid($uuid))
|
||||
{
|
||||
throw new RequestException('Invalid attachment UUID', 400);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$attachment = FileAttachmentManager::getRecord($uuid);
|
||||
if(!$attachment)
|
||||
{
|
||||
throw new RequestException('Attachment not found', 404);
|
||||
}
|
||||
|
||||
$evidence = EvidenceManager::getEvidence($attachment->getEvidence());
|
||||
if($evidence && $evidence->isConfidential())
|
||||
{
|
||||
// Require authentication if confidential
|
||||
$operator = FederationServer::getAuthenticatedOperator();
|
||||
if(!$operator->canManageBlacklist())
|
||||
{
|
||||
throw new RequestException('Insufficient Permissions to view confidential evidence', 401);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Throwable $e)
|
||||
{
|
||||
throw new RequestException('Error retrieving attachment: ' . $e->getMessage(), 500, $e);
|
||||
}
|
||||
|
||||
$fileLocation = Configuration::getServerConfiguration()->getStoragePath() . DIRECTORY_SEPARATOR . $attachment->getUuid();
|
||||
if(!file_exists($fileLocation))
|
||||
{
|
||||
throw new RequestException('Attachment file not found', 404);
|
||||
}
|
||||
|
||||
// Set headers for file download
|
||||
header('Content-Type: ' . $attachment->getFileMime());
|
||||
header('Content-Disposition: attachment; filename="' . $attachment->getFileName() . '"');
|
||||
header('Content-Length: ' . filesize($fileLocation));
|
||||
header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1
|
||||
header('Pragma: no-cache'); // HTTP 1.0
|
||||
header('Expires: 0'); // Proxies
|
||||
|
||||
$chunkSize = 8192; // 8KB per chunk
|
||||
$handle = fopen($fileLocation, 'rb');
|
||||
|
||||
if ($handle === false)
|
||||
{
|
||||
throw new RequestException('Failed to open attachment file for reading', 500);
|
||||
}
|
||||
|
||||
while (!feof($handle))
|
||||
{
|
||||
$buffer = fread($handle, $chunkSize);
|
||||
if ($buffer === false)
|
||||
{
|
||||
fclose($handle);
|
||||
throw new RequestException('Error reading attachment file', 500);
|
||||
}
|
||||
|
||||
print($buffer);
|
||||
|
||||
// Flush output buffers to send data immediately
|
||||
if (ob_get_level())
|
||||
{
|
||||
ob_flush();
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue