3

I've recently gotten an error when I deployed an application. It used "is_readable" on a path within the include path, but one that was restricted by "open_basedir". This gave me a fatal error. Is there another function that I could use to see if a file is includable, before actually including it?


Edit: this works, but how do I detect if the error was because the include failed or because of some error inside the included file?

try {
 include 'somefile.php';
 $included = true; 
} catch (Exception $e) {
 // Code to run if it didn't work out
 $included = false;
}
Bart van Heukelom
  • 43,244
  • 59
  • 186
  • 301
  • If your framework throws everything as an exception as you commented below, you can go into the error handler function and check what the $severity of the error generated is. Or set up your own on top. There's really no limit to the number of custom error handlers you can use. – Jan Gorman Sep 28 '09 at 21:30
  • In fact you can even get the severity from the ErrorException itself, but how does that help me detect if the actual include caused the error? – Bart van Heukelom Sep 28 '09 at 21:33

3 Answers3

2

You could 'try' this ;)

<?php

function exceptions_error_handler($severity, $message, $filename, $lineno) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
set_error_handler('exceptions_error_handler');
try {
    include 'somefile.php';
    $included = true;
} catch (Exception $e) {
    // Code to run if it didn't work out
    $included = false;
}
echo 'File has ' . ($included ? '' : 'not ') . 'been included.';
?>

If it doesn't work, $included will be set to true, and then to false in the catch. If it did work, $included remains true.

James Hall
  • 7,507
  • 2
  • 22
  • 15
  • 2
    Nice try :p, but a false include does not throw an exception but a classic error. – Bart van Heukelom Sep 28 '09 at 16:02
  • Ahh yes. I once used an error handler that threw PHP errors into exceptions. function exceptions_error_handler($severity, $message, $filename, $lineno) { throw new ErrorException($message, 0, $severity, $filename, $lineno); } set_error_handler('exceptions_error_handler'); No idea if that's a good idea though. – James Hall Sep 28 '09 at 16:23
  • Infact, the framework I use throws all standard PHP errors as exceptions. – James Hall Sep 28 '09 at 16:32
  • My framework (to which this question applies) does that as well. I thought that the error wouldn't be catchable, but of course, it is. – Bart van Heukelom Sep 28 '09 at 17:40
1

You can check the value of the open_basedir rescriction (if set) using

ini_get( 'open_basedir' );

It will return the allowed path(s) or an empty string if not set.

Edit:

Checking the include path in a open_basedir restriction safe way could go something like this:

if ( strlen( ini_get( 'open_basedir' ) ) > 0 )
{
    $includeFile = 'yourInclude.php';
    $includePath = dirname( realpath( $includeFile ) );

    $baseDirs = explode( PATH_SEPARATOR, ini_get( 'open_basedir' ) );
    foreach ( $baseDirs as $dir )
    {
        if ( strstr( $includePath, $dir ) && is_readable( $includeFile ) )
        {
            include $includeFile;
        }
    }
}

But feel free to improve upon this if you see a shortcut.

Jan Gorman
  • 1,004
  • 2
  • 11
  • 16
  • Yes, but that does tell me if a file is includable, since you can sometimes do that even with files that are outside the basedir, right? – Bart van Heukelom Sep 28 '09 at 14:39
  • The way the basedir restriction works (from my understanding) is that all files above each basedir should be at least accessible, so you would need to check if the file you're trying to include is within your basedirs, once that's done you can use is_readable without a fatal error. I'm just on my way out of the office, I can post a proper example later on if you need further help. – Jan Gorman Sep 28 '09 at 16:11
0

You could try using stat to achieve the same effect as is_readable which I hear is very buggy when base dir is set.

Neel
  • 854
  • 5
  • 7
  • 1
    The buggy behaviour of is_readable has been fixed as of PHP 5.2. For older versions it is indeed preferable to use stat – Jan Gorman Sep 28 '09 at 21:12