It's not cleaned up, and I haven't finished really organizing this code, but it works... I put it together from several pieces of code that I had written earlier, and have been facing the same challenge. Namely, that of creating a recursive directory listing function in php. The attached code will actually generate a complete sitemap for you. I plan to release it very shortly with documentation etc.
BEGIN LONG SECTION OF CODE
<?php
$GoodDirsList = array('company', 'services', 'employee','projects');
// function RecurseDir returns an array of all the directories from DocRoot
function RecurseDir($basedir, $AllDirectories=array()) {
global $GoodDirsList;
#Create array for current directories contents
$CurrentDir=array();
#switch to the directory we wish to scan THIS IS CRITICAL... SEEMS is_dir AND is_file WON'T WORK RIGHT UNLESS YOU FIRST chdir
chdir($basedir);
$CurrentPathString=getcwd();
// find out whether we're on a windows box, or a unix box
if (stristr( $CurrentPathString, '\')) $slash='\'; # windows style
elseif (stristr( $CurrentPathString, '/')) $slash = '/'; # unix style
else die ("Could not find a slash in the directory path [_buildIndex.php line 14]");
#open current directory for reading
$handle=opendir(".");
while(false !== ( $entry = readdir($handle) )) { // otherwise directory names that evaluate to false will break the loop. Consider the directory named '0-series'
if (is_dir($entry)) {
//if (($entry!='..') & ($entry!='.')) { #Don't add special directories '..' or '.' to the list
if ($entry=='.'||$entry=='..') continue; // skip . and .. directories VERY IMPORTANT, OR YOU WILL GET AN INFINITE LOOP
if ( !in_array($entry,$GoodDirsList) ) continue; // if the needle isn't in the haystack
#build an array of contents for this directory
array_push($CurrentDir,$CurrentPathString.$slash.$entry);# unix style
//array_push($CurrentDir,$CurrentPathString.'\'.$entry); # windows style
}
}
closedir($handle);
#Loop through each directory,run RecurseDir function on each one
foreach ($CurrentDir as $key=>$value) {
array_push($AllDirectories, $value); // add the list of directories in CurrentDir to the global list of directories
$AllDirectories=RecurseDir($value, $AllDirectories);
}
chdir($basedir); #make sure we go back to our origin (not sure why original author does this)
return $AllDirectories;
}
/*
Example
$dirlist=RecurseDir($DOCUMENT_ROOT);
foreach ($dirlist as $key=>$val) {
openBox ($val);
$myFiles = getFileList($val);
closeBox();
}
*/
/ #######################################################
This is the "Greg Grep" module.
Create 'fancy indexing' or 'grep' for certain files, and
only display those
Greg Grep will build an alternating color html table
listing the contents of a directory,
Greg Grep will let you choose the colors
Greg Grep will let you choose what file types to list
(or patterns in filenames)
Greg Grep configuration variables begin with 'cfgGG_'
to avoid namespace collisions.
####HISTORY#####
v. 0.01 first version
v. 0.1
rewrote the whole thing, adding icons, and get current directory
v. 0.2 Greg Rundlett greg@freephile.com 08/29/2001
added the maintainer option
v. 0.3 Greg Rundlett greg@freephile.com 09/10/2001
integrated with the VAN extranet
corrected filter bug
moved images to /images
added ppt.gif
added line to describe "NEW" icon
v. 0.4 Greg Rundlett greg@freephile.com 11/09/2001
added support for listing files chronologically v. alphabetically
v. 0.5 Greg Rundlett greg@freephile.com 02/26/2002
put the display into a round-corner box, then extracted the display into an
outside function
removed the internal call to getFileList, so that this file could become
part of the siteMapper, and also removed the $cfgGG_path variable, since now
you supply the name of the directory at the time you call getFileList(). use getcwd()
if you want to make it dynamic in a nav.
############################################################ */
/ #########################################################
BEGIN GREG GREP CONFIGURATION VARIABLES
############################################################ /
$cfgGG_newDays = 30; # how many days to display 'new' icon?
$cfgGG_tableCaption = ''; # do you want to put a caption at the top of the table
$cfgGG_showMaintainer = false; # do you want to show an email link to the page maintainer?
$cfgGG_maintainer = ""; # defaults to 'webmaster @ $HTTP_HOST' if you set it to '' or you comment the whole line
isset($cfgGG_showDetails)?$cfgGG_showDetails:$cfgGG_showDetails = false;
$cfgGG_tableColor = ""; # any hex or browser compatible string
$cfgGG_rowColor1 = $complementaryBackgroundColor;
$cfgGG_rowColor2 = ""; # #99ccff also try #c9c9c9
$cfgGG_newImage = '<img src="/images/icons/new.gif" width="31" height="12" border="0" alt="NEW">';
//isset($cfgGG_filter)?$cfgGG_filter:$cfgGG_filter = '/.(pdf)$/i'; # display ONLY pdf's
//$cfgGG_filter = '/.(pdf|doc|xls)$/i'; # display pdf's doc's and xls
//$cfgGG_filter = '/2.1..(pdf|doc|xls)$/i'; # display only v 2.1 stuff
//$cfgGG_filter = '/.(gif|jpg|png)$/i'; # images
//$cfgGG_filter = '/.(htm|html|shtml)$/i'; # web files
//$cfgGG_filter = '/.(htm|html|shtml|js|asp|php|cgi|pl|inc|css|txt)$/i'; # almost all
$cfgGG_filter = '/[_]..(php|cgi|pdf|doc|xls|ppt|zip)$/i'; # php and office docs
//$cfgGG_filter = '/.*/i'; # display everything
$cfgGG_useIcons = true; # icon-style or text description of file format
$cfgGG_sortOrder = ""; # default setting is blank -> does an alpha sort
$cfgGG_sortOrder = $reverseChronologicalSort; # $reverseChronologicalSort is set in each directory index.php file, to controll sorting
/ #########################################################
END OF GREG GREP CONFIGURATION VARIABLES
############################################################ /
ver 1.1 added $expiresDays
gives the ability to control the expiry date,
ie. the amount of time before something was stale
function isNew ($date,$expiresDays) {
$epoch = time();
$stale = ($epoch-($expiresDays2460*60));
$formattedDate = date ('m/d/y',$date);
if ($date > $stale) {
return true;
}
else return false;
}
#-------------------------------------------------------------------
BubbleSort:
Performs a bubble sort on a give array.
Parameters:
$sort_array - the array to be sorted
$reverse - sorts the array in reverse order if set to non-zero
Output:
Returns the sorted array.
#-------------------------------------------------------------------
modified by Greg Rundlett to work on file mtime
function BubbleSort($sort_array,$reverse=false)
{
for ($i = 0; $i < sizeof($sort_array); $i++){
for ($j = $i + 1; $j < sizeof($sort_array); $j++){
if($reverse){
if (filemtime($sort_array[$i]) < filemtime($sort_array[$j]) ){
$tmp = $sort_array[$i];
$sort_array[$i] = $sort_array[$j];
$sort_array[$j] = $tmp;
}
}else{
if (filemtime($sort_array[$i]) > filemtime($sort_array[$j]) ){
$tmp = $sort_array[$i];
$sort_array[$i] = $sort_array[$j];
$sort_array[$j] = $tmp;
}
}
}
}
return $sort_array;
}
function getFileList($dir) {
global $cfgGG_filter;
global $cfgGG_sortOrder;
// Initialize temporary arrays for sorting
$dir_files = array();
// Change to directory
chdir($dir) or die("Could not change to \" $dir \" directory.");
// Open directory;
$handle = @opendir($dir) or die("Unable to open \" $dir \" .");
// Loop through all directory entries, construct
// two temporary arrays containing files and sub directories
while($entry = readdir($handle)) {
if(is_dir($entry)) continue;
if(!preg_match($cfgGG_filter,$entry)) { // here the filter is applied
continue;
}
$dir_files[] = $entry;
}
sort the files we will list
sort($dir_files);
if( empty($cfgGG_sortOrder) ) { # sort them alphabetically
sort($dir_files) ;
}
else if ($cfgGG_sortOrder = true) { # pass it to bubblesort
$sorted = BubbleSort($dir_files,true); # true means reverse sort it
$dir_files = $sorted;
}
// Close directory
closedir($handle);
return $dir_files;
}
function getFile ($url) {
$fp = @fopen($url, 'r') // get the page contents
or die("Cannot Open $url");
while ($line = @fgets($fp, 1024)) {
$contents .= $line;
}
fclose($fp);
return $contents;
}
function fancyIndex($dir_files, $dir='.') {
global $browser; // from _sniffer.php
global $cfgGG_tableCaption;
global $cfgGG_maintainer;
global $cfgGG_showMaintainer;
global $cfgGG_showDetails;
global $cfgGG_newDays;
global $cfgGG_tableColor;
global $cfgGG_rowColor1;
global $cfgGG_rowColor2;
global $cfgGG_newImage;
global $cfgGG_filter;
global $cfgGG_useIcons;
global $HTTP_HOST;
global $DOCUMENT_ROOT;
chdir($dir) or die("Could not change to \" $dir \" directory.");
// Open directory;
$handle = @opendir($dir) or die("Unable to open \" $dir \" .");
$anchorPath = '/';
if ( strlen($dir) > strlen ($DOCUMENT_ROOT) ) {
$removeChars = strlen ($DOCUMENT_ROOT);
$anchorPath .= substr ($dir, $removeChars+1).'/';
}
/
for debugging purposes
echo strlen($dir);
echo "remove chars is " .$removeChars . "<br>";
echo "doc root is ".$DOCUMENT_ROOT . "<br>";
echo "This is the anchor path:".$anchorPath;
/
// Print current directory
// ($dir=='.')? print("<h2>Contents</h2>\n") : print("<h2>Contents of $anchorPath</h2>\n");
// open a table
print ('<table class="ggIndexTable" style="background-color:'.$cfgGG_tableColor.';" cellpadding="0" cellspacing="0">');
$cfgGG_tableCaption ? print("<caption align=\"\" valign=\"\">$cfgGG_tableCaption</caption>"):'';
if ($cfgGG_showDetails) print <<<HERE
<tr>
<th>Name</th>
<th>Size</th>
<th>Type</th>
<th>Modified</th>
</tr>
HERE;
// Print all files in the curent directory
for($i=0; $i<count($dir_files); $i++) {
preg_match($cfgGG_filter,$dir_files[$i],$type); // here we setup the $type variable
$type=$type[1]; // get the matched value
($browser['type']=='Netscape')? $browserGif='nn':$browserGif='ie'; // $browser[] comes from sniffer
$browserFileList = array('html','htm','php','shtml','cgi','pl'); // these file types are 'browser' files
in_array($type, $browserFileList)? $imgIcon = $browserGif : $imgIcon = $type;
$file = $dir_files[$i];
$contents = getFile($file);
$myTitleTag = preg_match("/$title = \"([^\"]*)\"/im",$contents,$matches);
$myTitleTag = $matches[1];
if ($myTitleTag == '') $myTitleTag=$file;
cfgGG_useIcons ? $format='<img src="/images/icons/'.$imgIcon.'.gif" border="0" align="middle" alt="'.$type.' file" />' : $format = $type;
if ($cfgGG_showDetails) $lstmod = date('m/d/y',filemtime($file)); else $lstmod=' ';
if (isNew(filemtime($file),$cfgGG_newDays)) $lstmod = $lstmod .$cfgGG_newImage;
if ($cfgGG_showDetails) $size = number_format (filesize($file)/1028) . " KB"; else $size=' ';
(($i%2)==0)? $rowColor = $cfgGG_rowColor1 : $rowColor = $cfgGG_rowColor2;
print <<<HERE
<tr style="background-color: $rowColor;">
<td nowrap style="background-color: $rowColor; padding:3px;"><a href="$anchorPath$file">$myTitleTag</a></td>
<td nowrap style="background-color: $rowColor;">$size</td>
<td align="center" style="background-color: $rowColor;">$format</td>
<td style="background-color: $rowColor;">$lstmod</td>
</tr>
HERE;
}
print ("</table>");
if ($cfgGG_showMaintainer) {
(isset($cfgGG_maintainer)&&$cfgGG_maintainer!="")? $cfgGG_maintainer : $cfgGG_maintainer="webmaster@$HTTP_HOST";
print ("<br><div>send questions to <a href=\"mailto:$cfgGG_maintainer?subject=$path&cc=webmaster@$HTTP_HOST\">$cfgGG_maintainer</a></div>");
}
print ('<br clear="all" />' . "\n");
print ("<div class=\"ggIndexTable\">Files marked 'new' have been modified in the last <b>$cfgGG_newDays</b> days</div>");
// Close directory
closedir($handle);
}
/*
examples
isset($dir)? $dir : $dir = getcwd(); # index the current directory
or $dir = "$DOCUMENT_ROOT$filePath"; # the directory the script is called from $path is set in _header.php
or $dir = "$DOCUMENT_ROOT/products"; # you could always tell it to index some other dir.
$myFiles = getFileList($dir);
*/
/
to get the name of the directory only from the full path,
ust the following function
$boxLabel = substr(strrchr($val,'\'),1);
/
function openBox ($boxLabel=" ") {
print ('<table border="0" cellspacing="0" cellpadding="0" align="left">');
print <<<HERE
<tr>
<td width="20" valign="top"><!-- buffer left --><img src="/images/box_upper_left.gif" height="21" width="20" border="0" alt=""></td>
<td height="21" class="shaded" align="center"><!-- buffer top --><img src="/images/clear.gif" height="1" width="1" border="0 alt="">$boxLabel</td>
<td width="20" valign="top"><!-- buffer right --><img src="/images/box_upper_right.gif" height="21" width="20" border="0" alt=""></td>
</tr>
<tr>
<td class="leftBoxSide"> </td>
<td valign="top" style="border:solid 0px gray; padding:3px;">
HERE;
}
function closeBox () {
print <<<HERE
</td>
<td class="rightBoxSide"> </td>
</tr>
<tr>
<td valign="bottom"><img src="/images/box_lower_left.gif" width="20" height="10" border="0" alt=""></td>
<td height="10" class="bottomBoxSide"><!-- bottom buffer --><img src="/images/clear.gif" height="10" width="1" border="0" alt=""></td>
<td valign="bottom"><img src="/images/box_lower_right.gif" width="20" height="10" border="0" alt=""></td>
</tr>
</table>
HERE;
}
?>
END LONG SECTION OF CODE