PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

readdir> <getcwd
Last updated: Fri, 18 Jul 2008

view this page in

opendir

(PHP 4, PHP 5)

opendir — Open directory handle

Description

resource opendir ( string $path [, resource $context ] )

Opens up a directory handle to be used in subsequent closedir(), readdir(), and rewinddir() calls.

Parameters

path

The directory path that is to be opened

context

For a description of the context parameter, refer to the streams section of the manual.

Return Values

Returns a directory handle resource on success, or FALSE on failure.

If path is not a valid directory or the directory can not be opened due to permission restrictions or filesystem errors, opendir() returns FALSE and generates a PHP error of level E_WARNING. You can suppress the error output of opendir() by prepending '@' to the front of the function name.

ChangeLog

Version Description
5.0.0 path supports the ftp:// URL wrapper.
4.3.0 path can also be any URL which supports directory listing, however only the file:// URL wrapper supports this in PHP 4

Examples

Example #1 opendir() example

<?php
$dir 
"/etc/php5/";

// Open a known directory, and proceed to read its contents
if (is_dir($dir)) {
    if (
$dh opendir($dir)) {
        while ((
$file readdir($dh)) !== false) {
            echo 
"filename: $file : filetype: " filetype($dir $file) . "\n";
        }
        
closedir($dh);
    }
}
?>

The above example will output something similar to:

filename: . : filetype: dir
filename: .. : filetype: dir
filename: apache : filetype: dir
filename: cgi : filetype: dir
filename: cli : filetype: dir



readdir> <getcwd
Last updated: Fri, 18 Jul 2008
 
add a note add a note User Contributed Notes
opendir
archipel dot gb at online dot fr
22-Jun-2008 02:20
Here are two versions of the same function to list all files in a directory tree.

The first one is recursive (calls itself while going through subdirectories) :
<?php
function rec_listFiles( $from = '.')
{
    if(!
is_dir($from))
        return
false;
   
   
$files = array();
    if(
$dh = opendir($from))
    {
        while(
false !== ($file = readdir($dh)))
        {
           
// Skip '.' and '..'
           
if( $file == '.' || $file == '..')
                continue;
           
$path = $from . '/' . $file;
            if(
is_dir($path) )
               
$files += rec_listFiles($path);
            else
               
$files[] = $path;
        }
       
closedir($dh);
    }
    return
$files;
}
?>

The second one is iterative (uses less memory) :
<?php
function listFiles( $from = '.')
{
    if(!
is_dir($from))
        return
false;
   
   
$files = array();
   
$dirs = array( $from);
    while(
NULL !== ($dir = array_pop( $dirs)))
    {
        if(
$dh = opendir($dir))
        {
            while(
false !== ($file = readdir($dh)))
            {
                if(
$file == '.' || $file == '..')
                    continue;
               
$path = $dir . '/' . $file;
                if(
is_dir($path))
                   
$dirs[] = $path;
                else
                   
$files[] = $path;
            }
           
closedir($dh);
        }
    }
    return
$files;
}
?>
The iterative version should be a little faster most of the time, but the big difference is in the memory usage.

Here is also a profiling function (works in php5 only) :
<?php
function profile( $func, $trydir)
{
   
$mem1 = memory_get_usage();
    echo
'<pre>-----------------------
Test run for '
.$func.'() ...
'
; flush();

   
$time_start = microtime(true);
   
$list = $func( $trydir);
   
$time = microtime(true) - $time_start;

    echo
'Finished : '.count($list).' files</pre>';
   
$mem2 = memory_get_peak_usage();

   
printf( '<pre>Max memory for '.$func.'() : %0.2f kbytes
Running time for '
.$func.'() : %0.f s</pre>',
    (
$mem2-$mem1)/1024.0, $time);
    return
$list;
}
?>
kdouglas at satarah dot com
15-May-2008 08:22
Breadth-first-search (BFS) for a file or directory (vs. Depth-first-search)
http://en.wikipedia.org/wiki/Breadth-first_search

