PluginProbe
User Access Manager / 2.1.4
User Access Manager v2.1.4
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
user-access-manager / src / File / FileHandler.php

FileHandler.php in User Access Manager 2.1.4, at src/File/FileHandler.php

308 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * FileHandler.php
4 *
5 * The FileHandler class file.
6 *
7 * PHP versions 5
8 *
9 * @author Alexander Schneider <alexanderschneider85@gmail.com>
10 * @copyright 2008-2017 Alexander Schneider
11 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2
12 * @version SVN: $id$
13 * @link http://wordpress.org/extend/plugins/user-access-manager/
14 */
15 namespace UserAccessManager\File;
16
17 use UserAccessManager\Config\MainConfig;
18 use UserAccessManager\Config\WordpressConfig;
19 use UserAccessManager\Wrapper\Php;
20 use UserAccessManager\Wrapper\Wordpress;
21
22 /**
23 * Class FileHandler
24 *
25 * @package UserAccessManager\FileHandler
26 */
27 class FileHandler
28 {
29 /**
30 * @var Php
31 */
32 private $php;
33
34 /**
35 * @var Wordpress
36 */
37 private $wordpress;
38
39 /**
40 * @var WordpressConfig
41 */
42 private $wordpressConfig;
43
44 /**
45 * @var MainConfig
46 */
47 private $mainConfig;
48
49 /**
50 * @var FileProtectionFactory
51 */
52 private $fileProtectionFactory;
53
54 /**
55 * FileHandler constructor.
56 *
57 * @param Php $php
58 * @param Wordpress $wordpress
59 * @param WordpressConfig $wordpressConfig
60 * @param MainConfig $mainConfig
61 * @param FileProtectionFactory $fileProtectionFactory
62 */
63 public function __construct(
64 Php $php,
65 Wordpress $wordpress,
66 WordpressConfig $wordpressConfig,
67 MainConfig $mainConfig,
68 FileProtectionFactory $fileProtectionFactory
69 ) {
70 $this->php = $php;
71 $this->wordpress = $wordpress;
72 $this->wordpressConfig = $wordpressConfig;
73 $this->mainConfig = $mainConfig;
74 $this->fileProtectionFactory = $fileProtectionFactory;
75 }
76
77 /**
78 * Clears the buffer.
79 */
80 private function clearBuffer()
81 {
82 //TODO find better solution (prevent '\n' / '0A')
83 if (is_numeric(ob_get_length()) === true) {
84 ob_clean();
85 }
86
87 flush();
88 }
89
90 /**
91 * Returns the file mine type.
92 *
93 * @param $file
94 *
95 * @return string
96 */
97 private function getFileMineType($file)
98 {
99 $fileName = basename($file);
100
101 /*
102 * This only for compatibility
103 * mime_content_type has been deprecated as the PECL extension file info
104 * provides the same functionality (and more) in a much cleaner way.
105 */
106 $explodedFileName = explode('.', $fileName);
107 $lastElement = array_pop($explodedFileName);
108 $fileExt = strtolower($lastElement);
109
110 $mimeTypes = $this->wordpressConfig->getMimeTypes();
111
112 if ($this->php->functionExists('finfo_open') === true) {
113 $fileInfo = finfo_open(FILEINFO_MIME);
114 $fileMimeType = finfo_file($fileInfo, $file);
115 finfo_close($fileInfo);
116 } elseif ($this->php->functionExists('mime_content_type')) {
117 $fileMimeType = mime_content_type($file);
118 } elseif (isset($mimeTypes[$fileExt]) === true) {
119 $fileMimeType = $mimeTypes[$fileExt];
120 } else {
121 $fileMimeType = 'application/octet-stream';
122 }
123
124 return (string)$fileMimeType;
125 }
126
127 /**
128 * Delivers the file via fopen.
129 *
130 * @param string $file
131 */
132 private function deliverFileViaFopen($file)
133 {
134 $handler = fopen($file, 'r');
135
136 while (feof($handler) === false) {
137 if ($this->php->iniGet('safe_mode') !== '') {
138 $this->php->setTimeLimit(30);
139 }
140
141 echo $this->php->fread($handler, 1024);
142 }
143 }
144
145 /**
146 * Delivers the file.
147 *
148 * @param string $file
149 * @param bool $isImage
150 */
151 private function deliverFile($file, $isImage)
152 {
153 header('Content-Transfer-Encoding: binary');
154 header('Content-Length: '.filesize($file));
155 $this->clearBuffer();
156
157 if ($this->mainConfig->getDownloadType() === 'fopen' && $isImage === false) {
158 $this->deliverFileViaFopen($file);
159 } else {
160 readfile($file);
161 }
162 }
163
164 /**
165 * Sets the seek start and end.
166 *
167 * @param string $rangeOrigin
168 * @param int $fileSize
169 * @param int $seekStart
170 * @param int $seekEnd
171 */
172 private function getSeekStartEnd($rangeOrigin, $fileSize, &$seekStart, &$seekEnd)
173 {
174 //just serve the first range
175 $range = explode(',', $rangeOrigin)[0];
176 //figure out download piece from range (if set)
177 $seek = explode('-', $range);
178 $seekStart = abs((int)$seek[0]);
179 $seekEnd = isset($seek[1]) === true ? abs((int)$seek[1]) : 0;
180 //start and end based on range (if set), else set defaults also check for invalid ranges.
181 $seekEnd = ($seekEnd === 0) ? ($fileSize - 1) : min($seekEnd, ($fileSize - 1));
182 $seekStart = ($seekEnd < $seekStart) ? 0 : max($seekStart, 0);
183 }
184
185 /**
186 * Delivers the file partial.
187 *
188 * @param string $file
189 */
190 private function deliverFilePartial($file)
191 {
192 $httpRange = explode('=', $_SERVER['HTTP_RANGE']);
193 $sizeUnit = $httpRange[0];
194 $rangeOrigin = isset($httpRange[1]) === true ? $httpRange[1] : '';
195
196 if ($sizeUnit === 'bytes') {
197 $fileSize = filesize($file);
198 $this->getSeekStartEnd($rangeOrigin, $fileSize, $seekStart, $seekEnd);
199
200 header('HTTP/1.1 206 Partial Content');
201 header('Content-Transfer-Encoding: binary');
202 header('Accept-Ranges: bytes');
203 header('Content-Range: bytes '.$seekStart.'-'.$seekEnd.'/'.$fileSize);
204 header('Content-Length: '.($seekEnd - $seekStart + 1));
205
206 $handler = fopen($file, 'r');
207 fseek($handler, $seekStart);
208
209 while (feof($handler) === false) {
210 echo $this->php->fread($handler, 1024 * 8);
211 $this->clearBuffer();
212
213 if ($this->php->connectionStatus() !== 0) {
214 $this->php->fClose($handler);
215 break;
216 }
217 }
218 } else {
219 header('HTTP/1.1 416 Requested Range Not Satisfiable');
220 }
221 }
222
223 /**
224 * Delivers the content of the requested file.
225 *
226 * @param string $file
227 * @param bool $isImage
228 */
229 public function getFile($file, $isImage)
230 {
231 //Deliver content
232 if (file_exists($file) === true) {
233 $fileMimeType = $this->getFileMineType($file);
234
235 header('Content-Description: File Transfer');
236 header('Content-Type: '.$fileMimeType);
237
238 if ($isImage === false) {
239 $baseName = str_replace(' ', '_', basename($file));
240 header('Content-Disposition: attachment; filename="'.$baseName.'"');
241 }
242
243 if (isset($_SERVER['HTTP_RANGE']) === true
244 && isset($_SERVER['REQUEST_METHOD']) === true
245 && $_SERVER['REQUEST_METHOD'] === 'GET'
246 ) {
247 $this->deliverFilePartial($file);
248 } else {
249 $this->deliverFile($file, $isImage);
250 }
251
252 $this->php->callExit();
253 } else {
254 $this->wordpress->wpDie(
255 TXT_UAM_FILE_NOT_FOUND_ERROR_MESSAGE,
256 TXT_UAM_FILE_NOT_FOUND_ERROR_TITLE,
257 ['response' => 404]
258 );
259 }
260 }
261
262 /**
263 * Creates a protection file.
264 *
265 * @param string $dir The destination directory.
266 * @param string $objectType The object type.
267 *
268 * @return false
269 */
270 public function createFileProtection($dir = null, $objectType = null)
271 {
272 $dir = ($dir === null) ? $this->wordpressConfig->getUploadDirectory() : $dir;
273
274 if ($dir !== null) {
275 if ($this->wordpress->isNginx() === true) {
276 return $this->fileProtectionFactory->createNginxFileProtection()->create($dir, $objectType);
277 } else {
278 return $this->fileProtectionFactory->createApacheFileProtection()->create($dir, $objectType);
279 }
280 }
281
282 return false;
283 }
284
285
286 /**
287 * Deletes the protection files.
288 *
289 * @param string $dir The destination directory.
290 *
291 * @return false
292 */
293 public function deleteFileProtection($dir = null)
294 {
295 $dir = ($dir === null) ? $this->wordpressConfig->getUploadDirectory() : $dir;
296
297 if ($dir !== null) {
298 if ($this->wordpress->isNginx() === true) {
299 return $this->fileProtectionFactory->createNginxFileProtection()->delete($dir);
300 } else {
301 return $this->fileProtectionFactory->createApacheFileProtection()->delete($dir);
302 }
303 }
304
305 return false;
306 }
307 }
308