diff --git a/error_report.php b/error_report.php
index 7bc310f067..756fa2f4a0 100644
--- a/error_report.php
+++ b/error_report.php
@@ -7,66 +7,124 @@
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/error_report.lib.php';
+require_once 'libraries/user_preferences.lib.php';
+
+if (!isset($_REQUEST['exception_type'])
+ ||!in_array($_REQUEST['exception_type'], array('js', 'php'))
+) {
+ die('Oops, something went wrong!!');
+}
$response = PMA_Response::getInstance();
if (isset($_REQUEST['send_error_report'])
- && $_REQUEST['send_error_report'] == true
+ && ($_REQUEST['send_error_report'] == true
+ || $_REQUEST['send_error_report'] == '1')
) {
- $server_response = PMA_sendErrorReport(PMA_getReportData());
-
- if ($server_response === false) {
- $success = false;
- } else {
- $decoded_response = json_decode($server_response, true);
- $success = !empty($decoded_response) ? $decoded_response["success"] : false;
- }
-
- /* Message to show to the user */
- if ($success) {
- if (isset($_REQUEST['automatic'])
- && $_REQUEST['automatic'] === "true"
+ if ($_REQUEST['exception_type'] == 'php') {
+ /**
+ * Prevent inifnite error submission.
+ * Happens in case error submissions fails.
+ * If reporting is done in some time interval,
+ * just clear them & clear json data too.
+ */
+ if (isset($_SESSION['prev_error_subm_time'])
+ && isset($_SESSION['error_subm_count'])
+ && $_SESSION['error_subm_count'] >= 3
+ && ($_SESSION['prev_error_subm_time']-time()) <= 3000
) {
- $message = __(
- 'An error has been detected and an error report has been '
- . 'automatically submitted based on your settings.'
- );
+ $_SESSION['error_subm_count'] = 0;
+ $_SESSION['prev_errors'] = '';
+ $response = PMA_Response::getInstance();
+ $response->addJSON('_stopErrorReportLoop', '1');
} else {
- $message = __('Thank you for submitting this report.');
+ $_SESSION['prev_error_subm_time'] = time();
+ $_SESSION['error_subm_count'] = (
+ (isset($_SESSION['error_subm_count']))
+ ? ($_SESSION['error_subm_count']+1)
+ : (0)
+ );
}
- } else {
- $message = __(
- 'An error has been detected and an error report has been '
- . 'generated but failed to be sent.'
- )
- . ' '
- . __(
- 'If you experience any '
- . 'problems please submit a bug report manually.'
- );
}
- $message .= ' ' . __('You may want to refresh the page.');
+ $reportData = PMA_getReportData($_REQUEST['exception_type']);
+ // report if and only if there were 'actual' errors.
+ if (count($reportData) > 0) {
+ $server_response = PMA_sendErrorReport($reportData);
+ if ($server_response === false) {
+ $success = false;
+ } else {
+ $decoded_response = json_decode($server_response, true);
+ $success = !empty($decoded_response) ?
+ $decoded_response["success"] : false;
+ }
- /* Create message object */
- if ($success) {
- $message = PMA_Message::notice($message);
- } else {
- $message = PMA_Message::error($message);
- }
+ /* Message to show to the user */
+ if ($success) {
+ if ((isset($_REQUEST['automatic'])
+ && $_REQUEST['automatic'] === "true")
+ || $GLOBALS['cfg']['SendErrorReports'] == 'always'
+ ) {
+ $msg = __(
+ 'An error has been detected and an error report has been '
+ . 'automatically submitted based on your settings.'
+ );
+ } else {
+ $msg = __('Thank you for submitting this report.');
+ }
+ } else {
+ $msg = __(
+ 'An error has been detected and an error report has been '
+ . 'generated but failed to be sent.'
+ )
+ . ' '
+ . __(
+ 'If you experience any '
+ . 'problems please submit a bug report manually.'
+ );
+ }
+ $msg .= ' ' . __('You may want to refresh the page.');
- /* Add message to JSON response */
- $response->addJSON('message', $message);
+ /* Create message object */
+ if ($success) {
+ $msg = PMA_Message::notice($msg);
+ } else {
+ $msg = PMA_Message::error($msg);
+ }
- /* Persist always send settings */
- if (! isset($_REQUEST['automatic'])
- && $_REQUEST['automatic'] !== "true"
- && isset($_REQUEST['always_send'])
- && $_REQUEST['always_send'] === "true"
- ) {
- PMA_persistOption("SendErrorReports", "always", "ask");
+ /* Add message to response */
+ if ($response->isAjax()) {
+ if ($_REQUEST['exception_type'] == 'js') {
+ $response->addJSON('message', $msg);
+ } else {
+ $response->addJSON('_errSubmitMsg', $msg);
+ }
+ } elseif ($_REQUEST['exception_type'] == 'php') {
+ $jsCode = 'PMA_ajaxShowMessage("
'
+ . $msg
+ . '
", false);';
+ $response->getFooter()->getScripts()->addCode($jsCode);
+ }
+
+ if ($_REQUEST['exception_type'] == 'php') {
+ // clear previous errors & save new ones.
+ $GLOBALS['error_handler']->savePreviousErrors();
+ }
+
+ /* Persist always send settings */
+ if (isset($_REQUEST['always_send'])
+ && $_REQUEST['always_send'] === "true"
+ ) {
+ PMA_persistOption("SendErrorReports", "always", "ask");
+ }
}
} elseif (! empty($_REQUEST['get_settings'])) {
$response->addJSON('report_setting', $GLOBALS['cfg']['SendErrorReports']);
} else {
- $response->addHTML(PMA_getErrorReportForm());
+ if ($_REQUEST['exception_type'] == 'js') {
+ $response->addHTML(PMA_getErrorReportForm());
+ } else {
+ // clear previous errors & save new ones.
+ $GLOBALS['error_handler']->savePreviousErrors();
+ }
}
+?>
diff --git a/js/ajax.js b/js/ajax.js
index cb41d2ed6d..e81eb8419c 100644
--- a/js/ajax.js
+++ b/js/ajax.js
@@ -388,11 +388,47 @@ var AJAX = {
}
$('#pma_errors').remove();
+
+ var msg = '';
+ if(data._errSubmitMsg){
+ msg = data._errSubmitMsg;
+ }
if (data._errors) {
$('', {id : 'pma_errors'})
.insertAfter('#selflink')
.append(data._errors);
+ // bind for php error reporting forms (bottom)
+ $("#pma_ignore_errors_bottom").bind("click",
+ function() {
+ PMA_ignorePhpErrors();
+ });
+ $("#pma_ignore_all_errors_bottom").bind("click",
+ function() {
+ PMA_ignorePhpErrors(false);
+ });
+ // In case of 'sendErrorReport'='always'
+ // submit the hidden error reporting form.
+ if (data._sendErrorAlways == '1'
+ && data._stopErrorReportLoop != '1'
+ ) {
+ $("#pma_report_errors_form").submit();
+ PMA_ajaxShowMessage(PMA_messages['phpErrorsBeingSubmitted'], false);
+ $('html, body').animate({scrollTop:$(document).height()}, 'slow');
+ } else if (data._promptPhpErrors) {
+ // otherwise just prompt user if it is set so.
+ msg = msg + PMA_messages['phpErrorsFound'];
+ // scroll to bottom where all the erros are displayed.
+ $('html, body').animate({scrollTop:$(document).height()}, 'slow');
+ }
}
+ PMA_ajaxShowMessage(msg, false);
+ // bind for php error reporting forms (popup)
+ $("#pma_ignore_errors_popup").bind("click", function() {
+ PMA_ignorePhpErrors()
+ });
+ $("#pma_ignore_all_errors_popup").bind("click", function() {
+ PMA_ignorePhpErrors(false)
+ });
if (typeof AJAX._callback === 'function') {
AJAX._callback.call();
diff --git a/js/error_report.js b/js/error_report.js
index 853a76cfed..a8e7da7dd1 100644
--- a/js/error_report.js
+++ b/js/error_report.js
@@ -23,7 +23,8 @@ var ErrorReport = {
ajax_request: true,
server: PMA_commonParams.get('server'),
token: PMA_commonParams.get('token'),
- get_settings: true
+ get_settings: true,
+ exception_type: 'js'
}, function (data) {
if (data.success !== true) {
PMA_ajaxShowMessage(data.error, false);
@@ -227,7 +228,8 @@ var ErrorReport = {
"token": PMA_commonParams.get('token'),
"exception": exception,
"current_url": window.location.href,
- "microhistory": ErrorReport._get_microhistory()
+ "microhistory": ErrorReport._get_microhistory(),
+ "exception_type": 'js'
};
if (typeof AJAX.cache.pages[AJAX.cache.current - 1] !== 'undefined') {
report_data.scripts = AJAX.cache.pages[AJAX.cache.current - 1].scripts.map(
diff --git a/js/functions.js b/js/functions.js
index 000704fee6..7f9a86694c 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -4379,3 +4379,29 @@ function PMA_previewSQL($form)
}
});
}
+
+/**
+ * Ignore the displayed php errors.
+ * Simply removes the displayed errors.
+ *
+ * @param clearPrevErrors whether to clear errors stored
+ * in $_SESSION['prev_errors'] at server
+ *
+ */
+function PMA_ignorePhpErrors(clearPrevErrors){
+ if (typeof(clearPrevErrors) === "undefined"
+ || clearPrevErrors === null
+ ) {
+ str = false;
+ }
+ // send AJAX request to error_report.php with send_error_report=0, exception_type=php & token.
+ // It clears the prev_errors stored in session.
+ if(clearPrevErrors){
+ $('#pma_report_errors_form input[name="send_error_report"]').val(0); // change send_error_report to '0'
+ $('#pma_report_errors_form').submit();
+ }
+
+ // remove dislayed errors
+ $('#pma_errors').fadeOut( "slow");
+ $('#pma_errors').remove();
+}
diff --git a/js/messages.php b/js/messages.php
index 1f3c1edb85..a50184b485 100644
--- a/js/messages.php
+++ b/js/messages.php
@@ -426,6 +426,29 @@ $js_messages['strTooManyInputs'] = __(
. "max_input_vars configuration."
);
+$js_messages['phpErrorsFound'] = '
'
+ . __('Warning: Some errors have been detected on the server!!')
+ . '
'
+ . __('Please look at the bottom of this window.')
+ . ''
+ . ''
+ . '
';
+
+$js_messages['phpErrorsBeingSubmitted'] = '
'
+ . __('Some errors have been detected on the server!!')
+ . ' '
+ . __('As per your settings, they are being submitted currently.')
+ . __(' Please be patient.')
+ . ' '
+ . ''
+ . '
';
+
echo "var PMA_messages = new Array();\n";
foreach ($js_messages as $name => $js_message) {
PMA_printJsValue("PMA_messages['" . $name . "']", $js_message);
diff --git a/libraries/Error.class.php b/libraries/Error.class.php
index fd4a2fc83c..842af8c66e 100644
--- a/libraries/Error.class.php
+++ b/libraries/Error.class.php
@@ -188,12 +188,19 @@ class PMA_Error extends PMA_Message
}
/**
- * returns PMA_Error::$_backtrace
+ * returns PMA_Error::$_backtrace for first $count frames
+ * pass $count = -1 to get full backtrace.
+ * The same can be done by not passing $count at all.
+ *
+ * @param integer $count Number of stack frames.
*
* @return array PMA_Error::$_backtrace
*/
- public function getBacktrace()
+ public function getBacktrace($count = -1)
{
+ if ($count != -1) {
+ return array_slice($this->backtrace, 0, $count);
+ }
return $this->backtrace;
}
diff --git a/libraries/Error_Handler.class.php b/libraries/Error_Handler.class.php
index c9c3176eee..7592c322cb 100644
--- a/libraries/Error_Handler.class.php
+++ b/libraries/Error_Handler.class.php
@@ -94,6 +94,17 @@ class PMA_Error_Handler
return $this->errors;
}
+ /**
+ * returns the errors occured in the current run only.
+ * Does not include the errors save din the SESSION
+ *
+ * @return array of current errors
+ */
+ public function getCurrentErrors()
+ {
+ return $this->errors;
+ }
+
/**
* Error handler - called when errors are triggered/occurred
*
@@ -281,7 +292,10 @@ class PMA_Error_Handler
public function getDispErrors()
{
$retval = '';
- if ($GLOBALS['cfg']['Error_Handler']['display']) {
+ // display errors if SendErrorReports is set to 'ask'.
+ if ($GLOBALS['cfg']['SendErrorReports'] != 'never'
+ || $GLOBALS['cfg']['Error_Handler']['display']
+ ) {
foreach ($this->getErrors() as $error) {
if ($error instanceof PMA_Error) {
if (! $error->isDisplayed()) {
@@ -297,6 +311,46 @@ class PMA_Error_Handler
} else {
$retval .= $this->getDispUserErrors();
}
+ // if preference is not 'never' and
+ // there are 'actual' errors to be reported
+ if ($GLOBALS['cfg']['SendErrorReports'] != 'never'
+ && $this->countErrors() != $this->countUserErrors()
+ ) {
+ // add report button.
+ $retval .= ''
+ . ''
+ . ''
+ . ''
+ . ''
+ . ''
+ . '';
+
+ if ($GLOBALS['cfg']['SendErrorReports'] == 'ask') {
+ // add ignore buttons
+ $retval .= '';
+ }
+ $retval .= '';
+ }
return $retval;
}
@@ -389,7 +443,9 @@ class PMA_Error_Handler
*/
public function countDisplayErrors()
{
- if ($GLOBALS['cfg']['Error_Handler']['display']) {
+ if ($GLOBALS['cfg']['SendErrorReports'] != 'never'
+ || $GLOBALS['cfg']['Error_Handler']['display']
+ ) {
return $this->countErrors();
} else {
return $this->countUserErrors();
@@ -405,5 +461,102 @@ class PMA_Error_Handler
{
return (bool) $this->countDisplayErrors();
}
+
+ /**
+ * Deletes prevsiously stored errors in SESSION.
+ * Saves current errors in session as previous errros.
+ * Required to save current errors in case 'ask'
+ *
+ * @return void
+ */
+ public function savePreviousErrors()
+ {
+ unset($_SESSION['prev_errors']);
+ $_SESSION['prev_errors'] = $GLOBALS['error_handler']->getCurrentErrors();
+ }
+
+ /**
+ * Function to check if there are any errors to be prompted.
+ * Needed because user warnings raised are
+ * also collected by global error handler.
+ * This dishtingushes between the actual errors
+ * and user errors raised to warn user.
+ *
+ *@return boolean: true if there are errors to be "prompted", false otherwise
+ */
+ public function hasErrorsForPrompt()
+ {
+ return (
+ ($GLOBALS['cfg']['SendErrorReports'] != 'never'
+ || $GLOBALS['cfg']['Error_Handler']['display'])
+ && $this->countErrors() != $this->countUserErrors()
+ );
+ }
+
+ /**
+ * Function to report all the collected php errors.
+ * Must be called at the end of each script
+ * by the $GLOBALS['error_handler'] only.
+ *
+ * @return void
+ */
+
+ public function reportErrors()
+ {
+ // if there're no actual errors,
+ if (!$this->hasErrors()
+ || $this->countErrors() == $this->countUserErrors()
+ ) {
+ // then simply return.
+ return;
+ }
+ // Delete all the prev_errors in session & store new prev_errors in session
+ $this->savePreviousErrors();
+ $response = PMA_Response::getInstance();
+ $jsCode = '';
+ if ($GLOBALS['cfg']['SendErrorReports'] == 'always') {
+ if ($response->isAjax()) {
+ // set flag for automatic report submission.
+ $response->addJSON('_sendErrorAlways', '1');
+ } else {
+ // send the error reports asynchronously & without asking user
+ $jsCode .= '$("#pma_report_errors_form").submit();'
+ . 'PMA_ajaxShowMessage(
+ PMA_messages["phpErrorsBeingSubmitted"], false
+ );';
+ // js code to appropriate focusing,
+ $jsCode .= '$("html, body").animate({
+ scrollTop:$(document).height()
+ }, "slow");';
+ }
+ } elseif ($GLOBALS['cfg']['SendErrorReports'] == 'ask') {
+ //ask user whether to submit errors or not.
+ if (!$response->isAjax()) {
+ // js code to show appropriate msgs, event binding & focusing.
+ $jsCode = 'PMA_ajaxShowMessage(PMA_messages["phpErrorsFound"], '
+ . ' 2000);'
+ . '$("#pma_ignore_errors_popup").bind("click", function() {
+ PMA_ignorePhpErrors()
+ });'
+ . '$("#pma_ignore_all_errors_popup").bind("click",
+ function() {
+ PMA_ignorePhpErrors(false)
+ });'
+ . '$("#pma_ignore_errors_bottom").bind("click", function() {
+ PMA_ignorePhpErrors()
+ });'
+ . '$("#pma_ignore_all_errors_bottom").bind("click",
+ function() {
+ PMA_ignorePhpErrors(false)
+ });'
+ . '$("html, body").animate({
+ scrollTop:$(document).height()
+ }, "slow");';
+ }
+ }
+ // The errors are already sent from the resnpose.
+ // Just focus on errors division upon load event.
+ $response->getFooter()->getScripts()->addCode($jsCode);
+ }
}
?>
diff --git a/libraries/Footer.class.php b/libraries/Footer.class.php
index 095552e73c..a114d5e2f4 100644
--- a/libraries/Footer.class.php
+++ b/libraries/Footer.class.php
@@ -209,6 +209,12 @@ class PMA_Footer
$retval .= $GLOBALS['error_handler']->getDispErrors();
$retval .= '';
}
+
+ /**
+ * Report php errors
+ */
+ $GLOBALS['error_handler']->reportErrors();
+
return $retval;
}
diff --git a/libraries/Message.class.php b/libraries/Message.class.php
index 4132faa555..6bffe87b7c 100644
--- a/libraries/Message.class.php
+++ b/libraries/Message.class.php
@@ -655,6 +655,17 @@ class PMA_Message
return $message;
}
+ /**
+ * Returns only message string without image & other HTML.
+ *
+ * @return $message string
+ */
+ public function getOnlyMessage()
+ {
+ return $this->message;
+ }
+
+
/**
* returns PMA_Message::$string
*
diff --git a/libraries/Response.class.php b/libraries/Response.class.php
index 45a4fd2c98..c34cf23ddf 100644
--- a/libraries/Response.class.php
+++ b/libraries/Response.class.php
@@ -316,6 +316,9 @@ class PMA_Response
if (strlen($errors)) {
$this->addJSON('_errors', $errors);
}
+ $promptPhpErrors = $GLOBALS['error_handler']->hasErrorsForPrompt();
+ $this->addJSON('_promptPhpErrors', $promptPhpErrors);
+
if (empty($GLOBALS['error_message'])) {
// set current db, table and sql query in the querywindow
$query = '';
diff --git a/libraries/error_report.lib.php b/libraries/error_report.lib.php
index 0df479c8fe..d2279f1c24 100644
--- a/libraries/error_report.lib.php
+++ b/libraries/error_report.lib.php
@@ -52,37 +52,80 @@ function PMA_getPrettyReportData()
* returns the error report data collected from the current configuration or
* from the request parameters sent by the error reporting js code.
*
- * @return Array the report
+ * @param string $exception_type whether exception is 'js' or 'php'
+ *
+ * @return Array error report if success, Empty Array otherwise
*/
-function PMA_getReportData()
+function PMA_getReportData($exception_type = 'js')
{
- if (empty($_REQUEST['exception'])) {
- return array();
- }
- $exception = $_REQUEST['exception'];
- $exception["stack"] = PMA_translateStacktrace($exception["stack"]);
- List($uri, $script_name) = PMA_sanitizeUrl($exception["url"]);
- $exception["uri"] = $uri;
- unset($exception["url"]);
+ $relParams = PMA_getRelationsParam();
+ // common params for both, php & js execptions
$report = array(
- "exception" => $exception,
- "script_name" => $script_name,
- "pma_version" => PMA_VERSION,
- "browser_name" => PMA_USR_BROWSER_AGENT,
- "browser_version" => PMA_USR_BROWSER_VER,
- "user_os" => PMA_USR_OS,
- "server_software" => $_SERVER['SERVER_SOFTWARE'],
- "user_agent_string" => $_SERVER['HTTP_USER_AGENT'],
- "locale" => $_COOKIE['pma_lang'],
- "configuration_storage" =>
- empty($GLOBALS['cfg']['Servers'][1]['pmadb']) ? "disabled" :
- "enabled",
- "php_version" => phpversion(),
- "microhistory" => $_REQUEST['microhistory'],
- );
+ "pma_version" => PMA_VERSION,
+ "browser_name" => PMA_USR_BROWSER_AGENT,
+ "browser_version" => PMA_USR_BROWSER_VER,
+ "user_os" => PMA_USR_OS,
+ "server_software" => $_SERVER['SERVER_SOFTWARE'],
+ "user_agent_string" => $_SERVER['HTTP_USER_AGENT'],
+ "locale" => $_COOKIE['pma_lang'],
+ "configuration_storage" =>
+ is_null($relParams['db']) ? "disabled" :
+ "enabled",
+ "php_version" => phpversion()
+ );
- if (! empty($_REQUEST['description'])) {
- $report['steps'] = $_REQUEST['description'];
+ if ($exception_type == 'js') {
+ if (empty($_REQUEST['exception'])) {
+ return array();
+ }
+ $exception = $_REQUEST['exception'];
+ $exception["stack"] = PMA_translateStacktrace($exception["stack"]);
+ List($uri, $script_name) = PMA_sanitizeUrl($exception["url"]);
+ $exception["uri"] = $uri;
+ unset($exception["url"]);
+
+ $report ["exception_type"] = 'js';
+ $report ["exception"] = $exception;
+ $report ["script_name"] = $script_name;
+ $report ["microhistory"] = $_REQUEST['microhistory'];
+
+ if (! empty($_REQUEST['description'])) {
+ $report['steps'] = $_REQUEST['description'];
+ }
+ } elseif ($exception_type == 'php') {
+ $errors = array();
+ // create php error report
+ $i=0;
+ if (!isset($_SESSION['prev_errors'])
+ || $_SESSION['prev_errors'] == ''
+ ) {
+ return array();
+ }
+ foreach ($_SESSION['prev_errors'] as $errorObj) {
+ if ($errorObj->getLine()
+ && $errorObj->getType()
+ && $errorObj->getNumber() != E_USER_WARNING
+ ) {
+ $errors[$i++] = array(
+ "lineNum" => $errorObj->getLine(),
+ "file" => $errorObj->getFile(),
+ "type" => $errorObj->getType(),
+ "msg" => $errorObj->getOnlyMessage(),
+ "stackTrace" => $errorObj->getBacktrace(5),
+ "stackhash" => $errorObj->getHash()
+ );
+
+ }
+ }
+
+ // if there were no 'actual' errors to be submitted.
+ if ($i==0) {
+ return array(); // then return empty array
+ }
+ $report ["exception_type"] = 'php';
+ $report["errors"] = $errors;
+ } else {
+ return array();
}
return $report;
diff --git a/libraries/plugins/auth/AuthenticationCookie.class.php b/libraries/plugins/auth/AuthenticationCookie.class.php
index 0f2a883dac..96771075a0 100644
--- a/libraries/plugins/auth/AuthenticationCookie.class.php
+++ b/libraries/plugins/auth/AuthenticationCookie.class.php
@@ -284,7 +284,7 @@ class AuthenticationCookie extends AuthenticationPlugin
// END Swekey Integration
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
- echo '