<?php

// Breadth-First Recursive Directory Search, for a File or Directory
// with optional black-list paths and optional callback function.
//
// $root -- is the relative path to the start-of-search directory
// $file -- is the qualified file name: 'name.ext' EX: 'data.xml'
//    (or) $file -- is the target directory name EX: 'xml_files'
// $callback -- is an optional function name and will be passed all
//    matching paths EX: 'my_func', instead of exiting on first match
// $omit -- is an optional array of exclude paths -- relative to root
//    To use $omit but not $callback, pass NULL as the $callback argument
//
// TESTING VALUES FOLLOW ...

function my_func ( $path ) {
  print
"<strong>$path</strong><br>\n";
}

$root = '../public_html';
$file = 'data.xml';
$callback = 'my_func';
$omit = array( 'include/img', 'include/css', 'scripts' );

//print breadth_first_file_search ( $root, $file );
//print breadth_first_file_search ( $root, $file, $callback );
//print breadth_first_file_search ( $root, $file, NULL, $omit );
print breadth_first_file_search ( $root, $file, $callback, $omit );

function
breadth_first_file_search ( $root, $file, $callback = NULL, $omit = array() ) {
 
$queue = array( rtrim( $root, '/' ).'/' ); // normalize all paths
 
foreach ( $omit as &$path ) { // &$path Req. PHP ver 5.x and later
   
$path = $root.trim( $path, '/' ).'/';
  }
  while (
$base = array_shift( $queue ) ) {
   
$file_path = $base.$file;
    if (
file_exists( $file_path ) ) { // file found
     
if ( is_callable( $callback ) ) {
       
$callback( $file_path ); // callback => CONTINUE
     
} else {
        return
$file_path; // return file-path => EXIT
     
}
    }
    if ( (
$handle = opendir( $base ) ) ) {
      while ( (
$child = readdir( $handle ) ) !== FALSE ) {
        if (
is_dir( $base.$child ) && $child != '.' && $child != '..' ) {
         
$combined_path = $base.$child.'/';
          if ( !
in_array( $combined_path, $omit ) ) {
           
array_push( $queue, $combined_path);
          }
        }
      }
     
closedir( $handle );
    }
// else unable to open directory => NEXT CHILD
 
}
  return
FALSE; // end of tree, file not found
}

?>
info at myweb dot lu
15-May-2008 12:01
Read a Windows SMB Directory ;)

<?

function SMBMap($username, $password, $server, $dir) {
   
$command = "mount -t smbfs -o username=$username,password=$password //$server/$dir /mnt/tmp";
    echo
system($command);
}

function
SMBRelease() {
   
$command = "umount /mnt/tmp";
    echo
system($command);
}

function
GetFiles($dir) {
   
$files = array();
    if (
is_dir($dir)) {
        if (
$dh = opendir($dir)) {
            while ((
$file = readdir($dh)) !== false) {
               
$files[] = $file."{".filetype("$dir/$file")."}";
            }
           
closedir($dh);
        }
    }
    return
$files;               
}

SMBMap("Daniel", "", "10.0.0.2", "Kram");
$any = GetFiles("/mnt/tmp");
SMBRelease();
print_r($any);

?>
Peter Hkansson
11-Dec-2007 02:01
Would you like to view your directories in your browser this script might come in handy.

<?php
$sub
= ($_GET['dir']);
$path = 'enter/your/directory/here/';
$path = $path . "$sub";
$dh = opendir($path);
$i=1;
while ((
$file = readdir($dh)) !== false) {
    if(
$file != "." && $file != "..") {
            if (
substr($file, -4, -3) =="."){
            echo
"$i. $file <br />";
            }else{           
        echo
"$i. <a href='?dir=$sub/$file'>$file</a><br />";
          }
       
$i++;
    }
}
closedir($dh);
?>
mana at averna dot com
07-Dec-2007 08:02
I was trying to access network drives using this opendir function. I read so many posts saying that it was almost impossible to access a network drive and finally, I found the answer; there are 2 steps to be followed to access a network drive with PHP either on the same machine or another machine.

