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>.
Related
While usign the function get_headers() for example, If i wrote
get_headers("www.websitedoesntexist.com");
i get the following error
Warning: get_headers(): php_network_getaddresses: getaddrinfo failed:
No such host is known Warning:
get_headers(www.websitedoesntexist.com): failed to open stream:
php_network_getaddresses: getaddrinfo failed: No such host is known
I want to know how to handle these problems, Something like
if (isset(get_headers("www.websitedoesntexist.com"))) {
echo "URL Exists";
}
Suppress errors on the get_headers() function. Assign get_headers to a variable. Then check the Boolean value of that variable.
$file_headers = #get_headers("www.websitedoesntexist.com");
if(!$file_headers) {
$exists = false;
}
else {
$exists = true;
}
Edit:
Based on the comments, for a better, long-term solution using curl see https://stackoverflow.com/a/36743670/4374801
From the PHP manual :
Returns an indexed or associative array with the headers, or FALSE on failure.
Which means you can test against FALSE.
Read more : http://php.net/manual/en/function.get-headers.php
Edit
If you want just to check if the URL exists or not, instead of supressing the errors I suggest you use curl, a simple function like this can do the job :
function url_exists($url) {
if (!$fp = curl_init($url)) {
return false;
}
return true;
}
if you want to check the url exist or not in php, simply code this.testing purpose
$array = get_headers('url');
$string = $array[0];
if (strpos($string, "200")) {
echo "thats cool dude";
} else {
echo "Bad request";
}
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";
}
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.
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";
}
I'm running PHP5 on Windows XP Professional. I'm trying to write a telnet php script which simply connects, sends a text string and grabs the response buffer and outputs it. I'm using the telnet class file from here:
http://cvs.adfinis.ch/cvs.php/phpStreamcast/telnet.class.php
which i found in another thread.
<?php
error_reporting(255);
ini_set('display_errors', true);
echo "1<br>";
require_once("telnet_class.php");
$telnet = new Telnet();
$telnet->set_host("10.10.5.7");
$telnet->set_port("2002");
$telnet->connect();
//$telnet->wait_prompt();
$telnet->write('SNRD 1%0d');
echo "3<br>";
$result = $telnet->get_buffer();
echo $result;
print_r($result);
// flush_now();
echo "4<br>";
$telnet->disconnect();
?>
I'm not receiving any kind of errors or response. If I send an invalid string, I should get an 'ERR' response in the least however I don't even get that. Any ideas what i could be doing wrong? If I do the same thing from the command prompt, I receive the string output I need. Could this is because the write function is sending
After some reading in the source code and on the original (french) site referred to in the header....
<?php
error_reporting(255);
ini_set('display_errors', true);
echo "1<br>";
require_once("telnet_class.php");
$telnet = new Telnet();
$telnet->set_host("10.10.5.7");
$telnet->set_port("2002");
if ($telnet->connect() != TELNET_OK) {
printf("Telnet error on connect, %s\n",$telnet->get_last_error());
}
//$telnet->wait_prompt();
if ($telnet->write('SNRD 1' . "\xd") != TELNET_OK) {
printf("Telnet error on write, %s\n",$telnet->get_last_error());
}
// read to \n or whatever terminates the string you need to read
if ($telnet->read_to("\n") != TELNET_OK) {
printf("Telnet error on read_to, %s\n",$telnet->get_last_error());
}
echo "3<br>";
$result = $telnet->get_buffer();
echo $result;
print_r($result);
// flush_now();
echo "4<br>";
$telnet->disconnect();
?>
Okay, explanation: get_buffer() does just that, read what's in the buffer. To get something in the buffer you have to execute read_to($match) who will read into buffer up to $match. After that, get_buffer should give you the desired string.
EDIT:
if you cannot find some string that follows the string you are interested in read_to will end in an error due to this part of the read_to method (translation of original french comment is mine):
if ($c === false){
// plus de caracteres a lire sur la socket
// --> no more characters to read on the socket
if ($this->contientErreur($buf)){
return TELNET_ERROR;
}
$this->error = " Couldn't find the requested : '" . $chaine . "', it was not in the data returned from server : '" . $buf . "'" ;
$this->logger($this->error);
return TELNET_ERROR;
}
Meaning that when the socket is closed without a match of the requested string, TELNET_ERROR will be returned. However, the string you're looking for should at that point be in the buffer.... What did you put in read_to's argument? "\n" like what I did or just "" ?
EDIT2 :
there's also a problem with get_buffer. IMO this class is not really a timesaver ;-)
//------------------------------------------------------------------------
function get_buffer(){
$buf = $this->buffer;
// cut last line (is always prompt)
$buf = explode("\n", $buf);
unset($buf[count($buf)-1]);
$buf = join("\n",$buf);
return trim($buf);
}
It will throw away the last line of the response, in your case the one that contains the
answer.
I suggest to add a "light" version of get_buffer to the class, like this
//------------------------------------------------------------------------
function get_raw_buffer(){
return $this->buffer;
}
and do the necessary trimming/searching in the result yourself.
You might also want to add the following constant
define ("TELNET_EOF", 3);
and change read_to like this
...
if ($c === false){
// plus de caracteres a lire sur la socket
if ($this->contientErreur($buf)){
return TELNET_EOF;
}
$this->error = " Couldn't find the requested : '" . $chaine . "', it was not in the data returned from server : '" . $buf . "'" ;
$this->logger($this->error);
return TELNET_EOF;
}
...
in order to treat that special case yourself (a result code TELNET_EOF doesn't have to be treated as an error in your case). So finally your code should look more or less like this:
// read to \n or whatever terminates the string you need to read
if ($telnet->read_to("\n") == TELNET_ERROR) {
printf("Telnet error on read_to, %s\n",$telnet->get_last_error()); } echo "3<br>";
} else {
$result = $telnet->get_raw_buffer();
echo $result;
print_r($result);
}
Have you checked how the telnet class works? Maybe it wasn't designed to run under windows. If it's a simple socket that you're speaking to, maybe consider using a regular socket-connection instead.
http://se2.php.net/sockets
If you open up a socket which you don't close, you should se an entry in netstat as long as your script is running.
netstat -na|find ":2002"
You can't insert hex values like that. The remote process just sees
SRND 1%0d
and now it's waiting for the line to be terminated. Try this
$telnet->write('SNRD 1' . "\r");
or
$telnet->write("SNRD 1\xd");
The double quotes are quite critical, see here
EDIT:
you might try adding some error reporting as right now you don't really check much (error_reporting won't show anything on the errors in the telnet class).... For example:
<?php
error_reporting(255);
ini_set('display_errors', true);
echo "1<br>";
require_once("telnet_class.php");
$telnet = new Telnet();
$telnet->set_host("10.10.5.7");
$telnet->set_port("2002");
if ($telnet->connect() != TELNET_OK) {
printf("Telnet error on connect, %s\n",$telnet->get_last_error());
}
//$telnet->wait_prompt();
if ($telnet->write('SNRD 1' . "\xd") != TELNET_OK) {
printf("Telnet error on write, %s\n",$telnet->get_last_error());
}
echo "3<br>";
$result = $telnet->get_buffer();
echo $result;
print_r($result);
// flush_now();
echo "4<br>";
$telnet->disconnect();
?>
also, are you sure you need \r\n line termination? write is defined as
function write($buffer, $valeurLoggee = "", $ajouterfinLigne = true){
and does
if ($ajouterfinLigne){
$buffer .= "\n";
}
?
Also, did you test the host and port with the command line telnet client? Like
telnet 10.10.5.7 2002
?