@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\HeaderUtils;
|
||||
|
||||
/** Authorization/publication stays with the consumer; originals share integrity and cipher handling. */
|
||||
class VerifiedDocumentBinary
|
||||
{
|
||||
public function respond(object $document, bool $inline = false): Response|BinaryFileResponse
|
||||
{
|
||||
abort_unless($document->status === 'active' && $document->malware_scan_status === 'clean'
|
||||
&& ($document->deleted_at ?? null) === null && hash_equals(trim($document->sha256), trim((string) $document->malware_scanned_sha256)), 404);
|
||||
$disk = Storage::disk('local');
|
||||
$root = realpath($disk->path(''));
|
||||
$path = realpath($disk->path($document->storage_key));
|
||||
abort_unless($root && $path && str_starts_with(strtolower($path), strtolower($root.DIRECTORY_SEPARATOR)) && is_file($path), 404);
|
||||
$headers = ['X-Content-Type-Options' => 'nosniff', 'Cache-Control' => 'private, no-store'];
|
||||
if ($inline) {
|
||||
$headers['Content-Type'] = $document->media_type;
|
||||
$headers['Content-Security-Policy'] = "sandbox; default-src 'none'; style-src 'unsafe-inline'";
|
||||
}
|
||||
if (($document->storage_encryption ?? null) === 'laravel') {
|
||||
try {
|
||||
$bytes = Crypt::decryptString($disk->get($document->storage_key));
|
||||
} catch (DecryptException) {
|
||||
abort(404);
|
||||
}
|
||||
abort_unless(hash_equals(trim($document->sha256), hash('sha256', $bytes)), 404);
|
||||
$headers['Content-Type'] = $document->media_type;
|
||||
$headers['Content-Disposition'] = HeaderUtils::makeDisposition($inline ? 'inline' : 'attachment', basename($document->file_name), 'document');
|
||||
|
||||
return response($bytes, 200, $headers);
|
||||
}
|
||||
abort_unless(($document->storage_encryption ?? null) === null, 404);
|
||||
$checksum = hash_file('sha256', $path);
|
||||
abort_unless(is_string($checksum) && hash_equals(trim($document->sha256), $checksum), 404);
|
||||
|
||||
return $inline ? response()->file($path, $headers)->setContentDisposition('inline', basename($document->file_name)) : response()->download($path, basename($document->file_name), $headers);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user