But first of all, here's the error I was getting:
Warning: opendir(\\server\folder1\sub_folder) [function.opendir]: failed to open dir: No error in C:\wamp\www\PMOT\v0.1\REPORT_MENU\index.php on line 17

Firstly, one must make sure that the folder \\server\folder1\sub_folder can be accessed by a user, let's say USER_TEST with a password PASS_TEST. By setting properties to this folder, one can add this given user with the correct password (USER_TEST with PASS_TEST).

Secondly, the APACHE service must be set-up to take this user into account. If no user is specified, APACHE uses an anonymous user and this is where the problem/error message is coming from. One must go in control panel->administrative tools->services. One will see the list of services and must look for APACHE with Apache/2.X.X in the description. (For Wampserver, it will be called wampapache, and so on!) Right click on that and pop up the properties screen. In the tab LOG ON, there are 2 options: local system account and "this account" which will be a user specified account. This is where one must specify the USER_TEST and PASS_TEST.

Following these steps worked perfectly for me but if either the folder privileges or apache log on user is disabled, then I get the initial aforementioned error message.

Anyways, I hope this can help out someone!

Cheers!

Marc
microhost at msn dot com
27-Nov-2007 01:14
<?php
// images dir

$path = "../imp/images/";
//images them dir
$patha ="../imp/them";  
$dh = opendir($path);
while (
$file = readdir($dh))
if(
$file != "." && $file != ".." && $file != "Thumbs.db" && $file != "index.html" && $file != "index.php"      ) {
{
    echo
"<a  href='#top'>
    <img border='0' src='$path/$file'  onclick=\"window.open('$patha/$file', 'poppage$idd', 'toolbars=0, scrollbars=0, location=0, statusbars=0, menubars=0, resizable=1, $gg, left = 150, top = 50')\";    >
    "
;
}
}
closedir($dh); // close dir
?>

when you need view images in folder
MetaNull
04-Oct-2007 04:04
How to find files in a directory, using regular expressions (case-sensitive or not)

<?php

clearstatcache
();

$sourcepath = "C:/WINDOWS/TEMP";

// Replace \ by / and remove the final / if any
$root = ereg_replace( "/$", "", ereg_replace( "[\\]", "/", $sourcepath ));

// Search for text files
$results = m_find_in_dir( $root, ".*\.txt" );
if(
false === $results ) {
    echo
"'{$sourcepath}' is not a valid directory\n";
} else {
   
print_r( $results );
}

/**
 * Search for a file maching a regular expression
 *
 * @param string $root Root path
 * @param string $pattern POSIX regular expression pattern
 * @param boolean $recursive Set to true to walk the subdirectories recursively
 * @param boolean $case_sensitive Set to true for case sensitive search
 * @return array An array of string representing the path of the matching files, or false in case of error
 */
function m_find_in_dir( $root, $pattern, $recursive = true, $case_sensitive = false ) {
   
$result = array();
    if(
$case_sensitive ) {
        if(
false === m_find_in_dir__( $root, $pattern, $recursive, $result )) {
            return
false;
        }
    } else {
        if(
false === m_find_in_dir_i__( $root, $pattern, $recursive, $result )) {
            return
false;
        }
    }
   
    return
$result;
}

/**
 * @access private
 */
function m_find_in_dir__( $root, $pattern, $recursive, &$result ) {
   
$dh = @opendir( $root );
    if(
false === $dh ) {
        return
false;
    }
    while(
$file = readdir( $dh )) {
        if(
"." == $file || ".." == $file ){
            continue;
        }
        if(
false !== @ereg( $pattern, "{$root}/{$file}" )) {
           
$result[] = "{$root}/{$file}";
        }
        if(
false !== $recursive && is_dir( "{$root}/{$file}" )) {
           
m_find_in_dir__( "{$root}/{$file}", $pattern, $recursive, $result );
        }
    }
   
closedir( $dh );
    return
true;
}

