From 82c07bc02cafe9b8d6cb9fa2362b2ba6326d6a7b Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 26 Jun 2013 19:48:33 +0200 Subject: tmp-upload: support subdirs, duplicate detection --- tmp-upload | 103 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 27 deletions(-) (limited to 'tmp-upload') diff --git a/tmp-upload b/tmp-upload index 913c129..3578a50 100755 --- a/tmp-upload +++ b/tmp-upload @@ -2,6 +2,15 @@ host=0.0.0.0 port=1111 +if [ -n "$1" ]; then + if [[ $1 =~ ^[0-9]+$ ]]; then + port=$1 + else + echo "Usage: $0 port" + exit 1 + fi +fi + out="$(mktemp /tmp/tmp-upload-php.XXXXXXXX)" cleanup() { rm -v "$out" @@ -26,26 +35,40 @@ function get_mime_type($file) { } $url = $_SERVER['REQUEST_URI']; -if ($url != '/') { - /* Simply returning false causes PHP to parse (index).php. Unwanted, - * therefore serve it here. First check whether the path is within the - * current working directory, then whether the file exists or not. */ - $cwdir = realpath("."); - if ($cwdir === FALSE) { - http_response_code(500); - exit; - } - $path = realpath("." . $url); - if ($path === FALSE) { - http_response_code(404); - exit; - } - if (strpos($path, $cwdir . DIRECTORY_SEPARATOR) !== 0) { - http_response_code(403); +/* Simply returning false causes PHP to parse (index).php. Unwanted, + * therefore serve it here. First check whether the path is within the + * current working directory, then whether the file exists or not. */ +$cwdir = realpath("."); +if ($cwdir === FALSE) { + http_response_code(500); + exit; +} + +$path = realpath("./" . $url); +if ($path === FALSE) { + http_response_code(404); + exit; +} +if (strpos($path . DIRECTORY_SEPARATOR, $cwdir . DIRECTORY_SEPARATOR) !== 0) { + http_response_code(403); + exit; +} + +$relDir = ''; + +if (is_dir($path)) { + if (substr($url, -1) !== '/') { + header("Location: $url/"); exit; } + $relDir = substr($path, strlen($path . DIRECTORY_SEPARATOR)); + if (!strlen($relDir)) { + $relDir = '.'; + } + $relDir .= DIRECTORY_SEPARATOR; +} else { /* determine content type and size in bytes */ $filesize = filesize($path); $mimetype = get_mime_type($path); @@ -59,24 +82,34 @@ if ($url != '/') { header("Content-Length: $filesize"); } + error_log(sprintf("download %s %s %d", $mimetype, $path, $filesize)); readfile($path); exit; } $msg = NULL; if (isset($_FILES["file"]["name"])) { - $name = trim(basename($_FILES["file"]["name"]), "."); - if (!$name) { + $upload = $_FILES["file"]; + $name = trim(basename($upload["name"]), "."); + $name = preg_replace('/[\x00-\x1F\x7F]/', '', $name); + if ($relDir === '') { + $msg = 'Invalid upload directory!'; + } else if ($name === '') { $msg = "No filename is given!"; } else if (!$_FILES["file"]["size"]) { $msg = "I do not accept empty files!"; } else { - $filename = $name; - for ($i=1; file_exists($filename); $i++) { - $filename = "$filename.$i"; + $filename = $relDir . $name; + $is_dupe = file_equals($filename, $upload["tmp_name"], $upload["size"]); + for ($i=1; !$is_dupe && file_exists($filename); $i++) { + $filename = "$name.$i"; + $is_dupe = file_equals($filename, $upload["tmp_name"], $upload["size"]); } - if (move_uploaded_file($_FILES["file"]["tmp_name"], $filename)) { + if ($is_dupe) { + $msg = "Uploaded file is a duplicate of " . htmlspecialchars($filename); + } else if (move_uploaded_file($upload["tmp_name"], $filename)) { $msg = "File is saved as " . htmlspecialchars($filename); + error_log(sprintf("upload %s", $filename)); } else { $msg = "File could not be saved."; } @@ -99,26 +132,42 @@ if ($msg) echo "

$msg

"; isDot()) { - continue; + //continue; } $filename = $f->getFilename(); $len = mb_strlen($filename); - if ($len > 50) { - $dispName = mb_substr($filename, 0, 47) . '..>'; + $maxLen = $f->isDir() ? 49 : 50; + if ($len > $maxLen) { + $dispName = mb_substr($filename, 0, $maxLen - 3) . '..>'; } else { $dispName = $filename; } + if ($f->isDir()) { + $filename .= '/'; + $dispName .= '/'; + } printf('%s%s %s %20d' . "\n", htmlspecialchars($filename), htmlspecialchars($dispName), - str_repeat(' ', max(0, 50 - $len)), + str_repeat(' ', max(0, $maxLen - $len)), date('d-M-Y H:i', $f->getMTime()), $f->getSize() ); } +function file_equals($newFile, $refFile, $refSize) { + if (!file_exists($newFile)) { + return false; + } + $newSize = filesize($newFile); + if ($newSize !== $refSize) { + return false; + } + return md5_file($newFile) === md5_file($refFile); +} ?> -- cgit v1.2.1