Issues

ZF-9263: Auto-loading stopped working as before in 1.10.1

Description

I was working on a ZF application based on ZF 1.10.0. Then env is: WinXP, Apache 2.2.11, PHP 5.3.1, MySQL.

I made one very small change: replaced the 1.10.0 with 1.10.1 (or 1.10.2 the same effect) and no any other change and all over the application are errors because some resources doesn't seems to be auto-loaded properly.

Here is my include_path:

set_include_path(implode(PATH_SEPARATOR, array(
    ZF_LIBRARY_PATH,
    BASE_PATH . '/library',
    get_include_path()
)));

I tried to switch all the application resources to use absolute path but errors again....

Sample for Application Resources...

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(C:\php5\pear/ZendX/Application/Resource/Log.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php\pear) in D:\wamp\frameworks\ZendFramework-1.10.1\Zend\Loader.php on line 190

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(C:\php5\pear/Application/Application/Resource/Log.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php\pear) in D:\wamp\frameworks\ZendFramework-1.10.1\Zend\Loader.php on line 190


Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(C:\php5\pear/Imagis/Application/Resource/Log.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php\pear) in D:\wamp\frameworks\ZendFramework-1.10.1\Zend\Loader.php on line 190

Sample for view helpers:

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(C:\php5\pear/D:/_Work/vxwiki2/application/modules/default/views\helpers/Partial.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php\pear) in D:\wamp\frameworks\ZendFramework-1.10.1\Zend\Loader.php on line 190

As i repeat: there is no other application or WAMP environment change than changing the ZF version from 1.10.0 to .1/.2

Comments

It's clear you're using open_basedir, which places filesystem access restrictions. Prior to 1.10.1, we were using a hack that utilized some functionality in fopen() -- basically, fopen() allows a flag that will allow it to search for the file specified on the include_path. Unfortunately, due to the way it worked, we had to use the error suppression operator to eliminate notices, it would not work with stream wrappers, and it circumvented the open_basedir settings. We've moved to a solution that iterates over the include_path and calls is_readable() instead, which solves all three issues.

The obvious downside, of course, is if you had an open_basedir setting, and had files that lived outside that path. This was something we had not anticipated with the change, and which we didn't discover until after the release.

The solution is to ensure that all files used by your application live within the tree specified by open_basedir. This may require copying trees (versus symlinking them) into your project directory. Better yet, don't use open_basedir, as it's a setting that's easily circumvented (as our fopen() hack proved) and which provides very limited security benefits.

Thanks Matthew!

I partially fixed the problems, still fixed the rest.

I am not sure if on documentation is mentioned this change as might be important for many...

I also noticed some related weird behavior as:

Warning: is_readable(): open_basedir restriction in effect. File(D:\wamp\frameworks\ZendFramework-1.10.2/D:_Work\myapp/application/modules\articles/views\helpers/HeadLink.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php5\pear) in D:\wamp\frameworks\ZendFramework-1.10.2\Zend\Loader.php on line 190

So basically looking for the helpers is failing, as are checked the Zend_View_Helper into modules helpers paths, not into Zend/View/Helper.

This is NOT a open_basedir problem actually...

So there is problem: all files reside under open_basedir paths but won't load. So that upgrade made on 1.10.1 is fine as long has a patch to solve the below problems (which probably is not impossible)...

Warning: is_readable(): open_basedir restriction in effect. File(D:\wamp\frameworks\ZendFramework-1.10.2/D:_Work\myapp/application/modules\articles/views\helpers/HeadLink.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php5\pear) in D:\wamp\frameworks\ZendFramework-1.10.2\Zend\Loader.php on line 190

I found a way to solve the problem. May not be the optimal way, but:

public static function isReadable($filename)
{
    if (is_readable($filename)) {
        // Return early if the filename is readable without needing the 
        // include_path
        return true;
    }

            //added the if, basically to skip any absolute filename path
    if(!is_readable(dirname($filename)))
        foreach (self::explodeIncludePath() as $path) {
            if ($path == '.') {
                if (is_readable($filename)) {
                    return true;
                }
                continue;
            }
            $file = $path . '/' . $filename;
            if (is_readable($file)) {
                return true;
            }
        }

    return false;
}

This would solve the problem of this raising a Warning.