/**
 * @access private
 */
function m_find_in_dir_i__( $root, $pattern, $recursive, &$result ) {
   
$dh = @opendir( $root );
    if(
false === $dh ) {
        return
false;
    }
    while(
$file = readdir( $dh )) {
        if(
"." == $file || ".." == $file ){
            continue;
        }
        if(
false !== @eregi( $pattern, "{$root}/{$file}" )) {
           
$result[] = "{$root}/{$file}";
        }
        if(
false !== $recursive && is_dir( "{$root}/{$file}" )) {
           
m_find_in_dir__( "{$root}/{$file}", $pattern, $recursive, $result );
        }
    }
   
closedir( $dh );
    return
true;
}

?>
MetaNull
04-Oct-2007 03:39
An other way to recursively walk a directory and it's content, applying a callback to each file.

Exemple: Update the last modification time of each file in a folder

<?php

clearstatcache
();

$sourcepath = "C:/WINDOWS/TEMP";

// Replace \ by / and remove the final / if any
$root = ereg_replace( "/$", "", ereg_replace( "[\\]", "/", $sourcepath ));
// Touch all the files from the $root directory
if( false === m_walk_dir( $root, "m_touch_file", true )) {
    echo
"'{$root}' is not a valid directory\n";
}

// Walk a directory recursivelly, and apply a callback on each file
function m_walk_dir( $root, $callback, $recursive = true ) {
   
$dh = @opendir( $root );
    if(
false === $dh ) {
        return
false;
    }
    while(
$file = readdir( $dh )) {
        if(
"." == $file || ".." == $file ){
            continue;
        }
       
call_user_func( $callback, "{$root}/{$file}" );
        if(
false !== $recursive && is_dir( "{$root}/{$file}" )) {
           
m_walk_dir( "{$root}/{$file}", $callback, $recursive );
        }
    }
   
closedir( $dh );
    return
true;
}

// if the path indicates a file, run touch() on it
function m_touch_file( $path ) {
    echo
$path . "\n";
    if( !
is_dir( $path )) {
       
touch( $path );
    }
}

?>
arjan at wepwn dot nl
09-Sep-2007 04:03
A simple function to count all the files and/or dirs inside a dir.
With optional extention when counting files.

Index of /
Some text file.txt
files/
num_files.phps
test.php

<?php
function num_files($dir, $type, $ext="")
{
// type 1: files only
// type 2: direcories only
// type 3: files and directories added
// type 4: files and directories separated with a space

   
if (!isset($dir) OR empty($dir))
    {
        echo
'<b>Syntax error:</b> $dir value empty.';
        exit;
    }

   
$num_files = 0;
   
$num_dirs = 0;
    switch(
$type)
    {
        case
1: // count only files, not dirs
           
if ($dir = @opendir($dir))
            {
                while ((
$file = readdir($dir)) !== false)
                {
                    if(
is_file($file) AND $file != "." AND $file != "..")
                    {
                        if (isset(
$ext) AND !empty($ext))
                        {
                           
$extension = end(explode(".", $file));
                            if (
$ext == $extension)
                            {
                               
$num_files++;
                            }
                        }
                        else
                        {
                           
$num_files++;
                        }
                    }
                } 
               
closedir($dir);
               
$total = $num_files;
            }
        break;

        case
2: // count only dirs, not files
           
if ($dir = @opendir($dir))
            {
                while ((
$file = readdir($dir)) !== false)
                {
                    if(
is_dir($file) AND $file != "." AND $file != "..")
                    {
                       
$num_dirs++;
                    }
                } 
               
closedir($dir);   
               
$total = $num_dirs;
            }
        break;

        case
3: // count files PLUS dirs in once variable
           
if ($dir = @opendir($dir))
            {
                while ((
$file = readdir($dir)) !== false)
                {
                    if(
is_dir($file) OR is_dir($file))
                    {
                        if (
$file != "." AND $file != "..")
                        {
                           
$num_files++;
                        }
                    }
                } 
               
closedir($dir);
               
$total = $num_files;
            }
        break;

        case
4: // count files AND dirs separately
           
if ($dir = @opendir($dir))
            {
                while ((
$file = readdir($dir)) !== false)
                {
                    if(
is_file($file) AND $file != "." AND $file != "..")
                    {
                       
$num_files++;
                    }

                    if(
is_dir($file) AND $file != "." AND $file != "..")
                    {
                       
$num_dirs++;
                    }
                } 
               
closedir($dir);
               
$total = $num_files." ".$num_dirs;
            }
        break;

        default:
            echo
'<b>Syntax error:</b> $type value empty.';
        break;
    }

    return
$total;
}

