patternphpMinor
Workaround for directory-browsing
Viewed 0 times
browsingdirectoryworkaroundfor
Problem
I'm in the process of cross-training myself from CFML to PHP as part of a learning exercise. I'm learning from the docs and online tutorials and googling.
As an initial exercise, I've knocked together the following PHP facsimile of some CFML code I have. I have a blog article explaining the requirement for the code. This is basically a work-around for the fact that the inbuilt PHP web server does not do directory browsing.
I'm just posting the PHP here in case anyone can make observations about how I might improve it. I'm more after PHP-specific info than coding structure "advice", but any observations one might make will be taken on board.
As an initial exercise, I've knocked together the following PHP facsimile of some CFML code I have. I have a blog article explaining the requirement for the code. This is basically a work-around for the fact that the inbuilt PHP web server does not do directory browsing.
I'm just posting the PHP here in case anyone can make observations about how I might improve it. I'm more after PHP-specific info than coding structure "advice", but any observations one might make will be taken on board.
[Parent Directory]";
echo "";
opendir($dirCurrent);
while ($entry = readdir()) {
if (in_array($entry, [".", ".."])){ // skip these two
continue;
}
$linkText = $entry;
$wholePathToFile = $dirCurrent . DIRECTORY_SEPARATOR . $entry;
if (is_dir($wholePathToFile)){
// we just want to link back to this file, passing the dir
$linkUrl = $_SERVER["SCRIPT_NAME"] . "?dir=" . $wholePathToFile;
$linkText .= "/"; // just to make it more clear it's a dir
}else{
// we want a link to the actual file
$linkUrl = $urlPath . "/" . $entry;
}
echo "$linkText";
}
closedir();
echo "";
}else{
header("HTTP/1.0 404 Not Found");
}
?>Solution
Took this from your blog post:
What I need to do is this:
Knowing these requirements, your code is way too complicated. That's quite normal for a beginner with PHP, so it's no problem. PHP offers built-in solutions that from time to time make experienced PHP programmers think: "Why didn't I find that before?" -- So what you missed, is
What I need to do is this:
- take a directory on the URL, which by default will be the current directory;
- list the files / directories;
- for each entry, convert the filesystem path to a URL, using the current HTTP host and port;
- also provide a "parent directory" link too, for browsing upstream.
Knowing these requirements, your code is way too complicated. That's quite normal for a beginner with PHP, so it's no problem. PHP offers built-in solutions that from time to time make experienced PHP programmers think: "Why didn't I find that before?" -- So what you missed, is
glob(), and maybe some other neat functions.// Directory to create listing for, defaulting to the current one
$dirCurrent = '';
if (!empty($_GET['dir'])) {
// Remove leading and trailing slashes
$dirCurrent = trim($_GET['dir'], '/.');
}
if (!empty($dirCurrent)) {
$dirCurrent .= '/';
}
$dirBase = realpath($_SERVER["DOCUMENT_ROOT"]);
// Since we make $dirCurrent relative, a basedir check is not needed
if (is_dir($dirBase . '/' . $dirCurrent)) {
// Provide a link to go up a level
if (!empty($dirCurrent)) {
$parentDir = dirname($dirCurrent);
$parentLinkUrl = $_SERVER["SCRIPT_NAME"] . "?dir=" . $parentDir;
echo "[Parent Directory]";
}
echo "";
foreach (glob("$dirBase/$dirCurrent*") as $entry) {
// Hidden files (those starting with a dot) are not returned by glob
$linkText = basename($entry);
if (is_dir($entry)) {
// We just want to link back to this file, passing the dir
$linkUrl = $_SERVER["SCRIPT_NAME"] . "?dir=" . urlencode($dirCurrent . basename($entry));
$linkText .= "/"; // Just to make it more clear it's a dir
} else {
// we want a link to the actual file
$linkUrl = $dirCurrent . basename($entry);
}
echo "$linkText";
}
echo "";
} else {
header("HTTP/1.0 404 Not Found");
}Code Snippets
// Directory to create listing for, defaulting to the current one
$dirCurrent = '';
if (!empty($_GET['dir'])) {
// Remove leading and trailing slashes
$dirCurrent = trim($_GET['dir'], '/.');
}
if (!empty($dirCurrent)) {
$dirCurrent .= '/';
}
$dirBase = realpath($_SERVER["DOCUMENT_ROOT"]);
// Since we make $dirCurrent relative, a basedir check is not needed
if (is_dir($dirBase . '/' . $dirCurrent)) {
// Provide a link to go up a level
if (!empty($dirCurrent)) {
$parentDir = dirname($dirCurrent);
$parentLinkUrl = $_SERVER["SCRIPT_NAME"] . "?dir=" . $parentDir;
echo "<a href=\"$parentLinkUrl\">[Parent Directory]</a><br>";
}
echo "<ul>";
foreach (glob("$dirBase/$dirCurrent*") as $entry) {
// Hidden files (those starting with a dot) are not returned by glob
$linkText = basename($entry);
if (is_dir($entry)) {
// We just want to link back to this file, passing the dir
$linkUrl = $_SERVER["SCRIPT_NAME"] . "?dir=" . urlencode($dirCurrent . basename($entry));
$linkText .= "/"; // Just to make it more clear it's a dir
} else {
// we want a link to the actual file
$linkUrl = $dirCurrent . basename($entry);
}
echo "<li><a href=\"$linkUrl\">$linkText</a></li>";
}
echo "</ul>";
} else {
header("HTTP/1.0 404 Not Found");
}Context
StackExchange Code Review Q#25800, answer score: 3
Revisions (0)
No revisions yet.