Warning: is_readable(): open_basedir restriction in effect. File(D:\wamp\frameworks\ZendFramework-1.10.2/D:_Work\myapp/application/modules\articles/views\helpers/HeadLink.php) is not within the allowed path(s): (D:_Work\;D:\wamp\;C:\Windows\Temp\;c:\php5\pear) in D:\wamp\frameworks\ZendFramework-1.10.2\Zend\Loader.php on line 190

It would be nice if this issue could be fixed for those where open_basedir is force upon. It's a rather dirty solution to distribute the full ZF library with every app, so a shared directory would be preferred.

As stated into last comment the problem itself has nothing to do directly with shared directory. The open_basedir warning is raised due to wrong isReadable implementation (and not due to using shared directory).

Anyway, using a shared directory with ZF would be possible again once this bug is fixed.

For now we are stuck at 1.10.0...

Unfortunately I can't use 1.10.0 either because of a bug in XCache. Which is resolved I believe in a recent update of XCache but Ubuntu 8.04 doesn't include that version.

Any chance the proposed code will get used in a next version?

@Christiaan Kras: The bug you're alluding to is fixed in 1.10.1 and up -- it had to do with Zend_Exception's definition, and we were able to find a solution that would work both with older versions of XCache as well as more recent versions.

@Matthew Weier O'Phinney: Yes I'm aware of that. The fact is that in 1.10.1 and up the way files are being checked for readability no longer works with open_basedir.

Matthew, the problems started on 1.10.1 (so not fixed on 1.10.1) and is not fixed even on 1.10.3

@Christiaan: I was simply responding to your previous comment, which noted issues with XCache; the way the comment was worded, it was not clear if you were also experiencing the issue reported here.

@Christian: I'm quite aware it's not fixed in 1.10.3. As noted on the mailing list, I need a reproduce case. Current versions work fine in Windows, Linux, and Mac using a stock PHP; I need to know if the only variable here is open_basedir, or if there are additional factors.

Ok, i will check and post back. Thanks.

I tested on Windows.

If open_basedir is On then warnings are triggered.

If open_basedir is Off then no warnings are triggered.

I had to say again, all the open_basedir are properly set and also include_paths...

I can test on a BSD environment if needed. Will post back this results also.

OK, i tested on a production server, on BSD and WITH open_basedir in effect all works properly on 1.10.2 (i guess same on .1 and .3).

So for now i am experiencing the problem only on: - Windows - open_basedir been enabled

@Christian Thanks -- that will help us isolate the issue.

I tested on Windows again, now with xDebug disabled (i have xDebug also), and same results. So is not an xDebug issue.

So same conclusion: on Windows with open_basedir enabled -> warning. Any other config ->ok.

@Matthew Weier O'Phinney: Sorry for not being clear. I'm not a native English speaker. I was just referring to the fact that I can't use 1.10.0 because of the XDebug bug, and can't use anything newer than that because of this auto-loading bug.

For me the open_basedir problem happens on Ubuntu 8.04.

@Chrstiaan: what version of PHP?

5.2.4, just the standard one that comes with Ubuntu 8.04. They do have it patched with the Suhosin patch. Further more safe-mode is on as well.

Matthew, i have PHP 5.3.1 on WinXP for dev environment which got me the warning...

So, for me works even with open_basedir enabled on a FreeBSD system having PHP 5.2.13

I think it is exclusively a Windows issue due to the fact that Windows uses drive letters and *nix does not. If you concatenate two Linux absolute paths, the result is still a valid path even if it does not point to an actual file. If you concatenate a Windows absolute path to the end of any other path (relative OR absolute), the result IS NOT a valid path.

For example:

include_path = /home/www/site/zendframework/library

openbase_dir = /home/www/site

$loader->isReadable('/home/www/site/application/controllers/helpers/Redirector.php');

Inside the isReadable method, it would eventually test this path:


Even though the path does not point to a valid file, the path itself is still valid and it meets the condition specified in openbase_dir.

On Windows, however it looks like this:

include_path = C:\www\site\zendframework\library

openbase_dir = C:\www\site

$loader->isReadable('C:\www\site\application\controllers\helpers\Redirector.php');


Inside the isReadable method, it would eventually test this path:

The drive letter specification inside the path is not valid, and PHP issues the warning.

