summaryrefslogtreecommitdiff
path: root/program/include
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2011-11-09 10:03:54 +0000
committeralecpl <alec@alec.pl>2011-11-09 10:03:54 +0000
commit51f7a5b2a09777d3a279757af620e42985ff9a86 (patch)
tree1b4700d4e4f3e5277dcb9877118acc1ee9098b74 /program/include
parent69cb80b0594add4d18f8de6b5c676f1dc4d0a835 (diff)
- Apply fixes from trunk up to r5401
Diffstat (limited to 'program/include')
-rw-r--r--program/include/main.inc86
-rw-r--r--program/include/rcmail.php1
-rw-r--r--program/include/rcube_contacts.php2
-rw-r--r--program/include/rcube_imap.php83
-rw-r--r--program/include/rcube_imap_generic.php56
-rw-r--r--program/include/rcube_ldap.php12
-rw-r--r--program/include/rcube_mdb2.php61
-rw-r--r--program/include/rcube_string_replacer.php2
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('&nbsp;', $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('&nbsp;', $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 = "/("