Tutorial: Directory/File Manager (Part 1)
In this tutorial were going to create a ftp-program like directory and file manager. I'm going to assume you know basic PHP here.
Now, the first thing were going to want to do is build a directory tree so that we can navigate. We can do this with a recursive (a function that calls itself) function.
I'll show you the PHP, then explain it.
PHP:
<?php
error_reporting('E_ALL');
$baseDir = '.';
isset($_GET['this']) ? $thisDir = base64_decode($_GET['this']) : $thisDir = '.';
# initial nest level
$nestLevel = 0;
function findDirs($baseDir, $thisDir)
{
global $nestLevel;
$nestLevel++;
if (is_dir($baseDir) && $dir = opendir($baseDir))
{
$name = explode('/', $baseDir);
$rName = $name[count($name)-1];
if($baseDir == $thisDir)
{
$rName = '<strong>' . $rName . '</strong>';
} else {
$rName = '<a href="' . $_ENV['PHP_SELF'] . '?this=' . base64_encode($baseDir) . '">' . $rName . '</a>';
}
$array[] = str_repeat( ' ', $nestLevel*2) . $rName;
while (($file = readdir($dir)) !== false)
{
if (is_dir($baseDir."/".$file) && $file != "." && $file != "..")
{
$array = array_merge($array, findDirs($baseDir."/".$file, $thisDir));
}
}
closedir($dir);
}
$nestLevel--;
return($array);
}
?>
So whats that do?
PHP:<?php
error_reporting('E_ALL');
$baseDir = '.';
isset($_GET['this']) ? $thisDir = base64_decode($_GET['this']) : $thisDir = '.';
# initial nest level
$nestLevel = 0;
?>
Thats pretty self explanatory - we hike up the error reporting, and then we check to see if we got a $_GET['this'] variable. Thats the variable that stores what directory were in, and its in base64 because sometimes directorys can have weird characters or spaces or what not. $thisDir isnt really this directory - its the highest directory we let the script access. Generally, if safe mode is on, we cant access a directory higher then the script, so I put it as '.' which means same as the script.
We use nestlevel so that when we form our tree, its pretty and indented.
PHP:<?php
function findDirs($baseDir, $thisDir)
{
global $nestLevel;
$nestLevel++;
?>
Starts the function, globals the nest level, and then increases it - were in it one block deeper. If you dont get it, trust me - nesting can be a bit confusing.
PHP:<?php
if (is_dir($baseDir) && $dir = opendir($baseDir))
{
?>
Makes sure $baseDir is a directory and we can open it.
PHP:<?php
$name = explode('/', $baseDir);
$rName = $name[count($name)-1];
if($baseDir == $thisDir)
{
$rName = '<strong>' . $rName . '</strong>';
} else {
$rName = '<a href="' . $_ENV['PHP_SELF'] . '?this=' . base64_encode($baseDir) . '">' . $rName . '</a>';
}
$array[] = str_repeat( ' ', $nestLevel*2) . $rName;
?>
This is mostly text formating. We explode and put the last section in $rName so we have something like images, not ./atc/img/. Then, we check if the directory is the same as the one were in (as indicated from the $thisDir, which comes from $_GET['this']). If were in the directory, we give it a bold face. if not, we make a link to it. The str_repeat makes our tree look nice and nested.
PHP:<?php
{
if (is_dir($baseDir."/".$file) && $file != "." && $file != "..")
{
?>
THis goes through all the files/dirs in a dir and picks out all non-symbolic directorys.
PHP:<?php
$array = array_merge($array, findDirs($baseDir."/".$file, $thisDir));
}
}
?>
It then checks each dir a level deeper, and keeps calling itself until it picks up all the subdirectorys. This is called recursing. It uses array_merge to add what it found to the array we'll return.
PHP:<?php
closedir($dir);
}
$nestLevel--;
return($array);
}
?>
?>
Closes te directory handle, takes nestlevel down one, and returns the array.
Using it?
I ended up using it like this:
PHP:
<?php
$dirs = findDirs($baseDir, $thisDir);
foreach($dirs as $dir) {
print $dir . '<br />' . "\n";
}
?>
SImply takes the array given to it, and loops through it printing each directory.
Then I wanted to get all the files from the current directory. I did that with this:
PHP:
<?php
$thisDirHandle = opendir($thisDir);
while (($file = readdir($thisDirHandle)) !== false)
{
if (!is_dir($file) && $file != "." && $file != "..")
{
print '<a href="' . $thisDir . '/' . $file . '" target="blank">' . $file . '</a><br />' . "\n";
}
}
?>
That simply opens up the directory were in, and then loops through all the files (we exclude directorys with the if line). It prints out each file as a link to itself in a new window.
My full code looked like this:
PHP:
<?php
error_reporting('E_ALL');
$baseDir = '.';
isset($_GET['this']) ? $thisDir = base64_decode($_GET['this']) : $thisDir = '.';
# initial nest level
$nestLevel = 0;
function findDirs($baseDir, $thisDir)
{
global $nestLevel;
$nestLevel++;
if (is_dir($baseDir) && $dir = opendir($baseDir))
{
$name = explode('/', $baseDir);
$rName = $name[count($name)-1];
if($baseDir == $thisDir)
{
$rName = '<strong>' . $rName . '</strong>';
} else {
$rName = '<a href="' . $_ENV['PHP_SELF'] . '?this=' . base64_encode($baseDir) . '">' . $rName . '</a>';
}
$array[] = str_repeat( ' ', $nestLevel*2) . $rName;
while (($file = readdir($dir)) !== false)
{
if (is_dir($baseDir."/".$file) && $file != "." && $file != "..")
{
$array = array_merge($array, findDirs($baseDir."/".$file, $thisDir));
}
}
closedir($dir);
}
$nestLevel--;
return($array);
}
?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>File Manager</title>
<style type="text/css">
body {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
font-family: tahoma, verdana, arial, helvetica, sans-serif;
font-size: 9pt;
color: #000;
background-color: #cccccc;
text-align: center;
/* part 1 of 2 centering hack */
}
#content {
width: 80%;
padding: 10px;
margin-top: 20px;
margin-bottom: 20px;
margin-right: auto;
margin-left: auto;
/* opera does not like 'margin:20px auto' */
background: #fff;
border: 1px solid #000;
text-align:left;
/* part 2 of 2 centering hack */
width: 80%; /* ie5win fudge begins */
voice-family: "\"}\"";
voice-family:inherit;
width: 75%;
}
html>body #content {
width: 75%px; /* ie5win fudge ends */
}
#tree {
width:30%;
float:left;
line-height: 150%;
}
#files {
width:70%;
float:right;
line-height: 150%;
}
</style>
</head>
<body>
<div id="content">
<div>
<h3>File Manager</h3>
</div>
<div id="tree">
<h5>Tree</h5>
<?php
$dirs = findDirs($baseDir, $thisDir);
foreach($dirs as $dir) {
print $dir . '<br />' . "\n";
}
?>
</div>
<div id="files">
<h5>Files</h5>
<?php
$thisDirHandle = opendir($thisDir);
while (($file = readdir($thisDirHandle)) !== false)
{
if (!is_dir($file) && $file != "." && $file != "..")
{
print '<a href="' . $thisDir . '/' . $file . '" target="blank">' . $file . '</a><br />' . "\n";
}
}
?>
</div>
</div>
</body>
</html>
In part 2, We'll implement uploading, deleting, chmoding, renaming, and directory creating. In part 3, we'll finish it off with a secure file based login system so that not everyone can use it.
This does work with safe mode.
___________________
http://www.philbrodeur.com - Expert PHP Development and Tutorials




