[FILE][TemporaryFile] Fix various issues now that we also have Symfony's file abstractions

This commit is contained in:
2021-07-20 21:17:53 +01:00
committed by Hugo Sales
parent 6c0f3a336e
commit c8cf8c3f13
14 changed files with 196 additions and 87 deletions

View File

@@ -22,49 +22,73 @@
namespace App\Core;
use App\Core\DB\DB;
use function App\Core\I18n\_m;
use App\Entity\Attachment;
use App\Util\Common;
use App\Util\Exception\ClientException;
use App\Util\Exception\DuplicateFoundException;
use App\Util\Exception\NoSuchFileException;
use App\Util\Exception\NotFoundException;
use App\Util\Exception\ServerException;
use InvalidArgumentException;
use SplFileInfo;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File as SymfonyFile;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
use function App\Core\I18n\_m;
/**
* GNU social's File Abstraction
*
* @category Files
* @package GNUsocial
*
* @author Hugo Sales <hugo@hsal.es>
* @author Diogo Peralta Cordeiro <mail@diogo.site>
* @copyright 2020-2021 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class GSFile
{
/**
* Perform file validation (checks and normalization) and store the given file
*
* @param SplFileInfo $file
* @param string $dest_dir
* @param null|string $title
* @param bool $is_local
* @param null|int $actor_id
*
* @return Attachment
* @throws DuplicateFoundException
*/
public static function validateAndStoreFileAsAttachment(SymfonyFile $sfile,
public static function validateAndStoreFileAsAttachment(SplFileInfo $file,
string $dest_dir,
?string $title = null,
bool $is_local = true,
int $actor_id = null): Attachment
{
Event::handle('HashFile', [$sfile->getPathname(), &$hash]);
$hash = null;
Event::handle('HashFile', [$file->getPathname(), &$hash]);
try {
return DB::findOneBy('attachment', ['file_hash' => $hash]);
} catch (NotFoundException) {
// The following properly gets the mimetype with `file` or other
// available methods, so should be safe
$mimetype = $sfile->getMimeType();
Event::handle('AttachmentValidation', [&$sfile, &$mimetype, &$title, &$width, &$height]);
$mimetype = $file->getMimeType();
$title = $width = $height = null;
Event::handle('AttachmentValidation', [&$file, &$mimetype, &$title, &$width, &$height]);
$attachment = Attachment::create([
'file_hash' => $hash,
'file_hash' => $hash,
'gsactor_id' => $actor_id,
'mimetype' => $mimetype,
'title' => $title ?: _m('Untitled attachment'),
'filename' => $hash,
'is_local' => $is_local,
'size' => $sfile->getSize(),
'width' => $width,
'height' => $height,
'mimetype' => $mimetype,
'title' => $title ?: _m('Untitled attachment'),
'filename' => $hash,
'is_local' => $is_local,
'size' => $file->getSize(),
'width' => $width,
'height' => $height,
]);
$sfile->move($dest_dir, $hash);
$file->move($dest_dir, $hash);
DB::persist($attachment);
Event::handle('AttachmentStoreNew', [&$attachment]);
return $attachment;
@@ -74,32 +98,32 @@ class GSFile
/**
* Create an attachment for the given URL, fetching the mimetype
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public static function validateAndStoreURLAsAttachment(string $url): Attachment
{
if (Common::isValidHttpUrl($url)) {
$head = HTTPClient::head($url);
// This must come before getInfo given that Symfony HTTPClient is lazy (thus forcing curl exec)
$headers = $head->getHeaders();
$url = $head->getInfo('url'); // The last effective url (after getHeaders so it follows redirects)
$headers = $head->getHeaders();
$url = $head->getInfo('url'); // The last effective url (after getHeaders so it follows redirects)
$url_hash = hash(Attachment::URLHASH_ALGO, $url);
try {
return DB::findOneBy('attachment', ['remote_url_hash' => $url_hash]);
} catch (NotFoundException) {
$headers = array_change_key_case($headers, CASE_LOWER);
$headers = array_change_key_case($headers, CASE_LOWER);
$attachment = Attachment::create([
'remote_url' => $url,
'remote_url' => $url,
'remote_url_hash' => $url_hash,
'mimetype' => $headers['content-type'][0],
'is_local' => false,
'mimetype' => $headers['content-type'][0],
'is_local' => false,
]);
DB::persist($attachment);
Event::handle('AttachmentStoreNew', [&$attachment]);
return $attachment;
}
} else {
throw new \InvalidArgumentException();
throw new InvalidArgumentException();
}
}
@@ -116,9 +140,9 @@ class GSFile
Response::HTTP_OK,
[
'Content-Description' => 'File Transfer',
'Content-Type' => $mimetype,
'Content-Type' => $mimetype,
'Content-Disposition' => HeaderUtils::makeDisposition($disposition, $output_filename ?: _m('Untitled attachment'), _m('Untitled attachment')),
'Cache-Control' => 'public',
'Cache-Control' => 'public',
],
$public = true,
$disposition = null,
@@ -181,7 +205,7 @@ class GSFile
*/
public static function getAttachmentFileInfo(int $id): array
{
$res = self::getFileInfo($id);
$res = self::getFileInfo($id);
$res['filepath'] = Common::config('attachments', 'dir') . $res['file_hash'];
return $res;
}