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