# Workaround for directory-browsing

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.

<?php
// directory to create listing for, defaulting to the current one
if (array_key_exists("dir", $_GET)){$dirCurrent = $_GET["dir"]; }else{$dirCurrent = getcwd();
}

// sort out some baseline dirs / URLs
$dirCurrent = realpath($dirCurrent);
$dirBase = realpath($_SERVER["DOCUMENT_ROOT"]);
$urlBase = "http://" .$_SERVER["HTTP_HOST"];

if (strpos($dirCurrent,$dirBase) !== false && file_exists($dirCurrent)){ // Used for building links to files$relativePath = str_replace($dirBase, "",$dirCurrent);
$urlPath = str_replace("\\", "/",$relativePath);

// provide a link to go up a level
$parentDir = preg_replace("#[\\\/][^\\\/]+$#", "", $dirCurrent);$parentLinkUrl = $_SERVER["SCRIPT_NAME"] . "?dir=" .$parentDir;
echo "<a href=\"$parentLinkUrl\">[Parent Directory]</a><br>"; echo "<ul>"; 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 "<li><a href=\"$linkUrl\">$linkText</a></li>"; } closedir(); echo "</ul>"; }else{ header("HTTP/1.0 404 Not Found"); } ?>  • It boggles my mind that you thought that edit was necessary, Jamal. Do you not have anything better to do with your time? My wording was deliberate, and you have removed the tone & voice I was trying to convey. You should never edit someone else's writing to your own pointless cosmetic ends, especially if your tool is a linguistically blunt axe. At best you should offer suggestions. You are part of what makes Stack Exchange such an oppressive, negative place. Please find something better to do with your time. – Adam Cameron Oct 23 '14 at 19:37 ## 1 Answer Took this from your blog post: 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 "<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 {

• Sorry for that - I forgot some calls to basename() in order to remove the path information from the file. Now it should work as intended. – nibra May 7 '13 at 11:53