diff options
author | alecpl <alec@alec.pl> | 2011-11-09 10:03:54 +0000 |
---|---|---|
committer | alecpl <alec@alec.pl> | 2011-11-09 10:03:54 +0000 |
commit | 51f7a5b2a09777d3a279757af620e42985ff9a86 (patch) | |
tree | 1b4700d4e4f3e5277dcb9877118acc1ee9098b74 /program/include | |
parent | 69cb80b0594add4d18f8de6b5c676f1dc4d0a835 (diff) |
- Apply fixes from trunk up to r5401
Diffstat (limited to 'program/include')
-rw-r--r-- | program/include/main.inc | 86 | ||||
-rw-r--r-- | program/include/rcmail.php | 1 | ||||
-rw-r--r-- | program/include/rcube_contacts.php | 2 | ||||
-rw-r--r-- | program/include/rcube_imap.php | 83 | ||||
-rw-r--r-- | program/include/rcube_imap_generic.php | 56 | ||||
-rw-r--r-- | program/include/rcube_ldap.php | 12 | ||||
-rw-r--r-- | program/include/rcube_mdb2.php | 61 | ||||
-rw-r--r-- | program/include/rcube_string_replacer.php | 2 |
8 files changed, 179 insertions, 124 deletions
diff --git a/program/include/main.inc b/program/include/main.inc index 3980794eb..95d422d6a 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -1018,15 +1018,15 @@ function rcube_strtotime($date) * Convert the given date to a human readable form * This uses the date formatting properties from config * - * @param mixed Date representation (string or timestamp) + * @param mixed Date representation (string or timestamp) * @param string Date format to use + * @param bool Enables date convertion according to user timezone + * * @return string Formatted date string */ -function format_date($date, $format=NULL) +function format_date($date, $format=NULL, $convert=true) { global $RCMAIL, $CONFIG; - - $ts = NULL; if (!empty($date)) $ts = rcube_strtotime($date); @@ -1034,23 +1034,29 @@ function format_date($date, $format=NULL) if (empty($ts)) return ''; - // get user's timezone offset - $tz = $RCMAIL->config->get_timezone(); - - // convert time to user's timezone - $timestamp = $ts - date('Z', $ts) + ($tz * 3600); + if ($convert) { + // get user's timezone offset + $tz = $RCMAIL->config->get_timezone(); - // get current timestamp in user's timezone - $now = time(); // local time - $now -= (int)date('Z'); // make GMT time - $now += ($tz * 3600); // user's time - $now_date = getdate($now); + // convert time to user's timezone + $timestamp = $ts - date('Z', $ts) + ($tz * 3600); - $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']); - $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); + // get current timestamp in user's timezone + $now = time(); // local time + $now -= (int)date('Z'); // make GMT time + $now += ($tz * 3600); // user's time + } + else { + $now = time(); + $timestamp = $ts; + } // define date format depending on current time if (!$format) { + $now_date = getdate($now); + $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']); + $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']); + if ($CONFIG['prettydate'] && $timestamp > $today_limit && $timestamp < $now) { $format = $RCMAIL->config->get('date_today', $RCMAIL->config->get('time_format', 'H:i')); $today = true; @@ -1226,7 +1232,7 @@ function rcmail_mailbox_select($p = array()) if ($p['noselection']) $select->add($p['noselection'], ''); - rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p['exceptions']); + rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p); return $select; } @@ -1275,9 +1281,9 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='') $path .= $prefix.$currentFolder; if (!isset($arrFolders[$currentFolder])) { - // Check \Noselect option (if options are in cache) - if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) { - $virtual = in_array('\\Noselect', $opts); + // Check \Noselect attribute (if attributes are in cache) + if (!$virtual && ($attrs = $RCMAIL->imap->mailbox_attributes($path))) { + $virtual = in_array('\\Noselect', $attrs); } $arrFolders[$currentFolder] = array( @@ -1396,30 +1402,40 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at * @access private * @return string */ -function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $exceptions=array()) +function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $opts=array()) { + global $RCMAIL; + $out = ''; foreach ($arrFolders as $key => $folder) { - if (empty($exceptions) || !in_array($folder['id'], $exceptions)) { - if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id']))) - $foldername = rcube_label($folder_class); - else { - $foldername = $folder['name']; - - // shorten the folder name to a given length - if ($maxlength && $maxlength>1) - $foldername = abbreviate_string($foldername, $maxlength); - } - - $select->add(str_repeat(' ', $nestLevel*4) . $foldername, $folder['id']); + // skip exceptions (and its subfolders) + if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) { + continue; } - else if ($nestLevel) + + // skip folders in which it isn't possible to create subfolders + if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id'])) + && in_array('\\Noinferiors', $attrs) + ) { continue; + } + + if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id']))) + $foldername = rcube_label($folder_class); + else { + $foldername = $folder['name']; + + // shorten the folder name to a given length + if ($maxlength && $maxlength>1) + $foldername = abbreviate_string($foldername, $maxlength); + } + + $select->add(str_repeat(' ', $nestLevel*4) . $foldername, $folder['id']); if (!empty($folder['folders'])) $out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength, - $select, $realnames, $nestLevel+1, $exceptions); + $select, $realnames, $nestLevel+1, $opts); } return $out; diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 1ecdfcde0..969e101f7 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -594,7 +594,6 @@ class rcmail return; $this->imap = new rcube_imap(); - $this->imap->debug_level = $this->config->get('debug_level'); $this->imap->skip_deleted = $this->config->get('skip_deleted'); // enable caching of imap data diff --git a/program/include/rcube_contacts.php b/program/include/rcube_contacts.php index a2eeffc8a..e822d2c24 100644 --- a/program/include/rcube_contacts.php +++ b/program/include/rcube_contacts.php @@ -41,7 +41,6 @@ class rcube_contacts extends rcube_addressbook private $user_id = 0; private $filter = null; private $result = null; - private $name; private $cache; private $table_cols = array('name', 'email', 'firstname', 'surname'); private $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'nickname', @@ -50,6 +49,7 @@ class rcube_contacts extends rcube_addressbook // public properties public $primary_key = 'contact_id'; + public $name; public $readonly = false; public $groups = true; public $undelete = true; diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index d2f954733..7508acda5 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -32,7 +32,6 @@ */ class rcube_imap { - public $debug_level = 1; public $skip_deleted = false; public $page_size = 10; public $list_page = 1; @@ -318,6 +317,19 @@ class rcube_imap /** + * Activate/deactivate debug mode + * + * @param boolean $dbg True if IMAP conversation should be logged + * @access public + */ + function set_debug($dbg = true) + { + $this->options['debug'] = $dbg; + $this->conn->setDebug($dbg, array($this, 'debug_handler')); + } + + + /** * Set default message charset * * This will be used for message decoding if a charset specification is not available @@ -3075,7 +3087,19 @@ class rcube_imap */ function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false) { - // @TODO: caching + $cache_key = $root.':'.$name; + if (!empty($filter)) { + $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter)); + } + $cache_key .= ':'.$rights; + $cache_key = 'mailboxes.list.'.md5($cache_key); + + // get cached folder list + $a_mboxes = $this->get_cache($cache_key); + if (is_array($a_mboxes)) { + return $a_mboxes; + } + // Give plugins a chance to provide a list of mailboxes $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list', array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST')); @@ -3097,6 +3121,11 @@ class rcube_imap array_unshift($a_mboxes, 'INBOX'); } + // cache folder attributes + if ($root == '' && $name == '*' && empty($filter)) { + $this->update_cache('mailboxes.attributes', $this->conn->data['LIST']); + } + // filter folders list according to rights requirements if ($rights && $this->get_capability('ACL')) { $a_folders = $this->filter_rights($a_folders, $rights); @@ -3107,6 +3136,9 @@ class rcube_imap $a_mboxes = $this->_sort_mailbox_list($a_mboxes); } + // write mailboxlist to cache + $this->update_cache($cache_key, $a_mboxes); + return $a_mboxes; } @@ -3438,30 +3470,29 @@ class rcube_imap /** - * Gets folder options from LIST response, e.g. \Noselect, \Noinferiors + * Gets folder attributes from LIST response, e.g. \Noselect, \Noinferiors * * @param string $mailbox Folder name - * @param bool $force Set to True if options should be refreshed - * Options are available after LIST command only + * @param bool $force Set to True if attributes should be refreshed * * @return array Options list */ - function mailbox_options($mailbox, $force=false) + function mailbox_attributes($mailbox, $force=false) { - if ($mailbox == 'INBOX') { - return array(); + // get attributes directly from LIST command + if (!empty($this->conn->data['LIST']) && is_array($this->conn->data['LIST'][$mailbox])) { + $opts = $this->conn->data['LIST'][$mailbox]; } - - if (!is_array($this->conn->data['LIST']) || !is_array($this->conn->data['LIST'][$mailbox])) { - if ($force) { - $this->conn->listMailboxes('', $mailbox); - } - else { - return array(); - } + // get cached folder attributes + else if (!$force) { + $opts = $this->get_cache('mailboxes.attributes'); + $opts = $opts[$mailbox]; } - $opts = $this->conn->data['LIST'][$mailbox]; + if (!is_array($opts)) { + $this->conn->listMailboxes('', $mailbox); + $opts = $this->conn->data['LIST'][$mailbox]; + } return is_array($opts) ? $opts : array(); } @@ -3544,17 +3575,17 @@ class rcube_imap } } - $options['name'] = $mailbox; - $options['options'] = $this->mailbox_options($mailbox, true); - $options['namespace'] = $this->mailbox_namespace($mailbox); - $options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array(); - $options['special'] = in_array($mailbox, $this->default_folders); + $options['name'] = $mailbox; + $options['attributes'] = $this->mailbox_attributes($mailbox, true); + $options['namespace'] = $this->mailbox_namespace($mailbox); + $options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array(); + $options['special'] = in_array($mailbox, $this->default_folders); // Set 'noselect' and 'norename' flags - if (is_array($options['options'])) { - foreach ($options['options'] as $opt) { - $opt = strtolower($opt); - if ($opt == '\noselect' || $opt == '\nonexistent') { + if (is_array($options['attributes'])) { + foreach ($options['attributes'] as $attrib) { + $attrib = strtolower($attrib); + if ($attrib == '\noselect' || $attrib == '\nonexistent') { $options['noselect'] = true; } } diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php index 5c7a41c73..a4e921fe6 100644 --- a/program/include/rcube_imap_generic.php +++ b/program/include/rcube_imap_generic.php @@ -2242,12 +2242,29 @@ class rcube_imap_generic list($code, $response) = $this->execute($subscribed ? 'LSUB' : 'LIST', $args); if ($code == self::ERROR_OK) { - $folders = array(); - while ($this->tokenizeResponse($response, 1) == '*') { - $cmd = strtoupper($this->tokenizeResponse($response, 1)); + $folders = array(); + $last = 0; + $pos = 0; + $response .= "\r\n"; + + while ($pos = strpos($response, "\r\n", $pos+1)) { + // literal string, not real end-of-command-line + if ($response[$pos-1] == '}') { + continue; + } + + $line = substr($response, $last, $pos - $last); + $last = $pos + 2; + + if (!preg_match('/^\* (LIST|LSUB|STATUS) /i', $line, $m)) { + continue; + } + $cmd = strtoupper($m[1]); + $line = substr($line, strlen($m[0])); + // * LIST (<options>) <delimiter> <mailbox> if ($cmd == 'LIST' || $cmd == 'LSUB') { - list($opts, $delim, $mailbox) = $this->tokenizeResponse($response, 3); + list($opts, $delim, $mailbox) = $this->tokenizeResponse($line, 3); // Add to result array if (!$lstatus) { @@ -2258,31 +2275,21 @@ class rcube_imap_generic } // Add to options array - if (!empty($opts)) { - if (empty($this->data['LIST'][$mailbox])) - $this->data['LIST'][$mailbox] = $opts; - else - $this->data['LIST'][$mailbox] = array_unique(array_merge( - $this->data['LIST'][$mailbox], $opts)); - } + if (empty($this->data['LIST'][$mailbox])) + $this->data['LIST'][$mailbox] = $opts; + else if (!empty($opts)) + $this->data['LIST'][$mailbox] = array_unique(array_merge( + $this->data['LIST'][$mailbox], $opts)); } // * STATUS <mailbox> (<result>) else if ($cmd == 'STATUS') { - list($mailbox, $status) = $this->tokenizeResponse($response, 2); + list($mailbox, $status) = $this->tokenizeResponse($line, 2); for ($i=0, $len=count($status); $i<$len; $i += 2) { list($name, $value) = $this->tokenizeResponse($status, 2); $folders[$mailbox][$name] = $value; } } - // other untagged response line, skip it - else { - $response = ltrim($response); - if (($position = strpos($response, "\n")) !== false) - $response = substr($response, $position+1); - else - $response = ''; - } } return $folders; @@ -3392,15 +3399,10 @@ class rcube_imap_generic // String atom, number, NIL, *, % default: - // empty or one character - if ($str === '') { + // empty string + if ($str === '' || $str === null) { break 2; } - if (strlen($str) < 2) { - $result[] = $str; - $str = ''; - break; - } // excluded chars: SP, CTL, ), [, ] if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) { diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index e20c8b430..00ee1c87b 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -1342,6 +1342,18 @@ class rcube_ldap extends rcube_addressbook /** + * Activate/deactivate debug mode + * + * @param boolean $dbg True if LDAP commands should be logged + * @access public + */ + function set_debug($dbg = true) + { + $this->debug = $dbg; + } + + + /** * Quotes attribute value string * * @param string $str Attribute value diff --git a/program/include/rcube_mdb2.php b/program/include/rcube_mdb2.php index b3976c37d..3b7a6129b 100644 --- a/program/include/rcube_mdb2.php +++ b/program/include/rcube_mdb2.php @@ -35,16 +35,16 @@ */ class rcube_mdb2 { - var $db_dsnw; // DSN for write operations - var $db_dsnr; // DSN for read operations - var $db_connected = false; // Already connected ? - var $db_mode = ''; // Connection mode - var $db_handle = 0; // Connection handle - var $db_error = false; - var $db_error_msg = ''; + public $db_dsnw; // DSN for write operations + public $db_dsnr; // DSN for read operations + public $db_connected = false; // Already connected ? + public $db_mode = ''; // Connection mode + public $db_handle = 0; // Connection handle + public $db_error = false; + public $db_error_msg = ''; private $debug_mode = false; - private $write_failure = false; + private $conn_failure = false; private $a_query_results = array('dummy'); private $last_res_id = 0; private $tables; @@ -58,7 +58,7 @@ class rcube_mdb2 */ function __construct($db_dsnw, $db_dsnr='', $pconn=false) { - if ($db_dsnr == '') + if (empty($db_dsnr)) $db_dsnr = $db_dsnw; $this->db_dsnw = $db_dsnw; @@ -122,30 +122,33 @@ class rcube_mdb2 */ function db_connect($mode) { + // previous connection failed, don't attempt to connect again + if ($this->conn_failure) { + return; + } + + // no replication + if ($this->db_dsnw == $this->db_dsnr) { + $mode = 'w'; + } + // Already connected if ($this->db_connected) { - // connected to read-write db, current connection is ok - if ($this->db_mode == 'w' && !$this->write_failure) - return; - - // no replication, current connection is ok for read and write - if (empty($this->db_dsnr) || $this->db_dsnw == $this->db_dsnr) { - $this->db_mode = 'w'; + // connected to db with the same or "higher" mode + if ($this->db_mode == 'w' || $this->db_mode == $mode) { return; } - - // Same mode, current connection is ok - if ($this->db_mode == $mode) - return; } $dsn = ($mode == 'r') ? $this->db_dsnr : $this->db_dsnw; - $this->db_handle = $this->dsn_connect($dsn); + $this->db_handle = $this->dsn_connect($dsn); $this->db_connected = !PEAR::isError($this->db_handle); if ($this->db_connected) - $this->db_mode = $mode; + $this->db_mode = $mode; + else + $this->conn_failure = true; } @@ -256,10 +259,6 @@ class rcube_mdb2 // Read or write ? $mode = (strtolower(substr(trim($query),0,6)) == 'select') ? 'r' : 'w'; - // don't event attempt to connect if previous write-operation failed - if ($this->write_failure && $mode == 'w') - return false; - $this->db_connect($mode); // check connection before proceeding @@ -284,7 +283,7 @@ class rcube_mdb2 raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $this->db_error_msg), true, false); - + $result = false; } else { @@ -293,10 +292,6 @@ class rcube_mdb2 } } - // remember that write-operation failed - if ($mode == 'w' && ($result === false || PEAR::isError($result))) - $this->write_failure = true; - // add result, even if it's an error return $this->_add_result($result); } @@ -447,7 +442,7 @@ class rcube_mdb2 if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) { return $result; } - + return null; } @@ -530,7 +525,7 @@ class rcube_mdb2 */ function now() { - switch($this->db_provider) { + switch ($this->db_provider) { case 'mssql': case 'sqlsrv': return "getdate()"; diff --git a/program/include/rcube_string_replacer.php b/program/include/rcube_string_replacer.php index 5d743bfff..8997ca342 100644 --- a/program/include/rcube_string_replacer.php +++ b/program/include/rcube_string_replacer.php @@ -39,7 +39,7 @@ class rcube_string_replacer // Support unicode/punycode in top-level domain part $utf_domain = '[^?&@"\'\\/()\s\r\t\n]+\\.([^\\x00-\\x2f\\x3b-\\x40\\x5b-\\x60\\x7b-\\x7f]{2,}|xn--[a-z0-9]{2,})'; $url1 = '.:;,'; - $url2 = 'a-z0-9%=#@+?&\\/_~\\[\\]-'; + $url2 = 'a-z0-9%=#@+?&\\/_~\\[\\]{}-'; $this->link_pattern = "/([\w]+:\/\/|\Wwww\.)($utf_domain([$url1]?[$url2]+)*)/i"; $this->mailto_pattern = "/(" |