[Media] Copy media subsystem from v2 and roughly structure it for v3

This commit is contained in:
2021-04-11 20:53:23 +00:00
parent 6606a72e67
commit 66ed6fb658
14 changed files with 422 additions and 295 deletions

View File

@@ -0,0 +1,227 @@
<?php
// {{{ License
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
// }}}
namespace Plugin\Media\Controller;
use App\Core\Controller;
use Symfony\Component\HttpFoundation\Request;
/**
* Show note attachments
*
* @author Evan Prodromou <evan@status.net>
* @author Hugo Sales <hugo@hsal.es>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
*
* @see http://status.net/
*/
class Attachment extends Controller
{
public function handle(Request $request)
{
return [
'_template' => 'doc/tos.html.twig',
];
}
/**
* Attachment File object to show
*/
public $attachment;
public $filehash;
public $filepath;
public $filesize;
public $mimetype;
public $filename;
/**
* Load attributes based on database arguments
*
* Loads all the DB stuff
*
* @param array $args $_REQUEST array
*
* @throws ClientException
* @throws FileNotFoundException
* @throws FileNotStoredLocallyException
* @throws InvalidFilenameException
* @throws ServerException
*
* @return bool flag
*/
protected function prepare(array $args = [])
{
// parent::prepare($args);
try {
if (!empty($id = $this->trimmed('attachment'))) {
$this->attachment = File::getByID((int) $id);
} elseif (!empty($this->filehash = $this->trimmed('filehash'))) {
$file = File::getByHash($this->filehash);
$file->fetch();
$this->attachment = $file;
}
} catch (Exception $e) {
// Not found
}
if (!$this->attachment instanceof File) {
// TRANS: Client error displayed trying to get a non-existing attachment.
$this->clientError(_m('No such attachment.'), 404);
}
$this->filesize = $this->attachment->size;
$this->mimetype = $this->attachment->mimetype;
$this->filename = $this->attachment->filename;
if ($this->attachment->isLocal() || $this->attachment->isFetchedRemoteFile()) {
$this->filesize = $this->attachment->getFileOrThumbnailSize();
$this->mimetype = $this->attachment->getFileOrThumbnailMimetype();
$this->filename = MediaFile::getDisplayName($this->attachment);
}
return true;
}
/**
* Is this action read-only?
*
* @param mixed $args
*
* @return bool true
*/
public function isReadOnly($args): bool
{
return true;
}
/**
* Title of the page
*
* @return string title of the page
*/
public function title(): string
{
$a = new self($this->attachment);
return $a->title();
}
public function showPage(): void
{
if (empty($this->filepath)) {
// if it's not a local file, gtfo
common_redirect($this->attachment->getUrl(), 303);
}
// parent::showPage();
}
/**
* Fill the content area of the page
*
* Shows a single notice list item.
*
* @return void
*/
public function showContent(): void
{
$ali = new self($this->attachment, $this);
$ali->show();
}
/**
* Don't show page notice
*
* @return void
*/
public function showPageNoticeBlock(): void
{
}
/**
* Show aside: this attachments appears in what notices
*
* @return void
*/
public function showSections(): void
{
$ns = new AttachmentNoticeSection($this);
$ns->show();
}
/**
* Last-modified date for file
*
* @throws ServerException
*
* @return int last-modified date as unix timestamp
*/
public function lastModified(): ?int
{
if (common_config('site', 'use_x_sendfile')) {
return null;
}
$path = $this->filepath;
if (!empty($path)) {
return filemtime($path);
} else {
return null;
}
}
/**
* etag header for file
*
* This returns the same data (inode, size, mtime) as Apache would,
* but in decimal instead of hex.
*
* @throws ServerException
*
* @return string etag http header
*/
public function etag(): ?string
{
if (common_config('site', 'use_x_sendfile')) {
return null;
}
$path = $this->filepath;
$cache = Cache::instance();
if ($cache) {
if (empty($path)) {
return null;
}
$key = Cache::key('attachments:etag:' . $path);
$etag = $cache->get($key);
if ($etag === false) {
$etag = crc32(file_get_contents($path));
$cache->set($key, $etag);
}
return $etag;
}
if (!empty($path)) {
$stat = stat($path);
return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
} else {
return null;
}
}
}

