ID: 48746
Updated by: [email protected]
Reported By: ddkees at illinois dot edu
-Status: Assigned
+Status: Feedback
Bug Type: Directory function related
Operating System: win32 only - Windows Server 2003
PHP Version: 5.3.0
Assigned To: pajoye
New Comment:
@dr dot e dot sheppard at web dot de
Can you try using CLI/CGI please? As you can see below it works just
fine.
C:\Users\pierre\Documents\php-sdk\php53\vc9\x86>dir
..
10.08.2009 17:36 <JUNCTION> apps
[C:\Users\pierre\Documents\php-sdk\php53\vc9\x86\deps]
28.07.2009 00:59 <DIR> deps
...
php.exe -r "var_dump(file_exists('./apps'));"
bool(true)
Previous Comments:
------------------------------------------------------------------------
[2009-06-30 20:30:47] dr dot e dot sheppard at web dot de
This bug can easily be reproduced with the following scenario:
- change to a directory within your webserver's document root
- create a junction named "apps" pointing to the desired target within
the directory tree
- calling a php file (residing in parallel to the "apps" folder) with
the following code:
if(file_exists('./apps') === true){
echo 'yes!';
} else {
echo 'no!';
}
The result will be "no!".
------------------------------------------------------------------------
[2009-06-30 19:10:21] ddkees at illinois dot edu
The file structure looks like this. Junction points are followed by an
asterisk; that asterisk is _not_ a part of the folder's name within the
filesystem.
/
/includes
/includes/classes*
/includes/classes/.SwiftMailer
/includes/classes/course_websites
/includes/classes/directory
/includes/classes/faculty_awards*
/includes/classes/FirePHP
There are more folders than what's listed above, but that's enough to
give you the idea, I hope. If not, let me know.
As you can see from the code example above, we start the process in
/includes/classes and look for folders/files to identify class
definitions to include. Using this code and 5.3.0 this morning, we
found that, using the above list, only the faculty_awards junction point
would be identified as a directory when using is_dir() and when using
DirectoryIterator::isDir().
Here's a script to show what fails:
function find_directories($directory) {
$files = new DirectoryIterator($directory);
foreach($files as $file) {
if($file->isDot() || $file->getFilename()=="_notes") continue;
echo "Analyzing: $file<br>";
var_dump($file->isDir());
echo "Analysis Complete.<br><br>";
}
}
---
If we execute that function as follows:
find_directories($_SERVER["DOCUMENT_ROOT"] . "/includes/classes");
We would expect that all of the information listed above would result
in true. However, the actual results of that test were:
Analyzing: .SwiftMailer
bool(false) Analysis Complete
Analyzing: course_websites
bool(false) Analysis Complete
Analyzing: directories
bool(false) Analysis Complete
Analyzing: faculty_awards
bool(true) Analysis Complete
Analyzing: FirePHP
bool(false) Analysis Complete
------------------------------------------------------------------------
[2009-06-30 17:58:46] [email protected]
Please provide a simple example to show what exactly does not work,
which function or method exactly and using which path:
- describe the directory tree you use and which parts of it are
junction
- provide a simple script to show which function(s) fail(s)
------------------------------------------------------------------------
[2009-06-30 17:35:59] ddkees at illinois dot edu
It should be noted, that using 5.2.9-1 works exactly as expected.
------------------------------------------------------------------------
[2009-06-30 17:19:27] ddkees at illinois dot edu
Description:
------------
After updating this morning (June 30) to 5.3.0, our __autoload()
function failed to identify any classes located in subfolders of the
windows Junction Point which contains our class files.
Our __autoload() function is recursive, descending into the filesystem
looking for class files which match the one that we're trying to load.
However, since the /includes/classes folder is a Junction Point, only
other Junction Points return true when we use both is_dir() and
DirectoryIterator::isDir() to try and identify folders from files.
DirectoryIterator::isLink() also returns false.
However, if we change our __autoloader() to include files from the
source of the Junction Point, it works as expected, but this is only a
solution for a sub-set of the sites that are available on our server.
Reproduce code:
---------------
function __autoload($class) {
if(!function_exists("find_file")) {
function find_file($directory, $target) {
$dir = opendir($directory);
while(($file = readdir($dir))!==false) {
if($file == "_notes" || substr($file, 0,
1)==".") continue;
if(is_dir($directory . "/" . $file))
find_file($directory . "/" .
$file, $target);
elseif(basename($file, ".php") == $target) {
require_once($directory . "/" . $file); return; }
}
}
}
find_file($_SERVER['DOCUMENT_ROOT'] . "includes/classes",
strtolower($class));
}
Expected result:
----------------
The expected result is that starting from $_SERVER["DOCUMENT_ROOt"] .
"/includes/classes" we identify folders and descend into them to look
for a file named $class.php where $class is the parameter sent to
__autoload(). When that file is found, it's included.
Actual result:
--------------
No folders are actually traversed, either when using the code above or
when altering it to use the DirectoryIteratory SPL object. All
non-Junction Points return false from is_dir() and, as a result, they
are never traversed and the system will also attempt to include them as
files if the elseif-conditional evaluates to true.
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=48746&edit=1