* Validates and retrieves information needed to download a file. * * @param string $folder The folder from which to download (e.g., "root" or a subfolder). * @param string $file The file name. * @return array An associative array with "error" key on failure, * or "filePath" and "mimeType" keys on success. */
($folder, $file)
| 1330 | * or "filePath" and "mimeType" keys on success. |
| 1331 | */ |
| 1332 | public static function getDownloadInfo($folder, $file) |
| 1333 | { |
| 1334 | $storage = self::storage(); |
| 1335 | $isLocal = $storage->isLocal(); |
| 1336 | $root = self::uploadRoot(); |
| 1337 | |
| 1338 | // Validate file name using REGEX_FILE_NAME. |
| 1339 | $file = basename(trim($file)); |
| 1340 | if (!preg_match(REGEX_FILE_NAME, $file)) { |
| 1341 | return ["error" => "Invalid file name."]; |
| 1342 | } |
| 1343 | |
| 1344 | if (!$isLocal) { |
| 1345 | // Remote adapter path resolution (no realpath). |
| 1346 | if (strtolower($folder) !== 'root' && trim($folder) !== '') { |
| 1347 | if (strpos($folder, '..') !== false) { |
| 1348 | return ["error" => "Invalid folder name."]; |
| 1349 | } |
| 1350 | $parts = explode('/', trim((string)$folder, "/\\ ")); |
| 1351 | foreach ($parts as $part) { |
| 1352 | if ($part === '' || !preg_match(REGEX_FOLDER_NAME, $part)) { |
| 1353 | return ["error" => "Invalid folder name."]; |
| 1354 | } |
| 1355 | } |
| 1356 | $directory = rtrim($root, '/\\') . DIRECTORY_SEPARATOR . trim($folder, "/\\ "); |
| 1357 | } else { |
| 1358 | $directory = rtrim($root, '/\\'); |
| 1359 | } |
| 1360 | |
| 1361 | $filePath = $directory . DIRECTORY_SEPARATOR . $file; |
| 1362 | $stat = $storage->stat($filePath); |
| 1363 | if ($stat === null || ($stat['type'] ?? '') !== 'file') { |
| 1364 | $probe = $storage->openReadStream($filePath, 1, 0); |
| 1365 | if ($probe === false) { |
| 1366 | return ["error" => "File not found."]; |
| 1367 | } |
| 1368 | if (is_resource($probe)) { |
| 1369 | @fclose($probe); |
| 1370 | } elseif (is_object($probe) && method_exists($probe, 'close')) { |
| 1371 | $probe->close(); |
| 1372 | } |
| 1373 | $stat = [ |
| 1374 | 'type' => 'file', |
| 1375 | 'size' => 0, |
| 1376 | ]; |
| 1377 | } |
| 1378 | |
| 1379 | $downloadName = $file; |
| 1380 | $downloadExt = $stat['downloadExt'] ?? ''; |
| 1381 | if (is_string($downloadExt)) { |
| 1382 | $downloadExt = ltrim($downloadExt, '.'); |
| 1383 | if ($downloadExt !== '') { |
| 1384 | $suffix = '.' . strtolower($downloadExt); |
| 1385 | if (!str_ends_with(strtolower($downloadName), $suffix)) { |
| 1386 | $downloadName .= '.' . $downloadExt; |
| 1387 | } |
| 1388 | } |
| 1389 | } |
no test coverage detected