Preventing crash in user-written includes() - php

Consider the following code:
try {
include_once "malformedFile.php";
} catch(Exception $e) {
return null;
}
I have no way to ensure that the file malformedFile.php is valid PHP code, won't crash or won't call die(). How can I continue onto the catch even if malformedFile.php dies or crashes? My interest is to make the application as robust as possible while still allowing users to implement their own plugins via includes.
Thanks.

Unfortunately, you cannot. If the included code causes a fatal error (e.g. bad syntax) you 're dead in the water.
What you could try is loading the file manually and then calling eval:
$code = file_get_contents("malformedFile.php");
eval($code);
Of course this is something you should think thrice before doing because as we all know eval is evil etc.
The most robust option would be to spawn another process that does the include for you (so if it dies unexpectedly no big deal), but communicating between the parent and child processes will be much harder than just having one process.

Include will include source, no way around it.
Maybe you can call this file as an external process and just use the results. This could be done like a CLI script or with a separate CURL call.

Related

Most efficient way of writing a (To File) logger in PHP?

Hopefully someone here can help me out - basically I have a logging class that I'm updating (Made it ages ago), and I want to make sure it logs messages under 98-99% of circumstances. However right now it doesn't handle exit()s, it basically just writes to a file (Opening, writing, and closing) every time a message/error is sent to the logger.
What would be the best way to handle exit()s, and be efficient in terms of disk writes? Right now I'm looking at __destruct in the logger class (With fopen, fwrite, and fclose being called in it), however I'm not quite sure if this is safe, or efficient.
Edit: What about set_error_handler()? I remember reading years ago that this was very slow and not very good for custom errors/messages (Like SQL issues)
If you wish to log something when your script ends, you should take a look at PHP's register_shutdown_function():
function shutdown()
{
// .. log code here.
}
register_shutdown_function('shutdown');
You should avoid using the __destruct() method as there is no guarantee that it will be called when you expect it to be called.
You could also take a look at PHP's built in error_log() method to write the contents to the actual PHP error log file (this is possibly more reliable than writing your own logger).
References:
http://php.net/manual/en/function.register-shutdown-function.php
http://php.net/manual/en/function.error-log.php
I always use some global function, e.g.
function BeforeExit () {
//do stuff like logging
exit;
}

Errors when calling exit() function for fastCGI?

