A good looking replacement for Apache DirectoryIndex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> | |
<!-- Folder Listing --> | |
<!-- v1.1.2 (February 8, 2023) --> | |
<!-- A good looking replacement for Directory Listings (Options +Indexes): --> | |
<!-- Rename this file to "index.php" and copy it into a web server --> | |
<!-- directory to enable browsing on that directory. --> | |
<!-- Requirement: --> | |
<!-- Apache HTTP Server Project with php_module enabled --> | |
<!-- (see: /usr/local/etc/httpd/httpd.conf) --> | |
<!-- Example page: --> | |
<!-- https://centerkey.com/files --> | |
<!-- WTFPL --> | |
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> | |
<html lang=en> | |
<head> | |
<meta charset=utf-8> | |
<meta name=viewport content="width=device-width, initial-scale=1"> | |
<meta name=robots content="index, follow"> | |
<meta name=description content="Folder listing for <?=basename(__DIR__)?>"> | |
<meta name=apple-mobile-web-app-title content="<?=basename(__DIR__)?>"> | |
<title>Folder: <?=basename(__DIR__)?></title> | |
<link rel=icon href=https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.3/svgs/solid/folder.svg color=darkgoldenrod> | |
<link rel=mask-icon href=https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.3/svgs/solid/folder.svg color=darkgoldenrod> | |
<link rel=apple-touch-icon href=https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.3/svgs/solid/folder.svg color=darkgoldenrod> | |
<link rel=preconnect href=https://fonts.googleapis.com> | |
<link rel=preconnect href=https://fonts.gstatic.com crossorigin> | |
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.3/css/all.min.css> | |
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/dna-engine@2.3/dist/dna-engine.css> | |
<link rel=stylesheet href=https://cdn.jsdelivr.net/npm/web-ignition@1.6/dist/reset.min.css> | |
<style> | |
body { margin: 0px 20px; } | |
body >main { min-height: auto; } | |
body >main h1 { color: cadetblue; } | |
body >main a { border-color: cadetblue; } | |
body >main a { outline-color: white; } /* workaround for ghost line on hover in safari */ | |
body >main a:hover { background-color: cadetblue; outline-color: cadetblue; } | |
body >main ul.simple-text { margin: 0px 0px 30px 15px; } | |
body >main ul.simple-text li { display: flex; align-items: center; margin-bottom: 10px; } | |
body >main ul.simple-text li i.font-icon { width: 1.8em; text-align: center; color: darkslateblue; } | |
body >main ul.simple-text li i.font-icon[data-icon=arrow-alt-circle-up] { color: dimgray; } | |
body >main ul.simple-text li i.font-icon[data-icon=folder] { color: darkgoldenrod; } | |
body >main ul.simple-text li i.font-icon[data-icon=external-link-square-alt] { color: brown; } | |
body >main p a { margin-right: 8px; } | |
@media (max-width: 667px) { /* selects iPhone 6/6s/7/8/SE(2020) landscape and anything narrower */ | |
body { margin: 0px; } | |
body >main h1 { font-size: 1.7em; } | |
body >main ul.simple-text { margin-left: 0px; } | |
} | |
</style> | |
<script defer src=https://cdn.jsdelivr.net/npm/jquery@3.6/dist/jquery.min.js></script> | |
<script defer src=https://cdn.jsdelivr.net/npm/dna-engine@2.3/dist/dna-engine.min.js></script> | |
<script defer src=https://cdn.jsdelivr.net/npm/web-ignition@1.6/dist/lib-x.min.js></script> | |
<script data-on-load=displayPath> | |
const displayPath = () => { | |
// Show the URL of the current folder. | |
$('main >h2').text(globalThis.location.origin + globalThis.location.pathname); | |
$('.home-link').attr({ href: globalThis.location.origin }); | |
}; | |
</script> | |
<?php | |
if (!function_exists("str_ends_with")) { | |
function str_ends_with($haystack, $needle) { | |
return substr($haystack, -strlen($needle)) === $needle; | |
} | |
} | |
function showFile($file) { | |
// Don't display hidden files, php files, link files, or folders. | |
$extension = pathinfo($file, PATHINFO_EXTENSION); | |
$extOk = !in_array($extension, array("php")); | |
$isLink = str_ends_with($file, ".link.md"); | |
return !is_dir($file) && $file[0] !== "." && $file !== "error_log" && $extOk && !$isLink; | |
} | |
function fileIcon($fileExtension) { | |
$fileTypes = array( | |
"gif" => "file-image", | |
"html" => "file-code", | |
"jpeg" => "file-image", | |
"jpg" => "file-image", | |
"md" => "file-pen", | |
"mp3" => "file-audio", | |
"pdf" => "file-pdf", | |
"png" => "file-image", | |
"svg" => "file-image", | |
"txt" => "file-lines", | |
"xml" => "file-code", | |
"zip" => "file-zipper", | |
); | |
return array_key_exists($fileExtension, $fileTypes) ? $fileTypes[$fileExtension] : "file"; | |
}; | |
function toHtml($file) { | |
// Create the <li> string to render a line representing a file or folder. | |
$isFolder = is_dir($file); | |
$icon = $isFolder ? "folder" : fileIcon(pathinfo($file, PATHINFO_EXTENSION)); | |
$title = $file; | |
if (!$isFolder && str_ends_with($file, ".link.md")) { | |
// Looks for the ".link.md" extension and reads the markdown syntax for a | |
// hyperlink. For example, the file "example-website.link.md" could have | |
// one line of text like "[Click me](https://example.org)". | |
$icon = "external-link-square-alt"; | |
$md = preg_split("/[\[\]()]/", htmlspecialchars(file_get_contents($file))); | |
$file = $md[3]; | |
$url = parse_url($file); | |
$relLinkHost = $_SERVER["HTTP_HOST"] ?: $_SERVER["SERVER_NAME"]; | |
$host = isset($url["host"]) ? $url["host"] : $relLinkHost; | |
$title = $md[1] . " [" . $host . "]"; | |
} | |
return "<li><a href='$file'><i data-icon=$icon></i></a> <a href='$file'>$title</a></li>"; | |
} | |
?> | |
</head> | |
<body> | |
<main> | |
<h1>Folder Listing</h1> | |
<h2></h2> | |
<ul class=simple-text> | |
<li><a href=..><i data-icon=arrow-alt-circle-up></i></a> <a href=..>Parent folder</a></li> | |
<?=implode(PHP_EOL, array_map("toHtml", glob("*", GLOB_ONLYDIR)))?> | |
<?=implode(PHP_EOL, array_map("toHtml", glob("*.link.md")))?> | |
<?=implode(PHP_EOL, array_map("toHtml", array_filter(glob("*"), "showFile")))?> | |
</ul> | |
<p> | |
<a href=# class=home-link><i data-icon=home></i></a> | |
<a href=https://gist.github.com/dpilafian/930e1677d0c08eed3c39f04d32d7bf19><i data-brand=github-alt></i></a> | |
</p> | |
</main> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
################## | |
# Folder Listing # | |
# WTFPL # | |
################## | |
# To make this file runnable: | |
# $ chmod +x *.sh.command | |
banner="Folder Listing" | |
projectHome=$(cd $(dirname $0); pwd) | |
apacheCfg=/usr/local/etc/httpd | |
apacheLog=/usr/local/var/log/httpd/error_log | |
webDocRoot=$(grep ^DocumentRoot $apacheCfg/httpd.conf | awk -F'"' '{ print $2 }') | |
displayIntro() { | |
cd $projectHome | |
echo | |
echo $banner | |
echo $(echo $banner | sed s/./=/g) | |
pwd | |
version=$(grep "<\!\-\- v" *.php | awk '{ print $2 }') | |
echo $version | |
echo | |
} | |
lintPhp() { | |
cd $projectHome | |
echo "Linting:" | |
php --syntax-check *.php | |
echo | |
} | |
publishWebFiles() { | |
cd $projectHome | |
publishSite=$webDocRoot/centerkey.com | |
publishFolder=$publishSite/files | |
publish() { | |
echo "Publishing:" | |
mkdir -p $publishFolder | |
cp -v *.php $publishFolder/index.php | |
echo | |
} | |
test -w $publishSite && publish | |
} | |
launchBrowser() { | |
cd $projectHome | |
url=https://centerkey.com/files | |
test -w $publishSite && url=http://localhost/centerkey.com/files | |
echo "Opening:" | |
echo $url | |
sleep 2 | |
open $url | |
echo | |
} | |
displayIntro | |
lintPhp | |
publishWebFiles | |
launchBrowser |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment