Check if open_basedir restriction is in effect - php

I'm getting the following warning when using PHPass (http://www.openwall.com/phpass/):
open_basedir restriction in effect. File(/dev/urandom) is not within the allowed path(s)
Although this is not a big problem (it will fall back on something else), I'd like not to have this warning. The PHP application should run on different servers, some users will be able to add that path to their allowed open_basedir paths, but others won't have access to that configuration.
My first guess was to check readability with is_readable(), however, I'm still getting the warning.
The question: How do I check if a certain path or file has been added to the open_basedir paths?

You can read the value of PHP directives with the ini_get() function:
ini_get('open_basedir')
If the directive's not empty, it should contain a string with one ore more paths separated by PATH_SEPARATOR.

You can use is_readable and disable the warning for this function with a #.
If is_readable returns false then you know that it's not readable.
$readable = #is_readable(..);
if(!$readable) {
....not readable
}

file_exists emits a warning if directory is restricted. Let's use it:
function isRestricted($path)
{
// Default error handler is required
set_error_handler(null);
// Clean last error info. You can do it using error_clean_last in PHP 7.
#trigger_error('__clean_error_info');
// Testing...
#file_exists($path);
// Restore previous error handler
restore_error_handler();
// Return `true` if error has occured
return ($error = error_get_last()) && $error['message'] !== '__clean_error_info';
}

Related

How to display those errors which are disabled by #-operator - Error Control Operators?

I am using some external libraries which uses the # error silencing operator.
The library is generating some errors and it becomes difficult to point the exact location where the error occurs as the # operator hides it.
Is there any way to easily disable the #-operator in the code without making any actual changes to the code?
I have tried Scream Pecl extension but it does not seem to work. It's available for PHP 5.6 version while I am using PHP 7.
Scream extension is installed and is enabled in php.ini by using scream.enabled=1 (as per their documentation) but the error still doesn't show or log.
You cannot disable the behaviour of the # symbol, but you can log/handle these errors nonetheless by using your own error handler.
From the docs:
If you have set a custom error handler function with set_error_handler() then it will still get called,
What this operator does is basically set error_reporting to 0 for one statement. Which is also reflected on the same docs:
but this custom error handler can (and should) call error_reporting() which will return 0 when the call that triggered the error was preceded by an #.
So, assuming you could have something like this very simple implementation, you would need to fine tune the details:
function exceptional_error_handler($severity, $message, $file, $line)
{
if (error_reporting() === 0) {
// assuming your application always runs with `error_handling !== 0`,
// e.g. by setting this during application bootstrap
// that we got here means this is was a "silenced" error
throw new \ErrorException("Silenced error! '$message'", 0, $severity, $file, $line);
}
// regular (non-silenced) errors should respect your error_reporting levels
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
}
// everything else is converted to an exception
throw new \ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exceptional_error_handler");
This converts all errors to exceptions, simply noting with a different message when it was a "silenced" error, but your error handler could do logging or have any kind of custom logic.
By doing this, you could leave the existing/third party code untouched, and just add the error handling logic to the bootstrapping part of your application.
Docs for set_error_handler().

Hide copy warnings in PHP

I know it's not a good practice to hide the warnings using #copy, but what other alternatives are there?
Is there any way you can make sure copy would work or not ?
Use is_readable() and is_writable() to check the status of the source and target before attempting the copy().
Really, you should not be displaying errors to the browser. Turn off display_errors in php.ini.
Then you can test if it succeeded by its boolean return value, without needing to worry about the warnings on screen.
if (!copy('srcfile', 'destfile')) {
// something failed.
}
If you use '#' before a function you'll not the warning or the notice returned but you'll keep the result (boolean, string...).
Try this :
if (!#copy('srcfile', 'destfile')) {
// something failed.
}

Avoid DOMDocument XML warnings in php

