PluginProbe
WPIDE – File Manager & Code Editor / 3.2
WPIDE – File Manager & Code Editor v3.2
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 3.3 3.4 All 54 releases
wpide / App / Controllers / FileManager / UploadController.php

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

155 lines 4.9 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\Services\Auth\AuthInterface;
9 use WPIDE\App\Services\Storage\Filesystem;
10 use WPIDE\App\Services\Tmpfs\TmpfsInterface;
11
12 /**
13 *
14 */
15 class UploadController
16 {
17 /**
18 * @var AuthInterface
19 */
20 protected $auth;
21
22 /**
23 * @var Config
24 */
25 protected $config;
26
27 /**
28 * @var Filesystem
29 */
30 protected $storage;
31
32 /**
33 * @var TmpfsInterface
34 */
35 protected $tmpfs;
36
37 /**
38 * @param Config $config
39 * @param AuthInterface $auth
40 * @param Filesystem $storage
41 * @param TmpfsInterface $tmpfs
42 */
43 public function __construct(Config $config, AuthInterface $auth, Filesystem $storage, TmpfsInterface $tmpfs)
44 {
45 $this->config = $config;
46 $this->auth = $auth;
47 $this->tmpfs = $tmpfs;
48
49 $user = $this->auth->user() ?: $this->auth->getGuest();
50
51 $this->storage = $storage;
52 $this->storage->setPathPrefix($user->getHomeDir());
53 }
54
55 /**
56 * @param Request $request
57 * @param Response $response
58 * @return void
59 */
60 public function chunkCheck(Request $request, Response $response)
61 {
62 $file_name = $request->input('resumableFilename', 'file');
63 $identifier = (string) preg_replace('/[^0-9a-zA-Z_]/', '', (string) $request->input('resumableIdentifier'));
64 $chunk_number = (int) $request->input('resumableChunkNumber');
65
66 $chunk_file = 'multipart_'.$identifier.$file_name.'.part'.$chunk_number;
67
68 if ($this->tmpfs->exists($chunk_file)) {
69 return $response->json('Chunk exists', 200);
70 }
71
72 return $response->json('Chunk does not exists', 204);
73 }
74
75 /**
76 * @param Request $request
77 * @param Response $response
78 * @return void
79 */
80 public function upload(Request $request, Response $response)
81 {
82 $file_name = $request->input('resumableFilename', 'file');
83 $destination = $request->input('resumableRelativePath');
84 $chunk_number = (int) $request->input('resumableChunkNumber');
85 $total_chunks = (int) $request->input('resumableTotalChunks');
86 $total_size = (int) $request->input('resumableTotalSize');
87 $identifier = (string) preg_replace('/[^0-9a-zA-Z_]/', '', (string) $request->input('resumableIdentifier'));
88
89 $filebag = $request->files;
90 $file = $filebag->get('file');
91
92 $overwrite_on_upload = (bool) $this->config->get('file.overwrite_on_upload', false);
93
94 // php 8.1 fix
95 // remove new key 'full_path' so it can preserve compatibility with symfony FileBag
96 // see https://php.watch/versions/8.1/$_FILES-full-path
97 if ($file && is_array($file) && array_key_exists('full_path', $file)) {
98 unset($file['full_path']);
99 $filebag->set('file', $file);
100 $file = $filebag->get('file');
101 }
102
103 if (! $file || ! $file->isValid() || $file->getSize() > $this->config->get('file.upload_max_size')) {
104 return $response->json('Bad file', 422);
105 }
106
107 $prefix = 'multipart_'.$identifier;
108
109 if ($this->tmpfs->exists($prefix.'_error')) {
110 return $response->json('Chunk too big', 422);
111 }
112
113 $stream = fopen($file->getPathName(), 'r');
114
115 $this->tmpfs->write($prefix.$file_name.'.part'.$chunk_number, $stream);
116
117 // check if all the parts present, and create the final destination file
118 $chunks_size = 0;
119 foreach ($this->tmpfs->findAll($prefix.'*') as $chunk) {
120 $chunks_size += $chunk['size'];
121 }
122
123 // file too big, cleanup to protect server, set error trap
124 if ($chunks_size > $this->config->get('file.upload_max_size')) {
125 foreach ($this->tmpfs->findAll($prefix.'*') as $tmp_chunk) {
126 $this->tmpfs->remove($tmp_chunk['name']);
127 }
128 $this->tmpfs->write($prefix.'_error', '');
129
130 return $response->json('Chunk too big', 422);
131 }
132
133 // if all the chunks are present, create final file and store it
134 if ($chunks_size >= $total_size) {
135 for ($i = 1; $i <= $total_chunks; ++$i) {
136 $part = $this->tmpfs->readStream($prefix.$file_name.'.part'.$i);
137 $this->tmpfs->write($file_name, $part['stream'], true);
138 }
139
140 $final = $this->tmpfs->readStream($file_name);
141 $res = $this->storage->storeStream($destination, $final['filename'], $final['stream'], $overwrite_on_upload);
142
143 // cleanup
144 $this->tmpfs->remove($file_name);
145 foreach ($this->tmpfs->findAll($prefix.'*') as $expired_chunk) {
146 $this->tmpfs->remove($expired_chunk['name']);
147 }
148
149 return $res ? $response->json('Stored') : $response->json('Error storing file');
150 }
151
152 return $response->json('Uploaded');
153 }
154 }
155