View File

@@ -0,0 +1,58 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
namespace Plugin\Media\Controller;
/**
* Download notice attachment
*
* @category Personal
* @package GNUsocial
*
* @author Mikael Nordfeldth <mmn@hethane.se>
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
*
* @see https:/gnu.io/social
*/
class AttachmentDownload extends Attachment
{
public function showPage(): void
{
// Disable errors, to not mess with the file contents (suppress errors in case access to this
// function is blocked, like in some shared hosts). Automatically reset at the end of the
// script execution, and we don't want to have any more errors until then, so don't reset it
@ini_set('display_errors', 0);
if ($this->attachment->isLocal()) {
try {
$this->filepath = $this->attachment->getFileOrThumbnailPath();
} catch (Exception $e) {
$this->clientError(
_m('Requested local URL for a file that is not stored locally.'),
404
);
}
common_send_file(
$this->filepath,
$this->mimetype,
$this->filename,
'attachment'
);
} else {
common_redirect($this->attachment->getUrl(), 303);
}
}
}

View File

@@ -0,0 +1,79 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
namespace Plugin\Media\Controller;
/**
* Show notice attachments
*
* @category Personal
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class Attachment_thumbnailAction extends Attachment_viewAction
{
protected $thumb_w; // max width
protected $thumb_h; // max height
protected $thumb_c; // crop?
protected function doPreparation()
{
parent::doPreparation();
$this->thumb_w = $this->int('w');
$this->thumb_h = $this->int('h');
$this->thumb_c = $this->boolean('c');
}
/**
* Show an inline representation of an attachment of the size
* requested in the GET variables (read in the constructor). Tries
* to send the most appropriate file with the correct size and
* headers or displays an error if it's not possible.
*
* @throws ClientException
* @throws ReflectionException
* @throws ServerException
*/
public function showPage(): void
{
// Returns a File_thumbnail object or throws exception if not available
$filename = $this->filename;
$filepath = $this->filepath;
try {
$thumbnail = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_c);
$file = $thumbnail->getFile();
} catch (UseFileAsThumbnailException $e) {
// With this exception, the file exists locally $e->file;
} catch (FileNotFoundException $e) {
$this->clientError(_m('No such attachment'), 404);
} catch (Exception $e) {
if (is_null($filepath)) {
$this->clientError(_m('No such thumbnail'), 404);
}
// Remote file
}
// Disable errors, to not mess with the file contents (suppress errors in case access to this
// function is blocked, like in some shared hosts). Automatically reset at the end of the
// script execution, and we don't want to have any more errors until then, so don't reset it
@ini_set('display_errors', 0);
common_send_file($filepath, image_type_to_mime_type(IMAGETYPE_WEBP), $filename, 'inline');
}
}

View File

@@ -0,0 +1,54 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
namespace Plugin\Media\Controller;
/**
* View notice attachment
*
* @package GNUsocial
*
* @author Miguel Dantas <biodantasgs@gmail.com>
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
*/
class AttachmentView extends Attachment
{
public function showPage(): void
{
// Disable errors, to not mess with the file contents (suppress errors in case access to this
// function is blocked, like in some shared hosts). Automatically reset at the end of the
// script execution, and we don't want to have any more errors until then, so don't reset it
@ini_set('display_errors', 0);
if ($this->attachment->isLocal() || $this->attachment->isFetchedRemoteFile()) {
try {
$this->filepath = $this->attachment->getFileOrThumbnailPath();
} catch (Exception $e) {
$this->clientError(
_m('Requested local URL for a file that is not stored locally.'),
404
);
}
$disposition = 'attachment';
if (in_array(common_get_mime_media($this->mimetype), ['image', 'video'])) {
$disposition = 'inline';
}
common_send_file($this->filepath, $this->mimetype, $this->filename, $disposition);
} else {
common_redirect($this->attachment->getUrl(), 303);
}
}
}