From 3c9a07677e60eb2bd6c6989338f36655a6d6ebbc Mon Sep 17 00:00:00 2001 From: Miguel Dantas Date: Tue, 25 Jun 2019 23:20:17 +0100 Subject: [PATCH] [CORE] Attachments and thumbnails aren't accessed directly by the file under the file storage folder, but indirectly from PHP, so that access to the file folder can be blocked in the server config --- README.md | 2 +- actions/attachment_thumbnail.php | 39 +++++++++++++++++++++++++++++--- classes/File.php | 5 ++++ lib/attachment.php | 2 +- lib/framework.php | 2 +- lib/mediafile.php | 37 ------------------------------ 6 files changed, 44 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index c4529dd6b0..e14c7d6b92 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GNU social 1.22.x +# GNU social 1.23.x (c) 2010-2019 Free Software Foundation, Inc This is the README file for GNU social, the free diff --git a/actions/attachment_thumbnail.php b/actions/attachment_thumbnail.php index cc1b0f09c6..577505c8e1 100644 --- a/actions/attachment_thumbnail.php +++ b/actions/attachment_thumbnail.php @@ -57,11 +57,44 @@ class Attachment_thumbnailAction extends AttachmentAction { // Returns a File_thumbnail object or throws exception if not available try { - $thumbnail = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_c); + $file = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_c)->getFile(); } catch (UseFileAsThumbnailException $e) { - common_redirect($e->file->getUrl(), 302); + // With this exception, the file exists locally + $file = $e->file; } - common_redirect(File_thumbnail::url($thumbnail->getFilename()), 302); + if (!$file->isLocal()) { + // Not locally stored, redirect to the URL the file came from + // Don't use getURL because it can give us a local URL, which we don't want + common_redirect($file->url, 302); + } else { + $filepath = $this->attachment->getPath(); + $filename = MediaFile::getDisplayName($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); + + header("Content-Description: File Transfer"); + header("Content-Type: {$file->mimetype}"); + header("Content-Disposition: inline; filename=\"{$filename}\""); + header('Expires: 0'); + header('Content-Transfer-Encoding: binary'); + $filesize = $this->file->size; + // 'if available', it says, so ensure we have it + if (empty($filesize)) { + $filesize = filesize($this->attachment->filename); + } + header("Content-Length: {$filesize}"); + // header('Cache-Control: private, no-transform, no-store, must-revalidate'); + + $ret = @readfile($filepath); + + if ($ret === false || $ret !== $filesize) { + common_log(LOG_ERR, "The lengths of the file as recorded on the DB (or on disk) for the file " . + "{$filepath}, with id={$this->attachment->id} differ from what was sent to the user."); + } + } } } diff --git a/classes/File.php b/classes/File.php index 4bf91cebff..902cafeabc 100644 --- a/classes/File.php +++ b/classes/File.php @@ -594,6 +594,11 @@ class File extends Managed_DataObject return common_local_url('attachment', array('attachment'=>$this->getID())); } + public function getAttachmentDownloadUrl() + { + return common_local_url('attachment_download', array('attachment'=>$this->getID())); + } + /** * @param mixed $use_local true means require local, null means prefer local, false means use whatever is stored * @return string diff --git a/lib/attachment.php b/lib/attachment.php index d001337dd6..8e69b5a59a 100644 --- a/lib/attachment.php +++ b/lib/attachment.php @@ -56,6 +56,6 @@ class Attachment extends AttachmentListItem } function linkAttr() { - return array('rel' => 'external', 'href' => $this->attachment->getUrl()); + return array('rel' => 'external', 'href' => $this->attachment->getAttachmentDownloadUrl()); } } diff --git a/lib/framework.php b/lib/framework.php index 385acb36b2..664e8707b3 100644 --- a/lib/framework.php +++ b/lib/framework.php @@ -32,7 +32,7 @@ defined('GNUSOCIAL') || die(); define('GNUSOCIAL_ENGINE', 'GNU social'); define('GNUSOCIAL_ENGINE_URL', 'https://www.gnu.org/software/social/'); -define('GNUSOCIAL_BASE_VERSION', '1.22.1'); +define('GNUSOCIAL_BASE_VERSION', '1.23.0'); define('GNUSOCIAL_LIFECYCLE', 'dev'); // 'dev', 'alpha[0-9]+', 'beta[0-9]+', 'rc[0-9]+', 'release' define('GNUSOCIAL_VERSION', GNUSOCIAL_BASE_VERSION . '-' . GNUSOCIAL_LIFECYCLE); diff --git a/lib/mediafile.php b/lib/mediafile.php index b38bab6436..76e5541ea0 100644 --- a/lib/mediafile.php +++ b/lib/mediafile.php @@ -83,9 +83,7 @@ class MediaFile array('attachment' => $this->fileRecord->id) ); - $this->maybeAddRedir($this->fileRecord->id, $this->fileurl); $this->short_fileurl = common_shorten_url($this->fileurl); - $this->maybeAddRedir($this->fileRecord->id, $this->short_fileurl); } } @@ -210,41 +208,6 @@ class MediaFile return $file; } - public function rememberFile($file, $short) - { - $this->maybeAddRedir($file->id, $short); - } - - /** - * Adds Redir if needed. - * - * @param $file_id - * @param $url - * @return bool false if no need to add, true if added - * @throws ClientException If failed adding - */ - public function maybeAddRedir($file_id, $url) - { - try { - File_redirection::getByUrl($url); - return false; - } catch (NoResultException $e) { - $file_redir = new File_redirection; - $file_redir->urlhash = File::hashurl($url); - $file_redir->url = $url; - $file_redir->file_id = $file_id; - - $result = $file_redir->insert(); - - if ($result===false) { - common_log_db_error($file_redir, "INSERT", __FILE__); - // TRANS: Client exception thrown when a database error was thrown during a file upload operation. - throw new ClientException(_('There was a database error while saving your file. Please try again.')); - } - return $result; - } - } - /** * The maximum allowed file size, as a string */