echo
num_files($_SERVER['DOCUMENT_ROOT'], 1, "php"). " file(s) met php extention<br /> ";
echo
num_files($_SERVER['DOCUMENT_ROOT'], 1). " file(s)<br />";
echo
num_files($_SERVER['DOCUMENT_ROOT'], 2). " dir(s)<br />";
echo
num_files($_SERVER['DOCUMENT_ROOT'], 3). " file(s) + dir(s)<br />";
$nummers = explode(" ", num_files($_SERVER['DOCUMENT_ROOT'], 4));
echo
reset($nummers) ." file(s) en ". end($nummers) ." dir(s)";
?>

will output:
1 file(s) with php extention
3 file(s)
1 dir(s)
1 file(s) + dir(s)
3 file(s) en 1 dir(s)
lolwut
13-May-2007 10:00
I sometimes find this useful. Hope you will too.

<?php
//list_by_ext: returns an array containing an alphabetic list of files in the specified directory ($path) with a file extension that matches $extension

function list_by_ext($extension, $path){
   
$list = array(); //initialise a variable
   
$dir_handle = @opendir($path) or die("Unable to open $path"); //attempt to open path
   
while($file = readdir($dir_handle)){ //loop through all the files in the path
       
if($file == "." || $file == ".."){continue;} //ignore these
       
$filename = explode(".",$file); //seperate filename from extenstion
       
$cnt = count($filename); $cnt--; $ext = $filename[$cnt]; //as above
       
if(strtolower($ext) == strtolower($extension)){ //if the extension of the file matches the extension we are looking for...
           
array_push($list, $file); //...then stick it onto the end of the list array
       
}
    }
    if(
$list[0]){ //...if matches were found...
   
return $list; //...return the array
   
} else {//otherwise...
   
return false;
    }
}

//example usage
if($win32_exectuables = list_by_ext("exe", "C:\WINDOWS")){
   
var_dump($win32_exectuables);
} else {
    echo
"No windows executables found :(\n";
}

?>
Michael mt1955 (a) gmail.com
11-May-2007 11:59
# simple directory walk with callback function

<?php
function callbackDir($dir)
{
  
# do whatever you want here
  
echo "$dir\n";
}

function
walkDir($dir,$fx)
{
 
$arStack = array();
 
$fx($dir);
  if( (
$dh=opendir($dir)) )
  { while( (
$file=readdir($dh))!==false )
    { if(
$file=='.' || $file=='..' ) continue;
      if(
is_dir("$dir/$file") )
      { if( !
in_array("$dir/$file",$arStack) ) $arStack[]="$dir/$file";
      }
    }
   
closedir($dh);
  }
  if(
count($arStack) )
  { foreach(
$arStack as $subdir )
    {
walkDir($subdir,$fx);
    }
  }
}

