first commit
This commit is contained in:
commit
3309431ac7
|
@ -0,0 +1,24 @@
|
|||
# Renadexer
|
||||
|
||||
A no-bullshit solution to list your files! Have you ever looked at apache2's directory listing feature and went
|
||||
>damn, I really want to load and search this list of 100k+ files and folders without killing Firefox
|
||||
|
||||
Look no further!!
|
||||
|
||||
## Features
|
||||
- Configurable pagination
|
||||
- Configurable search function with AND, OR and Regex PCRE modes
|
||||
- Configurable MOTD
|
||||
- Mimetype detection using magic bytes
|
||||
- Seek videos, pause downloads and transfer large files with little memory consumption
|
||||
- Lighter than your average 2009 anorexic altgirl
|
||||
- Absolutely horrible URL scheme
|
||||
|
||||
## Installation
|
||||
Requires PHP 8. Drag `listdir.php` on any server that supports PHP. Change the variables at the top of the file and you're set!!
|
||||
|
||||
## Singular piece of shit screenshot
|
||||
![screenshot](https://i.imgur.com/Q9X9SZ1.png)
|
||||
|
||||
## License
|
||||
Do whatever the fuck you want license (WTFPL)
|
|
@ -0,0 +1,464 @@
|
|||
<?php
|
||||
|
||||
// do NOT append / at the end
|
||||
// Eg: /home/will/Downloads
|
||||
$folder_base = "/home/will/Downloads";
|
||||
$items_per_page = 20;
|
||||
$max_results = 100; // will break; once we reach limit, -1 for no limit
|
||||
$motd = "get fucked";
|
||||
$script_name = "listdir.php";
|
||||
|
||||
function do_error($code, $title, $text, $motd, $script_name){
|
||||
|
||||
http_response_code($code);
|
||||
echo
|
||||
'<!DOCTYPE html>' .
|
||||
'<html lang="en">' .
|
||||
'<head>' .
|
||||
'<title>' . $title . '</title>' .
|
||||
'</head>' .
|
||||
'<body>' .
|
||||
'<h1>' . $title . '</h1>' .
|
||||
'<p>' . $text . '<br><ul><li><a href="' . $script_name . '">Go home yankee!</a></ul></li></p>' .
|
||||
'<hr>' .
|
||||
$motd .
|
||||
'</body>' .
|
||||
'</html>';
|
||||
die();
|
||||
}
|
||||
|
||||
function do_filesize($path, $is_dir){
|
||||
|
||||
if($is_dir){
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$filesize = filesize($path);
|
||||
|
||||
if($filesize === 0){
|
||||
|
||||
echo "0.00 B";
|
||||
}
|
||||
|
||||
$s = ["B", "KB", "MB", "GB", "TB", "PB"];
|
||||
$e = floor(log($filesize, 1024));
|
||||
|
||||
return round($filesize / pow(1024, $e), 2) . " " . $s[$e];
|
||||
}
|
||||
|
||||
function do_header($title, $search, $check, $is_search, $script_name, $up){
|
||||
|
||||
echo
|
||||
'<!DOCTYPE html>' .
|
||||
'<html lang="en">' .
|
||||
'<head>' .
|
||||
'<title>' . $title . '</title>' .
|
||||
'</head>' .
|
||||
'<body>' .
|
||||
'<h1>' . $title . '</h1>' .
|
||||
'<form autocomplete="off" method="GET">' .
|
||||
'<input type="text" name="query" placeholder="search query" value="' . $search . '">' .
|
||||
' <input type="submit" value="search"><br>' .
|
||||
'<input id="and" type="radio" name="filter" value="and"' . ($check === "and" ? " checked" : "") . '>' .
|
||||
'<label for="and">AND </label>' .
|
||||
'<input id="or" type="radio" name="filter" value="or"' . ($check === "or" ? " checked" : "") . '>' .
|
||||
'<label for="or">OR </label>' .
|
||||
'<input id="pcre" type="radio" name="filter" value="pcre"' . ($check === "pcre" ? " checked" : "") . '>' .
|
||||
'<label for="pcre">PCRE </label>' .
|
||||
'</form><br>' .
|
||||
($is_search === true ? '<a href="' . $script_name . '">< Go back to index</a><br><br>' : "") .
|
||||
($up !== false ? '<a href="' . $up . '">^ Go up</a><br><br>' : "") .
|
||||
'<table>' .
|
||||
'<tr>' .
|
||||
($is_search === false ? '<th></th>' : "") .
|
||||
'<th>' .
|
||||
'type' .
|
||||
'</th>' .
|
||||
'<th>' .
|
||||
'name' .
|
||||
'</th>' .
|
||||
'<th>' .
|
||||
'size' .
|
||||
'</th>' .
|
||||
($is_search === false ? '<th></th>' : "") .
|
||||
'</tr>' .
|
||||
'<tr>' .
|
||||
'<th colspan="5"><hr></th>' .
|
||||
'</tr>';
|
||||
|
||||
}
|
||||
|
||||
// handle search
|
||||
if(isset($_GET["query"])){
|
||||
|
||||
$query =
|
||||
(
|
||||
isset($_GET["query"]) &&
|
||||
!empty(trim($_GET["query"])) &&
|
||||
is_string($_GET["query"])
|
||||
) ? trim($_GET["query"]) : false;
|
||||
|
||||
$filter =
|
||||
(
|
||||
isset($_GET["filter"]) &&
|
||||
(
|
||||
$_GET["filter"] == "and" ||
|
||||
$_GET["filter"] == "or" ||
|
||||
$_GET["filter"] == "pcre"
|
||||
)
|
||||
) ? $_GET["filter"] : "and";
|
||||
|
||||
$folder_base_strlen = strlen($folder_base);
|
||||
|
||||
if($query === false){
|
||||
|
||||
do_error(
|
||||
400,
|
||||
"Search query is empty",
|
||||
"You need to search for something you dumb shit!",
|
||||
$motd,
|
||||
$script_name
|
||||
);
|
||||
}
|
||||
|
||||
$query_escaped = htmlspecialchars($query);
|
||||
|
||||
do_header("search results for "" . $query_escaped . """, $query_escaped, $filter, true, $script_name, false);
|
||||
|
||||
// prepare search cmp
|
||||
$query_arr =
|
||||
explode(
|
||||
" ",
|
||||
preg_replace(
|
||||
'/ +/',
|
||||
" ",
|
||||
$query
|
||||
)
|
||||
);
|
||||
|
||||
$dir_iterator = new RecursiveDirectoryIterator($folder_base, FilesystemIterator::SKIP_DOTS);
|
||||
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
$matches = 0;
|
||||
while(true){
|
||||
|
||||
$iterator->next();
|
||||
|
||||
if(!$iterator->valid()){
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$filename = $iterator->getFilename();
|
||||
|
||||
switch($filter){
|
||||
|
||||
case "and":
|
||||
$check = true;
|
||||
foreach($query_arr as $q){
|
||||
|
||||
if(stripos($filename, $q) === false){
|
||||
|
||||
$check = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "or":
|
||||
$check = false;
|
||||
foreach($query_arr as $q){
|
||||
|
||||
if(stripos($filename, $q) !== false){
|
||||
|
||||
$check = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "pcre":
|
||||
$match = preg_match($query, $filename);
|
||||
|
||||
if($match === false){
|
||||
|
||||
if(preg_last_error() !== PREG_NO_ERROR){
|
||||
|
||||
// regex error
|
||||
echo
|
||||
'<tr><td colspan="3"><b>RegEx error: ' . preg_last_error_msg() . '</b></td></tr><tr><td colspan="3"><hr></td></tr>' .
|
||||
'</table><br>' .
|
||||
$motd .
|
||||
'</body>' .
|
||||
'</html>';
|
||||
die();
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}elseif($match === 1){
|
||||
|
||||
$check = true;
|
||||
}else{
|
||||
|
||||
$check = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if($check){
|
||||
|
||||
$matches++;
|
||||
$internal_path = $iterator->getPath() . "/" . $filename;
|
||||
$fullpath =
|
||||
substr_replace(
|
||||
$internal_path,
|
||||
"",
|
||||
0,
|
||||
$folder_base_strlen
|
||||
);
|
||||
|
||||
$is_dir = is_dir($internal_path);
|
||||
|
||||
echo
|
||||
'<tr>' .
|
||||
'<td>' . ($is_dir ? "<DIR>" : "<FILE>") . '</td>' .
|
||||
'<td>' .
|
||||
'<a href="' . $script_name . '?path=' . urlencode($fullpath) . '">' .
|
||||
htmlspecialchars(
|
||||
$filename
|
||||
) .
|
||||
'</a>' .
|
||||
'</td>' .
|
||||
'<td>' . do_filesize($internal_path, $is_dir) . '</td>' .
|
||||
'</tr>';
|
||||
}
|
||||
|
||||
if($matches === $max_results){
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// pagination
|
||||
echo
|
||||
'<tr><td colspan="3"><hr></td></tr>' .
|
||||
'<td colspan="3"><center>Found ' . $matches . ' matches (max=' . $max_results . ')</center></td>' .
|
||||
'</tr></table><br>' .
|
||||
$motd .
|
||||
'</body>' .
|
||||
'</html>';
|
||||
die();
|
||||
}
|
||||
|
||||
$path =
|
||||
(
|
||||
isset($_GET["path"]) &&
|
||||
is_string($_GET["path"]) &&
|
||||
!empty($_GET["path"])
|
||||
)
|
||||
? $_GET["path"] : "";
|
||||
|
||||
$realpath = realpath($folder_base . "/" . $path);
|
||||
|
||||
// file or folder does not exist
|
||||
if($realpath === false){
|
||||
|
||||
do_error(
|
||||
404,
|
||||
"Nobody here but us chickens!",
|
||||
'Nothing exists under <b>' . htmlspecialchars("/" . ltrim($path, "/")) . '</b>',
|
||||
$motd,
|
||||
$script_name
|
||||
);
|
||||
}
|
||||
|
||||
// path traversal exploit
|
||||
if(strpos($realpath, $folder_base) !== 0){
|
||||
|
||||
do_error(
|
||||
403,
|
||||
"Get off my lawn",
|
||||
'You do not have access to this shit',
|
||||
$motd,
|
||||
$script_name
|
||||
);
|
||||
}
|
||||
|
||||
// handle GETs to files and folders
|
||||
if(is_dir($realpath)){
|
||||
|
||||
// handle directory
|
||||
$page =
|
||||
(
|
||||
isset($_GET["page"]) &&
|
||||
is_numeric($_GET["page"]) &&
|
||||
$_GET["page"] > 0
|
||||
)
|
||||
? (int)$_GET["page"] : 1;
|
||||
|
||||
$relative_path = htmlspecialchars("/" . ltrim(str_replace($folder_base, "", $realpath), "/"));
|
||||
|
||||
$iterator = new FilesystemIterator($realpath);
|
||||
|
||||
try{
|
||||
$iterator->seek(($page - 1) * $items_per_page);
|
||||
}catch(OutOfBoundsException){
|
||||
|
||||
do_error(
|
||||
400,
|
||||
"Out of bounds",
|
||||
"You requested a page index that does not exist you overweight buffoon",
|
||||
$motd,
|
||||
$script_name
|
||||
);
|
||||
}
|
||||
|
||||
if($relative_path == "/"){
|
||||
|
||||
$up = false;
|
||||
}else{
|
||||
|
||||
$up = explode("/", $relative_path);
|
||||
unset($up[count($up) - 1]);
|
||||
$up = $script_name . "?path=" . urlencode(implode("/", $up));
|
||||
}
|
||||
|
||||
do_header("index of " . $relative_path, "", "and", false, "", $up);
|
||||
|
||||
for($i=0; $i<$items_per_page; $i++){
|
||||
|
||||
if(!$iterator->valid()){
|
||||
|
||||
// reached end of file list
|
||||
break;
|
||||
}
|
||||
|
||||
$filename = $iterator->getFilename();
|
||||
$absolute = $realpath . "/" . $filename;
|
||||
$is_dir = is_dir($absolute);
|
||||
|
||||
echo
|
||||
'<tr><td></td>' .
|
||||
'<td>' . ($is_dir ? "<DIR>" : "<FILE>") . '</td>' .
|
||||
'<td>' .
|
||||
'<a href="' . $script_name . '?path=' . urlencode(rtrim($relative_path, "/") . "/" . $filename) . '">' .
|
||||
htmlspecialchars(
|
||||
$filename
|
||||
) .
|
||||
'</a>' .
|
||||
'</td>' .
|
||||
'<td>' . do_filesize($absolute, $is_dir) .
|
||||
'</td><td></td>' .
|
||||
'</tr>';
|
||||
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
// pagination
|
||||
echo
|
||||
'<tr>' .
|
||||
'<td colspan="5"><hr></td>' .
|
||||
'</tr>' .
|
||||
'<tr>';
|
||||
|
||||
// previous page check
|
||||
if($page !== 1){
|
||||
|
||||
echo
|
||||
'<td>' .
|
||||
'<a href="' . $script_name . '?path=' . urlencode($path) . '&page=' . ($page - 1) . '"><PREV></a>' .
|
||||
'</td>';
|
||||
}else{
|
||||
|
||||
echo '<td><END></td>';
|
||||
}
|
||||
|
||||
echo '<td colspan="3"><center>Page ' . $page . '</center></td>';
|
||||
|
||||
// next page check
|
||||
$iterator->next();
|
||||
if($iterator->valid()){
|
||||
|
||||
echo
|
||||
'<td>' .
|
||||
'<a href="' . $script_name . '?path=' . urlencode($path) . '&page=' . ($page + 1) . '"><NEXT></a>' .
|
||||
'</td>';
|
||||
}else{
|
||||
|
||||
echo '<td><END></td>';
|
||||
}
|
||||
|
||||
echo
|
||||
'</tr></table><br>' .
|
||||
$motd .
|
||||
'</body>' .
|
||||
'</html>';
|
||||
die();
|
||||
|
||||
}elseif(is_file($realpath)){
|
||||
|
||||
// handle file
|
||||
set_time_limit(0);
|
||||
ob_end_clean();
|
||||
|
||||
// tell browser you can seek the file
|
||||
header("Accept-Ranges: bytes");
|
||||
header('Content-Disposition: inline; filename="' . rawurlencode(basename($realpath)) . '"');
|
||||
|
||||
// report right file type
|
||||
header("Content-Type: " . mime_content_type($realpath));
|
||||
|
||||
$filesize = filesize($realpath);
|
||||
|
||||
// detect content range
|
||||
$headers = getallheaders();
|
||||
$handle = fopen($realpath, "r");
|
||||
|
||||
if(isset($headers["Range"])){
|
||||
|
||||
// do range
|
||||
preg_match(
|
||||
'/^bytes=([0-9]*)-/',
|
||||
$headers["Range"],
|
||||
$matches
|
||||
);
|
||||
|
||||
$range = isset($matches[1]) ? (int)$matches[1] : null;
|
||||
|
||||
if(
|
||||
$range !== null &&
|
||||
$range >= 0 &&
|
||||
$range < $filesize
|
||||
){
|
||||
|
||||
http_response_code(206); // partial content
|
||||
header("Content-Range: bytes " . $range . "-" . ($filesize - 1) . "/" . $filesize);
|
||||
header("Content-Length: " . $filesize - $range);
|
||||
|
||||
fseek($handle, $range);
|
||||
}else{
|
||||
|
||||
http_response_code(416); // range not satisfiable
|
||||
die();
|
||||
}
|
||||
}else{
|
||||
|
||||
header("Content-Length: " . $filesize);
|
||||
}
|
||||
|
||||
fpassthru($handle);
|
||||
die();
|
||||
|
||||
}else{
|
||||
|
||||
// what the fuck
|
||||
do_error(
|
||||
400,
|
||||
"What the fuck",
|
||||
'You requested something that is neither a file nor a directory, what the actual fuck',
|
||||
$motd,
|
||||
$script_name
|
||||
);
|
||||
}
|
||||
?>
|
Loading…
Reference in New Issue