I think the solution to this problem would be check for a drive letter at the beginning of the path to be tested if the OS is Windows, and if a drive letter is found it is clearly an absolute path that cannot be appended to any of the paths found in include_path. I'm not sure if the PHP_OS test below is totally correct, but I think the solution is to change Zend_Loader::isReadable() to look like this:


    public static function isReadable($filename)
    {
        if (is_readable($filename)) {
            // Return early if the filename is readable without needing the 
            // include_path
            return true;
        }

        if (PHP_OS == 'WINNT' && preg_match('/^[A-Z]:/i', $file)) {
            // This is an absolute path for a Windows system. We already tried
            // is_readable on the path and it failed, so return false
            return false;
        }
        
        foreach (self::explodeIncludePath() as $path) {
            if ($path == '.') {
                if (is_readable($filename)) {
                    return true;
                }
                continue;
            }
            $file = $path . '/' . $filename;
            if (is_readable($file)) {
                return true;
            }
        }
        return false;
    }

@Andrew Ballard: Like I said, it also happens for me on Linux (Ubuntu 8.04, PHP 5.2.4 with suhosin patch, open_basedir and safe_mode in effect).

Started to happen for me on another FreeBSD server, so somehow is happening also on *Nix.

Andrew -- thanks for the analysis! I noticed the same issue about the full path being added in, and that clearly represents an issue. I was initially worried about the usage of PCRE, but realized that it would only kick in on Windows, and only if the initial test failed. The performance hit should hopefully be fairly minimal, and restricted to Windows environments.

I've added a test and patched the code in trunk and the 1.10 release branch; the fix should be released in 1.10.4.

I'm sorry but this bug still isn't resolved on Linux (Ubuntu 8.04, suhosin patch, safe_mode on and open_basedir in effect).

I followed your suggestion in ZF-9166 made sure all paths were absolute. Which then led to an issue of not being able to include a file that was symlinked. So instead of symlinking I copied it to the same directory, made sure permissions were correct and included the file. Right after that all the include errors popped up again.

Below is on of the messages I'm getting, amongst many other failed attempts to load other plugins.


Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/lib/include/KD/View/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/usr/share/pear/lib/include/KD/View/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/lib/modules/default/views/helpers/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/usr/share/pear/lib/modules/default/views/helpers/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/lib/include/DP/View/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/usr/share/pear/lib/include/DP/View/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/Zend/View/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198

Here's how I've set my include path:


set_include_path(
    PATH_SEPARATOR . '/usr/local/share/ZendFramework/1.10.4/library/' . 
    PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'] . '/lib/modules/default/models/' .
    PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'] . '/lib/modules/software/models/' .
    PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'] . '/lib/modules/bijlage/models/' .
    PATH_SEPARATOR . $_SERVER['DOCUMENT_ROOT'] . '/lib/include/' .
    PATH_SEPARATOR . get_include_path()
);

By default my include_path contains {{:/usr/share/php:/usr/share/pear}}. After modifieng it it contains {{:/usr/local/share/ZendFramework/1.10.4/library/:/var/www/www_domain_com/app/current/www/lib/modules/default/models/:/var/www/www_domain_com/app/current/www/lib/modules/software/models/:/var/www/www_domain_com/app/current/www/lib/modules/bijlage/models/:/var/www/www_domain_com/app/current/www/lib/include/:.:/usr/share/php:/usr/share/pear}}.

My {{$_SERVER['DOCUMENT_ROOT']}} points to {{/var/www/www_domain_com/app/current/www}}. All paths are correct, as well as any file permissions.

My Apache configuration:



    DocumentRoot /var/www/www_domain_com/app/current/www
    ServerName www.domain.com
    CustomLog /var/log/apache2/www.domain.com-access_log combined
    ErrorLog /var/log/apache2/www.domain.com-error_log
    php_admin_value open_basedir "/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php"

Output of {{php -v}} in case it's required:


PHP 5.2.4-2ubuntu5.10 with Suhosin-Patch 0.9.6.2 (cli) (built: Jan  6 2010 22:01:14)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
    with XCache v1.2.1, Copyright (c) 2005-2007, by mOo

As i mentioned myself, i encountered the same problem on a BSD system. I had to disable open_basedir as a quick solution. Sorry, i can't provide now a sample myself.

@Christiaan