I'm fetching xml files from a server and sometimes I'm getting a non-valid xml files, because of this I'm getting a warning:
Warning: DOMDocument::load() [domdocument.load]: Start tag expected, '<' not found in
How can I catch this warning and delete the file?
You have two choices. Either use the # error control operator in your load() call, e.g. #$dom->load(), which is somewhat slow because it globally changes the value of display_errors to off, executes the function and sets it back to on.
The other option, which I personally prefer (I hate the # operator, I can't stand to see it in my code) is to save the old value of libxml_use_internal_errors, enable it using libxml_use_internal_errors(TRUE), call the function, clear the errors buffer and restore the old value. Here's a snippet from my code that does that:
<?php
$previous_value = libxml_use_internal_errors(TRUE);
$doc->loadHTML((string)$e->response->getBody());
libxml_clear_errors();
libxml_use_internal_errors($previous_value);
I can't comment on answers yet, so I'll write it here:
Michael solution makes it less strict, but it'll still issue warnings for some of the errors:
nadav#shesek:~$ php -r '$dom=new DOMDocument; $dom->strictErrorChecking = FALSE ; $dom->loadHTML("<xy></zx>");'
PHP Warning: DOMDocument::loadHTML(): Tag xy invalid in Entity, line: 1 in Command line code on line 1
DON'T do what Fran Verona suggested - globally disabling error reporting is something you should never do. In production, set your own error handler and display a prettier message to the user, and make sure the error is logged somewhere - but never disable it completely. Setting error_reporting to 0 will cause PHP to disable error logging too.
Xeon06 solution is problematic because you're effecting the entire script error handler for a specific piece of code. Using your own error handler that simply ignores the error causes the same issues as Fran's solution.
Use set_error_handler.
set_error_handler("yourHandler", E_WARNING);
Turn off strict error checking:
$dom = new DOMDocument();
$dom->strictErrorChecking = FALSE ;
$dom->load('/path/to/file.xml');
if (!$dom->validate()) {
// Invalid XML!
}

How to make smarty output debug info when template fails to compile?

I'm already set its debugging option to true,but when there's error in smarty template(i.e. there is no corresponding plugin for a specific smarty_modifier),nothing is output for information.
UPDATE
For anyone that wants to have a try,this is the most simple template I can think of :
{$var|nosuch_modifier}
1- First, you can check if error_reporting is on. this is usually done in php.ini but you can place these statements on top of your php source.
ini_set('display_errors', 1);
ini_set('error_reporting', E_ALL);
and make sure it is not disabled elsewhere.
2- smarty may report errors as throwing an exception. You can define a global exception handler to catch them, here is an example;
try {
// place your code here
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Update upon comments:
The only reason I can think of is that you've set compile_check to false.
$tpl->compile_check = false;
In this case, Smarty will show the latest compiled source, whatever you do to the tpl file. So, did you check and set compile_check to true?
$tpl->compile_check = true;
Try
ini_set('display_errors', true);
error_reporting(E_ALL);
in the PHP code.
Smarty error reporting can be set manually.
$smarty->error_reporting = E_ALL ^ E_NOTICE;
Some comments from the Smarty.class.php
error muting is done because some people implemented custom
error_handlers using http://php.net/set_error_handler and for some
reason did not understand the following paragraph:
It is important to remember that the standard PHP error handler is
completely bypassed for the error types specified by error_types
unless the callback function returns FALSE. error_reporting() settings
will have no effect and your error handler will be called regardless -
however you are still able to read the current value of
error_reporting and act appropriately. Of particular note is that this
value will be 0 if the statement that caused the error was prepended
by the # error-control operator.
Smarty deliberately uses #filemtime() over file_exists() and
filemtime() in some places. Reasons include
- #filemtime() is almost twice as fast as using an additional file_exists()
- between file_exists() and filemtime() a possible race condition is opened, which does not exist using the simple #filemtime() approach.

How to suppress error if an argument is missing in a function call?

I made a function like this (no need to write the whole function here) :
public function selectNode($from, $attributes = null, $childs = null)
and, of course, if I call it this way :
$node->selectNode();
The argument $from isn't initialized and then you got a warning error.
I know you can suppress the error doing #$node->selectNode(); or something like that thanks to #.
But, I want to handle it myself. How can I do that if that's possible?
The only way I found is to initialize it like this public function selectNode($from = null, $attributes = null, $childs = null) but that doesn't make it clear ($from is not an option as the others).
(And, of course, this function, here, is just an example. It could be extended to other functions)
How come you can miss a required parameter? It is not a file or an outside variable! You will get this error just by trying to call this script. It is like parse error. What to handle here?
It's development phase error. It just needs to be corrected, not handled.
Anyway, you are doing it wrong.
Never add intentional errors to your code.
Language's error reporting mechanism is for handling unexpected errors, not intentional ones.
If you expect an error here - handle it yourself. Don't make PHP to raise error
So, make it $from = null,, yes. And then handle this null whatever you want.
Surely if the $from parameter is not required you should assign it a default variable so it's optional and then do checking based on this.
It would probably be most elegant to just check if $from isset in the code before you reference it and supply it with null as default in the parameters, isset will return false from a null value.
I guess you've got display_errors set to on in php.ini and now these warnings are popping up on your screen and you don't want to see them popping up anymore? If that's the case, then change your php.ini :
display_errors = Off
log_errors = On
error_log = /path/to/php-error.log
Errors will then be logged to the file you specified in error_log, and won't show up on your screen anymore.
You could use a try-catch block handling the error yourself.
try {
$node->selectNode();
}
catch (Exception $e){
echo $e; // do whatever you like here with error info $e, if you leave the parenthesis empty here nothing is done and the error message is suppressed
}
Are you looking for the following (or one of its variants)?
<?php error_reporting(0); ?>

Categories