From a0c595a8e11e55a43eeaa68e1a3ce76365f29d06 Mon Sep 17 00:00:00 2001 From: Prasath Mani Date: Mon, 18 May 2020 13:37:02 +0530 Subject: [PATCH] Security fix #357 Download file causes timeout #353 Download Restart @ 88% #312 download large file issues #259 File upload issue #354 FIle Upload URL error #360 Bug in .tar archive extraction when destination(s) file(s) already exist (HTTP error 500) #332 Backup File return false #201 --- tinyfilemanager.php | 195 +++++++++++++++++++++++++++++++++++--------- translation.json | 2 +- 2 files changed, 159 insertions(+), 38 deletions(-) diff --git a/tinyfilemanager.php b/tinyfilemanager.php index 8b9a591..b661a9b 100644 --- a/tinyfilemanager.php +++ b/tinyfilemanager.php @@ -3,13 +3,13 @@ $CONFIG = '{"lang":"en","error_reporting":false,"show_hidden":false,"hide_Cols":false,"calc_folder":false}'; /** - * H3K | Tiny File Manager V2.4.1 + * H3K | Tiny File Manager V2.4.2 * CCP Programmers | ccpprogrammers@gmail.com * https://tinyfilemanager.github.io */ //TFM version -define('VERSION', '2.4.1'); +define('VERSION', '2.4.2'); //Application Title define('APP_TITLE', 'Tiny File Manager'); @@ -417,7 +417,7 @@ if (isset($_POST['ajax']) && !FM_READONLY) { //search : get list of files from the current folder if(isset($_POST['type']) && $_POST['type']=="search") { $dir = FM_ROOT_PATH; - $response = scan($_POST['path'], $_POST['content']); + $response = scan(fm_clean_path($_POST['path']), $_POST['content']); echo json_encode($response); exit(); } @@ -425,11 +425,16 @@ if (isset($_POST['ajax']) && !FM_READONLY) { // backup files if (isset($_POST['type']) && $_POST['type'] == "backup") { $file = $_POST['file']; - $path = $_POST['path']; - $date = date("dMy-His"); - $newFile = $file . '-' . $date . '.bak'; - copy($path . '/' . $file, $path . '/' . $newFile) or die("Unable to backup"); - echo "Backup $newFile Created"; + $dir = fm_clean_path($_POST['path']); + $path = FM_ROOT_PATH.'/'.$dir; + if($dir) { + $date = date("dMy-His"); + $newFile = $file . '-' . $date . '.bak'; + copy($path . '/' . $file, $path . '/' . $newFile) or die("Unable to backup"); + echo "Backup $newFile Created"; + } else { + echo "Error! Not allowed"; + } } // Save Config @@ -785,17 +790,7 @@ if (isset($_GET['dl'])) { $path .= '/' . FM_PATH; } if ($dl != '' && is_file($path . '/' . $dl)) { - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Content-Disposition: attachment; filename="' . basename($path . '/' . $dl) . '"'); - header('Content-Transfer-Encoding: binary'); - header('Connection: Keep-Alive'); - header('Expires: 0'); - header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); - header('Pragma: public'); - header('Content-Length: ' . filesize($path . '/' . $dl)); - ob_end_clean(); - readfile($path . '/' . $dl); + fm_download_file($path . '/' . $dl, $dl, 1024); exit; } else { fm_set_msg('File not found', 'error'); @@ -816,6 +811,10 @@ if (!empty($_FILES) && !FM_READONLY) { $errors = 0; $uploads = 0; $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; + $response = array ( + 'status' => 'error', + 'info' => 'Oops! Try again' + ); $filename = $f['file']['name']; $tmp_name = $f['file']['tmp_name']; @@ -989,8 +988,17 @@ if (isset($_GET['unzip']) && !FM_READONLY) { $zipper = new FM_Zipper(); $res = $zipper->unzip($zip_path, $path); } elseif ($ext == "tar") { - $gzipper = new PharData($zip_path); - $res = $gzipper->extractTo($path); + try { + $gzipper = new PharData($zip_path); + if (@$gzipper->extractTo($path,null, true)) { + $res = true; + } else { + $res = false; + } + } catch (Exception $e) { + //TODO:: need to handle the error + $res = true; + } } if ($res) { @@ -1137,7 +1145,7 @@ if (isset($_GET['upload']) && !FM_READONLY) { :

