Support for WebP images (#3861)
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / page / MediaPage.class.php
CommitLineData
59ab4d0f
MS
1<?php
2namespace wcf\page;
3use wcf\data\media\Media;
76125db4 4use wcf\data\media\MediaEditor;
59ab4d0f 5use wcf\system\exception\IllegalLinkException;
306b6bdd 6use wcf\system\exception\PermissionDeniedException;
59ab4d0f
MS
7use wcf\util\FileReader;
8use wcf\util\StringUtil;
9
10/**
11 * Shows a media file.
12 *
13 * @author Matthias Schmidt
7b7b9764 14 * @copyright 2001-2019 WoltLab GmbH
59ab4d0f 15 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
e71525e4
MW
16 * @package WoltLabSuite\Core\Page
17 * @since 3.0
59ab4d0f
MS
18 */
19class MediaPage extends AbstractPage {
773159c4
AE
20 const AVAILABLE_DURING_OFFLINE_MODE = true;
21
59ab4d0f
MS
22 /**
23 * etag for the media file
24 * @var string
25 */
306b6bdd 26 public $eTag;
59ab4d0f
MS
27
28 /**
29 * file reader object
30 * @var FileReader
31 */
306b6bdd 32 public $fileReader;
59ab4d0f
MS
33
34 /**
35 * requested media file
36 * @var Media
37 */
306b6bdd
MS
38 public $media;
39
59ab4d0f
MS
40 /**
41 * id of the requested media file
42 * @var integer
43 */
44 public $mediaID = 0;
45
46 /**
47 * size of the requested thumbnail
48 * @var string
49 */
50 public $thumbnail = '';
51
52 /**
00cefc6d 53 * @inheritDoc
59ab4d0f
MS
54 */
55 public $useTemplate = false;
56
57 /**
58 * list of mime types which belong to files that are displayed inline
59 * @var string[]
60 */
61 public static $inlineMimeTypes = [
62 'image/gif',
63 'image/jpeg',
64 'image/png',
65 'image/x-png',
66 'application/pdf',
58b2ac93
AE
67 'image/pjpeg',
68 'image/webp',
59ab4d0f
MS
69 ];
70
59ab4d0f 71 /**
00cefc6d 72 * @inheritDoc
59ab4d0f
MS
73 */
74 public function readData() {
75 parent::readData();
76
77 // get file data
78 if ($this->thumbnail) {
79 $mimeType = $this->media->{$this->thumbnail.'ThumbnailType'};
80 $filesize = $this->media->{$this->thumbnail.'ThumbnailSize'};
81 $location = $this->media->getThumbnailLocation($this->thumbnail);
82 $this->eTag = strtoupper($this->thumbnail).'_'.$this->mediaID;
83 }
84 else {
85 $mimeType = $this->media->fileType;
86 $filesize = $this->media->filesize;
87 $location = $this->media->getLocation();
88 $this->eTag = $this->mediaID;
89 }
90
f56fc83f
MS
91 $this->eTag .= '_' . $this->media->fileHash;
92
59ab4d0f 93 // init file reader
f56fc83f 94 $maxAge = 3600;
59ab4d0f
MS
95 $this->fileReader = new FileReader($location, [
96 'filename' => $this->media->filename,
97 'mimeType' => $mimeType,
98 'filesize' => $filesize,
63b9817b
MS
99 'showInline' => in_array($mimeType, self::$inlineMimeTypes),
100 'enableRangeSupport' => $this->thumbnail ? true : false,
c2e9de94 101 'lastModificationTime' => $this->media->fileUpdateTime ?? $this->media->uploadTime,
f56fc83f
MS
102 'expirationDate' => TIME_NOW + $maxAge,
103 'maxAge' => $maxAge,
59ab4d0f
MS
104 ]);
105
106 if ($this->eTag !== null) {
107 $this->fileReader->addHeader('ETag', '"'.$this->eTag.'"');
108 }
109 }
110
111 /**
00cefc6d 112 * @inheritDoc
59ab4d0f
MS
113 */
114 public function readParameters() {
115 parent::readParameters();
116
117 if (isset($_REQUEST['id'])) $this->mediaID = intval($_REQUEST['id']);
118 $this->media = new Media($this->mediaID);
119 if (!$this->media->mediaID) {
120 throw new IllegalLinkException();
121 }
c14f5026
MS
122 if (!$this->media->isAccessible()) {
123 throw new PermissionDeniedException();
124 }
59ab4d0f
MS
125
126 if (isset($_REQUEST['thumbnail'])) $this->thumbnail = StringUtil::trim($_REQUEST['thumbnail']);
86ddf3dd
MW
127 if ($this->thumbnail === 'original') {
128 // The 'original' size is required by the editor, but is not a valid thumbnail size.
129 $this->thumbnail = '';
130 }
59ab4d0f
MS
131 if ($this->thumbnail && !isset(Media::getThumbnailSizes()[$this->thumbnail])) {
132 throw new IllegalLinkException();
133 }
134
306b6bdd 135 if ($this->thumbnail && !$this->media->{$this->thumbnail.'ThumbnailType'}) {
59ab4d0f
MS
136 $this->thumbnail = '';
137 }
59ab4d0f
MS
138 }
139
140 /**
00cefc6d 141 * @inheritDoc
59ab4d0f
MS
142 */
143 public function show() {
144 parent::show();
145
146 // etag caching
147 if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == '"'.$this->eTag.'"') {
148 @header('HTTP/1.1 304 Not Modified');
149 exit;
150 }
151
76125db4
MS
152 if (!$this->thumbnail) {
153 // update download count
154 (new MediaEditor($this->media))->update([
155 'downloads' => $this->media->downloads + 1,
156 'lastDownloadTime' => TIME_NOW
157 ]);
158 }
159
59ab4d0f
MS
160 // send file to client
161 $this->fileReader->send();
162 exit;
163 }
164}