Display custom error page on all PHP errors and email them to administrator - error-handling

Afternoon,
I've been looking around for a while without success to see if there's a method to display a custom error page, whenever any PHP error arises, hiding the error from users - currently achieved by error_reporting(0), then emailing the specific error to my email address.
Initial logic (I know it's not right, it's just to help you understand better):
if(error_reporting){
ob_clean();
include('classes/email.php');
$email = new email($pdo);
$email->mailError(ERROR_REPORT);
include('error-page.php');
die();
}
Any help would be much appreciated, thanks!

Well, you could use a custom error handling function. See set_error_handler()
function sendMailOnError($errno, $errstr, $errfile, $errline, $errcontext) {
$subject = 'An Error Occured';
$body = "An Error Occured\n\n".
"$errstr [$errno]\n".
"File: $errfile\n".
"Line: $errline\n".
"Current local variables: ".print_r($errcontext, true);
//send the email here
}
set_error_handler('sendMailOnError');

You can define a custom error handler function, and have that show the error page, no problem.
The only difficulty with this is with errors that occur after some HTML has already been output. In most cases, you can nevertheless shove a full error page down the browser's throat, but that is horrible practice, as you would essentially output two HTML structures, one of them broken.
What I like to do in such cases is either just output a message, or output a position: fixed div that will overlay anything that has already been output.
Something like
function errorPage($errno, $errstr, $errfile, $errline, $errcontext) {
// Perform some filtering here, you don't want to die on every notice
// or deprecated warning
echo "<div style='position: fixed; left: 0px; top: 0px; bottom: 0px;'>";
// ... you get the drift... add some more styling here
echo "Error message goes here</div>";
}
set_error_handler('errorPage');
The way to show a complete, clean error page, uncluttered by any previous output, is making extensive use of output buffering, and flushing the content only if no error has occurred at the end of the page.

I'm just about to release an open source project that does this, and more. It collects errors, sends them to an issue tracker, detects duplicates, turns them into issues and emails staff.
Details are at https://sourceforge.net/news/?group_id=317819&id=293422 and the version 0.1.7 it mentions is due out in a couple of days.
The open source tracker is at http://elastik.sourceforge.net/
Any feedback welcome,
Thanks

Related

Problem with Prefix in Discord.js (including .toUpperCase())

Basically, I've been developing a bot for several weeks now using the discord.js library and recently encountered a small but crucial issue. Essentially when I declare my argument, I also made it so that the message content (message.content) would be capitalized using .toUpperCase(). Essentially in doing so regardless of the type of prefix you would enter (symbol wise) it would all be read by the program as valid.
For example only: !help - should work, however if I would enter .help, it would also be read as valid.
In any case, here's the code. I appreciate all the help!
bot.on('message', message =>{
let args = message.content.toUpperCase().substring(PREFIX.length).split(" ");
const sender = message.member;
switch(args[0])
{
case 'HELP':
message.reply("I've sent you some documentation on all the commands that you can use...").then(d_msg => {d_msg.delete(3000); });
message.delete(3000);
const attachment = new Attachment('./UtilityBot_Documentation.txt')
message.author.send('[Education] Bot - Documentation');
message.author.send(attachment);
break;
}
})
The discord.js tutorial covers an extremely similar problem to what you're trying to do. I recommend you check it out. The page I linked in specific is doing a very similar thing to you, but it's worth giving the whole thing a read through if you haven't done so already. In general, I would include the following line just above where you established args.
if (!message.content.startsWith(PREFIX)) return;
What I'm doing here is saying if the message does not start with the prefix, stop running until a new message is sent. I might be missing something, but certainly check out the tutorial. It's really well written.
https://discordjs.guide/creating-your-bot/commands-with-user-input.html#basic-arguments

Cache files always created with wrong permissions in Yii 2

