From fd1bd705c5d460ddf5835b099aaa5cd102f64722 Mon Sep 17 00:00:00 2001 From: stilez Date: Wed, 24 May 2017 07:39:28 +0100 Subject: [PATCH] If user-entered PHP errors out, display the error line in context to help the user If the user enters PHP in the command-line page, and it errors out, it's usually a typo or something minor. But the user is left with an error that references a /tmp file which doesn't exist at the point they read the message, a line number that's incorrect, and their input which doesn't display line numbers anyhow. This patch fixes this, so that a user who wants to enter php command-line in the GUI and gets an error, can quickly identify the exact line causing the error. If an error occurs (detected by either non-zero return value or output matching an error message referencing the temp script file), then an short DIV is shown above the usual PHP output for "error location". It gives the correct error line number, and shows the code with line numbers and syntax highlighting (using php's native "-s" option), pre-scrolled to the error line. --- src/usr/local/www/diag_command.php | 70 +++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/src/usr/local/www/diag_command.php b/src/usr/local/www/diag_command.php index bac4848c0a..b6e0c543fd 100755 --- a/src/usr/local/www/diag_command.php +++ b/src/usr/local/www/diag_command.php @@ -255,39 +255,85 @@ if ($_POST['submit'] == "EXEC" && !isBlank($_POST['txtCommand'])):?>

PHP Response

"); - $tmpname = tempnam("/tmp", ""); - $phpfile = fopen($tmpname, "w"); - fwrite($phpfile, "\n"); - fclose($phpfile); + $tmpfile = tempnam("/tmp", ""); + $phpcode = << +END_FILE; + $lineno_correction = 6; // line numbering correction, this should be the number of lines added above, BEFORE the user's code + + file_put_contents($tmpfile, sprintf($phpcode, $_POST['txtPHPCommand'])); + + $output = $matches = array(); + $retval = 0; + exec("/usr/local/bin/php -d log_errors=off {$tmpfile}", $output, $ret_val); + + puts('

PHP Response

'); + + // Help user to find bad code line, if it gave an error + + $errmsg_found = preg_match("`error.*:.* (?:in|File:) {$tmpfile}(?: on line|, Line:) (\d+)(?:$|, Message:)`i", implode("\n", $output), $matches); + + if ($retval || $errmsg_found) { + /* Trap failed code - test both retval and output message + * Typical messages as at 2.3.x: + * "Parse error: syntax error, ERR_DETAILS in FILE on line NN" + * "PHP ERROR: Type: NN, File: FILE, Line: NN, Message: ERR_DETAILS" + */ + $errline = $matches[1] - $lineno_correction; + $syntax_output = array(); + $html = ""; + exec("/usr/local/bin/php -s -d log_errors=off {$tmpfile}", $syntax_output); + // Lines 0, 2 and 3 are CSS wrapper for the syntax highlighted code which is at line 1
separated. + $syntax_output = explode("
", $syntax_output[1]); + $chars = strlen(count($syntax_output)) + 1; + for ($lineno = 1; $lineno < count($syntax_output) - $lineno_correction; $lineno++) { + if ($lineno == $errline) { + $lineno_prefix = ">>>" . str_repeat(' ', $chars - strlen($lineno)); + } else { + $lineno_prefix = str_repeat(' ', ($chars + 3) - strlen($lineno)); + } + $html .= "" . $lineno_prefix . $lineno . ":  {$syntax_output[$lineno + $lineno_correction - 1]}
\n"; + } + echo sprintf(gettext('Line %s appears to have generated an error, and has been highlighted. The full response is below.
' . + 'Note that the line number in the full PHP response will be %s lines too large.'), $errline, $lineno_correction); + echo "
" . gettext("Error locator:") . "\n"; + echo "
\n"; + echo $html . "\n
\n"; + } $output = implode("\n", $output); print("
" . htmlspecialchars($output) . "
"); // echo eval($_POST['txtPHPCommand']); + puts("
"); + + unlink($tmpfile); ?> +