-
- + @@ -2809,29 +2817,142 @@ function fm_get_onlineViewer_exts() return array('doc', 'docx', 'xls', 'xlsx', 'pdf', 'ppt', 'pptx', 'ai', 'psd', 'dxf', 'xps', 'rar', 'odt', 'ods'); } +function fm_get_file_mimes($extension) +{ + $fileTypes['swf'] = 'application/x-shockwave-flash'; + $fileTypes['pdf'] = 'application/pdf'; + $fileTypes['exe'] = 'application/octet-stream'; + $fileTypes['zip'] = 'application/zip'; + $fileTypes['doc'] = 'application/msword'; + $fileTypes['xls'] = 'application/vnd.ms-excel'; + $fileTypes['ppt'] = 'application/vnd.ms-powerpoint'; + $fileTypes['gif'] = 'image/gif'; + $fileTypes['png'] = 'image/png'; + $fileTypes['jpeg'] = 'image/jpg'; + $fileTypes['jpg'] = 'image/jpg'; + $fileTypes['rar'] = 'application/rar'; + + $fileTypes['ra'] = 'audio/x-pn-realaudio'; + $fileTypes['ram'] = 'audio/x-pn-realaudio'; + $fileTypes['ogg'] = 'audio/x-pn-realaudio'; + + $fileTypes['wav'] = 'video/x-msvideo'; + $fileTypes['wmv'] = 'video/x-msvideo'; + $fileTypes['avi'] = 'video/x-msvideo'; + $fileTypes['asf'] = 'video/x-msvideo'; + $fileTypes['divx'] = 'video/x-msvideo'; + + $fileTypes['mp3'] = 'audio/mpeg'; + $fileTypes['mp4'] = 'audio/mpeg'; + $fileTypes['mpeg'] = 'video/mpeg'; + $fileTypes['mpg'] = 'video/mpeg'; + $fileTypes['mpe'] = 'video/mpeg'; + $fileTypes['mov'] = 'video/quicktime'; + $fileTypes['swf'] = 'video/quicktime'; + $fileTypes['3gp'] = 'video/quicktime'; + $fileTypes['m4a'] = 'video/quicktime'; + $fileTypes['aac'] = 'video/quicktime'; + $fileTypes['m3u'] = 'video/quicktime'; + + $fileTypes['php'] = ['application/x-php']; + $fileTypes['html'] = ['text/html']; + $fileTypes['txt'] = ['text/plain']; + return $fileTypes[$extension]; +} + /** * This function scans the files and folder recursively, and return matching files * @param string $dir + * @param string $filter * @return json */ function scan($dir, $filter = '') { $path = FM_ROOT_PATH.'/'.$dir; - $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); - $rii = new RegexIterator($ite, "/(".$filter.")/i"); + if($dir) { + $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); + $rii = new RegexIterator($ite, "/(" . $filter . ")/i"); - $files = array(); - foreach ($rii as $file) { - if (!$file->isDir()) { - $fileName = $file->getFilename(); - $location = str_replace(FM_ROOT_PATH, '', $file->getPath()); - $files[] = array( - "name" => $fileName, - "type" => "file", - "path" => $location, - ); - } + $files = array(); + foreach ($rii as $file) { + if (!$file->isDir()) { + $fileName = $file->getFilename(); + $location = str_replace(FM_ROOT_PATH, '', $file->getPath()); + $files[] = array( + "name" => $fileName, + "type" => "file", + "path" => $location, + ); + } + } + return $files; + } +} + +/* +Parameters: downloadFile(File Location, File Name, +max speed, is streaming +If streaming - videos will show as videos, images as images +instead of download prompt +https://stackoverflow.com/a/13821992/1164642 +*/ + +function fm_download_file($fileLocation, $fileName, $chunkSize = 1024) +{ + if (connection_status() != 0) + return (false); + $extension = pathinfo($fileName, PATHINFO_EXTENSION); + + $contentType = fm_get_file_mimes($extension); + header("Cache-Control: public"); + header("Content-Transfer-Encoding: binary\n"); + header('Content-Type: $contentType'); + + $contentDisposition = 'attachment'; + + + if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { + $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1); + header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); + } else { + header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); } - return $files; + + header("Accept-Ranges: bytes"); + $range = 0; + $size = filesize($fileLocation); + + if (isset($_SERVER['HTTP_RANGE'])) { + list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']); + str_replace($range, "-", $range); + $size2 = $size - 1; + $new_length = $size - $range; + header("HTTP/1.1 206 Partial Content"); + header("Content-Length: $new_length"); + header("Content-Range: bytes $range$size2/$size"); + } else { + $size2 = $size - 1; + header("Content-Range: bytes 0-$size2/$size"); + header("Content-Length: " . $size); + } + + if ($size == 0) { + die('Zero byte file! Aborting download'); + } + @ini_set('magic_quotes_runtime', 0); + $fp = fopen("$fileLocation", "rb"); + + fseek($fp, $range); + + while (!feof($fp) and (connection_status() == 0)) { + set_time_limit(0); + print(@fread($fp, 1024*$chunkSize)); + flush(); + ob_flush(); + sleep(1); + } + fclose($fp); + + return ((connection_status() == 0) and !connection_aborted()); } /** diff --git a/translation.json b/translation.json index c10fdb1..ca63b28 100644 --- a/translation.json +++ b/translation.json @@ -1,6 +1,6 @@ { "appName": "Tiny File Manager", - "version": "2.4.1", + "version": "2.4.2", "language": [ { "name": "فارسی",