if (!$this->attachment instanceof File) {
// TRANS: Client error displayed trying to get a non-existing attachment.
$this->clientError(_('No such attachment.'), 404);
- } elseif (empty($this->attachment->filename)) {
+ }
+
+ $filename = $this->attachment->getFileOrThumbnailPath();
+
+ if (empty($filename)) {
$this->clientError(_('Requested local URL for a file that is not stored locally.'), 404);
}
return true;
public function showPage()
{
- if (empty($this->attachment->filename)) {
+ if (empty($this->attachment->getFileOrThumbnailPath())) {
// if it's not a local file, gtfo
common_redirect($this->attachment->getUrl(), 303);
}
if (common_config('site', 'use_x_sendfile')) {
return null;
}
- try {
- return filemtime($this->attachment->getPath());
- } catch (InvalidFilenameException $e) {
+ $path = $this->attachment->getFileOrThumbnailPath();
+ if (!empty($path)) {
+ return filemtime($path);
+ } else {
return null;
}
}
function etag()
{
if (common_config('site', 'use_x_sendfile')) {
+
return null;
}
+ $path = $this->attachment->getFileOrThumbnailPath();
+
$cache = Cache::instance();
if($cache) {
- try {
- $key = Cache::key('attachments:etag:' . $this->attachment->getPath());
- $etag = $cache->get($key);
- if($etag === false) {
- $etag = crc32(file_get_contents($this->attachment->getPath()));
- $cache->set($key,$etag);
- }
- } catch (InvalidFilenameException $e) {
+ 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;
}
- $stat = stat($this->path);
- return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
+ if (!empty($path)) {
+ $stat = stat($path);
+ return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
+ } else {
+ return null;
+ }
}
/**
$ret = @readfile($filepath);
- if (ret === false) {
+ if ($ret === false) {
common_log(LOG_ERR, "Couldn't read file at {$filepath}.");
} elseif ($ret !== $filesize) {
common_log(LOG_ERR, "The lengths of the file as recorded on the DB (or on disk) for the file " .
{
public function showPage()
{
- // Checks file exists or throws FileNotStoredLocallyException
- $filepath = $this->attachment->getPath();
- $filesize = $this->attachment->size;
+ // Checks file exists or throws FileNotFoundException
+ $filepath = $this->attachment->getFileOrThumbnailPath();
+ $filesize = $this->attachment->size ?: 0;
+ $mimetype = $this->attachment->getFileOrThumbnailMimetype();
+
+ if (empty($filepath)) {
+ $thiis->clientError(_('No such attachment'), 404);
+ }
+
$filename = MediaFile::getDisplayName($this->attachment);
// Disable errors, to not mess with the file contents (suppress errors in case access to this
@ini_set('display_errors', 0);
header("Content-Description: File Transfer");
- header("Content-Type: {$this->attachment->mimetype}");
+ header("Content-Type: {$mimetype}");
header("Content-Disposition: attachment; filename=\"{$filename}\"");
header('Expires: 0');
header('Content-Transfer-Encoding: binary'); // FIXME? Can this be different?
public function showPage()
{
+ // Checks file exists or throws FileNotFoundException
+ $size = $this->attachment->size ?: 0;
+
// Returns a File_thumbnail object or throws exception if not available
try {
- $thumb = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_c);
- $file = $thumb->getFile();
+ $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
$file = $e->file;
+ } catch(FileNotFoundException $e) {
+ $this->clientError(_('No such attachment'), 404);
}
- try {
- if (!empty($thumb)) {
- $filepath = $thumb->getPath();
- $size = 0;
- } elseif ($file->isLocal()) {
- $filepath = $file->getPath();
- $size = $file->size;
- }
- // XXX PHP: Upgrade to PHP 7.1
- // FileNotFoundException | InvalidFilenameException
- } catch (Exception $e) {
- // We don't have a file to display
- $this->clientError(_('No such attachment.'), 404);
- return false;
- }
-
+ $filepath = $file->getFileOrThumbnailPath();
+ $mimetype = $file->getFileOrThumbnailMimetype();
$filename = MediaFile::getDisplayName($file);
// Disable errors, to not mess with the file contents (suppress errors in case access to this
@ini_set('display_errors', 0);
header("Content-Description: File Transfer");
- header("Content-Type: {$file->mimetype}");
+ header("Content-Type: {$mimetype}");
header("Content-Disposition: inline; filename=\"{$filename}\"");
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
{
public function showPage()
{
- // Checks file exists or throws FileNotStoredLocallyException
- $filepath = $this->attachment->getPath();
- $filesize = $this->attachment->size;
+ // Checks file exists or throws FileNotFoundException
+ $filepath = $this->attachment->getFileOrThumbnailPath();
+ $filesize = $this->attachment->size ?: 0;
+ $mimetype = $this->attachment->getFileOrThumbnailMimetype();
+
+ if (empty($filepath)) {
+ $thiis->clientError(_('No such attachment'), 404);
+ }
$filename = MediaFile::getDisplayName($this->attachment);
@ini_set('display_errors', 0);
header("Content-Description: File Transfer");
- header("Content-Type: {$this->attachment->mimetype}");
- if (in_array(common_get_mime_media($this->attachment->mimetype), ['image', 'video'])) {
+ header("Content-Type: {$mimetype}");
+ if (in_array(common_get_mime_media($mimetype), ['image', 'video'])) {
header("Content-Disposition: inline; filename=\"{$filename}\"");
} else {
header("Content-Disposition: attachment; filename=\"{$filename}\"");
return $filepath;
}
+ /**
+ * Returns the path to either a file, or it's thumbnail if the file doesn't exist.
+ * This is useful in case the original file is deleted, or, as is the case for Embed
+ * thumbnails, we only have a thumbnail and not a file
+ * @return string Path
+ * @throws FileNotFoundException
+ * @throws FileNotStoredLocallyException
+ * @throws InvalidFilenameException
+ * @throws ServerException
+ */
+ public function getFileOrThumbnailPath() : string
+ {
+ if (!empty($this->filename)) {
+ $filepath = self::path($this->filename);
+ if (file_exists($filepath)) {
+ return $filepath;
+ } else {
+ throw new FileNotFoundException($filepath);
+ }
+ } else {
+ try {
+ return File_thumbnail::byFile($this)->getPath();
+ } catch (NoResultException $e) {
+ // File not stored locally
+ throw new FileNotStoredLocallyException($this);
+ }
+ }
+ }
+
+ /**
+ * Return the mime type of the thumbnail if we have it, or, if not, of the File
+ * @return string
+ * @throws FileNotFoundException
+ * @throws NoResultException
+ * @throws ServerException
+ * @throws UnsupportedMediaException
+ */
+ public function getFileOrThumbnailMimetype() : string
+ {
+ if (empty($this->filename)) {
+ $filepath = File_thumbnail::byFile($this)->getPath();
+ $info = @getimagesize($filepath);
+ if ($info !== false) {
+ return $info['mime'];
+ } else {
+ throw new UnsupportedMediaException(_("Thumbnail is not an image."));
+ }
+ } else {
+ return $this->mimetype;
+ }
+ }
+
public function getAttachmentUrl()
{
return common_local_url('attachment', array('attachment'=>$this->getID()));
$attachments = $this->notice->attachments();
foreach ($attachments as $key=>$att) {
// Remove attachments which are not representable with neither a title nor thumbnail
- if ($att->getTitle() === null && !$att->hasThumbnail()) {
+ if ($att->getTitle() === _('Untitled attachment') && !$att->hasThumbnail()) {
unset($attachments[$key]);
}
}
} else {
try {
// getUrl(true) because we don't want to hotlink, could be made configurable
- $this->out->element('img', ['class'=>'u-photo', 'src'=>$this->attachment->getUrl(true), 'alt' => $this->attachment->getTitle()]);
+ $this->out->element('img', ['class'=>'u-photo',
+ 'src'=>$this->attachment->getUrl(true),
+ 'alt' => $this->attachment->getTitle()]);
} catch (FileNotStoredLocallyException $e) {
$url = $e->file->getUrl(false);
$this->out->element('a', ['href'=>$url, 'rel'=>'external'], $url);
throw new ServerException('No File object attached to this ImageFile object.');
}
- // File not stored locally, can't generate a thumbnail
- if (empty($this->fileRecord->filename)) {
- throw new FileNotStoredLocallyException($this->fileRecord);
- }
+ // Throws FileNotFoundException or FileNotStoredLocallyException
+ $this->filepath = $this->fileRecord->getFileOrThumbnailPath();
if ($width === null) {
$width = common_config('thumbnail', 'width');
return $thumb;
}
- $filename = $this->fileRecord->filehash ?: $this->filename; // Remote files don't have $this->filehash
+ $filename = basename($this->filepath);
$extension = File::guessMimeExtension($this->mimetype);
$outname = "thumb-{$this->fileRecord->getID()}-{$width}x{$height}-{$filename}." . $extension;
$outpath = File_thumbnail::path($outname);
* states where it isn't oEmbed data, so it doesn't mess up the event handle
* for other things hooked into it), or the exception if it fails.
*/
- public function onCreateFileImageThumbnailSource(File $file, &$imgPath)
+ public function onCreateFileImageThumbnailSource(File $file, &$imgPath, $media)
{
// If we are on a private node, we won't do any remote calls (just as a precaution until
// we can configure this from config.php for the private nodes)