I get this error in my log files every time a cache file doesn't exist it seems. On the first page load, I always get this error
[message] => filemtime(): stat failed for [...]/runtime/cache/my/myapp03eab921185f7b68bbca50d8debc0dda.bin
[file] => [...]/vendor/yiisoft/yii2/caching/FileCache.php
[line] => 113
It doesn't happen anymore on next page loads but that one time is really annoying since the slack bot watcher is spamming our channel with this useless warning. Is there a way to avoid that, or is it a permission problem?
The "runtime", "cache" and "my" folders all have 775.
Update
Turns out the issue is that I'm using error_get_last() that is also getting warning-level errors. So it's a different issue entirely, not Yii-related
Make sure that you don't have enabled scream in your php.ini. Warnings from this filemtime() call should be suppressed by # operator, but scream setting can override this operator and generate warning anyway.
if (#filemtime($cacheFile) > time()) {
// ...
}
You must be getting this in PHP 7.1. try to run this with PHP 5.5 and see if you are getting the same error.
To reproduce you need to delete all files from runtime/cache directory
Then start app again(reload page) and look into runtime/cache. It is empty
Yii2 doesn't make cache again
Got same issue in Yii. The error was on the same string (FileCache.php:113)
if (#filemtime($cacheFile) > time()) {...
In my case reason was that my custom php error handler (heir
of the class yii\base\ErrorHandler) didn't check if
error type need to be handled according error_reporting().
Custom handlers allways gets every error, even muted by Error Control operator (#)
https://www.php.net/manual/en/function.set-error-handler.php
error_reporting() settings will have no effect and your error handler will be called regardless

Casperjs "casper.test property is only available using the `casperjs test` command" but not calling casper test

The error:
casper.test property is only available using the `casperjs test` command
Searched my entire codebase for "casper.test", "this.test", "#test", etc, and none are present. Looking at the casper code, one of these needs to be triggered for this error to be raised.
The error is intermittent and only occurs on some casper runs. Has anyone else gotten this bug? I'm running 1.1.0-beta3.
You can add
phantom.casperTest = true;
at the top of the test file.
Have you launch your script like this ?
casperjs test yourScript.js
It has nothing to do with launching it. Not sure why, but I also received this error on my code before writing to file. It went away after removing...
JSON.stringify(obj);
Again, I dont know what caused the issue. And it may be something else causing it for you. But if you find which piece of code is causing it, I have a solution.
My solution:
Use a handler for errors with a basic variable switch and turn off the error log for that portion of the step.
casper.on("error", function(err) {
if(custLog) {console.log(err);} //log the error
});
and in the step...
casper.then(function() {
custLog = false;
fs.write(fileName, JSON.stringify(content), 'w');
custLog = true;
});
You may or may not need to order the reorder the inner stack there.

PHP Error handling: die() Vs trigger_error() Vs throw Exception

In regards to Error handling in PHP -- As far I know there are 3 styles:
die()or exit() style:
$con = mysql_connect("localhost","root","password");
if (!$con) {
die('Could not connect: ' . mysql_error());
}
throw Exception style:
if (!function_exists('curl_init')) {
throw new Exception('need the CURL PHP extension.
Recomplie PHP with curl');
}
trigger_error() style:
if(!is_array($config) && isset($config)) {
trigger_error('Error: config is not an array or is not set', E_USER_ERROR);
}
Now, in the PHP manual all three methods are used.
What I want to know is which style should I prefer & why?
Are these 3 drop in replacements of each other & therefore can be used interchangeably?
Slightly OT: Is it just me or everyone thinks PHP error handling options are just too many to the extent it confuses php developers?
The first one should never be used in production code, since it's transporting information irrelevant to end-users (a user can't do anything about "Cannot connect to database").
You throw Exceptions if you know that at a certain critical code point, your application can fail and you want your code to recover across multiple call-levels.
trigger_error() lets you fine-grain error reporting (by using different levels of error messages) and you can hide those errors from end-users (using set_error_handler()) but still have them be displayed to you during testing.
Also trigger_error() can produce non-fatal messages important during development that can be suppressed in production code using a custom error handler. You can produce fatal errors, too (E_USER_ERROR) but those aren't recoverable. If you trigger one of those, program execution stops at that point. This is why, for fatal errors, Exceptions should be used. This way, you'll have more control over your program's flow:
// Example (pseudo-code for db queries):
$db->query('START TRANSACTION');
try {
while ($row = gather_data()) {
$db->query('INSERT INTO `table` (`foo`,`bar`) VALUES(?,?)', ...);
}
$db->query('COMMIT');
} catch(Exception $e) {
$db->query('ROLLBACK');
}
Here, if gather_data() just plain croaked (using E_USER_ERROR or die()) there's a chance, previous INSERT statements would have made it into your database, even if not desired and you'd have no control over what's to happen next.
I usually use the first way for simple debugging in development code. It is not recommended for production. The best way is to throw an exception, which you can catch in other parts of the program and do some error handling on.
The three styles are not drop-in replacements for each other. The first one is not an error at all, but just a way to stop the script and output some debugging info for you to manually parse. The second one is not an error per se, but will be converted into an error if you don't catch it. The last one is triggering a real error in the PHP engine which will be handled according to the configuration of your PHP environment (in some cases shown to the user, in other cases just logged to a file or not saved at all).

facebook asynchronous validation doesn't show errors

The javascript console keeps showing "Not a custom field name: username" when its supposed to show an error for the username field. There clearly is a field named "username". I tried changing it to some other name everywhere, but it still didn't work.
Any idea what is going on?
<fb:registration redirect-uri="<?=$pageurl?>"
fields="[{'name':'name'},{'name':'email'},{'name':'location'},{'name':'username','description':'Username','type':'text'},{'name':'password','view':'not_prefilled'},{'name':'captcha','view':'not_prefilled'}]"
onvalidate="validate" width="400"></fb:registration>
and my validate function...
function validate(form,cb)
{
console.dir(form);
$.get('/api/?f=user_email_present&username='+form.username+"&email="+form.email,function(data){
console.log(data);
if(data.username==false)
{
cb();
}
else
{
if(data.username=='username')
cb({username: 'That username is already taken. Please try another username.'});
else if(data.username=='usernamelength')
cb({username: 'The username cannot exceed 20 characters in length.'});
}
});
}
I can't be too sure, but I think I remember all this working a while back. Took me by complete shock when we are 2 days from launch.
Update: I scrapped out asynchronous validation and used the other validation. It still throws the same error!
After spending the better part of two days, I managed to figure out what is going on. It is a silly but potent bug on facebook's end. If the width of the widget is too less, it gives this error. Increasing the width to 800px fixed it promptly. Probably they don't render the proper error fields when the width is too small.
I have filed a bug report: https://github.com/facebook/connect-js/issues/275
If you guys can give it a shot and comment on my bug report so that they can take action immediately, it would be awesome.