[FILE][TemporaryFile] Fix various issues now that we also have Symfony's file abstractions
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user