walkDir($root,callBackDir);
?>
Dblurred
07-May-2007 09:04
In reponse to Tozeiler.  Nice short directory dump.  However, that displays the "." and "..".  This removes those.  It also makes an ordered list in case I needed to be on the phone while looking at the page.  Easy to call out.

<?php

$path
= "your path";
$dh = opendir($path);
$i=1;
while ((
$file = readdir($dh)) !== false) {
    if(
$file != "." && $file != "..") {
        echo
"$i. <a href='$path/$file'>$file</a><br />";
       
$i++;
    }
}
closedir($dh);
?>
samantha dot vincent at gmail dot com
02-May-2007 03:46
Using Apache 2.2.4 with PHP and MySQL I was trying to connect to a Novell Netware drive using opendir("R:/") where R: was pointing to a Netware resource on another server. The error returned was

Warning: opendir(R:/) [function.opendir]: failed to open dir: No such file or directory in path/to/my/phpfile/containing/opendir on line 34.

Basically it is a problem with Netware rights and users and how the apache service was trying to connect to the resource.

To get everything working as expected in the end we set up a Windows user account eg: webhost with the same password as a Netware account with username webhost, set the Netware account to have rights to the resource R:/ (we just used admin rights), and set the apache service to run as the webhost user using the username password combo.

Hope this helps someone else out.
.....alexander[at]gmail.com
14-Apr-2007 02:13
This is a script that prints all the file and directory names  on your server no matter where the script file is located
(could take a lot of time to execute, if you have a lot of directories and files...)
Hope someone finds it useful...

<?php
print $_SERVER['DOCUMENT_ROOT'] . "<br />";
$root = @opendir($_SERVER['DOCUMENT_ROOT']);
$dirs = array();

while(
$file = readdir($root)){
    print
$file;
    if((
is_dir($file) || !stristr($file, ".")) && $file!="." && $file!=".."){
        
$dirs[] = ($_SERVER['DOCUMENT_ROOT'] . "/" . $file);
    print
"(adding directory)";
    }
    print 
"<br />";
}
closedir($root);

print
"<br /><br />Inside Dirs: (" . (count($dirs)) . ")<br />";

$i = 0;
    while(
$i < count($dirs)){

       
$d = @opendir($dirs[$i]);
        print
"<br /><br />Directory: " . $dirs[$i] . "<br />";

        while(
$f = readdir($d)){
            print
$f;

            if((
is_dir($f) || !stristr($f, ".")) && $f!="." && $f!=".."){
                
$dirs[] = $dirs[$i]  . "/" $f;
            print
"(adding directory)";
            }

            print
"<br />";
        }
       
closedir($d);

       
$i = $i + 1;
    }
$i = $i - 1;

?>
NerdyDork
08-Feb-2007 01:36
Here is a snippet to create a site map of all html files in a folder:

<?php
   
// read all html file in the current directory
   
if ($dh = opendir('./')) {
       
$files = array();
        while ((
$file = readdir($dh)) !== false) {
            if (
substr($file, strlen($file) - 5) == '.html') {
               
array_push($files, $file);
            }
        }
       
closedir($dh);
    }
   
   
// Sort the files and display
   
sort($files);
    echo
"<ul>\n";
    foreach (
$files as $file) {
       
$title = Title($file);
        echo
"<li><a href=\"$file\" title=\"$title\">$title</a></li>\n";
    }
    echo
"</ul>\n";
   
   
// Function to get a human readable title from the filename
   
function Title($filename) {
       
$title = substr($filename, 0, strlen($filename) - 5);
       
$title = str_replace('-', ' ', $title);
       
$title = ucwords($title);
        return
$title;
    }
?>
frogstarr78 at yahoo dot com
21-Jan-2007 05:30
Here's a function that will recrusively turn a directory into a hash of directory hashes and file arrays, automatically ignoring "dot" files.