I've been reading that people face problems when using the exit function in their php script while running fastCGI
https://serverfault.com/questions/84962/php-via-fastcgi-terminated-by-calling-exit
http://php.net/manual/en/function.exit.php
"It should be noted that if building a site that runs on FastCGI, calling exit will generate an error in the server's log file. This can quickly fill up."
However my error log isn't reporting this problem after running this simple script even though I have fastCGI configured:
<?php
$num=2;
if($num==2){
exit();
}
?>
Would it be safe to use the exit function while I have fastCGI configured? And are there any alternatives to the exit function in php?
EDIT: I'm using the exit() function form form validation (ie if a form is valid exit, if not parse all the posted variables into the text fields.)
There are a few legitimate reasons to use exit() which is the same as die(). One example would be to follow a header Location: redirect.
Form validation is not the place to use die(). Structure your code so that you utilize functions or classes with methods that return values instead, and utilize branching logic.
In terms of fastcgi, if exit is used appropriately for situations where code is reached that should not be, then those situations will be atypical and a few log messages should not be a problem. Having a log file fill up seems a pretty silly reason not to do something -- an active webserver is logging every request and nobody argues that you shouldn't have a web log.
There's a really nice alternative to exit() posted on the exit() man page by
"dexen dot devries at gmail dot com":
If you want to avoid calling exit() in FastCGI as per the comments
below, but really, positively want to exit cleanly from nested
function call or include, consider doing it the Python way:
define an exception named `SystemExit', throw it instead of calling
exit() and catch it in index.php with an empty handler to finish
script execution cleanly.
<?php
// file: index.php
class SystemExit extends Exception {}
try {
/* code code */
}
catch (SystemExit $e) { /* do nothing */ }
// end of file: index.php
// some deeply nested function or .php file
if (SOME_EXIT_CONDITION)
throw new SystemExit(); // instead of exit()
?>

How to halt execution of current PHP script?

I'm writing some simple PHP to back up a microsite. In my controller, I have a quick security/sanity check
if(!preg_match('/^[a-z]$/i', $req)) { gohome(); }
I'd like to continue my the main code after this, but for aesthetics, I'd like to avoid putting the rest of it inside the else block. What's the best way around this? I can think of setting up a fairly simple wrapper to handle authentication and security logic, but I feel like I just missed a really simple solution in my training.
You can use the die/exit function to end the script with (or without) an error.
You could
return gohome();
or
throw new Exception('Request may only contain letters');
Either will stop the execution of that particular script at that point.
If this is in a function, you can usually just return early.
Try the following.
preg_match('/^[a-z]$/i', $req) or die("exit message here, if you'd like");
It's no better functionally than Xavier's but I just like the syntax/idea of "do this or DIE" :) Also kind of makes me think of those old Nintendo games Skate Or Die and Ski Or Die.
exit() is a pretty good way to terminate the current script...
if(!preg_match('/^[a-z]$/i', $req)) { gohome(); exit() }
I prefer to keep exit()/die() calls in the main flow. Or as Phil suggests, throw an Exception and exit() somewhere lower in the stack
You can quite simply just write;
return;
The command will return program control to the calling script, so;
If linear code in an included PHP file, the control will return to the script that invoked the running of that file.
If in a function (or object method) the function will immediately return the argument if supplied, and null if not.
It will not stop the running of the script completely (you need to use exit or die for that) unless there is no calling script.
So in your case;
if(!preg_match('/^[a-z]$/i', $req))
{
gohome();
return;
}
and the else block is not required since it will only continue the script if the condition returns false.

php OOP Exceptions or die()?

I am developing some project. And I want to control different errors. I know that in all popular frameworks and php projects there are different Exceptions. But I think that is not required work. If the error is occured we can make die() with our message.
1. What are the main pluses of Exceptions?
2. Can I control my errors with die()?
Thank you.
Well, you could use die(). But that makes all errors fatal. Meaning that you cannot try to recover from the error at all. In some cases that's fine to do.
But in most cases, you may want the ability to "clean up" after the error, or to try another method. This is where exceptions come in handy... They let you chose where and if you want to handle the error. They let you try to gracefully recover from the errors.
For example, let's say you have a method which downloads a file from a remote server: downloadFromRemoteServer($address);
If you use die(), if the download fails, the script terminates. End of story.
But if you use exceptions, you could try another server or even try a different method (HTTP vs FTP, etc):
try {
$file = downloadFromRemoteServer('http://example.com/foo');
} catch (DownloadFailedException $e) {
try {
$file = downloadFromRemoteServer('http://secondtry.example.com/foo');
} catch (DownloadFailedException $e2) {
die('Could not download file');
}
}
return $file;
But remember that Exceptions are useful only for exceptional circumstances. They are not meant to be used for any possible error. For example, if a user doesn't verify their email address correctly, that's not exceptional. But if you can't connect to the database server, or have a conflict in the DB, that would be an exception circumstance...
Alexander,
die() and Exceptions accomplish different things.
the "die" language construct just halts the execution of a script and possibly outputs the parameters if it has been called like a function.
On the other hand, exceptions are more advanced structures that are used in OOP contexts to give the developer more flexibility as to whether a script needs to be stopped and if so, in what manner, what output to be shown to the user etc.
Exceptions are a little bit more complex than this so you should perhaps document yourself with some OOP first or for that matter read about zend framework and you'll get a grasp of what Exceptions are.
For simple stuff though, you can always use exit (or die, which is the same thing).
I hope this helps,
Slavic
1 What are the main pluses of Exceptions?
The main advantages are:
failing functions don't have to pollute their return with error conditions
typed exceptions can be handled at appropriate levels in the code, you decide which portion of the code can handle which errors
you can store a lot more information about the error condition in the exception itself, making handling it, and possibly recovering from it, easier.
2 Can I control my errors with die()?
I'd hardly call it control, I'd call it giving up on actually handling an error. At no point in my projects is a die() actually user-friendly, and all those die('...some error condition...'); examples of PHP code are IMHO only suited for projects in development. In production, you'll want your users to be able to continue their tasks / programs in the easiest way possible, so a 'try again' (if error condition is not likely to be met again), 'sorry that doesn't work' / other kinds of messages, forms / pages are all more desirable then die().

Can PHP tell when the browser goes away?

If I'm generating a stream of data to send out to a browser, and the user closes the browser, can I tell within PHP that I don't need to bother generating or sending the rest of the stream? I'd like to insert something into this loop:
while (!feof($pipes[1])) {
echo fgets($pipes[1]);
}
My fallback plan is to have the browser use a JavaScript onunload to hit another PHP page to kill the process that's generating the data, but it would be cleaner if PHP could tell when I'm echoing to nowhere.
By default PHP will abort the script if the user navigates away. There are however times where you don't want this to happen so php has a config you set called ignore_user_abort.
http://php.net/manual/en/misc.configuration.php
There's also a function called register_shutdown_function() that is supposedly executed when execution halts. I've never actually used it, so I won't vouch for how well it works, but I thought I'd mention it for completeness.
I believe that script will automatically abort when loaded normally (No ajax). But if you want to implement some sort of long polling via php using xmlhttprequest I think you will have to do it with some sort of javascript because then php can't detect it. Also like to know the precise case.
These answers pointed me towards what I was looking for. The underlying process needed special attention to kill it. I needed to jump out of the loop. Thanks again, Stack Overflow.
while (!feof($pipes[1]) && !connection_aborted())
{
echo fgets($pipes[1]);
}
if (connection_aborted())
{
exec('kill -4 '.$mypid);
}

Categories