Prevent internal error on false from file_get_contents - php

I would like to use the following to detect if a file exists, however there is a warning triggered when when this is the case. It works fine when file_get_contents does not return false.
$nothing = "http://www.google.com/bababababa.doc";
if (false === file_get_contents($nothing,0,null,0,1)) {
echo "File Not Found";
} else {
echo "File Found";
}

First, I'll assume that you only want to hide this error from your logs, because of course you have display_errors turned off on a production server.
You could just hide your errors away with the # error suppression operator, but that's a bad road to start down. Instead you want to define an error handler:
<?php
// define the custom handler that just returns true for everything
$handler = function ($err, $msg, $file, $line, $ctx) {return true;}
$nothing = "http://www.google.com/bababababa.doc";
// update the error handler for warnings, keep the old value for later
$old_handler = set_error_handler($handler, E_WARNING);
// run the code
$result = file_get_contents($nothing);
// go back to normal error handling
set_error_handler($old_handler);
if (false === $result) {
echo "File Not Found";
} else {
echo "File Found";
}

Related

PHP How can I suppress errors thrown by file_get_contents?

Trying to suppress errors for file_get_contents ONLY but neither of these methods work.. is there another way?
$data=#file_get_contents('invalid');
try { $data=#file_get_contents('invalid'); } catch($e Exception) { echo "error"; }
Fix problems, don't hide them.
Errors, Warnings, and Notices, should be fixed rather hidden ("supressed").
For your case, all you need do is a check for is_readable.
function getFile(string $filename = 'invalid')
{
if (!is_readable($filename)) {
return false;
}
return file_get_contents($filename);
}
$fileContents = getFile('maybevalid');
if (false !== $fileContents) {
// success
} else {
// couldn't read
}

PHP imap_reopen no error returned

I have a script that connects to a mailbox.
I'd like to check if I can connect to a folder that does not exist, but imap_reopen does not return errors.
<?php
$imap_url = "{mybox.mail.box:143}";
$mbox = imap_open($imap_url, "Mylogin", "Mypassword");
if ($mbox == false) {
echo "Opening mailbox failed\n";
}
$submbox = imap_listmailbox($mbox, $imap_url, "*");
if ($submbox == false) {
echo "Listing sub-mailboxes failed\n";
}
else {
foreach ($submbox as $name) {
echo $name . PHP_EOL;
}
}
$test = imap_reopen($mbox, $imap_url . "INBOX.MBOX3") or die(implode(", ", imap_errors()));
if ($test == false) {
echo "Opening submbox failed\n";
}
?>
Script output :
{mybox.mail.box:143}.INBOX
{mybox.mail.box:143}.INBOX.MBOX1
{mybox.mail.box:143}.INBOX.MBOX2
PHP Notice: Unknown: Mailbox does not exist (errflg=2) in Unknown on line 0
Do you have an idea ?
Regards,
Stiti
Your statement ending with or die() is actually terminating execution before the if test against the return value in $test.
$test = imap_reopen($mbox, $imap_url . "INBOX.MBOX3") or die(implode(", ", imap_errors()));
// This code is never reached because of die()!
if ($test == false) {
echo "Opening submbox failed\n";
}
So just remove the or die() expression and your if ($test == false) will be evaluated. I'll also use === here since it should return a true boolean:
// Call imap_reopen() without (or die())
$test = imap_reopen($mbox, $imap_url . "INBOX.MBOX3");
if ($test === false) {
echo "Opening submbox failed\n";
}
You may alternatively use
if (!$test) {
echo "Opening submbox failed\n";
}
Note about the PHP E_NOTICE emitted - if imap_reopen() emits that notice even when returning false, this is one instance in which you may want to use the # operator for error suppression since you are correctly testing for errors in your if block.
// # is not usually recommended but if imap_reopen()
// prints an E_NOTICE while still returning false you can
// suppress it with #. This is among the only times it's
// a good idea to use # for error suppresssion
$test = #imap_reopen($mbox, $imap_url . "INBOX.MBOX3");
if (!$test) {...}
Addendum after testing:
Documentation on imap_reopen() is slim and ambiguous stating its return as:
Returns TRUE if the stream is reopened, FALSE otherwise.
Some testing seems to imply that opening a non-existent mailbox is not considered an error state for which it returns false. When opening a non-existent mailbox on an otherwise valid stream, imap_reopen() will still return true but populate an error in imap_errors().
So you may check count(imap_errors()) > 0 for errors after opening the faulty mailbox. Couple that with a true return check, in case imap_reopen() does return a true error state.
For example my testing produces results similar to:
$test = imap_reopen($mbox, $imap_url . "NOTEXIST");
var_dump($test);
// bool(true);
var_dump(imap_errors()); array(1) {
[0] =>
string(28) "Mailbox doesn't exist: NOTEXIST"
}
You may work around this using logic to:
$test = #imap_reopen($mbox, $imap_url . "INBOX.MBOX3");
if (!$test) {
// An error with the stream
}
// Returns true, but imap_errors() is populated
else if ($test && count(imap_errors()) > 0) {
echo "Opening submbox failed\n";
// Do something with imap_errors() if needed
echo implode(',', imap_errors());
}
else {
// Everything is fine - the mailbox was opened
}
For what it's worth, imap_open() exhibits the same behavior. Successfully connecting and establishing the stream (your variable $mbox) is possible with a non-existent mailbox. The stream is created and valid, but imap_errors() will contain a message Mailbox doesn't exist: <mailbox>.

Upload Image via URL

Code:
if(isset($_POST['update_avatar'])) {
$url = $_POST['avatar'];
$info = getimagesize($url);
if(isset($info['name'])) {
echo "Exists";
} else {
echo "Error";
}
}
How can I avoid getting PHP errors when the user types an invalid URL, random piece of text or invalid image URL etc?
Use exception handling. Place your critical code into a try..catch block. You can find more information here.
If there's an error, getimagesize returns false, so test for that. And to suppress error messages from a function, put # before it:
$info = #getimagesize($url);
if (!$info) {
echo "Error";
} else {
// Process the image
}

Can I call die after echo with PHP?

I'm trying to add some error checking inside my PHP script. Is it valid to do this:
if (!mkdir($dir, 0)) {
$res->success = false;
$res->error = 'Failed to create directory';
echo json_encode($res);
die;
}
Is there a better way to exit the script after encountering an error like this?
That looks fine to me.
You can even echo data in the die like so:
if (!mkdir($dir, 0)) {
$res->success = false;
$res->error = 'Failed to create directory';
die(json_encode($res));
}
Throwing a exception. Put code into a try catch block, and throw exception when you need.
PHP has functions for error triggering and handling.
if (!mkdir($dir, 0)) {
trigger_error('Failed to create directory', E_USER_ERROR)
}
When you do this the script will end. The message will be written to the configured error log and it will also be displayed when error_reporting is enabled.

Handle error when getimagesize can't find a file

when I'm trying to getimagesize($img) and the image doesn't exist, I get an error. I don't want to first check whether the file exists, just handle the error.
I'm not sure how try catch works, but I want to do something like:
try: getimagesize($img) $works = true
catch: $works = flase
Like you said, if used on a non-existing file, getimagesize generates a warning :
This code :
if ($data = getimagesize('not-existing.png')) {
echo "OK";
} else {
echo "NOT OK";
}
will get you a
Warning: getimagesize(not-existing.png) [function.getimagesize]:
failed to open stream: No such file or directory
A solution would be to use the # operator, to mask that error :
if ($data = #getimagesize('not-existing.png')) {
echo "OK";
} else {
echo "NOT OK";
}
As the file doesn't exist, $data will still be false ; but no warning will be displayed.
Another solution would be to check if the file exists, before using getimagesize ; something like this would do :
if (file_exists('not-existing.png') &&
($data = getimagesize('not-existing.png'))
) {
echo "OK";
} else {
echo "NOT OK";
}
If the file doesn't exist, getimagesize is not called -- which means no warning
Still, this solution is not the one you should use for images that are on another server, and accessed via HTTP (if you are in this case), as it'll mean two requests to the remote server.
For local images, that would be quite OK, I suppose ; only problem I see is the notice generated when there is a read error not being masked.
Finally :
I would allow errors to be displayed on your developpement server,
And would not display those on your production server -- see display_errors, about that ;-)
Call me a dirty hacker zombie who will be going to hell, but I usually get around this problem by catching the warning output into an output buffer, and then checking the buffer. Try this:
ob_start();
$data = getimagesize('not-existing.png');
$resize_warning = ob_get_clean();
if(!empty($resize_warning)) {
print "NOT OK";
# We could even print out the warning here, just as PHP would do
print "$resize_warning";
} else {
print "OK"
}
Like I said, not the way to get a cozy place in programmer's heaven, but when it comes to dysfunctional error handling, a man has to do what a man has to do.
I'm sorry that raise such old topic. Recently encountered a similar problem and found this topic instead a solution. For religious reasons I think that '#' is bad decision. And then I found another solution, it looks something like this:
function exception_error_handler( $errno, $errstr, $errfile, $errline ) {
throw new Exception($errstr);
}
set_error_handler("exception_error_handler");
try {
$imageinfo = getimagesize($image_url);
} catch (Exception $e) {
$imageinfo = false;
}
This solution has worked for me.
try {
if (url_exists ($photoUrl) && is_array (getimagesize ($photoUrl)))
{
return $photoUrl;
}
} catch (\Exception $e) { return ''; }
Simple and working solution based on other answers:
$img_url = "not-existing.jpg";
if ( is_file($img_url) && is_array($img_size = getimagesize($img_url)) ) {
print_r($img_size);
echo "OK";
} else {
echo "NOT OK";
}

Categories