<?php
function hashify_directory($topdir, &$list, $ignoredDirectories=array()) {
    if (
is_dir($topdir)) {
        if (
$dh = opendir($topdir)) {
            while ((
$file = readdir($dh)) !== false) {
                if (!(
array_search($file,$ignoredDirectories) > -1) && preg_match('/^\./', $file) == 0) {
                    if (
is_dir("$topdir$file")) {
                        if(!isset(
$list[$file])) {
                           
$list[$file] = array();
                        }
                       
ksort($list);
                       
hashify_directory("$topdir$file/", $list[$file]);
                    } else {
                       
array_push($list, $file);
                    }
                }
            }
           
closedir($dh);
        }
    }
}
?>

e.g.
<?php
$public_html
["StudentFiles"] = array();
hashify_directory("StudentFiles/", $public_html["StudentFiles"]);
?>
on the directory structure:
./StudentFiles/tutorial_01/case1/file1.html
./StudentFiles/tutorial_01/case1/file2.html
./StudentFiles/tutorial_02/case1/file1.html
./StudentFiles/tutorial_02/case2/file2.html
./StudentFiles/tutorial_03/case1/file2.html
etc...
becomes:
<?php
print_r
($public_html);
/*
outputs:
array(
  "StudentFiles" => array (
        "tutorial_01" => array (
              "case1" => array( "file1.html", "file2.html")
        ),
        "tutorial_02" => array (
              "case1" => array( "file1.html"),
              "case2" => array( "file2.html")
        ),
       "tutorial_03" => array (
              "case1" => array( "file2.html")
       )
  )
)
*/
?>
I'm using it to create a tree view of a directory.
phpguy at mailstop dot yogelements dot omitme dot com
13-Dec-2006 06:40
An issue that I ran into is that opendir() could care less if you've got server authentication set on sub directories and so any such authentication is bypassed completely when accesses in this way. I did solve it for my application of a pretty file manager, by redirecting to all sub directories thusly:
$fdir = "./subdirectory_I_want_to_visit/";
if ($fdir != './') { //basically where we are or the parent
    //redirect the browser to force authentication check on any subdirectories
    header("Location: http://my.domain.com".dirname($_SERVER["PHP_SELF"]).substr($fdir,2));
    exit;
} else {
    $dir = opendir($fdir);
}
tony at glccom dot com
01-Nov-2006 02:49
John & I have edited the code posted by hendrik dot wermer at gmx dot de on 07-Feb-2005 06:06

This Code now allows for downloads form sub directories. We also used CSS to make the page's look customizable.

You can view the example at: http://www.asterikast.com/code/dirlist.txt
anon at no thing dot com
23-Oct-2006 01:55
In response to previous post,
you can use realpath() to fix the '/../../../' problem.
Christian
26-Jul-2006 07:10
Pointing on the previous post, I'd like to say the following.

You can use opendir on all valid (existant and reachable) folders.
This counts not only for windows but also for linux.
Under linux, you can also read root folders etc.

To avoid access to non-public data, you should check the given parameter for opendir before executing opendir.

Let's say you have this:

/home/users/mrsmith/
/home/users/mrsmith/info.txt
/home/users/mrsmith/test/photo.jpg
/home/users/mradmin/private.txt

Now you don't want mrsmith to access mradmin's folders/files.
In that case you could/should define the path where the data MUST be inside.

Attention:
Don't check the data with substr though, it's not a secure solution.
Exploit example: /home/users/mrsmith/../mradmin/
Exploit example2: /home/users/mrsmith/../../../../../../../../../../../../../dev/

I'd do a case sensitive regex match.
So after the first folder there may not be a subfolder named ".." because that would jump one folder back.

I hope this isn't too offtopic or so but I think it's important to think of that when creating file systems.
tim2005
13-May-2006 09:04
Hello,

A friend of mine is running a webhost, I think i found a security leak with this script:

