|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace TusPhp\Tus; |
|
4
|
|
|
|
|
5
|
|
|
use TusPhp\File; |
|
6
|
|
|
use Carbon\Carbon; |
|
7
|
|
|
use TusPhp\Request; |
|
8
|
|
|
use TusPhp\Response; |
|
9
|
|
|
use TusPhp\Cache\Cacheable; |
|
10
|
|
|
use TusPhp\Exception\FileException; |
|
11
|
|
|
use TusPhp\Exception\ConnectionException; |
|
12
|
|
|
use TusPhp\Exception\OutOfRangeException; |
|
13
|
|
|
use Illuminate\Http\Response as HttpResponse; |
|
14
|
|
|
use Symfony\Component\HttpFoundation\BinaryFileResponse; |
|
15
|
|
|
|
|
16
|
|
|
class Server extends AbstractTus |
|
17
|
|
|
{ |
|
18
|
|
|
/** @const Tus Creation Extension */ |
|
19
|
|
|
const TUS_EXTENSION_CREATION = 'creation'; |
|
20
|
|
|
|
|
21
|
|
|
/** @const Tus Termination Extension */ |
|
22
|
|
|
const TUS_EXTENSION_TERMINATION = 'termination'; |
|
23
|
|
|
|
|
24
|
|
|
/** @const Tus Checksum Extension */ |
|
25
|
|
|
const TUS_EXTENSION_CHECKSUM = 'checksum'; |
|
26
|
|
|
|
|
27
|
|
|
/** @const Tus Expiration Extension */ |
|
28
|
|
|
const TUS_EXTENSION_EXPIRATION = 'expiration'; |
|
29
|
|
|
|
|
30
|
|
|
/** @const Tus Concatenation Extension */ |
|
31
|
|
|
const TUS_EXTENSION_CONCATENATION = 'concatenation'; |
|
32
|
|
|
|
|
33
|
|
|
/** @const 460 Checksum Mismatch */ |
|
34
|
|
|
const HTTP_CHECKSUM_MISMATCH = 460; |
|
35
|
|
|
|
|
36
|
|
|
/** @var Request */ |
|
37
|
|
|
protected $request; |
|
38
|
|
|
|
|
39
|
|
|
/** @var Response */ |
|
40
|
|
|
protected $response; |
|
41
|
|
|
|
|
42
|
|
|
/** @var string */ |
|
43
|
|
|
protected $uploadDir; |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* TusServer constructor. |
|
47
|
|
|
* |
|
48
|
|
|
* @param Cacheable|string $cacheAdapter |
|
49
|
|
|
*/ |
|
50
|
3 |
|
public function __construct($cacheAdapter = 'file') |
|
51
|
|
|
{ |
|
52
|
3 |
|
$this->request = new Request; |
|
53
|
3 |
|
$this->response = new Response; |
|
54
|
3 |
|
$this->uploadDir = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'uploads'; |
|
55
|
|
|
|
|
56
|
3 |
|
$this->setCache($cacheAdapter); |
|
57
|
3 |
|
} |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* Set upload dir. |
|
61
|
|
|
* |
|
62
|
|
|
* @param string $path |
|
63
|
|
|
* |
|
64
|
|
|
* @return void |
|
65
|
|
|
*/ |
|
66
|
1 |
|
public function setUploadDir(string $path) |
|
67
|
|
|
{ |
|
68
|
1 |
|
$this->uploadDir = $path; |
|
69
|
1 |
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Get upload dir. |
|
73
|
|
|
* |
|
74
|
|
|
* @return string |
|
75
|
|
|
*/ |
|
76
|
1 |
|
public function getUploadDir() : string |
|
77
|
|
|
{ |
|
78
|
1 |
|
return $this->uploadDir; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Get request. |
|
83
|
|
|
* |
|
84
|
|
|
* @return Request |
|
85
|
|
|
*/ |
|
86
|
1 |
|
public function getRequest() : Request |
|
87
|
|
|
{ |
|
88
|
1 |
|
return $this->request; |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* Get request. |
|
93
|
|
|
* |
|
94
|
|
|
* @return Response |
|
95
|
|
|
*/ |
|
96
|
1 |
|
public function getResponse() : Response |
|
97
|
|
|
{ |
|
98
|
1 |
|
return $this->response; |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Get file checksum. |
|
103
|
|
|
* |
|
104
|
|
|
* @param string $filePath |
|
105
|
|
|
* |
|
106
|
|
|
* @return string |
|
107
|
|
|
*/ |
|
108
|
|
|
public function getChecksum(string $filePath) |
|
109
|
|
|
{ |
|
110
|
|
|
return hash_file($this->getChecksumAlgorithm(), $filePath); |
|
|
|
|
|
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Get checksum algorithm. |
|
115
|
|
|
* |
|
116
|
|
|
* @return null |
|
117
|
|
|
*/ |
|
118
|
|
|
public function getChecksumAlgorithm() |
|
119
|
|
|
{ |
|
120
|
|
|
$checksumHeader = $this->getRequest()->header('Upload-Checksum'); |
|
121
|
|
|
|
|
122
|
|
|
if (empty($checksumHeader)) { |
|
123
|
|
|
return null; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
list($checksumAlgorithm) = explode(' ', $checksumHeader); |
|
127
|
|
|
|
|
128
|
|
|
return $checksumAlgorithm; |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
/** |
|
132
|
|
|
* Handle all HTTP request. |
|
133
|
|
|
* |
|
134
|
|
|
* @return null|HttpResponse |
|
135
|
|
|
*/ |
|
136
|
2 |
|
public function serve() |
|
137
|
|
|
{ |
|
138
|
2 |
|
$method = $this->getRequest()->method(); |
|
139
|
|
|
|
|
140
|
2 |
|
if ( ! in_array($method, $this->request->allowedHttpVerbs())) { |
|
141
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_METHOD_NOT_ALLOWED); |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
1 |
|
$method = 'handle' . ucfirst(strtolower($method)); |
|
145
|
|
|
|
|
146
|
1 |
|
$this->{$method}(); |
|
147
|
|
|
|
|
148
|
1 |
|
$this->exit(); |
|
149
|
1 |
|
} |
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* Exit from current php process. |
|
153
|
|
|
* |
|
154
|
|
|
* @codeCoverageIgnore |
|
155
|
|
|
*/ |
|
156
|
|
|
protected function exit() |
|
157
|
|
|
{ |
|
158
|
|
|
exit(0); |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* Handle OPTIONS request. |
|
163
|
|
|
* |
|
164
|
|
|
* @return HttpResponse |
|
165
|
|
|
*/ |
|
166
|
1 |
|
protected function handleOptions() : HttpResponse |
|
167
|
|
|
{ |
|
168
|
1 |
|
return $this->response->send( |
|
169
|
1 |
|
null, |
|
170
|
1 |
|
HttpResponse::HTTP_OK, |
|
171
|
|
|
[ |
|
172
|
1 |
|
'Allow' => $this->request->allowedHttpVerbs(), |
|
173
|
1 |
|
'Tus-Version' => self::TUS_PROTOCOL_VERSION, |
|
174
|
1 |
|
'Tus-Extension' => implode(',', [ |
|
175
|
1 |
|
self::TUS_EXTENSION_CREATION, |
|
176
|
1 |
|
self::TUS_EXTENSION_TERMINATION, |
|
177
|
1 |
|
self::TUS_EXTENSION_CHECKSUM, |
|
178
|
1 |
|
self::TUS_EXTENSION_EXPIRATION, |
|
179
|
1 |
|
self::TUS_EXTENSION_CONCATENATION, |
|
180
|
|
|
]), |
|
181
|
1 |
|
'Tus-Checksum-Algorithm' => $this->getSupportedHashAlgorithms(), |
|
182
|
|
|
] |
|
183
|
|
|
); |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
/** |
|
187
|
|
|
* Handle HEAD request. |
|
188
|
|
|
* |
|
189
|
|
|
* @return HttpResponse |
|
190
|
|
|
*/ |
|
191
|
3 |
|
protected function handleHead() : HttpResponse |
|
192
|
|
|
{ |
|
193
|
3 |
|
$checksum = $this->request->checksum(); |
|
194
|
|
|
|
|
195
|
3 |
|
if ( ! $this->cache->get($checksum)) { |
|
196
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_NOT_FOUND); |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
2 |
|
$offset = $this->cache->get($checksum)['offset'] ?? false; |
|
200
|
|
|
|
|
201
|
2 |
|
if (false === $offset) { |
|
202
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_GONE); |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_OK, [ |
|
206
|
1 |
|
'Upload-Offset' => (int) $offset, |
|
207
|
1 |
|
'Cache-Control' => 'no-store', |
|
208
|
1 |
|
'Tus-Resumable' => self::TUS_PROTOCOL_VERSION, |
|
209
|
|
|
]); |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* Handle POST request. |
|
214
|
|
|
* |
|
215
|
|
|
* @return HttpResponse |
|
216
|
|
|
*/ |
|
217
|
2 |
|
protected function handlePost() : HttpResponse |
|
218
|
|
|
{ |
|
219
|
2 |
|
$fileName = $this->getRequest()->extractFileName(); |
|
220
|
|
|
|
|
221
|
2 |
|
if (empty($fileName)) { |
|
222
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_BAD_REQUEST); |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
1 |
|
$checksum = $this->getUploadChecksum(); |
|
226
|
1 |
|
$filePath = $this->uploadDir . DIRECTORY_SEPARATOR . $fileName; |
|
227
|
|
|
|
|
228
|
1 |
|
if ($this->getRequest()->isFinal()) { |
|
229
|
|
|
return $this->handleConcatenation($fileName, $filePath); |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
1 |
|
if ($this->getRequest()->isPartial()) { |
|
233
|
|
|
$filePath = $this->getPathForPartialUpload($checksum) . $fileName; |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
1 |
|
$location = $this->getRequest()->url() . '/' . basename($this->uploadDir) . '/' . $fileName; |
|
237
|
|
|
|
|
238
|
1 |
|
$file = $this->buildFile([ |
|
239
|
1 |
|
'name' => $fileName, |
|
240
|
1 |
|
'offset' => 0, |
|
241
|
1 |
|
'size' => $this->getRequest()->header('Upload-Length'), |
|
242
|
1 |
|
'file_path' => $filePath, |
|
243
|
1 |
|
'location' => $location, |
|
244
|
1 |
|
])->setChecksum($checksum); |
|
245
|
|
|
|
|
246
|
1 |
|
$this->cache->set($checksum, $file->details()); |
|
247
|
|
|
|
|
248
|
1 |
|
return $this->response->send( |
|
249
|
1 |
|
['data' => ['checksum' => $checksum]], |
|
250
|
1 |
|
HttpResponse::HTTP_CREATED, |
|
251
|
|
|
[ |
|
252
|
1 |
|
'Location' => $location, |
|
253
|
1 |
|
'Upload-Expires' => $this->cache->get($checksum)['expires_at'], |
|
254
|
1 |
|
'Tus-Resumable' => self::TUS_PROTOCOL_VERSION, |
|
255
|
|
|
] |
|
256
|
|
|
); |
|
257
|
|
|
} |
|
258
|
|
|
|
|
259
|
|
|
/** |
|
260
|
|
|
* Handle file concatenation. |
|
261
|
|
|
* |
|
262
|
|
|
* @param string $fileName |
|
263
|
|
|
* @param string $filePath |
|
264
|
|
|
* |
|
265
|
|
|
* @return HttpResponse |
|
266
|
|
|
*/ |
|
267
|
|
|
protected function handleConcatenation(string $fileName, string $filePath) : HttpResponse |
|
268
|
|
|
{ |
|
269
|
|
|
$files = []; |
|
270
|
|
|
$partials = $this->getRequest()->extractPartials(); |
|
271
|
|
|
$location = $this->getRequest()->url() . '/' . basename($this->uploadDir) . '/' . $fileName; |
|
272
|
|
|
|
|
273
|
|
|
foreach ($partials as $partial) { |
|
274
|
|
|
$fileMeta = $this->getCache()->get($partial); |
|
275
|
|
|
|
|
276
|
|
|
$files[] = $fileMeta['file_path']; |
|
277
|
|
|
} |
|
278
|
|
|
|
|
279
|
|
|
$file = (new File($fileName, $this->cache)) |
|
280
|
|
|
->setFilePath($filePath); |
|
281
|
|
|
|
|
282
|
|
|
$file->merge($files); |
|
283
|
|
|
|
|
284
|
|
|
// Verify checksum. |
|
285
|
|
|
$checksum = $this->getChecksum($filePath); |
|
286
|
|
|
|
|
287
|
|
|
if ($checksum !== $this->getUploadChecksum()) { |
|
288
|
|
|
return $this->response->send(null, self::HTTP_CHECKSUM_MISMATCH); |
|
289
|
|
|
} |
|
290
|
|
|
|
|
291
|
|
|
// Cleanup. |
|
292
|
|
|
$file->delete($files, true); |
|
293
|
|
|
|
|
294
|
|
|
return $this->response->send( |
|
295
|
|
|
['data' => ['checksum' => $checksum]], |
|
296
|
|
|
HttpResponse::HTTP_CREATED, |
|
297
|
|
|
[ |
|
298
|
|
|
'Location' => $location, |
|
299
|
|
|
'Tus-Resumable' => self::TUS_PROTOCOL_VERSION, |
|
300
|
|
|
] |
|
301
|
|
|
); |
|
302
|
|
|
} |
|
303
|
|
|
|
|
304
|
|
|
/** |
|
305
|
|
|
* Handle PATCH request. |
|
306
|
|
|
* |
|
307
|
|
|
* @return HttpResponse |
|
308
|
|
|
*/ |
|
309
|
6 |
|
protected function handlePatch() : HttpResponse |
|
310
|
|
|
{ |
|
311
|
6 |
|
$checksum = $this->request->checksum(); |
|
312
|
|
|
|
|
313
|
6 |
|
if ( ! $this->cache->get($checksum)) { |
|
314
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_GONE); |
|
315
|
|
|
} |
|
316
|
|
|
|
|
317
|
5 |
|
$meta = $this->cache->get($checksum); |
|
318
|
5 |
|
$file = $this->buildFile($meta); |
|
319
|
|
|
|
|
320
|
|
|
try { |
|
321
|
5 |
|
$fileSize = $file->getFileSize(); |
|
322
|
5 |
|
$offset = $file->setChecksum($checksum)->upload($fileSize); |
|
323
|
|
|
|
|
324
|
|
|
// If upload is done, verify checksum. |
|
325
|
2 |
|
if ($offset === $fileSize && $checksum !== $this->getUploadChecksum()) { |
|
326
|
2 |
|
return $this->response->send(null, self::HTTP_CHECKSUM_MISMATCH); |
|
327
|
|
|
} |
|
328
|
3 |
|
} catch (FileException $e) { |
|
329
|
1 |
|
return $this->response->send($e->getMessage(), HttpResponse::HTTP_UNPROCESSABLE_ENTITY); |
|
330
|
2 |
|
} catch (OutOfRangeException $e) { |
|
331
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE); |
|
332
|
1 |
|
} catch (ConnectionException $e) { |
|
333
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_CONTINUE); |
|
334
|
|
|
} |
|
335
|
|
|
|
|
336
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_NO_CONTENT, [ |
|
337
|
1 |
|
'Upload-Expires' => $this->cache->get($checksum)['expires_at'], |
|
338
|
1 |
|
'Upload-Offset' => $offset, |
|
339
|
1 |
|
'Tus-Resumable' => self::TUS_PROTOCOL_VERSION, |
|
340
|
|
|
]); |
|
341
|
|
|
} |
|
342
|
|
|
|
|
343
|
|
|
/** |
|
344
|
|
|
* Handle GET request. |
|
345
|
|
|
* |
|
346
|
|
|
* @return BinaryFileResponse|HttpResponse |
|
347
|
|
|
*/ |
|
348
|
4 |
|
protected function handleGet() |
|
349
|
|
|
{ |
|
350
|
4 |
|
$checksum = $this->request->checksum(); |
|
351
|
|
|
|
|
352
|
4 |
|
if (empty($checksum)) { |
|
353
|
1 |
|
return $this->response->send('400 bad request.', HttpResponse::HTTP_BAD_REQUEST); |
|
354
|
|
|
} |
|
355
|
|
|
|
|
356
|
3 |
|
$fileMeta = $this->cache->get($checksum); |
|
357
|
|
|
|
|
358
|
3 |
|
if ( ! $fileMeta) { |
|
359
|
1 |
|
return $this->response->send('404 upload not found.', HttpResponse::HTTP_NOT_FOUND); |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
2 |
|
$resource = $fileMeta['file_path'] ?? null; |
|
363
|
2 |
|
$fileName = $fileMeta['name'] ?? null; |
|
364
|
|
|
|
|
365
|
2 |
|
if ( ! $resource || ! file_exists($resource)) { |
|
366
|
1 |
|
return $this->response->send('404 upload not found.', HttpResponse::HTTP_NOT_FOUND); |
|
367
|
|
|
} |
|
368
|
|
|
|
|
369
|
1 |
|
return $this->response->download($resource, $fileName); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
/** |
|
373
|
|
|
* Handle DELETE request. |
|
374
|
|
|
* |
|
375
|
|
|
* @return HttpResponse |
|
376
|
|
|
*/ |
|
377
|
3 |
|
protected function handleDelete() : HttpResponse |
|
378
|
|
|
{ |
|
379
|
3 |
|
$checksum = $this->request->checksum(); |
|
380
|
3 |
|
$fileMeta = $this->cache->get($checksum); |
|
381
|
3 |
|
$resource = $fileMeta['file_path'] ?? null; |
|
382
|
|
|
|
|
383
|
3 |
|
if ( ! $resource) { |
|
384
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_NOT_FOUND); |
|
385
|
|
|
} |
|
386
|
|
|
|
|
387
|
2 |
|
$isDeleted = $this->cache->delete($checksum); |
|
388
|
|
|
|
|
389
|
2 |
|
if ( ! $isDeleted || ! file_exists($resource)) { |
|
390
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_GONE); |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
1 |
|
unlink($resource); |
|
394
|
|
|
|
|
395
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_NO_CONTENT, [ |
|
396
|
1 |
|
'Tus-Resumable' => self::TUS_PROTOCOL_VERSION, |
|
397
|
1 |
|
'Tus-Extension' => self::TUS_EXTENSION_TERMINATION, |
|
398
|
|
|
]); |
|
399
|
|
|
} |
|
400
|
|
|
|
|
401
|
|
|
/** |
|
402
|
|
|
* Build file object. |
|
403
|
|
|
* |
|
404
|
|
|
* @param array $meta |
|
405
|
|
|
* |
|
406
|
|
|
* @return File |
|
407
|
|
|
*/ |
|
408
|
1 |
|
protected function buildFile(array $meta) : File |
|
409
|
|
|
{ |
|
410
|
1 |
|
return (new File($meta['name'], $this->cache)) |
|
411
|
1 |
|
->setMeta($meta['offset'], $meta['size'], $meta['file_path'], $meta['location']); |
|
412
|
|
|
} |
|
413
|
|
|
|
|
414
|
|
|
/** |
|
415
|
|
|
* Get list of supported hash algorithms. |
|
416
|
|
|
* |
|
417
|
|
|
* @return string |
|
418
|
|
|
*/ |
|
419
|
1 |
|
protected function getSupportedHashAlgorithms() |
|
420
|
|
|
{ |
|
421
|
1 |
|
$supportedAlgorithms = hash_algos(); |
|
422
|
|
|
|
|
423
|
1 |
|
$algorithms = []; |
|
424
|
1 |
|
foreach ($supportedAlgorithms as $hashAlgo) { |
|
425
|
1 |
|
if (false !== strpos($hashAlgo, ',')) { |
|
426
|
1 |
|
$algorithms[] = "'{$hashAlgo}'"; |
|
427
|
|
|
} else { |
|
428
|
1 |
|
$algorithms[] = $hashAlgo; |
|
429
|
|
|
} |
|
430
|
|
|
} |
|
431
|
|
|
|
|
432
|
1 |
|
return implode(',', $algorithms); |
|
433
|
|
|
} |
|
434
|
|
|
|
|
435
|
|
|
/** |
|
436
|
|
|
* Verify and get upload checksum from header. |
|
437
|
|
|
* |
|
438
|
|
|
* @return string|HttpResponse |
|
439
|
|
|
*/ |
|
440
|
4 |
|
protected function getUploadChecksum() |
|
441
|
|
|
{ |
|
442
|
4 |
|
$checksumHeader = $this->getRequest()->header('Upload-Checksum'); |
|
443
|
|
|
|
|
444
|
4 |
|
if (empty($checksumHeader)) { |
|
445
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_BAD_REQUEST); |
|
446
|
|
|
} |
|
447
|
|
|
|
|
448
|
3 |
|
list($checksumAlgorithm, $checksum) = explode(' ', $checksumHeader); |
|
449
|
|
|
|
|
450
|
3 |
|
$checksum = base64_decode($checksum); |
|
451
|
|
|
|
|
452
|
3 |
|
if ( ! in_array($checksumAlgorithm, hash_algos()) || false === $checksum) { |
|
453
|
2 |
|
return $this->response->send(null, HttpResponse::HTTP_BAD_REQUEST); |
|
454
|
|
|
} |
|
455
|
|
|
|
|
456
|
1 |
|
return $checksum; |
|
457
|
|
|
} |
|
458
|
|
|
|
|
459
|
|
|
/** |
|
460
|
|
|
* Get expired but incomplete uploads. |
|
461
|
|
|
* |
|
462
|
|
|
* @param array|null $contents |
|
463
|
|
|
* |
|
464
|
|
|
* @return bool |
|
465
|
|
|
*/ |
|
466
|
3 |
|
protected function isExpired($contents) : bool |
|
467
|
|
|
{ |
|
468
|
3 |
|
$isExpired = empty($contents['expires_at']) || Carbon::parse($contents['expires_at'])->lt(Carbon::now()); |
|
469
|
|
|
|
|
470
|
3 |
|
if ($isExpired && $contents['offset'] !== $contents['size']) { |
|
471
|
3 |
|
return true; |
|
472
|
|
|
} |
|
473
|
|
|
|
|
474
|
2 |
|
return false; |
|
475
|
|
|
} |
|
476
|
|
|
|
|
477
|
|
|
/** |
|
478
|
|
|
* Get path for partial upload. |
|
479
|
|
|
* |
|
480
|
|
|
* @param string $checksum |
|
481
|
|
|
* |
|
482
|
|
|
* @return string |
|
483
|
|
|
*/ |
|
484
|
|
|
protected function getPathForPartialUpload(string $checksum) : string |
|
485
|
|
|
{ |
|
486
|
|
|
list($actualChecksum) = explode(self::PARTIAL_UPLOAD_NAME_SEPARATOR, $checksum); |
|
487
|
|
|
|
|
488
|
|
|
$path = $this->uploadDir . DIRECTORY_SEPARATOR . $actualChecksum . DIRECTORY_SEPARATOR; |
|
489
|
|
|
|
|
490
|
|
|
if ( ! file_exists($path)) { |
|
491
|
|
|
mkdir($path); |
|
492
|
|
|
} |
|
493
|
|
|
|
|
494
|
|
|
return $path; |
|
495
|
|
|
} |
|
496
|
|
|
|
|
497
|
|
|
/** |
|
498
|
|
|
* Delete expired resources. |
|
499
|
|
|
* |
|
500
|
|
|
* @return array |
|
501
|
|
|
*/ |
|
502
|
2 |
|
public function handleExpiration() |
|
503
|
|
|
{ |
|
504
|
2 |
|
$deleted = []; |
|
505
|
2 |
|
$cacheKeys = $this->cache->keys(); |
|
506
|
|
|
|
|
507
|
2 |
|
foreach ($cacheKeys as $key) { |
|
508
|
2 |
|
$fileMeta = $this->cache->get($key, true); |
|
509
|
|
|
|
|
510
|
2 |
|
if ( ! $this->isExpired($fileMeta)) { |
|
511
|
1 |
|
continue; |
|
512
|
|
|
} |
|
513
|
|
|
|
|
514
|
2 |
|
$cacheDeleted = $this->cache->delete($key); |
|
515
|
|
|
|
|
516
|
2 |
|
if ( ! $cacheDeleted) { |
|
517
|
1 |
|
continue; |
|
518
|
|
|
} |
|
519
|
|
|
|
|
520
|
1 |
|
if (file_exists($fileMeta['file_path']) && is_writable($fileMeta['file_path'])) { |
|
521
|
1 |
|
unlink($fileMeta['file_path']); |
|
522
|
|
|
} |
|
523
|
|
|
|
|
524
|
1 |
|
$deleted[] = $fileMeta; |
|
525
|
|
|
} |
|
526
|
|
|
|
|
527
|
2 |
|
return $deleted; |
|
528
|
|
|
} |
|
529
|
|
|
|
|
530
|
|
|
/** |
|
531
|
|
|
* No other methods are allowed. |
|
532
|
|
|
* |
|
533
|
|
|
* @param string $method |
|
534
|
|
|
* @param array $params |
|
535
|
|
|
* |
|
536
|
|
|
* @return HttpResponse|BinaryFileResponse |
|
537
|
|
|
*/ |
|
538
|
1 |
|
public function __call(string $method, array $params) |
|
539
|
|
|
{ |
|
540
|
1 |
|
return $this->response->send(null, HttpResponse::HTTP_BAD_REQUEST); |
|
541
|
|
|
} |
|
542
|
|
|
} |
|
543
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.