PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 3.3.1
GiveWP – Donation Plugin and Fundraising Platform v3.3.1
4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / vendor / vendor-prefixed / symfony / http-foundation / BinaryFileResponse.php
give / vendor / vendor-prefixed / symfony / http-foundation Last commit date
Exception 2 years ago File 2 years ago Session 2 years ago Tests 2 years ago AcceptHeader.php 2 years ago AcceptHeaderItem.php 2 years ago ApacheRequest.php 2 years ago BinaryFileResponse.php 2 years ago Cookie.php 2 years ago ExpressionRequestMatcher.php 2 years ago FileBag.php 2 years ago HeaderBag.php 2 years ago IpUtils.php 2 years ago JsonResponse.php 2 years ago LICENSE 2 years ago ParameterBag.php 2 years ago RedirectResponse.php 2 years ago Request.php 2 years ago RequestMatcher.php 2 years ago RequestMatcherInterface.php 2 years ago RequestStack.php 2 years ago Response.php 2 years ago ResponseHeaderBag.php 2 years ago ServerBag.php 2 years ago StreamedResponse.php 2 years ago
BinaryFileResponse.php
371 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 *
11 * Modified by impress-org on 23-January-2024 using Strauss.
12 * @see https://github.com/BrianHenryIE/strauss
13 */
14
15 namespace Give\Vendors\Symfony\Component\HttpFoundation;
16
17 use Give\Vendors\Symfony\Component\HttpFoundation\File\Exception\FileException;
18 use Give\Vendors\Symfony\Component\HttpFoundation\File\File;
19
20 /**
21 * BinaryFileResponse represents an HTTP response delivering a file.
22 *
23 * @author Niklas Fiekas <niklas.fiekas@tu-clausthal.de>
24 * @author stealth35 <stealth35-php@live.fr>
25 * @author Igor Wiedler <igor@wiedler.ch>
26 * @author Jordan Alliot <jordan.alliot@gmail.com>
27 * @author Sergey Linnik <linniksa@gmail.com>
28 */
29 class BinaryFileResponse extends Response
30 {
31 protected static $trustXSendfileTypeHeader = false;
32
33 /**
34 * @var File
35 */
36 protected $file;
37 protected $offset = 0;
38 protected $maxlen = -1;
39 protected $deleteFileAfterSend = false;
40
41 /**
42 * @param \SplFileInfo|string $file The file to stream
43 * @param int $status The response status code
44 * @param array $headers An array of response headers
45 * @param bool $public Files are public by default
46 * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename
47 * @param bool $autoEtag Whether the ETag header should be automatically set
48 * @param bool $autoLastModified Whether the Last-Modified header should be automatically set
49 */
50 public function __construct($file, $status = 200, $headers = [], $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
51 {
52 parent::__construct(null, $status, $headers);
53
54 $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified);
55
56 if ($public) {
57 $this->setPublic();
58 }
59 }
60
61 /**
62 * @param \SplFileInfo|string $file The file to stream
63 * @param int $status The response status code
64 * @param array $headers An array of response headers
65 * @param bool $public Files are public by default
66 * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename
67 * @param bool $autoEtag Whether the ETag header should be automatically set
68 * @param bool $autoLastModified Whether the Last-Modified header should be automatically set
69 *
70 * @return static
71 */
72 public static function create($file = null, $status = 200, $headers = [], $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
73 {
74 return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified);
75 }
76
77 /**
78 * Sets the file to stream.
79 *
80 * @param \SplFileInfo|string $file The file to stream
81 * @param string $contentDisposition
82 * @param bool $autoEtag
83 * @param bool $autoLastModified
84 *
85 * @return $this
86 *
87 * @throws FileException
88 */
89 public function setFile($file, $contentDisposition = null, $autoEtag = false, $autoLastModified = true)
90 {
91 if (!$file instanceof File) {
92 if ($file instanceof \SplFileInfo) {
93 $file = new File($file->getPathname());
94 } else {
95 $file = new File((string) $file);
96 }
97 }
98
99 if (!$file->isReadable()) {
100 throw new FileException('File must be readable.');
101 }
102
103 $this->file = $file;
104
105 if ($autoEtag) {
106 $this->setAutoEtag();
107 }
108
109 if ($autoLastModified) {
110 $this->setAutoLastModified();
111 }
112
113 if ($contentDisposition) {
114 $this->setContentDisposition($contentDisposition);
115 }
116
117 return $this;
118 }
119
120 /**
121 * Gets the file.
122 *
123 * @return File The file to stream
124 */
125 public function getFile()
126 {
127 return $this->file;
128 }
129
130 /**
131 * Automatically sets the Last-Modified header according the file modification date.
132 */
133 public function setAutoLastModified()
134 {
135 $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime()));
136
137 return $this;
138 }
139
140 /**
141 * Automatically sets the ETag header according to the checksum of the file.
142 */
143 public function setAutoEtag()
144 {
145 $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true)));
146
147 return $this;
148 }
149
150 /**
151 * Sets the Content-Disposition header with the given filename.
152 *
153 * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT
154 * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file
155 * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename
156 *
157 * @return $this
158 */
159 public function setContentDisposition($disposition, $filename = '', $filenameFallback = '')
160 {
161 if ('' === $filename) {
162 $filename = $this->file->getFilename();
163 }
164
165 if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) {
166 $encoding = mb_detect_encoding($filename, null, true) ?: '8bit';
167
168 for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) {
169 $char = mb_substr($filename, $i, 1, $encoding);
170
171 if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) {
172 $filenameFallback .= '_';
173 } else {
174 $filenameFallback .= $char;
175 }
176 }
177 }
178
179 $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback);
180 $this->headers->set('Content-Disposition', $dispositionHeader);
181
182 return $this;
183 }
184
185 /**
186 * {@inheritdoc}
187 */
188 public function prepare(Request $request)
189 {
190 if (!$this->headers->has('Content-Type')) {
191 $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
192 }
193
194 if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) {
195 $this->setProtocolVersion('1.1');
196 }
197
198 $this->ensureIEOverSSLCompatibility($request);
199
200 $this->offset = 0;
201 $this->maxlen = -1;
202
203 if (false === $fileSize = $this->file->getSize()) {
204 return $this;
205 }
206 $this->headers->set('Content-Length', $fileSize);
207
208 if (!$this->headers->has('Accept-Ranges')) {
209 // Only accept ranges on safe HTTP methods
210 $this->headers->set('Accept-Ranges', $request->isMethodSafe(false) ? 'bytes' : 'none');
211 }
212
213 if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) {
214 // Use X-Sendfile, do not send any content.
215 $type = $request->headers->get('X-Sendfile-Type');
216 $path = $this->file->getRealPath();
217 // Fall back to scheme://path for stream wrapped locations.
218 if (false === $path) {
219 $path = $this->file->getPathname();
220 }
221 if ('x-accel-redirect' === strtolower($type)) {
222 // Do X-Accel-Mapping substitutions.
223 // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect
224 foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) {
225 $mapping = explode('=', $mapping, 2);
226
227 if (2 === \count($mapping)) {
228 $pathPrefix = trim($mapping[0]);
229 $location = trim($mapping[1]);
230
231 if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) {
232 $path = $location.substr($path, \strlen($pathPrefix));
233 // Only set X-Accel-Redirect header if a valid URI can be produced
234 // as nginx does not serve arbitrary file paths.
235 $this->headers->set($type, $path);
236 $this->maxlen = 0;
237 break;
238 }
239 }
240 }
241 } else {
242 $this->headers->set($type, $path);
243 $this->maxlen = 0;
244 }
245 } elseif ($request->headers->has('Range') && $request->isMethod('GET')) {
246 // Process the range headers.
247 if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) {
248 $range = $request->headers->get('Range');
249
250 if (0 === strpos($range, 'bytes=')) {
251 list($start, $end) = explode('-', substr($range, 6), 2) + [0];
252
253 $end = ('' === $end) ? $fileSize - 1 : (int) $end;
254
255 if ('' === $start) {
256 $start = $fileSize - $end;
257 $end = $fileSize - 1;
258 } else {
259 $start = (int) $start;
260 }
261
262 if ($start <= $end) {
263 $end = min($end, $fileSize - 1);
264 if ($start < 0 || $start > $end) {
265 $this->setStatusCode(416);
266 $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize));
267 } elseif ($end - $start < $fileSize - 1) {
268 $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
269 $this->offset = $start;
270
271 $this->setStatusCode(206);
272 $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize));
273 $this->headers->set('Content-Length', $end - $start + 1);
274 }
275 }
276 }
277 }
278 }
279
280 return $this;
281 }
282
283 private function hasValidIfRangeHeader($header)
284 {
285 if ($this->getEtag() === $header) {
286 return true;
287 }
288
289 if (null === $lastModified = $this->getLastModified()) {
290 return false;
291 }
292
293 return $lastModified->format('D, d M Y H:i:s').' GMT' === $header;
294 }
295
296 /**
297 * Sends the file.
298 *
299 * {@inheritdoc}
300 */
301 public function sendContent()
302 {
303 if (!$this->isSuccessful()) {
304 return parent::sendContent();
305 }
306
307 if (0 === $this->maxlen) {
308 return $this;
309 }
310
311 $out = fopen('php://output', 'wb');
312 $file = fopen($this->file->getPathname(), 'rb');
313
314 stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);
315
316 fclose($out);
317 fclose($file);
318
319 if ($this->deleteFileAfterSend && file_exists($this->file->getPathname())) {
320 unlink($this->file->getPathname());
321 }
322
323 return $this;
324 }
325
326 /**
327 * {@inheritdoc}
328 *
329 * @throws \LogicException when the content is not null
330 */
331 public function setContent($content)
332 {
333 if (null !== $content) {
334 throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.');
335 }
336
337 return $this;
338 }
339
340 /**
341 * {@inheritdoc}
342 */
343 public function getContent()
344 {
345 return false;
346 }
347
348 /**
349 * Trust X-Sendfile-Type header.
350 */
351 public static function trustXSendfileTypeHeader()
352 {
353 self::$trustXSendfileTypeHeader = true;
354 }
355
356 /**
357 * If this is set to true, the file will be unlinked after the request is sent
358 * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used.
359 *
360 * @param bool $shouldDelete
361 *
362 * @return $this
363 */
364 public function deleteFileAfterSend($shouldDelete)
365 {
366 $this->deleteFileAfterSend = $shouldDelete;
367
368 return $this;
369 }
370 }
371