ZF-11699: Zend_Loader::isReadable creates incorrect paths and then throws warnings

Description

In vhost file for site I have php_admin_value open_basedir "/opt/fed/lib:/opt/fed/options:/usr/share/pear:/usr/share/php"

I add include paths for /opt/fed/lib ( Zend and Company Core libs ) /opt/fed/options/library ( application specific library )

include path already has /usr/share/pear and /usr/share/php

If I run site with PHP error reporting set to include warnings I get a load of them on the page.

here is one: Warning: is_readable(): open_basedir restriction in effect. File(/usr/share/pear//opt/fed/lib/FED/Application/Resource/Frontcontroller.php) is not within the allowed path(s): (/opt/fed/lib:/opt/fed/options:/usr/share/pear:/usr/share/php) in /opt/fed/lib/Zend/Loader.php on line 198 Warning: is_readable(): open_basedir restriction in effect.

The culprit is at about L198 of Zend_Loader and I see a couple of things happening a/ the $file = $path . '/' . $filename; on L197 is creating rubbish paths. In the above example /usr/share/pear/ is part of include paths /opt/fed/lib is part of include paths and in the open_basedir directive L197 (irrespective of the fact that it is creating a none existant path, is not taking care to strip any trailing slashes from $path.

I saw the comments in another ticket about not being able to use PHP5.3 functionality for the V1.X branch and understand that but wouldn't it be better to put if (file_exists($path)) .... at L198 to prevent teh is_readable() warnings.?

Comments

file_exists() doesn't tell us if we can actually read it. is_readable() tells us both -- that it exists, and that we can read it. If we did first a file_exists(), we'd be doing two I/O stat calls, which would introduce a performance bottleneck.

As for open_basedir warnings, that's next to impossible for us to account for at a framework level, and in fact its utility has been hotly debated even amongst PHP internals developers; the only real solutions have to be application-specific.

I understand the point about file_exists vs is_readable and I/O. However, there are two issues here:

1/ as per my example, L197 is testing for rubbish paths being generated in the class, and will therefore fail for open_basedir - so if that was fixed the problem would be resolved

2/ not using open_basedir is not an option for some installations. In this particular case, a major European telecom, is insisting we use it.

I completely understand your issues. However, making the changes you suggest will break existing behavior (I know, because we've done it in the past) and will introduce a performance degradation (again, I know, because we've done it in the past). Changing it in the framework is simply not an option.

This is one case where I'd suggest monkey-patching the Zend_Loader class in your install to suit your specific needs. You can easily do so by copying it elsewhere, modifying the method, and ensuring that the path to your patched class is early in your include_path.