Search code examples
phpzend-frameworksafe-mode

PHP Safe Mode Restriction for Zend Framework


I want to upload a Zend Framework Project to a site where "safe_mode" is on and I can't controll it.

I get the following warning message from PHP:

PHP Warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid/gid is 954/815 is not allowed to access /tmp owned by uid/gid 0/0 in /blabla/phpapps/include/library/Zend/Cache/Backend.php on line 185

I don't use Zend_Cache, so why is safe_mode angry about my script?

How do I set a default /tmp directory in my project to avoid this error?

thx


Solution

  • I don't use Zend_Cache, so why is safe_mode angry about my script?

    Because Zend_Cache is also used internally from some other ZF components (Zend_Db, Zend_Translate and so on).

    How do I set a default /tmp directory in my project to avoid this error?

    You have two choices here:

    1. Track down what component uses Zend_Cache and configure it to use a custom instance of cache with a defined backend which doesn't use /tmp storage (check for Apc or Memcached)
    2. Look at Zend_Cache_Backend implementation near line 185 and update your code to avoid that error.

    I would choose option 1 for better performances (apc or memcached are faster storage than filesystem) and for having more control on what's happening in your project. However this could require more than one change for your project, because there could be more than one component which need to be configured.

    If you choose option 2 you could hack the whole thing with a single change and it will reflect all the components which uses a default cache instance, but since your hacking your code to work with an internal implementation future releases of ZF could break your code. That said you could achieve this by defining an ENV or SERVER variable with one of the keys that ZF checks for. These are the lines before where your warning is raised:

    public function getTmpDir()
    {
        $tmpdir = array();
        foreach (array($_ENV, $_SERVER) as $tab) {
            foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
                if (isset($tab[$key])) {
                    if (($key == 'windir') or ($key == 'SystemRoot')) {
                        $dir = realpath($tab[$key] . '\\temp');
                    } else {
                        $dir = realpath($tab[$key]);
                    }
                    if ($this->_isGoodTmpDir($dir)) {
                        return $dir;
                    }
                }
            }
        }
    

    So a code like this in the bootstrap will solve your issue:

    // I assume you're using the default ZF project structure
    // and that your-root/data/tmp is both writable and readable for
    // the webserver user, because the _isGoodTmpDir method will check for that
    $_SERVER['TMP'] = APPLICATION_PATH . '/../data/tmp';