From e70d6ea64e711096af36b1234f8545b870ea5f45 Mon Sep 17 00:00:00 2001 From: thomascube Date: Sat, 5 Apr 2008 12:49:21 +0000 Subject: Apply changes from trunk to 0.1-stable --- program/include/main.inc | 27 +++++++++++------ program/include/rcube_db.inc | 12 +++++++- program/include/rcube_imap.inc | 63 +++++++++++++++++++++++++++------------- program/include/rcube_ldap.inc | 16 +++++----- program/include/rcube_mdb2.inc | 52 +++++++++++++++++++++++++++++++-- program/include/rcube_shared.inc | 3 ++ program/include/rcube_user.inc | 4 +-- 7 files changed, 135 insertions(+), 42 deletions(-) (limited to 'program/include') diff --git a/program/include/main.inc b/program/include/main.inc index f3d0e263b..1d35682ce 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -74,6 +74,7 @@ function rcmail_startup($task='mail') $DB = new $dbclass($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']); $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql'; + $DB->set_debug((bool)$CONFIG['sql_debug']); $DB->db_connect('w'); // use database for storing session data @@ -289,6 +290,9 @@ function rcmail_imap_init($connect=FALSE) function rcmail_set_imap_prop() { global $CONFIG, $IMAP; + + if (!empty($CONFIG['default_charset'])) + $IMAP->set_charset($CONFIG['default_charset']); // set root dir from config if (!empty($CONFIG['imap_root'])) @@ -955,22 +959,23 @@ function rcube_charset_convert($str, $from, $to=NULL) 'X-USER-DEFINED' => 'ISO-8859-15', 'ISO-8859-8-I' => 'ISO-8859-8', 'KS_C_5601-1987' => 'EUC-KR', - 'GB2312' => 'GB18030' ); // convert charset using iconv module if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') { + $aliases['GB2312'] = 'GB18030'; return iconv(($aliases[$from] ? $aliases[$from] : $from), ($aliases[$to] ? $aliases[$to] : $to) . "//IGNORE", $str); } // convert charset using mbstring module if ($MBSTRING) { - $mb_map = $aliases + array('UTF-7' => 'UTF7-IMAP'); + $aliases['UTF-7'] = 'UTF7-IMAP'; + $aliases['WINDOWS-1257'] = 'ISO-8859-13'; // return if convert succeeded - if (($out = mb_convert_encoding($str, ($mb_map[$to] ? $mb_map[$to] : $to), ($mb_map[$from] ? $mb_map[$from] : $from))) != '') + if (($out = mb_convert_encoding($str, ($aliases[$to] ? $aliases[$to] : $to), ($aliases[$from] ? $aliases[$from] : $from))) != '') return $out; } @@ -1372,6 +1377,7 @@ function rcmail_mail_domain($host) /** * Replace all css definitions with #container [def] + * and remove css-inlined scripting * * @param string CSS source code * @param string Container ID to use as prefix @@ -1381,6 +1387,10 @@ function rcmail_mod_css_styles($source, $container_id, $base_url = '') { $a_css_values = array(); $last_pos = 0; + + // ignore the whole block if evil styles are detected + if (stristr($source, 'expression') || stristr($source, 'behavior')) + return ''; // cut out all contents between { and } while (($pos = strpos($source, '{', $last_pos)) && ($pos2 = strpos($source, '}', $pos))) @@ -1391,7 +1401,7 @@ function rcmail_mod_css_styles($source, $container_id, $base_url = '') $last_pos = $pos+2; } - // remove html commends and add #container to each tag selector. + // remove html comments and add #container to each tag selector. // also replace body definition because we also stripped off the tag $styles = preg_replace( array( @@ -1562,7 +1572,10 @@ function format_date($date, $format=NULL) function format_email_recipient($email, $name='') { if ($name && $name != $email) - return sprintf('%s <%s>', strpos($name, ",") ? '"'.$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, $email); + } else return $email; } @@ -1787,10 +1800,6 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, $maxlength, $ } } - // add unread message count display - if ($unread_count = $IMAP->messagecount($folder['id'], 'RECENT', ($folder['id']==$mbox_name))) - $foldername .= sprintf(' (%d)', $unread_count); - // make folder name safe for ids and class names $folder_id = preg_replace('/[^A-Za-z0-9\-_]/', '', $folder['id']); $class_name = preg_replace('/[^a-z0-9\-_]/', '', $folder_class ? $folder_class : strtolower($folder['id'])); diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.inc index 4c3e9fc62..63c6759b9 100644 --- a/program/include/rcube_db.inc +++ b/program/include/rcube_db.inc @@ -153,8 +153,18 @@ class rcube_db $this->db_handle = $this->dsn_connect($dsn); $this->db_connected = $this->db_handle ? TRUE : FALSE; } + + + /** + * Activate/deactivate debug mode + * (not implemented) + */ + function set_debug($dbg = true) + { - + } + + /** * Getter for error state * diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index dce778968..9a594854c 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.inc @@ -51,6 +51,7 @@ class rcube_imap var $sort_order = 'DESC'; var $delimiter = NULL; var $caching_enabled = FALSE; + var $default_charset = 'ISO-8859-1'; var $default_folders = array('INBOX'); var $default_folders_lc = array('inbox'); var $cache = array(); @@ -203,6 +204,20 @@ class rcube_imap } + /** + * Set default message charset + * + * This will be used for message decoding if a charset specification is not available + * + * @param string Charset string + * @access public + */ + function set_charset($cs) + { + $this->default_charset = $ch; + } + + /** * This list of folders will be listed above all other folders * @@ -1146,7 +1161,7 @@ class rcube_imap // normalize filename property if ($filename_mime = $struct->d_parameters['filename'] ? $struct->d_parameters['filename'] : $struct->ctype_parameters['name']) - $struct->filename = $this->decode_mime_string($filename_mime); + $struct->filename = rcube_imap::decode_mime_string($filename_mime, $this->default_charset); else if ($filename_encoded = $struct->d_parameters['filename*'] ? $struct->d_parameters['filename*'] : $struct->ctype_parameters['name*']) { // decode filename according to RFC 2231, Section 4 @@ -1154,7 +1169,7 @@ class rcube_imap $struct->filename = rcube_charset_convert(urldecode($filename_urlencoded), $filename_charset); } else if (!empty($struct->headers['content-description'])) - $struct->filename = $this->decode_mime_string($struct->headers['content-description']); + $struct->filename = rcube_imap::decode_mime_string($struct->headers['content-description'], $this->default_charset); return $struct; } @@ -1241,9 +1256,9 @@ class rcube_imap // convert charset (if text or message part) if ($o_part->ctype_primary=='text' || $o_part->ctype_primary=='message') { - // assume ISO-8859-1 if no charset specified + // assume default if no charset specified if (empty($o_part->charset)) - $o_part->charset = 'ISO-8859-1'; + $o_part->charset = $this->default_charset; $body = rcube_charset_convert($body, $o_part->charset); } @@ -1633,16 +1648,14 @@ class rcube_imap /** * Subscribe to a specific mailbox(es) * - * @param string Mailbox name(s) + * @param array Mailbox name(s) * @return boolean True on success */ - function subscribe($mbox_name) + function subscribe($a_mboxes) { - if (is_array($mbox_name)) - $a_mboxes = $mbox_name; - else if (is_string($mbox_name) && strlen($mbox_name)) - $a_mboxes = explode(',', $mbox_name); - + if (!is_array($a_mboxes)) + $a_mboxes = array($a_mboxes); + // let this common function do the main work return $this->_change_subscription($a_mboxes, 'subscribe'); } @@ -1651,15 +1664,13 @@ class rcube_imap /** * Unsubscribe mailboxes * - * @param string Mailbox name(s) + * @param array Mailbox name(s) * @return boolean True on success */ - function unsubscribe($mbox_name) + function unsubscribe($a_mboxes) { - if (is_array($mbox_name)) - $a_mboxes = $mbox_name; - else if (is_string($mbox_name) && strlen($mbox_name)) - $a_mboxes = explode(',', $mbox_name); + if (!is_array($a_mboxes)) + $a_mboxes = array($a_mboxes); // let this common function do the main work return $this->_change_subscription($a_mboxes, 'unsubscribe'); @@ -2213,6 +2224,9 @@ class rcube_imap */ function remove_message_cache($key, $index) { + if (!$this->caching_enabled) + return; + $this->db->query( "DELETE FROM ".get_table_name('messages')." WHERE user_id=? @@ -2228,6 +2242,9 @@ class rcube_imap */ function clear_message_cache($key, $start_index=1) { + if (!$this->caching_enabled) + return; + $this->db->query( "DELETE FROM ".get_table_name('messages')." WHERE user_id=? @@ -2257,6 +2274,8 @@ class rcube_imap { $a = $this->_parse_address_list($input, $decode); $out = array(); + // Special chars as defined by RFC 822 need to in quoted string (or escaped). + $special_chars = '[\(\)\<\>\\\.\[\]@,;:"]'; if (!is_array($a)) return $out; @@ -2270,7 +2289,7 @@ class rcube_imap $address = $val['address']; $name = preg_replace(array('/^[\'"]/', '/[\'"]$/'), '', trim($val['name'])); if ($name && $address && $name != $address) - $string = sprintf('%s <%s>', strpos($name, ',')!==FALSE ? '"'.$name.'"' : $name, $address); + $string = sprintf('%s <%s>', preg_match("/$special_chars/", $name) ? '"'.addcslashes($name, '"').'"' : $name, $address); else if ($address) $string = $address; else if ($name) @@ -2297,7 +2316,7 @@ class rcube_imap */ function decode_header($input, $remove_quotes=FALSE) { - $str = $this->decode_mime_string((string)$input); + $str = rcube_imap::decode_mime_string((string)$input, $this->default_charset); if ($str{0}=='"' && $remove_quotes) $str = str_replace('"', '', $str); @@ -2320,6 +2339,10 @@ class rcube_imap $pos = strpos($input, '=?'); if ($pos !== false) { + // rfc: all line breaks or other characters not found in the Base64 Alphabet must be ignored by decoding software + // delete all blanks between MIME-lines, differently we can receive unnecessary blanks and broken utf-8 symbols + $input = preg_replace("/\?=\s+=\?/", '?==?', $input); + $out = substr($input, 0, $pos); $end_cs_pos = strpos($input, "?", $pos+2); @@ -2414,7 +2437,7 @@ class rcube_imap return rcube_charset_convert($body, $ctype_param['charset']); // defaults to what is specified in the class header - return rcube_charset_convert($body, 'ISO-8859-1'); + return rcube_charset_convert($body, $this->default_charset); } diff --git a/program/include/rcube_ldap.inc b/program/include/rcube_ldap.inc index 29e7faa6b..969101b2a 100644 --- a/program/include/rcube_ldap.inc +++ b/program/include/rcube_ldap.inc @@ -119,20 +119,20 @@ class rcube_ldap */ function bind($dn, $pass) { - if (!$this->conn) + if (!$this->conn) { return false; + } - if (@ldap_bind($this->conn, $dn, $pass)) + if (ldap_bind($this->conn, $dn, $pass)) { return true; - else - { - raise_error(array( + } + + raise_error(array( 'code' => ldap_errno($this->conn), 'type' => 'ldap', 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)), - true); - } - + true); + return false; } diff --git a/program/include/rcube_mdb2.inc b/program/include/rcube_mdb2.inc index 63d156a08..72d906664 100644 --- a/program/include/rcube_mdb2.inc +++ b/program/include/rcube_mdb2.inc @@ -48,6 +48,7 @@ class rcube_mdb2 var $db_handle = 0; // Connection handle var $db_error = false; var $db_error_msg = ''; + var $debug_mode = false; var $a_query_results = array('dummy'); var $last_res_id = 0; @@ -94,8 +95,11 @@ class rcube_mdb2 function dsn_connect($dsn) { // Use persistent connections if available - $dbh = MDB2::connect($dsn, - array('persistent' => $this->db_pconn, + $dbh = MDB2::connect($dsn, array( + 'persistent' => $this->db_pconn, + 'emulate_prepared' => $this->debug_mode, + 'debug' => $this->debug_mode, + 'debug_handler' => 'mdb2_debug_handler', 'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL)); if (MDB2::isError($dbh)) @@ -156,6 +160,21 @@ class rcube_mdb2 } + /** + * Activate/deactivate debug mode + * + * @param boolean True if SQL queries should be logged + */ + function set_debug($dbg = true) + { + $this->debug_mode = $dbg; + if ($this->db_connected) + { + $this->db_handle->setOption('debug', $dbg); + $this->db_handle->setOption('emulate_prepared', $dbg); + } + } + /** * Getter for error state @@ -413,6 +432,22 @@ class rcube_mdb2 return $this->db_handle->quoteIdentifier($str); } + /** + * Escapes a string + * + * @param string The string to be escaped + * @return string The escaped string + * @access public + * @since 0.1.1 + */ + function escapeSimple($str) + { + if (!$this->db_handle) + $this->db_connect('r'); + + return $this->db_handle->escape($str); + } + /** * Return SQL function for current time and date @@ -569,4 +604,17 @@ class rcube_mdb2 } // end class rcube_db + +/* this is our own debug handler for the MDB2 connection */ +function mdb2_debug_handler(&$db, $scope, $message, $context = array()) +{ + if ($scope != 'prepare') + { + $debug_output = $scope . '('.$db->db_index.'): '; + $debug_output .= $message . $db->getOption('log_line_break'); + write_log('sqllog', $debug_output); + } +} + + ?> diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index bec254661..815331195 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -262,7 +262,10 @@ function send_modified_header($mdate, $etag=null) header("Etag: $etag"); if ($iscached) + { + ob_end_clean(); exit; + } } diff --git a/program/include/rcube_user.inc b/program/include/rcube_user.inc index 41b424f1d..e748758a9 100644 --- a/program/include/rcube_user.inc +++ b/program/include/rcube_user.inc @@ -361,7 +361,7 @@ class rcube_user // try to resolve user in virtusertable if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@')) - $user_email = self::user2email($user); + $user_email = rcube_user::user2email($user); $DB->query( "INSERT INTO ".get_table_name('users')." @@ -468,7 +468,7 @@ class rcube_user $arr = preg_split('/\s+/', $data); if (count($arr) > 0) { - $email = trim($arr[0]); + $email = trim(str_replace('\\@', '@', $arr[0])); break; } } -- cgit v1.2.3