view index.php @ 60:89049f2cdcca

Bump version
author nanaya <me@nanaya.pro>
date Sat, 03 Nov 2018 05:01:31 +0900
parents 612d99622699
children 72580314dd6a
line wrap: on
line source

<?php

    define('DL_VERSION', '2.2.4');
    // Required for strftime(). Set to UTC because :internet:.
    date_default_timezone_set('UTC');

    // $uri: web-facing path
    $uri = $_SERVER["REQUEST_URI"];
    $query_string_start = strpos($uri, "?");
    if ($query_string_start !== false) {
        $uri = substr($uri, 0, $query_string_start);
    }
    $uri = urldecode($uri);

    // $dir: filesystem path
    if (isset($_SERVER["DL_DIR"])) {
        $dir = $_SERVER["DL_DIR"];
    } elseif (isset($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
        $dir = $_SERVER["CONTEXT_DOCUMENT_ROOT"];
        $dir .= substr($uri, strlen($_SERVER["CONTEXT_PREFIX"]));
    } else {
        $dir = $_SERVER["DOCUMENT_ROOT"] . $uri;
    }

    if (realpath($dir) === false) {
        header("HTTP/1.0 404 Not Found");
    } elseif (substr($uri, -1) !== "/") {
        header("Location: " . $uri . "/");
    }

    if (http_response_code() !== 200) {
        exit;
    }

    $dir_handle = opendir($dir);
    $files = array();
    $dirs = array();
    while (($file = readdir($dir_handle)) !== false) {
        if ($file === "." || $file === "..") {
            continue;
        } elseif (!(isset($_SERVER["DL_SHOWALL"]) && $_SERVER["DL_SHOWALL"] === "1") && substr($file, 0, 1) === ".") {
            continue;
        } elseif (is_dir($dir . $file)) {
            $dirs[] = $file;
        } else {
            $files[] = $file;
        }
    }
    sort($files);
    sort($dirs);

    // BEGIN UTILITY
    function h($string)
    {
        return htmlspecialchars($string, ENT_QUOTES, "UTF-8");
    }
    function a($string)
    {
        return preg_replace("#(%2F)+#", "/", rawurlencode($string));
    }
    function link_to($target, $title)
    {
        return('<a href="' . a($target) . '">' . h($title) . "</a>");
    }

    function human_size($size)
    {
        $thousand_units = array("ko", "Mo", "Go", "To", "Po");

        $return_format = "%d %s";

        if ($size === 1) {
            $return_unit = "octet";
        } elseif ($size < 1000) {
            $return_unit = "octets";
        } else {
            $size /= 1000;
            for ($i = 0; $size >= 1000 && $i < count($thousand_units); $i++) {
                $size /= 1000;
            }
            $return_format = "%.2f %s";
            $return_unit = $thousand_units[$i];
        }
        return sprintf($return_format, $size, $return_unit);
    }

    function hidden_data($data = "", $is_dir = false)
    {
        return "<i> " . ($is_dir === true ? 0 : 1) . " " . $data . " </i>";
    }
    // END UTILITY

    function tree_link($uri)
    {
        $uri_array = explode("/", trim($uri, "/"));

        $tree_path = "/";
        $tree_link = link_to($tree_path, "[root]");
        $tree_link .= "/";

        foreach ($uri_array as $p) {
            if ($p === "") {
                continue;
            }
            $tree_path .= $p . "/";
            $tree_link .= link_to($tree_path, $p) . "/";
        }

        return $tree_link;
    }

    function up_link($uri)
    {
        if ($uri !== "/") {
            return "<tr><td colspan=3>" . link_to(dirname($uri) . "/", "[up]") . "</td></tr>";
        }
    }

    function file_rows($dir, $files, $is_dir)
    {
        $file_suffix = "";
        if ($is_dir) {
            $file_suffix = "/";
        }

        $file_rows = "";
        foreach ($files as $file) {
            $file_path = $dir."/".$file;

            if (!file_exists($file_path)) {
                continue;
            }
            $file_stat = stat($file_path);

            $file_rows .=
          "<tr>".
            "<td>".
              hidden_data("", $is_dir).
              link_to($file.$file_suffix, $file.$file_suffix).
            "</td>".
            "<td>".
              hidden_data($file_stat["size"], $is_dir).
              ($is_dir ? "[dir]" : human_size($file_stat["size"])).
            "</td>".
            "<td>".
              hidden_data("", $is_dir).
              h(strftime("%Y-%m-%d %H:%M %Z", $file_stat["mtime"])).
            "</td>".
          "</tr>";
        }
        return $file_rows;
    }

    header('Content-Type: text/html; charset=utf-8');
?>
<!doctype html>
<head>
    <meta charset="utf-8">
    <title>Index of <?= h($uri); ?></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.1.0/magnific-popup.css">

    <style type="text/css">
        .mfp-content figure { margin: 0; }
        * { box-sizing: border-box; }
        body {
            font-family: Segoe UI, sans-serif;
            font-size: 14px;
        }
        h1 { margin: 5px; }
        table {
            width: 100%;
        }
        th:first-child, td:first-child {
            width: 100%;
            white-space: pre-wrap;
            word-wrap: break-word;
            word-break: break-all;
        }
        tr {
            position: relative;
        }
        th, td {
            white-space: nowrap;
            padding: 2px 5px;
        }

        i {
            display: none;
        }

        input {
            width: 100%;
            margin: 10px 0px;
        }

        th span {
            display: block;
            text-decoration: underline;
        }
        th span.desc::after {
            content: " ▼";
        }
        th span.asc::after {
            content: " ▲";
        }

        @media (min-width: 768px) {
            th {
                background: #ccc;
                cursor: pointer;
            }
            tr:nth-child(even) { background: #eee; }
            tr:hover { background: #ddd; }
        }

        @media (max-width: 767px) {
            table {
                border-spacing: 0 10px;
            }
            th { display: none; }
            tr {
                background: #eee;
            }
            td {
                display: inline-block;
            }
            td:first-child {
                background: #ddd;
                padding: 5px;
            }
            table a {
                font-size: 18px;
                display: block;
            }
            input { font-size: 18px; }
        }
    </style>
</head>
<body id="files">
    <h1>Index of <?= tree_link($uri); ?></h1>

    <input placeholder="search (non-recursive)" class="search" />

    <table>
        <thead>
            <tr>
                <th><span class="sort" data-sort="filename">File</span></th>
                <th><span class="sort" data-sort="size">Size</span></th>
                <th><span class="sort" data-sort="date">Date</span></th>
            </tr>
            <?= up_link($uri); ?>
        </thead>
        <tbody class="list">
            <?= file_rows($dir, $dirs, true); ?>
            <?= file_rows($dir, $files, false); ?>
        </tbody>
    </table>

    <footer>
        <hr>
        <em>
            Running <a href="https://bitbucket.org/edogawaconan/dirlist-php">dirlist-php <?= DL_VERSION ?></a>.
            Powered by PHP <?= phpversion(); ?>.
        </em>
    </footer>

    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.1.0/jquery.magnific-popup.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/list.js/1.2.0/list.min.js"></script>

    <script>
        $("table td a").each(function() {
            if (!this.href.match(/\.(jpe?g|png|gif|webp)$/i)) return

            this.className = "image"
            this.setAttribute("title", this.innerHTML)
        })

        $("table > tbody").magnificPopup({
            delegate: "a.image",
            type: "image",
            gallery: { enabled: true }
        })

        $("tbody td:nth-child(3n + 1)").addClass("filename")
        $("tbody td:nth-child(3n + 2)").addClass("size")
        $("tbody td:nth-child(3n + 3)").addClass("date")

        new List("files", {
            valueNames: ["filename", "size", "date"],
            page: <?= count($dirs) + count($files); ?>
        })
    </script>
</body>