diff --git a/CHANGELOG b/CHANGELOG
index 047901f00..6a0f3351f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Fix handling of debug_level=4 in ajax requests (#1487831)
- Support 'abort' and 'result' response in 'preferences_save' hook, add error handling
- Fix bug where some content would cause hang on html2text conversion (#1487863)
- Improve space-stuffing handling in format=flowed messages (#1487861)
diff --git a/program/include/main.inc b/program/include/main.inc
index 64fea702d..54ce67d00 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1141,192 +1141,13 @@ function format_date($date, $format=NULL)
* @return string Formatted string
*/
function format_email_recipient($email, $name='')
- {
- if ($name && $name != $email)
- {
+{
+ if ($name && $name != $email) {
// Special chars as defined by RFC 822 need to in quoted string (or escaped).
return sprintf('%s <%s>', preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name) ? '"'.addcslashes($name, '"').'"' : $name, trim($email));
- }
- else
- return trim($email);
- }
-
-
-
-/****** debugging functions ********/
-
-
-/**
- * Print or write debug messages
- *
- * @param mixed Debug message or data
- * @return void
- */
-function console()
- {
- $args = func_get_args();
-
- if (class_exists('rcmail', false)) {
- $rcmail = rcmail::get_instance();
- if (is_object($rcmail->plugins))
- $rcmail->plugins->exec_hook('console', $args);
- }
-
- $msg = array();
- foreach ($args as $arg)
- $msg[] = !is_string($arg) ? var_export($arg, true) : $arg;
-
- if (!($GLOBALS['CONFIG']['debug_level'] & 4))
- write_log('console', join(";\n", $msg));
- else if ($GLOBALS['OUTPUT']->ajax_call)
- print "/*\n " . join(";\n", $msg) . " \n*/\n";
- else
- {
- print '
';
- print join(";
\n", $msg);
- print "
\n";
- }
}
-
-/**
- * Append a line to a logfile in the logs directory.
- * Date will be added automatically to the line.
- *
- * @param $name name of log file
- * @param line Line to append
- * @return void
- */
-function write_log($name, $line)
- {
- global $CONFIG, $RCMAIL;
-
- if (!is_string($line))
- $line = var_export($line, true);
-
- if (empty($CONFIG['log_date_format']))
- $CONFIG['log_date_format'] = 'd-M-Y H:i:s O';
-
- $date = date($CONFIG['log_date_format']);
-
- // trigger logging hook
- if (is_object($RCMAIL) && is_object($RCMAIL->plugins)) {
- $log = $RCMAIL->plugins->exec_hook('write_log', array('name' => $name, 'date' => $date, 'line' => $line));
- $name = $log['name'];
- $line = $log['line'];
- $date = $log['date'];
- if ($log['abort'])
- return true;
- }
-
- if ($CONFIG['log_driver'] == 'syslog') {
- $prio = $name == 'errors' ? LOG_ERR : LOG_INFO;
- syslog($prio, $line);
- return true;
- }
- else {
- $line = sprintf("[%s]: %s\n", $date, $line);
-
- // log_driver == 'file' is assumed here
- if (empty($CONFIG['log_dir']))
- $CONFIG['log_dir'] = INSTALL_PATH.'logs';
-
- // try to open specific log file for writing
- $logfile = $CONFIG['log_dir'].'/'.$name;
- if ($fp = @fopen($logfile, 'a')) {
- fwrite($fp, $line);
- fflush($fp);
- fclose($fp);
- return true;
- }
- else
- trigger_error("Error writing to log file $logfile; Please check permissions", E_USER_WARNING);
- }
- return false;
-}
-
-
-/**
- * Write login data (name, ID, IP address) to the 'userlogins' log file.
- *
- * @return void
- */
-function rcmail_log_login()
-{
- global $RCMAIL;
-
- if (!$RCMAIL->config->get('log_logins') || !$RCMAIL->user)
- return;
-
- write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s',
- $RCMAIL->user->get_username(), $RCMAIL->user->ID, rcmail_remote_ip()));
-}
-
-
-/**
- * Returns remote IP address and forwarded addresses if found
- *
- * @return string Remote IP address(es)
- */
-function rcmail_remote_ip()
-{
- $address = $_SERVER['REMOTE_ADDR'];
-
- // append the NGINX X-Real-IP header, if set
- if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
- $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP'];
- }
- // append the X-Forwarded-For header, if set
- if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
- }
-
- if (!empty($remote_ip))
- $address .= '(' . implode(',', $remote_ip) . ')';
-
- return $address;
-}
-
-
-/**
- * Check whether the HTTP referer matches the current request
- *
- * @return boolean True if referer is the same host+path, false if not
- */
-function rcube_check_referer()
-{
- $uri = parse_url($_SERVER['REQUEST_URI']);
- $referer = parse_url(rc_request_header('Referer'));
- return $referer['host'] == rc_request_header('Host') && $referer['path'] == $uri['path'];
-}
-
-
-/**
- * @access private
- * @return mixed
- */
-function rcube_timer()
-{
- return microtime(true);
-}
-
-
-/**
- * @access private
- * @return void
- */
-function rcube_print_time($timer, $label='Timer', $dest='console')
-{
- static $print_count = 0;
-
- $print_count++;
- $now = rcube_timer();
- $diff = $now-$timer;
-
- if (empty($label))
- $label = 'Timer '.$print_count;
-
- write_log($dest, sprintf("%s: %0.4f sec", $label, $diff));
+ return trim($email);
}
@@ -1844,7 +1665,6 @@ function rcube_sess_unset($var_name=null)
}
-
/**
* Replaces hostname variables
*
@@ -1995,6 +1815,178 @@ class rcube_base_replacer
}
+/****** debugging and logging functions ********/
+
+/**
+ * Print or write debug messages
+ *
+ * @param mixed Debug message or data
+ * @return void
+ */
+function console()
+{
+ $args = func_get_args();
+
+ if (class_exists('rcmail', false)) {
+ $rcmail = rcmail::get_instance();
+ if (is_object($rcmail->plugins)) {
+ $plugin = $rcmail->plugins->exec_hook('console', array('args' => $args));
+ if ($plugin['abort'])
+ return;
+ $args = $plugin['args'];
+ }
+ }
+
+ $msg = array();
+ foreach ($args as $arg)
+ $msg[] = !is_string($arg) ? var_export($arg, true) : $arg;
+
+ write_log('console', join(";\n", $msg));
+}
+
+
+/**
+ * Append a line to a logfile in the logs directory.
+ * Date will be added automatically to the line.
+ *
+ * @param $name name of log file
+ * @param line Line to append
+ * @return void
+ */
+function write_log($name, $line)
+{
+ global $CONFIG, $RCMAIL;
+
+ if (!is_string($line))
+ $line = var_export($line, true);
+
+ if (empty($CONFIG['log_date_format']))
+ $CONFIG['log_date_format'] = 'd-M-Y H:i:s O';
+
+ $date = date($CONFIG['log_date_format']);
+
+ // trigger logging hook
+ if (is_object($RCMAIL) && is_object($RCMAIL->plugins)) {
+ $log = $RCMAIL->plugins->exec_hook('write_log', array('name' => $name, 'date' => $date, 'line' => $line));
+ $name = $log['name'];
+ $line = $log['line'];
+ $date = $log['date'];
+ if ($log['abort'])
+ return true;
+ }
+
+ if ($CONFIG['log_driver'] == 'syslog') {
+ $prio = $name == 'errors' ? LOG_ERR : LOG_INFO;
+ syslog($prio, $line);
+ return true;
+ }
+ else {
+ $line = sprintf("[%s]: %s\n", $date, $line);
+
+ // log_driver == 'file' is assumed here
+ if (empty($CONFIG['log_dir']))
+ $CONFIG['log_dir'] = INSTALL_PATH.'logs';
+
+ // try to open specific log file for writing
+ $logfile = $CONFIG['log_dir'].'/'.$name;
+ if ($fp = @fopen($logfile, 'a')) {
+ fwrite($fp, $line);
+ fflush($fp);
+ fclose($fp);
+ return true;
+ }
+ else
+ trigger_error("Error writing to log file $logfile; Please check permissions", E_USER_WARNING);
+ }
+
+ return false;
+}
+
+
+/**
+ * Write login data (name, ID, IP address) to the 'userlogins' log file.
+ *
+ * @return void
+ */
+function rcmail_log_login()
+{
+ global $RCMAIL;
+
+ if (!$RCMAIL->config->get('log_logins') || !$RCMAIL->user)
+ return;
+
+ write_log('userlogins', sprintf('Successful login for %s (ID: %d) from %s',
+ $RCMAIL->user->get_username(), $RCMAIL->user->ID, rcmail_remote_ip()));
+}
+
+
+/**
+ * Returns remote IP address and forwarded addresses if found
+ *
+ * @return string Remote IP address(es)
+ */
+function rcmail_remote_ip()
+{
+ $address = $_SERVER['REMOTE_ADDR'];
+
+ // append the NGINX X-Real-IP header, if set
+ if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
+ $remote_ip[] = 'X-Real-IP: ' . $_SERVER['HTTP_X_REAL_IP'];
+ }
+ // append the X-Forwarded-For header, if set
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ $remote_ip[] = 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
+ }
+
+ if (!empty($remote_ip))
+ $address .= '(' . implode(',', $remote_ip) . ')';
+
+ return $address;
+}
+
+
+/**
+ * Check whether the HTTP referer matches the current request
+ *
+ * @return boolean True if referer is the same host+path, false if not
+ */
+function rcube_check_referer()
+{
+ $uri = parse_url($_SERVER['REQUEST_URI']);
+ $referer = parse_url(rc_request_header('Referer'));
+ return $referer['host'] == rc_request_header('Host') && $referer['path'] == $uri['path'];
+}
+
+
+/**
+ * @access private
+ * @return mixed
+ */
+function rcube_timer()
+{
+ return microtime(true);
+}
+
+
+/**
+ * @access private
+ * @return void
+ */
+function rcube_print_time($timer, $label='Timer', $dest='console')
+{
+ static $print_count = 0;
+
+ $print_count++;
+ $now = rcube_timer();
+ $diff = $now-$timer;
+
+ if (empty($label))
+ $label = 'Timer '.$print_count;
+
+ write_log($dest, sprintf("%s: %0.4f sec", $label, $diff));
+}
+
+
/**
* Throw system error and show error page
*
@@ -2015,7 +2007,7 @@ function raise_error($arg=array(), $log=false, $terminate=false)
// report bug (if not incompatible browser)
if ($log && $arg['type'] && $arg['message'])
- log_bug($arg);
+ rcube_log_bug($arg);
// display error page and terminate script
if ($terminate) {
@@ -2035,13 +2027,20 @@ function raise_error($arg=array(), $log=false, $terminate=false)
* @return void
* @see raise_error()
*/
-function log_bug($arg_arr)
+function rcube_log_bug($arg_arr)
{
global $CONFIG;
+
$program = strtoupper($arg_arr['type']);
+ $level = $CONFIG['debug_level'];
+
+ // disable errors for ajax requests, write to log instead (#1487831)
+ if (($level & 4) && !empty($_REQUEST['_remote'])) {
+ $level = ($level ^ 4) | 1;
+ }
// write error to local log file
- if ($CONFIG['debug_level'] & 1) {
+ if ($level & 1) {
$post_query = ($_SERVER['REQUEST_METHOD'] == 'POST' ? '?_task='.urlencode($_POST['_task']).'&_action='.urlencode($_POST['_action']) : '');
$log_entry = sprintf("%s Error: %s%s (%s %s)",
$program,
@@ -2056,13 +2055,13 @@ function log_bug($arg_arr)
}
}
- // resport the bug to the global bug reporting system
- if ($CONFIG['debug_level'] & 2) {
+ // report the bug to the global bug reporting system
+ if ($level & 2) {
// TODO: Send error via HTTP
}
// show error if debug_mode is on
- if ($CONFIG['debug_level'] & 4) {
+ if ($level & 4) {
print "$program Error";
if (!empty($arg_arr['file']) && !empty($arg_arr['line']))
diff --git a/program/include/rcube_config.php b/program/include/rcube_config.php
index 5d176053e..31608a3cc 100644
--- a/program/include/rcube_config.php
+++ b/program/include/rcube_config.php
@@ -87,12 +87,9 @@ class rcube_config
ini_set('error_log', $this->prop['log_dir'].'/errors');
}
}
- if ($this->prop['debug_level'] & 4) {
- ini_set('display_errors', 1);
- }
- else {
- ini_set('display_errors', 0);
- }
+
+ // enable display_errors in 'show' level, but not for ajax requests
+ ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4)));
// export config data
$GLOBALS['CONFIG'] = &$this->prop;