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.

&lt;?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 &amp;&amp; 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 "&lt;a href=\"$parentLinkUrl\"&gt;[Parent Directory]&lt;/a&gt;&lt;br&gt;";

        echo "&lt;ul&gt;";
        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 "&lt;li&gt;&lt;a href=\"$linkUrl\"&gt;$linkText&lt;/a&gt;&lt;/li&gt;";
        }
        closedir();
        echo "&lt;/ul&gt;";
    }else{
        header("HTTP/1.0 404 Not Found");
    }    
?&gt;
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 "&lt;a href=\"$parentLinkUrl\"&gt;[Parent Directory]&lt;/a&gt;&lt;br&gt;";
    }
    echo "&lt;ul&gt;";
    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 "&lt;li&gt;&lt;a href=\"$linkUrl\"&gt;$linkText&lt;/a&gt;&lt;/li&gt;";
    }
    echo "&lt;/ul&gt;";
} else {
    header("HTTP/1.0 404 Not Found");
}