123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- <?php
- /*
- * __
- * __ __/ _| ___
- * \ \ /\ / / |_ / _ \
- * \ V V /| _| __/
- * \_/\_/ |_| \___|
- *
- * Web File Explorer
- * This is free software!
- *
- * TODO
- * - Sorting
- * - Upload
- * - Download of gzipped folders
- * - REST API (?)
- * - Mobile version
- */
- # Debug
- ini_set('display_errors', 1);
- ini_set('display_startup_errors', 1);
- error_reporting(E_ALL);
- # Configuration
- // Code version
- $version = "1.1.0";
- // Set to 'false' to disable security
- $jail = false;
- # Constants
- // Folder in which the script runs
- define("FOLDER", getcwd());
- # Main variables (warning! Editing below this line is potentially dangerous!)
- // The script itself
- $url = $_SERVER["PHP_SELF"];
- $script = basename($url);
- // Working directory
- $path = getcwd();
- // Download file
- $download = null;
- // Open directory
- $directory = null;
- // Place for 'home' and 'parent directory' items
- $default = array();
- // Place for directories
- $directories = array();
- // Place for files
- $files = array();
- # Security stuff
- // Sanitize and deobfuscate qs parameters
- if (isset($_GET["f"])) {
- $download = filter_var($_GET["f"], FILTER_SANITIZE_STRING);
- $download = deobfuscate($download);
- }
- if (isset($_GET["d"])) {
- $directory = filter_var($_GET["d"], FILTER_SANITIZE_STRING);
- $directory = deobfuscate($directory);
- }
- // Canonicalized absolute pathname
- // Does not follow symbolic links
- $path = realpath($path) . "/";
- if ($directory !== null) {
- $path = realpath($directory) . "/";
- }
- // Document root directory
- $root = substr($path, 0, strlen(FOLDER));
- if ($download !== null) {
- $root = substr($download, 0, strlen(FOLDER));
- }
- // Do not access the entire file system!
- if ($jail === true && $root !== FOLDER) {
- header("Location: $url");
- exit;
- }
- # Main part
- // Download file
- if ($download !== null) {
- // See https://code-boxx.com/php-read-file/
- // Start output buffer
- ob_start();
- // HTTP headers to force download
- header("Content-Type: application/octet-stream");
- header("Content-Disposition: attachment; filename=\"" . basename($download) . "\"");
- header("Expires: 0");
- header("Cache-Control: must-revalidate");
- header("Pragma: public");
- header("Content-Length: " . filesize($download));
- // Output all the headers and stop buffering
- ob_end_flush();
- // Read and output file directly
- readfile($download);
- exit();
- }
- // Open directory
- // See https://www.php.net/manual/en/function.readdir.php
- if ($handle = opendir($path)) {
- // Get each entry
- while (false !== ($item = readdir($handle))) {
- $items[] = $item;
- }
- // Close directory
- closedir($handle);
- } else {
- // Unreadable data, or something worse
- header("Location: $url");
- exit;
- }
- // Loops through the array of items
- for ($i = 0; $i < count($items); $i++) {
- // Get item name
- $name = $items[$i];
- if ($name !== "." && $name !== "..") {
- // Directory
- if (is_dir($path . $name)) {
- if (is_readable($path . $name)) {
- $link = "?d=" . obfuscate($path . $name);
- } else {
- $link = null;
- }
- $directories[$i]["link"] = $link;
- $directories[$i]["name"] = "<b>↘</b> " . $name;
- $directories[$i]["type"] = "Directory";
- $directories[$i]["size"] = 0;
- $directories[$i]["date"] = prettydate($path . $items[$i]);
- }
- // File
- if (is_file($path . $name) && $name !== $script) {
- if (is_readable($path . $name)) {
- $link = "?f=" . obfuscate($path . $name);
- } else {
- $link = null;
- }
- $files[$i]["link"] = $link;
- $files[$i]["name"] = "<b>★</b> " . $name;
- $files[$i]["type"] = prettytype($path . $items[$i]);
- $files[$i]["size"] = prettysize(filesize($path . $items[$i]));
- $files[$i]["date"] = prettydate($path . $items[$i]);
- }
- }
- }
- // Home directory
- $default[0]["link"] = $url;
- $default[0]["name"] = "<b>⚑</b> Home";
- $default[0]["type"] = "Directory";
- $default[0]["size"] = 0;
- $default[0]["date"] = prettydate(__DIR__);
- // Parent directory
- $default[1]["link"] = $url . "?d=" . obfuscate($path . "../");
- $default[1]["name"] = "<b>↖</b> Parent directory";
- $default[1]["type"] = "Directory";
- $default[1]["size"] = 0;
- $default[1]["date"] = prettydate($path . "..");
- // Sort arrays
- $n = array_column($directories, "name");
- $d = array_column($directories, "date");
- array_multisort($n, SORT_ASC, $d, SORT_ASC, $directories);
- $n = array_column($files, "name");
- $d = array_column($files, "date");
- array_multisort($n, SORT_ASC, $d, SORT_ASC, $files);
- # Output
- // Favicon
- $png = <<<PNG
- iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABHNCSV
- QICAgIfAhkiAAAAAlwSFlzAAABGwAAARsBjfdO5QAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYX
- BlLm9yZ5vuPBoAAAJMSURBVEiJxdZfaI9RGAfwj22IjGEthiimxJ3SSk2SXCk3lOLChQs3qymS3Y
- ioFbmZGxcrV4ikkCTjRrlxofn/J4Qp/zMt82dzcc7b791se3+/31751uk973Oe5/mec55znufwnz
- CuRP0pWIMlqIv27/EQnfiS6+xQi2P4joER2k90YHZepPPxbBTCoe0FFuRBfLEE0qSdHCtpNX6VQf
- w5y3FFxng9KsuY8GQZBzeL+GuqP4A7eDyMXlccS/Ah6o8Jb6OT1pTsjMK2Hk7Jj0bZ2SynWSuGq/
- F7LSXrSvUvpfpP4vd4EX4zUYdPOIUazMF9/EZ/JJkU9e7gQh6kCS75++TuxP5h5HvyJG4WVpc4fy
- qc3Bq8S8n7sDZPYmjAPrzy9yofoQUz8iZNcBdbIlGfwuq3yjm2Q3ERt7EK04WtbsQ9Ocd2KGpxzu
- Bt7kc7JuZBUIkVmDDCeIsQ6yfYOILONOwW8n3R2C6s5jlWlmIYUadQSleXYnja4AJ/HutRNYpNBZ
- pwQEgwiX3rKDaDME8hdp14nXLyBoewKKXfgDZ0R51vuI6bCne76ArXiMWp/2XYiwepSd0Q8ne/kD
- 4vY4OQPhMsxtJiSbOwKxIlu/ADm/JyPhyW40ok68UR4XHXFydyQgjTmFElxK9JqL/9sXVgbkpvoc
- Ld7sVBTC2HsEJ4yvYYnCi6sW4Uu834GHV/46WQ6bYo8v0+K848TXpLyFpZqFd49iStBzOLISZcl2
- bhtTggFIFi0Z4ibVNm3BuwA+NLsKkWyue2cgj/Of4AiebN88P8fu4AAAAASUVORK5CYII=
- PNG;
- // CSS3 code
- $css3 = <<<CSS3
- body{background-color:DarkSlateGrey;color:FloralWhite;font:12pt "Lucida Console","Courier New",Monospace;margin:15pt}
- a{text-decoration:none;color:Chartreuse}
- b{color:BlanchedAlmond;font:lighter 14pt Sans-serif}
- h1{background-color:LightSlateGray;border-radius:15pt 15pt 0 0;margin-bottom:-12pt;padding:4pt 0 16pt;text-align:center}
- h1>span{color:DarkSlateGrey;font:35pt Sans-serif}
- footer{font:11pt Sans-serif;margin-top:10pt;text-align:center}
- footer>p{margin:0;padding-top:1pt}
- .container{background-color:DarkSlateGrey;border:3pt solid LightSlateGray;border-radius:15pt;padding:20pt 0 24pt 28pt}
- .flex-container{display:flex}
- .flex-container>div{height:16pt;line-height:16pt;overflow:hidden}
- CSS3;
- // HTML5 code
- // Useful link for SVG encoding: https://yoksel.github.io/url-encoder/
- $html5 = <<<HTML5
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <link rel="icon" href="data:image/png;base64,$png">
-
- <title>$script</title>
- <style>$css3</style>
- </head>
- <body>
- <h1><span>$script</span></h1>
- <div class="container">
- <div class="flex-container" style="margin-bottom: 8pt">
- <div style="flex-basis: 50%; font-weight: bolder; margin-left: 15pt">Name</div>
- <div style="flex-basis: 20%; font-weight: bolder">Type</div>
- <div style="flex-basis: 10%; font-weight: bolder">Size</div>
- <div style="flex-basis: 20%; font-weight: bolder">Date</div>
- </div>
- HTML5;
- echo $html5;
- foreach ($default as $value) {
- echo '<div class="flex-container">';
- echo '<div style="flex-basis: 50%"><a href="' . $value["link"] . '">' . $value["name"] . '</a></div>';
- echo '<div style="flex-basis: 20%; margin-left: 15pt">' . $value["type"] . '</div>';
- echo '<div style="flex-basis: 10%">' . $value["size"] . '</div>';
- echo '<div style="flex-basis: 20%">' . $value["date"] . '</div>';
- echo '</div>';
- }
- foreach ($directories as $value) {
- echo '<div class="flex-container">';
- if ($value["link"] === null) {
- echo '<div style="flex-basis: 50%; color: Pink">' . $value["name"] . '</div>';
- } else {
- echo '<div style="flex-basis: 50%"><a href="' . $value["link"] . '">' . $value["name"] . '</a></div>';
- }
- echo '<div style="flex-basis: 20%; margin-left: 15pt">' . $value["type"] . '</div>';
- echo '<div style="flex-basis: 10%">' . $value["size"] . '</div>';
- echo '<div style="flex-basis: 20%">' . $value["date"] . '</div>';
- echo '</div>';
- }
- foreach ($files as $value) {
- echo '<div class="flex-container">';
- if ($value["link"] === null) {
- echo '<div style="flex-basis: 50%; color: Pink">' . $value["name"] . '</div>';
- } else {
- echo '<div style="flex-basis: 50%"><a href="' . $value["link"] . '">' . $value["name"] . '</a></div>';
- }
- echo '<div style="flex-basis: 20%; margin-left: 13pt">' . $value["type"] . '</div>';
- echo '<div style="flex-basis: 10%">' . $value["size"] . '</div>';
- echo '<div style="flex-basis: 20%">' . $value["date"] . '</div>';
- echo '</div>';
- }
- $html5 = <<<HTML5
- </div>
- <footer>
- <p>Current path: <b>$path</b></p>
- <p>$script • Web File Explorer • v$version</p>
- </footer>
- </body>
- </html>
- HTML5;
- echo $html5;
- # Functions
- // String obfuscation
- // ROT-13 + Zlib compression + base64 encoding
- // See: https://stackoverflow.com/questions/2996049/how-to-compress-decompress-a-long-query-string-in-php
- function obfuscate($str)
- {
- return rtrim(strtr(base64_encode(gzdeflate(str_rot13($str), 9)), '+/', '-_'), '=');
- }
- function deobfuscate($str)
- {
- return str_rot13(gzinflate(base64_decode(strtr($str, '-_', '+/'))));
- }
- // Prettifies file size
- function prettysize($size)
- {
- if ($size < 1024) {
- $size = $size;
- } elseif (($size < 1048576) && ($size > 1023)) {
- $size = round($size / 1024, 1) . "K";
- } elseif (($size < 1073741824) && ($size > 1048575)) {
- $size = round($size / 1048576, 1) . "M";
- } else {
- $size = round($size / 1073741824, 1) . "G";
- }
- return $size;
- }
- // Prettifies file type
- function prettytype($file)
- {
- // Gets file extension
- $extn = pathinfo($file, PATHINFO_EXTENSION);
- switch ($extn) {
- case "png":
- $type = "PNG image";
- break;
- case "jpg":
- $type = "JPEG image";
- break;
- case "jpeg":
- $type = "JPEG image";
- break;
- case "svg":
- $type = "SVG image";
- break;
- case "gif":
- $type = "GIF image";
- break;
- case "ico":
- $type = "Windows icon";
- break;
- case "txt":
- $type = "Text file";
- break;
- case "log":
- $type = "Log file";
- break;
- case "htm":
- $type = "HTML file";
- break;
- case "html":
- $type = "HTML file";
- break;
- case "xhtml":
- $type = "HTML file";
- break;
- case "shtml":
- $type = "HTML file";
- break;
- case "php":
- $type = "PHP script";
- break;
- case "js":
- $type = "Javascript file";
- break;
- case "css":
- $type = "Stylesheet";
- break;
- case "pdf":
- $type = "PDF document";
- break;
- case "xls":
- $type = "Spreadsheet";
- break;
- case "xlsx":
- $type = "Spreadsheet";
- break;
- case "doc":
- $type = "Microsoft Word document";
- break;
- case "docx":
- $type = "Microsoft Word document";
- break;
- case "zip":
- $type = "ZIP archive";
- break;
- case "htaccess":
- $type = "Apache config file";
- break;
- case "exe":
- $type = "Windows executable";
- break;
- case "torrent":
- $type = "BitTorrent file";
- break;
- default:
- if ($extn !== "") {
- $type = strtoupper($extn) . " file";
- } else {
- $type = "Unknown";
- }
- break;
- }
- return $type;
- }
- // Prettifies modification date
- function prettydate($file)
- {
- return date("Y-m-d H:i:s", filemtime($file));
- }
|