I think your issue is slightly different. None of the paths in any of the warning messages you posted above are within your open_basedir restriction. The open_basedir restriction is doing what it was designed to do. If the warning were happening on line 176 (version 1.10.4) I could see an issue, but since it is happening on line 198 it means that your include paths are referring to paths that are not valid based on the open_basedir configured for your site.

One of your default include paths is {{/usr/share/pear}}, but that is not in your {{open_basedir}} restriction. Adding {{/usr/share/pear}} to your open_basedir should eliminate three (nearly half) of the warnings you listed.

Also, your {{include_path}} begins with a path separator, which means that when ZF tries resolving relative paths using your include_path setup, it will turn them into absolute paths.

For example, when attempting to locate {{Zend_View_Helper_HeadTitle}}, the {{Zend_Loader}} instance will call {{$this->isReadable('Zend/View/Helper/HeadTitle.php')}}. When it does, the first iteration of the loop inside the method will look like this:


190:        foreach (self::explodeIncludePath() as $path) { // $path = '', $filename = 'Zend/View/Helper/HeadTitle.php'
191:            if ($path == '.') {                         // false; skip this block; go to line 197
192:                if (is_readable($filename)) {
193:                    return true;
194:                }
195:                continue;
196:            }
197:            $file = $path . '/' . $filename;            // $file = '' . '/' . 'Zend/View/Helper/HeadTitle.php';
198:            if (is_readable($file)) {                   // is_readable('/Zend/View/Helper/HeadTitle.php') ---> WARNING!!!!
199:                return true;
200:            }
201:        }

{panel:title=Warning|borderStyle=solid|borderColor=#ccc|titleBGColor=#F7D6C1|bgColor=#FFFFCE}Warning: is_readable() [function.is-readable]: open_basedir restriction in effect. File(/Zend/View/Helper/HeadTitle.php) is not within the allowed path(s): (/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php) in /usr/local/share/ZendFramework/1.10.4/library/Zend/Loader.php on line 198{panel}

I'm not sure about the three remaining paths it is testing:

/lib/include/KD/View/Helper/HeadTitle.php
/lib/modules/default/views/helpers/Helper/HeadTitle.php
/lib/include/DP/View/Helper/HeadTitle.php

However, I suspect these are also warnings that result from trying to locate relative paths ( {{KD/View/Helper/HeadTitle.php}}, {{default/views/helpers/Helper/HeadTitle.php}}, and {{DP/View/Helper/HeadTitle.php}} ) that get converted to absolute paths as demonstrated above.

I think if you do three things:

1) Set your default include path to {{/usr/share/php:/usr/share/pear}} instead of {{:/usr/share/php:/usr/share/pear}} 2) Set {{php_admin_value open_basedir "/var/www/www_domain_com/www:/tmp:/usr/local/share/ZendFramework:/usr/share/php:/usr/share/pear"}} in your VirtualHost config 3) Change this block so that your include_path does not begin with an empty path:


set_include_path(
    '/usr/local/share/ZendFramework/1.10.4/library/' . PATH_SEPARATOR . 
    $_SERVER['DOCUMENT_ROOT'] . '/lib/modules/default/models/' . PATH_SEPARATOR . 
    $_SERVER['DOCUMENT_ROOT'] . '/lib/modules/software/models/' . PATH_SEPARATOR . 
    $_SERVER['DOCUMENT_ROOT'] . '/lib/modules/bijlage/models/' . PATH_SEPARATOR . 
    $_SERVER['DOCUMENT_ROOT'] . '/lib/include/' . PATH_SEPARATOR . 
    get_include_path()  // this works as long as your default include_path is not empty
);

most (if not all?) of these warnings will go away.

Or you could (as Matthew originally suggested, and Christian most recently mentioned) simply remove the open_basedir requirement.

Thanks a bunch! After changing all paths to their absolute value all problems were solved.

I have found another issue to this problem (it seems to be the same but shorter).

Just replace ZF default paths configuration in your index.php file by :

set_include_path( APPLICATION_PATH.'/../library'.PATH_SEPARATOR. APPLICATION_PATH.'/../library/Zend' );

Now the path to application/Zend/Views/Helpers... is readable!

@dvdgssm The default include path generated by Zend_Tool (zf) should be sufficient. Adding library/Zend to the include path doesn't make sense. Anyway, please open a new ticket instead of commenting in a resolved ticket if you think this is a bug that needs to be fixed. Thanks