<?php
function select_files($dir, $label = "", $select_name, $curr_val = "", $char_length = 30) {
   
$teller = 0;
    if (
$handle = opendir($dir)) {
       
$mydir = ($label != "") ? "<label for=\"".$select_name."\">".$label."</label>\n" : "";
       
$mydir .= "<select name=\"".$select_name."\">\n";
       
$curr_val = (isset($_REQUEST[$select_name])) ? $_REQUEST[$select_name] : $curr_val;
       
$mydir .= ($curr_val == "") ? "  <option value=\"\" selected>...\n" : "<option value=\"\">...\n";
        while (
false !== ($file = readdir($handle))) {
           
$files[] = $file;
        }
       
closedir($handle);
       
sort($files);
        foreach (
$files as $val) {
            if (
is_file($dir.$val)) { // show only real files (ver. 1.01)
               
$mydir .= "    <option value=\"".$val."\"";
               
$mydir .= ($val == $curr_val) ? " selected>" : ">";
               
$mydir .= (strlen($val) > $char_length) ? substr($val, 0, $char_length)."...\n" : $val."\n";
               
$teller++;   
            }
        }
       
$mydir .= "</select>";
    }
    if (
$teller == 0) {
       
$mydir = "No files!";
    } else {
        return
$mydir;
    }
}

echo
select_files("C:/winnt/", "", "", "", "60");
?>

Now i can see hist files in his windows dir. Is this a leak? and is it fixable? I'll report this as bug too!

Tim2005
tozeiler
15-Apr-2006 05:34
"opendir" said:
------------------------------------------------------------------

23-Jan-2006 08:04
I Just wanted a directory list and a clickable link to download the files

<snip>
------
<?
echo ("<h1>Directory Overzicht:</h1>");

function
getFiles($path) {

<
snip complicated function contents>

------------------------------------------------------------------
Here's a more straightforward way to linkify $path/files:

<?php

echo "<h1>Directory Overzicht:</h1>";

$dh = opendir($path);
while (($file = readdir($dh)) !== false) {
    echo "<a href='
$path/$file'>$file</a><br />";
}
closedir($dh);

?>
23-Jan-2006 12:04
I Just wanted a directory list and a clickable link to download the files because my plesk server does not give me this function. I edited the script a little bit.

Many thanks from a script-noob

------
<?
echo ("<h1>Directory Overzicht:</h1>");

function
getFiles($path) {
  
//Function takes a path, and returns a numerically indexed array of associative arrays containing file information,
   //sorted by the file name (case insensitive).  If two files are identical when compared without case, they will sort
   //relative to each other in the order presented by readdir()
  
$files = array();
  
$fileNames = array();
  
$i = 0;
  
   if (
is_dir($path)) {
       if (
$dh = opendir($path)) {
           while ((
$file = readdir($dh)) !== false) {
               if (
$file == "." || $file == "..") continue;
              
$fullpath = $path . "/" . $file;
              
$fkey = strtolower($file);
               while (
array_key_exists($fkey,$fileNames)) $fkey .= " ";
              
$a = stat($fullpath);
              
$files[$fkey]['size'] = $a['size'];
               if (
$a['size'] == 0) $files[$fkey]['sizetext'] = "-";
               else if (
$a['size'] > 1024) $files[$fkey]['sizetext'] = (ceil($a['size']/1024*100)/100) . " K";
               else if (
$a['size'] > 1024*1024) $files[$fkey]['sizetext'] = (ceil($a['size']/(1024*1024)*100)/100) . " Mb";
               else
$files[$fkey]['sizetext'] = $a['size'] . " bytes";
              
$files[$fkey]['name'] = $file;
              
$files[$fkey]['type'] = filetype($fullpath);
              
$fileNames[$i++] = $fkey;
           }
          
closedir($dh);
       } else die (
"Cannot open directory:  $path");
   } else die (
"Path is not a directory:  $path");
  
sort(