PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / Downloader / Downloader.php
backup / src / JetBackup / Downloader Last commit date
.htaccess 1 year ago Downloader.php 10 months ago index.html 1 year ago web.config 1 year ago
Downloader.php
84 lines
1 <?php
2
3 namespace JetBackup\Downloader;
4
5 use JetBackup\Exception\DownloaderException;
6 use JetBackup\Factory;
7
8 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
9
10 class Downloader {
11
12 const DEFAULT_CHUNK = 8192; // 8k
13
14 private ?string $_filename;
15 private string $_source;
16
17 /**
18 * @param string $source
19 * @param string|null $filename
20 */
21 public function __construct(string $source, ?string $filename=null) {
22 $this->_source = $source;
23 $this->_filename = $filename;
24 }
25
26 /**
27 * @return \stdClass
28 */
29 private static function _getRange($filesize):object {
30 $output = new \stdClass();
31 $output->start = 0;
32 $output->end = $filesize-1;
33
34 if (
35 !isset($_SERVER['HTTP_RANGE']) ||
36 !preg_match('/bytes=(\d+)-(\d*)/', $_SERVER['HTTP_RANGE'], $matches)
37 ) return $output;
38
39 $output->start = (int) $matches[1];
40 if (!empty($matches[2])) $output->end = (int) $matches[2];
41
42 return $output;
43 }
44
45 /**
46 * @param int $chunk
47 *
48 * @return void
49 * @throws DownloaderException
50 */
51 public function download(int $chunk=self::DEFAULT_CHUNK):void {
52
53 if( !$this->_source || !file_exists($this->_source) || is_dir($this->_source)) throw new DownloaderException('The provided download file does not exists');
54 if (!str_starts_with(trim($this->_source), trim(Factory::getLocations()->getDataDir()))) throw new DownloaderException('Invalid download source path');
55 if(!($fd = fopen($this->_source, 'rb'))) throw new DownloaderException('Unable to open download file');
56 if(!$this->_filename) $this->_filename = basename($this->_source);
57
58 $filesize = filesize($this->_source);
59 if ($filesize === false || $filesize < 0) throw new DownloaderException('Unable to stat download file');
60
61 $range = self::_getRange($filesize);
62
63 // gzip compression may corrupt binary data
64 if (function_exists('apache_setenv')) @apache_setenv('no-gzip', 1);
65 @ini_set('zlib.output_compression', 'Off');
66 while (ob_get_level()) @ob_end_clean();
67
68 header("Content-Type: application/octet-stream");
69 header('Content-Disposition: attachment; filename="' . $this->_filename . '"; filename*=UTF-8\'\'' . rawurlencode($this->_filename));
70 header("Accept-Ranges: bytes");
71 header("Content-Length: " . ($range->end - $range->start + 1));
72 header("Content-Range: bytes $range->start-$range->end/".$filesize);
73
74 if($range->start > 0) fseek($fd, $range->start);
75
76 while (!feof($fd) && ($pos = ftell($fd)) <= $range->end) {
77 echo fread($fd, min($chunk, $range->end - $pos + 1));
78 flush();
79 }
80
81 fclose($fd);
82 exit;
83 }
84 }