Add option to hide folders in share/other-user namespace or outside of the personal namespace root (#5073)

pull/6273/head^2
Aleksander Machniak 6 years ago
parent 5e3868eb10
commit 58e514970e

@ -26,6 +26,7 @@ CHANGELOG Roundcube Webmail
- Extend disabled_actions config so it accepts also button names (#5903) - Extend disabled_actions config so it accepts also button names (#5903)
- Handle remote stylesheets the same as remote images, ask the user to allow them (#5994) - Handle remote stylesheets the same as remote images, ask the user to allow them (#5994)
- Add Message-ID to the sendmail log (#5871) - Add Message-ID to the sendmail log (#5871)
- Add option to hide folders in share/other-user namespace or outside of the personal namespace root (#5073)
- Archive: Fix archiving by sender address on cyrus-imap - Archive: Fix archiving by sender address on cyrus-imap
- Archive: Style Archive folder also on folder selector and folder manager lists - Archive: Style Archive folder also on folder selector and folder manager lists
- Archive: Add Thunderbird compatible Month option (#5623) - Archive: Add Thunderbird compatible Month option (#5623)

@ -59,8 +59,6 @@ class rcube_imap extends rcube_storage
protected $plugins; protected $plugins;
protected $delimiter; protected $delimiter;
protected $namespace; protected $namespace;
protected $sort_field = '';
protected $sort_order = 'DESC';
protected $struct_charset; protected $struct_charset;
protected $search_set; protected $search_set;
protected $search_string = ''; protected $search_string = '';
@ -68,10 +66,14 @@ class rcube_imap extends rcube_storage
protected $search_sort_field = ''; protected $search_sort_field = '';
protected $search_threads = false; protected $search_threads = false;
protected $search_sorted = false; protected $search_sorted = false;
protected $sort_field = '';
protected $sort_order = 'DESC';
protected $options = array('auth_type' => 'check'); protected $options = array('auth_type' => 'check');
protected $caching = false; protected $caching = false;
protected $messages_caching = false; protected $messages_caching = false;
protected $threading = false; protected $threading = false;
protected $list_excludes = array();
protected $list_root;
/** /**
@ -90,6 +92,9 @@ class rcube_imap extends rcube_storage
if (isset($_SESSION['imap_delimiter'])) { if (isset($_SESSION['imap_delimiter'])) {
$this->delimiter = $_SESSION['imap_delimiter']; $this->delimiter = $_SESSION['imap_delimiter'];
} }
if (!empty($_SESSION['imap_list_conf'])) {
list($this->list_root, $this->list_excludes) = $_SESSION['imap_list_conf'];
}
} }
/** /**
@ -501,9 +506,9 @@ class rcube_imap extends rcube_storage
} }
else { else {
$this->namespace = array( $this->namespace = array(
'personal' => NULL, 'personal' => null,
'other' => NULL, 'other' => null,
'shared' => NULL, 'shared' => null,
); );
} }
@ -520,23 +525,46 @@ class rcube_imap extends rcube_storage
$this->delimiter = '/'; $this->delimiter = '/';
} }
$this->list_root = null;
$this->list_excludes = array();
// Overwrite namespaces // Overwrite namespaces
if ($imap_personal !== null) { if ($imap_personal !== null) {
$this->namespace['personal'] = NULL; $this->namespace['personal'] = null;
foreach ((array)$imap_personal as $dir) { foreach ((array)$imap_personal as $dir) {
$this->namespace['personal'][] = array($dir, $this->delimiter); $this->namespace['personal'][] = array($dir, $this->delimiter);
} }
} }
if ($imap_other !== null) {
$this->namespace['other'] = NULL; if ($imap_other === false) {
foreach ((array) $this->namespace['other'] as $dir) {
if (is_array($dir) && $dir[0]) {
$this->list_excludes[] = $dir[0];
}
}
$this->namespace['other'] = null;
}
else if ($imap_other !== null) {
$this->namespace['other'] = null;
foreach ((array)$imap_other as $dir) { foreach ((array)$imap_other as $dir) {
if ($dir) { if ($dir) {
$this->namespace['other'][] = array($dir, $this->delimiter); $this->namespace['other'][] = array($dir, $this->delimiter);
} }
} }
} }
if ($imap_shared !== null) {
$this->namespace['shared'] = NULL; if ($imap_shared === false) {
foreach ((array) $this->namespace['shared'] as $dir) {
if (is_array($dir) && $dir[0]) {
$this->list_excludes[] = $dir[0];
}
}
$this->namespace['shared'] = null;
}
else if ($imap_shared !== null) {
$this->namespace['shared'] = null;
foreach ((array)$imap_shared as $dir) { foreach ((array)$imap_shared as $dir) {
if ($dir) { if ($dir) {
$this->namespace['shared'][] = array($dir, $this->delimiter); $this->namespace['shared'][] = array($dir, $this->delimiter);
@ -544,6 +572,18 @@ class rcube_imap extends rcube_storage
} }
} }
// Performance optimization for case where we have no shared/other namespace
// and personal namespace has one prefix (#5073)
// In such a case we can tell the server to return only content of the
// specified folder in LIST/LSUB, no post-filtering
if (empty($this->namespace['other']) && empty($this->nmespace['shared'])
&& !empty($this->namespace['personal']) && count($this->namespace['personal']) === 1
&& strlen($this->namespace['personal'][0][0]) > 1
) {
$this->list_root = $this->namespace['personal'][0][0];
$this->list_excludes = array();
}
// Find personal namespace prefix(es) for self::mod_folder() // Find personal namespace prefix(es) for self::mod_folder()
if (is_array($this->namespace['personal']) && !empty($this->namespace['personal'])) { if (is_array($this->namespace['personal']) && !empty($this->namespace['personal'])) {
// There can be more than one namespace root, // There can be more than one namespace root,
@ -566,6 +606,7 @@ class rcube_imap extends rcube_storage
$_SESSION['imap_namespace'] = $this->namespace; $_SESSION['imap_namespace'] = $this->namespace;
$_SESSION['imap_delimiter'] = $this->delimiter; $_SESSION['imap_delimiter'] = $this->delimiter;
$_SESSION['imap_list_conf'] = array($this->list_root, $this->list_excludes);
} }
/** /**
@ -2887,33 +2928,28 @@ class rcube_imap extends rcube_storage
} }
$config = rcube::get_instance()->config; $config = rcube::get_instance()->config;
$list_root = $root === '' && $this->list_root ? $this->list_root : $root;
// Server supports LIST-EXTENDED, we can use selection options // Server supports LIST-EXTENDED, we can use selection options
// #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED // #1486225: Some dovecot versions return wrong result using LIST-EXTENDED
$list_extended = !$config->get('imap_force_lsub') && $this->get_capability('LIST-EXTENDED'); $list_extended = !$config->get('imap_force_lsub') && $this->get_capability('LIST-EXTENDED');
if ($list_extended) { if ($list_extended) {
// This will also set folder options, LSUB doesn't do that // This will also set folder options, LSUB doesn't do that
$result = $this->conn->listMailboxes($root, $name, $result = $this->conn->listMailboxes($list_root, $name,
NULL, array('SUBSCRIBED')); NULL, array('SUBSCRIBED'));
} }
else { else {
// retrieve list of folders from IMAP server using LSUB // retrieve list of folders from IMAP server using LSUB
$result = $this->conn->listSubscribed($root, $name); $result = $this->conn->listSubscribed($list_root, $name);
} }
if (!is_array($result)) { if (!is_array($result)) {
return array(); return array();
} }
// #1486796: some server configurations doesn't return folders in all namespaces // Add/Remove folders according to some configuration options
if ($root == '' && $name == '*' && $config->get('imap_force_ns')) { $this->list_folders_filter($result, $root . $name, ($list_extended ? 'ext-' : '') . 'subscribed');
$this->list_folders_update($result, ($list_extended ? 'ext-' : '') . 'subscribed');
}
// Remove hidden folders
if ($config->get('imap_skip_hidden_folders')) {
$result = array_filter($result, function($v) { return $v[0] != '.'; });
}
if ($list_extended) { if ($list_extended) {
// unsubscribe non-existent folders, remove from the list // unsubscribe non-existent folders, remove from the list
@ -3034,17 +3070,30 @@ class rcube_imap extends rcube_storage
return null; return null;
} }
$result = $this->conn->listMailboxes($root, $name); $list_root = $root === '' && $this->list_root ? $this->list_root : $root;
$result = $this->conn->listMailboxes($list_root, $name);
if (!is_array($result)) { if (!is_array($result)) {
return array(); return array();
} }
// Add/Remove folders according to some configuration options
$this->list_folders_filter($result, $root . $name);
return $result;
}
/**
* Apply configured filters on folders list
*/
protected function list_folders_filter(&$result, $root, $update_type = null)
{
$config = rcube::get_instance()->config; $config = rcube::get_instance()->config;
// #1486796: some server configurations doesn't return folders in all namespaces // #1486796: some server configurations doesn't return folders in all namespaces
if ($root == '' && $name == '*' && $config->get('imap_force_ns')) { if ($root === '*' && $config->get('imap_force_ns')) {
$this->list_folders_update($result); $this->list_folders_update($result, $update_type);
} }
// Remove hidden folders // Remove hidden folders
@ -3052,7 +3101,18 @@ class rcube_imap extends rcube_storage
$result = array_filter($result, function($v) { return $v[0] != '.'; }); $result = array_filter($result, function($v) { return $v[0] != '.'; });
} }
return $result; // Remove folders in shared namespaces (if configured, see self::set_env())
if ($root === '*' && !empty($this->list_excludes)) {
$result = array_filter($result, function($v) {
foreach ($this->list_excludes as $prefix) {
if (strpos($v, $prefix) === 0) {
return false;
}
}
return true;
});
}
} }
/** /**

Loading…
Cancel
Save