PluginProbe
WPIDE – File Manager & Code Editor / 3.5.10
WPIDE – File Manager & Code Editor v3.5.10
3.5.10 3.5.9 3.5.8 3.5.7 2.0.14 2.0.15 2.0.16 2.0.2 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1 2.2 2.3 2.3.1 2.3.2 2.4.0 2.5 2.6 3.0 3.1 3.2 All 56 releases
wpide / App / Controllers / FileManager / DownloadController.php

DownloadController.php in WPIDE – File Manager & Code Editor 3.5.10, at App/Controllers/FileManager/DownloadController.php

318 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPIDE\App\Controllers\FileManager;
4
5 use WPIDE\App\Config\Config;
6 use WPIDE\App\Kernel\Request;
7 use WPIDE\App\Kernel\Response;
8 use WPIDE\App\Kernel\StreamedResponse;
9 use WPIDE\App\Services\Archiver\ArchiverInterface;
10 use WPIDE\App\Services\Auth\AuthInterface;
11 use WPIDE\App\Services\Storage\Filesystem;
12 use WPIDE\App\Services\Tmpfs\TmpfsInterface;
13 use Symfony\Component\HttpFoundation\HeaderUtils;
14 use Symfony\Component\Mime\MimeTypes;
15
16 /**
17 *
18 */
19 class DownloadController
20 {
21 /**
22 * @var AuthInterface
23 */
24 protected $auth;
25
26 /**
27 * @var Mixed
28 */
29 protected $user;
30
31 /**
32 * @var Config
33 */
34 protected $config;
35
36 /**
37 * @var Filesystem
38 */
39 protected $storage;
40
41 /**
42 * @var
43 */
44 protected $separator;
45
46 /**
47 * @param Config $config
48 * @param AuthInterface $auth
49 * @param Filesystem $storage
50 */
51 public function __construct(Config $config, AuthInterface $auth, Filesystem $storage)
52 {
53 $this->config = $config;
54 $this->auth = $auth;
55
56 $this->user = $this->auth->user() ?: $this->auth->getGuest();
57
58 $this->storage = $storage;
59 $this->storage->setPathPrefix($this->user->getHomeDir());
60
61 $this->separator = $this->storage->getSeparator();
62 }
63
64 /**
65 * @param Request $request
66 * @param Response $response
67 * @param StreamedResponse $streamedResponse
68 * @return void
69 */
70 public function download(Request $request, Response $response, StreamedResponse $streamedResponse)
71 {
72
73 $path = (string) base64_decode($request->input('path'));
74
75 if(!$this->storage->fileExists($path)) {
76 return $response->json(__('Requested file does not exist', 'wpide'), 404);
77 }
78
79 try {
80 $file = $this->storage->readStream($path);
81 } catch (\Exception $e) {
82 return $response->redirect('/');
83 }
84
85 return $this->downloadFile($file, $request, $response, $streamedResponse);
86 }
87
88 public function readContent(Request $request, Response $response)
89 {
90 $encodedPath = $request->input('path');
91 $path = is_string($encodedPath) ? base64_decode($encodedPath, true) : false;
92
93 if ($path === false || !$this->storage->fileExists($path)) {
94 return $response->json(__('Requested file does not exist', 'wpide'), 404);
95 }
96
97 try {
98 $file = $this->storage->read($path);
99 } catch (\Exception $error) {
100 return $response->json(__('Cannot read file, please check file permissions!', 'wpide'), 422);
101 }
102
103 $content = $file['contents'];
104 if (!is_string($content) || strlen($content) !== (int) $file['filesize'] || preg_match('//u', $content) !== 1) {
105 return $response->json(__('Cannot read file, please check file permissions!', 'wpide'), 422);
106 }
107
108 return $response->json($content);
109 }
110
111 /**
112 * @param $file array
113 * @param Request $request
114 * @param StreamedResponse $streamedResponse
115 * @return void
116 */
117 public function downloadFile(array $file, Request $request, Response $response, StreamedResponse $streamedResponse)
118 {
119
120 if($file['stream'] === false) {
121 return $response->json('Cannot read file, please check file permissions!', 422);
122 }
123
124 // Output produced before this response would be prepended to the file. With
125 // Content-Length set below, clients can then lose the same number of bytes
126 // from the end of the file.
127 if (headers_sent()) {
128 fclose($file['stream']);
129 return $response->json('Cannot safely stream file!', 500);
130 }
131
132 while (ob_get_level() > 0) {
133 if (!@ob_end_clean()) {
134 fclose($file['stream']);
135 return $response->json('Cannot safely stream file!', 500);
136 }
137 }
138
139 $streamedResponse->setCallback(function () use ($file) {
140 // @codeCoverageIgnoreStart
141 @set_time_limit(0);
142
143 if ($file['stream']) {
144 while (! feof($file['stream'])) {
145 echo fread($file['stream'], 1024 * 8);
146 @ob_flush();
147 @flush();
148 }
149 fclose($file['stream']);
150 }
151 // @codeCoverageIgnoreEnd
152 });
153
154 $disposition = HeaderUtils::DISPOSITION_ATTACHMENT;
155 $extension = pathinfo($file['filename'], PATHINFO_EXTENSION);
156 $mimes = (new MimeTypes())->getMimeTypes($extension);
157 $contentType = !empty($mimes) ? $mimes[0] : 'application/octet-stream';
158
159 $download_inline = ['pdf'];
160 if (in_array($extension, $download_inline) || in_array('*', $download_inline)) {
161 $disposition = HeaderUtils::DISPOSITION_INLINE;
162 }
163
164 $contentDisposition = HeaderUtils::makeDisposition($disposition, $file['filename'], 'file');
165
166 $streamedResponse->headers->set(
167 'Content-Disposition',
168 $contentDisposition
169 );
170 $streamedResponse->headers->set(
171 'Content-Type',
172 $contentType
173 );
174 $streamedResponse->headers->set(
175 'Content-Transfer-Encoding',
176 'binary'
177 );
178 if (isset($file['filesize'])) {
179 $streamedResponse->headers->set(
180 'Content-Length',
181 $file['filesize']
182 );
183 }
184 // @codeCoverageIgnoreStart
185 if (defined('WP_DEBUG') && WP_DEBUG) {
186 $streamedResponse->headers->set(
187 'Access-Control-Allow-Origin',
188 $request->headers->get('Origin')
189 );
190 $streamedResponse->headers->set(
191 'Access-Control-Allow-Credentials',
192 'true'
193 );
194 }
195 // @codeCoverageIgnoreEnd
196
197 $streamedResponse->send();
198 }
199
200 /**
201 * @param Request $request
202 * @param Response $response
203 * @param ArchiverInterface $archiver
204 * @return void
205 */
206 public function batchDownloadChunks(Request $request, Response $response, ArchiverInterface $archiver)
207 {
208 $items = $request->input('items', []);
209 $recursive = (bool) $request->input('recursive', false);
210 $zipaction = $request->input('zipaction', 'create');
211
212 $destination = $request->input('destination', $this->separator);
213 $name = $request->input('name', $this->config->get('file.default_archive_name'));
214
215 if($zipaction === 'create') {
216 $uniqid = $archiver->createArchive($this->storage);
217 }else {
218 $uniqid = $request->input('uniqid');
219 $archiver->setArchive($this->storage, $uniqid);
220 }
221
222 foreach ($items as $item) {
223 if ($item->type == 'dir') {
224 if($recursive) {
225 $archiver->addDirectoryFromStorage($item->path, $destination);
226 }else{
227 $archiver->addEmptyDirectory($item->path, $destination);
228 }
229 }
230 if ($item->type == 'file') {
231 $archiver->addFileFromStorage($item->path, $destination);
232 }
233 }
234
235 if($zipaction === 'store') {
236
237 $archiver->storeArchive($destination, $name);
238
239 }else{
240
241 $archiver->closeArchive();
242 }
243
244 return $response->json(['uniqid' => $uniqid]);
245 }
246
247 /**
248 * @param Request $request
249 * @param StreamedResponse $streamedResponse
250 * @param TmpfsInterface $tmpfs
251 * @return void
252 */
253 public function batchDownloadStart(Request $request, StreamedResponse $streamedResponse, TmpfsInterface $tmpfs)
254 {
255
256
257 $uniqid = (string) preg_replace('/[^0-9a-zA-Z_]/', '', (string) $request->input('uniqid'));
258 $name = $request->input('name', $this->config->get('file.default_archive_name'));
259
260 $file = $tmpfs->readStream($uniqid);
261
262 $streamedResponse->setCallback(function () use ($file, $tmpfs, $uniqid) {
263 // @codeCoverageIgnoreStart
264 @set_time_limit(0);
265 if ($file['stream']) {
266 while (! feof($file['stream'])) {
267 echo fread($file['stream'], 1024 * 8);
268 @ob_flush();
269 @flush();
270 }
271 fclose($file['stream']);
272 }
273 $tmpfs->remove($uniqid);
274 // @codeCoverageIgnoreEnd
275 });
276
277 $streamedResponse->headers->set(
278 'Content-Disposition',
279 HeaderUtils::makeDisposition(
280 HeaderUtils::DISPOSITION_ATTACHMENT,
281 $name,
282 $this->config->get('file.default_archive_name')
283 )
284 );
285 $streamedResponse->headers->set(
286 'Content-Type',
287 'application/octet-stream'
288 );
289 $streamedResponse->headers->set(
290 'Content-Transfer-Encoding',
291 'binary'
292 );
293 if (isset($file['filesize'])) {
294 $streamedResponse->headers->set(
295 'Content-Length',
296 $file['filesize']
297 );
298 }
299
300 $streamedResponse->send();
301 }
302
303 /**
304 * @param Request $request
305 * @param Response $response
306 * @param TmpfsInterface $tmpfs
307 * @return void
308 */
309 public function batchDownloadCancelled(Request $request, Response $response, TmpfsInterface $tmpfs)
310 {
311
312 $uniqid = (string) preg_replace('/[^0-9a-zA-Z_]/', '', (string) $request->input('uniqid'));
313 $tmpfs->remove($uniqid);
314
315 return $response->json('Deleted');
316 }
317 }
318