- Fix problems with subfolders of INBOX folder on some IMAP servers (#1487725)

- Fix handling of folders that doesn't belong to any namespace (#1487637)
release-0.6
alecpl 14 years ago
parent 4764079c6a
commit d08333ea57

@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail CHANGELOG Roundcube Webmail
=========================== ===========================
- Fix problems with subfolders of INBOX folder on some IMAP servers (#1487725)
- Fix handling of folders that doesn't belong to any namespace (#1487637)
- Fix bug where messages were deleted instead moved to trash folder after Shift key was used (#1487902) - Fix bug where messages were deleted instead moved to trash folder after Shift key was used (#1487902)
- Enable multiselection for attachments uploading in capable browsers (#1485969) - Enable multiselection for attachments uploading in capable browsers (#1485969)
- Add possibility to change HTML editor configuration by skin - Add possibility to change HTML editor configuration by skin

@ -97,9 +97,13 @@ GO
ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL ALTER TABLE [dbo].[contacts] ALTER COLUMN [email] [varchar] (255) COLLATE Latin1_General_CI_AI NOT NULL
GO GO
-- Updates from version 0.5.1 -- Updates from version 0.5.2
ALTER TABLE [dbo].[contacts] ADD [words] [text] COLLATE Latin1_General_CI_AI NULL ALTER TABLE [dbo].[contacts] ADD [words] [text] COLLATE Latin1_General_CI_AI NULL
GO GO
CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY] CREATE INDEX [IX_contactgroupmembers_contact_id] ON [dbo].[contactgroupmembers]([contact_id]) ON [PRIMARY]
GO GO
DELETE FROM [dbo].[messages]
GO
DELETE FROM [dbo].[cache]
GO

@ -133,8 +133,11 @@ ALTER TABLE `contacts` MODIFY `email` varchar(255) NOT NULL;
TRUNCATE TABLE `messages`; TRUNCATE TABLE `messages`;
-- Updates from version 0.5.1 -- Updates from version 0.5.2
ALTER TABLE `contacts` ADD `words` TEXT NULL AFTER `vcard`; ALTER TABLE `contacts` ADD `words` TEXT NULL AFTER `vcard`;
ALTER TABLE `contacts` CHANGE `vcard` `vcard` LONGTEXT /*!40101 CHARACTER SET utf8 */ NULL DEFAULT NULL; ALTER TABLE `contacts` CHANGE `vcard` `vcard` LONGTEXT /*!40101 CHARACTER SET utf8 */ NULL DEFAULT NULL;
ALTER TABLE `contactgroupmembers` ADD INDEX `contactgroupmembers_contact_index` (`contact_id`); ALTER TABLE `contactgroupmembers` ADD INDEX `contactgroupmembers_contact_index` (`contact_id`);
TRUNCATE TABLE `messages`;
TRUNCATE TABLE `cache`;

@ -90,7 +90,10 @@ ALTER TABLE contacts ALTER email TYPE varchar(255);
TRUNCATE messages; TRUNCATE messages;
-- Updates from version 0.5.1 -- Updates from version 0.5.2
ALTER TABLE contacts ADD words TEXT NULL; ALTER TABLE contacts ADD words TEXT NULL;
CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id); CREATE INDEX contactgroupmembers_contact_id_idx ON contactgroupmembers (contact_id);
TRUNCATE messages;
TRUNCATE cache;

@ -183,7 +183,7 @@ DROP TABLE contacts_tmp;
DELETE FROM messages; DELETE FROM messages;
-- Updates from version 0.5.1 -- Updates from version 0.5.2
CREATE TABLE contacts_tmp ( CREATE TABLE contacts_tmp (
contact_id integer NOT NULL PRIMARY KEY, contact_id integer NOT NULL PRIMARY KEY,
@ -221,4 +221,5 @@ CREATE INDEX ix_contacts_user_id ON contacts(user_id, email);
DROP TABLE contacts_tmp; DROP TABLE contacts_tmp;
DELETE FROM messages; DELETE FROM messages;
DELETE FROM cache;
CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id); CREATE INDEX ix_contactgroupmembers_contact_id ON contactgroupmembers (contact_id);

@ -48,3 +48,6 @@ Post-Upgrade Activities
----------------------- -----------------------
1. Check .htaccess settings (some php settings could become required) 1. Check .htaccess settings (some php settings could become required)
2. If you're using build-in addressbook, run indexing script /bin/indexcontacts.sh. 2. If you're using build-in addressbook, run indexing script /bin/indexcontacts.sh.
3. When upgrading from version older than 0.6-beta you should make sure
your folder settings contain namespace prefix. For example Courier users
should add INBOX. prefix to folder names in main configuration file.

@ -374,21 +374,26 @@ $rcmail_config['date_format'] = 'Y-m-d';
// store draft message is this mailbox // store draft message is this mailbox
// leave blank if draft messages should not be stored // leave blank if draft messages should not be stored
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
$rcmail_config['drafts_mbox'] = 'Drafts'; $rcmail_config['drafts_mbox'] = 'Drafts';
// store spam messages in this mailbox // store spam messages in this mailbox
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
$rcmail_config['junk_mbox'] = 'Junk'; $rcmail_config['junk_mbox'] = 'Junk';
// store sent message is this mailbox // store sent message is this mailbox
// leave blank if sent messages should not be stored // leave blank if sent messages should not be stored
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
$rcmail_config['sent_mbox'] = 'Sent'; $rcmail_config['sent_mbox'] = 'Sent';
// move messages to this folder when deleting them // move messages to this folder when deleting them
// leave blank if they should be deleted directly // leave blank if they should be deleted directly
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
$rcmail_config['trash_mbox'] = 'Trash'; $rcmail_config['trash_mbox'] = 'Trash';
// display these folders separately in the mailbox list. // display these folders separately in the mailbox list.
// these folders will also be displayed with localized names // these folders will also be displayed with localized names
// NOTE: Use folder names with namespace prefix (INBOX. on Courier-IMAP)
$rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash'); $rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Junk', 'Trash');
// automatically create the above listed default folders on login // automatically create the above listed default folders on login

@ -361,7 +361,7 @@ echo $text_sentmbox->show($RCI->getprop('sent_mbox'));
?> ?>
<div>Store sent messages in this folder</div> <div>Store sent messages in this folder</div>
<p class="hint">Leave blank if sent messages should not be stored</p> <p class="hint">Leave blank if sent messages should not be stored. Note: folder must include namespace prefix if any.</p>
</dd> </dd>
<dt class="propname">trash_mbox</dt> <dt class="propname">trash_mbox</dt>
@ -374,7 +374,7 @@ echo $text_trashmbox->show($RCI->getprop('trash_mbox'));
?> ?>
<div>Move messages to this folder when deleting them</div> <div>Move messages to this folder when deleting them</div>
<p class="hint">Leave blank if they should be deleted directly</p> <p class="hint">Leave blank if they should be deleted directly. Note: folder must include namespace prefix if any.</p>
</dd> </dd>
<dt class="propname">drafts_mbox</dt> <dt class="propname">drafts_mbox</dt>
@ -387,7 +387,7 @@ echo $text_draftsmbox->show($RCI->getprop('drafts_mbox'));
?> ?>
<div>Store draft messages in this folder</div> <div>Store draft messages in this folder</div>
<p class="hint">Leave blank if they should not be stored</p> <p class="hint">Leave blank if they should not be stored. Note: folder must include namespace prefix if any.</p>
</dd> </dd>
<dt class="propname">junk_mbox</dt> <dt class="propname">junk_mbox</dt>
@ -399,6 +399,10 @@ echo $text_junkmbox->show($RCI->getprop('junk_mbox'));
?> ?>
<div>Store spam messages in this folder</div> <div>Store spam messages in this folder</div>
<p class="hint">Note: folder must include namespace prefix if any.</p>
</dd>
</dd> </dd>
</dl> </dl>
</fieldset> </fieldset>

@ -1228,9 +1228,12 @@ function rcmail_mailbox_select($p = array())
else else
$list = $RCMAIL->imap->list_mailboxes(); $list = $RCMAIL->imap->list_mailboxes();
foreach ($list as $folder) $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
foreach ($list as $folder) {
if (empty($p['exceptions']) || !in_array($folder, $p['exceptions'])) if (empty($p['exceptions']) || !in_array($folder, $p['exceptions']))
rcmail_build_folder_tree($a_mailboxes, $folder, $RCMAIL->imap->get_hierarchy_delimiter()); rcmail_build_folder_tree($a_mailboxes, $folder, $delimiter);
}
$select = new html_select($p); $select = new html_select($p);
@ -1252,6 +1255,17 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
{ {
global $RCMAIL; global $RCMAIL;
// Handle namespace prefix
$prefix = '';
if (!$path) {
$n_folder = $folder;
$folder = $RCMAIL->imap->mod_mailbox($folder);
if ($n_folder != $folder) {
$prefix = substr($n_folder, 0, -strlen($folder));
}
}
$pos = strpos($folder, $delm); $pos = strpos($folder, $delm);
if ($pos !== false) { if ($pos !== false) {
@ -1272,14 +1286,14 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
$virtual = false; $virtual = false;
} }
$path .= $currentFolder; $path .= $prefix.$currentFolder;
if (!isset($arrFolders[$currentFolder])) {
// Check \Noselect option (if options are in cache) // Check \Noselect option (if options are in cache)
if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) { if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) {
$virtual = in_array('\\Noselect', $opts); $virtual = in_array('\\Noselect', $opts);
} }
if (!isset($arrFolders[$currentFolder])) {
$arrFolders[$currentFolder] = array( $arrFolders[$currentFolder] = array(
'id' => $path, 'id' => $path,
'name' => rcube_charset_convert($currentFolder, 'UTF7-IMAP'), 'name' => rcube_charset_convert($currentFolder, 'UTF7-IMAP'),

@ -735,9 +735,13 @@ class rcmail
// user already registered -> update user's record // user already registered -> update user's record
if (is_object($user)) { if (is_object($user)) {
// fix some old settings according to namespace prefix
$this->fix_namespace_settings($user);
// create default folders on first login // create default folders on first login
if (!$user->data['last_login'] && $config['create_default_folders']) if (!$user->data['last_login'] && $config['create_default_folders'])
$this->imap->create_default_folders(); $this->imap->create_default_folders();
// update last login timestamp
$user->touch(); $user->touch();
} }
// create new system user // create new system user
@ -1453,4 +1457,104 @@ class rcmail
return strtr($this->action, '-', '_') . '.inc'; return strtr($this->action, '-', '_') . '.inc';
} }
/**
* Fixes some user preferences according to namespace handling change.
* Old Roundcube versions were using folder names with removed namespace prefix.
* Now we need to add the prefix on servers where personal namespace has prefix.
*
* @param rcube_user $user User object
*/
private function fix_namespace_settings($user)
{
$prefix = $this->imap->get_namespace('prefix');
$prefix_len = strlen($prefix);
if (!$prefix_len)
return;
$prefs = $user->get_prefs();
if (empty($prefs) || $prefs['namespace_fixed'])
return;
// Build namespace prefix regexp
$ns = $this->imap->get_namespace();
$regexp = array();
foreach ($ns as $entry) {
if (!empty($entry)) {
foreach ($entry as $item) {
if (strlen($item[0])) {
$regexp[] = preg_quote($item[0], '/');
}
}
}
}
$regexp = '/^('. implode('|', $regexp).')/';
// Fix preferences
$opts = array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox', 'archive_mbox');
foreach ($opts as $opt) {
if ($value = $prefs[$opt]) {
if ($value != 'INBOX' && !preg_match($regexp, $value)) {
$prefs[$opt] = $prefix.$value;
}
}
}
if (!empty($prefs['default_imap_folders'])) {
foreach ($prefs['default_imap_folders'] as $idx => $name) {
if ($name != 'INBOX' && !preg_match($regexp, $name)) {
$prefs['default_imap_folders'][$idx] = $prefix.$name;
}
}
}
if (!empty($prefs['search_mods'])) {
$folders = array();
foreach ($prefs['search_mods'] as $idx => $value) {
if ($idx != 'INBOX' && $idx != '*' && !preg_match($regexp, $idx)) {
$idx = $prefix.$idx;
}
$folders[$idx] = $value;
}
$prefs['search_mods'] = $folders;
}
if (!empty($prefs['message_threading'])) {
$folders = array();
foreach ($prefs['message_threading'] as $idx => $value) {
if ($idx != 'INBOX' && !preg_match($regexp, $idx)) {
$idx = $prefix.$idx;
}
$folders[$prefix.$idx] = $value;
}
$prefs['message_threading'] = $folders;
}
if (!empty($prefs['collapsed_folders'])) {
$folders = explode('&&', $prefs['collapsed_folders']);
$count = count($folders);
$folders_str = '';
if ($count) {
$folders[0] = substr($folders[0], 1);
$folders[$count-1] = substr($folders[$count-1], 0, -1);
}
foreach ($folders as $value) {
if ($value != 'INBOX' && !preg_match($regexp, $value)) {
$value = $prefix.$value;
}
$folders_str .= '&'.$value.'&';
}
$prefs['collapsed_folders'] = $folders_str;
}
$prefs['namespace_fixed'] = true;
// save updated preferences and reset imap settings (default folders)
$user->save_prefs($prefs);
$this->set_imap_prop();
}
} }

File diff suppressed because it is too large Load Diff

@ -130,7 +130,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage', 'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
'copy', 'move', 'quota'); 'copy', 'move', 'quota');
$OUTPUT->set_pagetitle(rcmail_localize_foldername($mbox_name)); $OUTPUT->set_pagetitle(rcmail_localize_foldername($IMAP->mod_mailbox($mbox_name)));
} }

@ -54,6 +54,20 @@ function rcube_folder_form($attrib)
else { else {
$options = array(); $options = array();
$path = $parent_imap; $path = $parent_imap;
// allow creating subfolders of INBOX folder
if ($path == 'INBOX') {
$path = $RCMAIL->imap->mod_mailbox($path, 'in');
}
}
// remove personal namespace prefix
if (strlen($path)) {
$path_id = $path;
$path = $RCMAIL->imap->mod_mailbox($path.$delimiter);
if ($path[strlen($path)-1] == $delimiter) {
$path = substr($path, 0, -1);
}
} }
$form = array(); $form = array();
@ -93,15 +107,15 @@ function rcube_folder_form($attrib)
); );
if (strlen($path)) { if (strlen($path)) {
if ($options['norename'] || $options['namespace'] != 'personal') { if (!empty($options) && ($options['norename'] || $options['namespace'] != 'personal')) {
// prevent user from moving folder // prevent user from moving folder
$hidden_path = new html_hiddenfield(array('name' => '_parent', 'value' => $path)); $hidden_path = new html_hiddenfield(array('name' => '_parent', 'value' => $path));
$form['props']['fieldsets']['location']['content']['name']['value'] .= $hidden_path->show(); $form['props']['fieldsets']['location']['content']['name']['value'] .= $hidden_path->show();
} }
else { else {
$radio1 = new html_radiobutton(array('name' => '_parent', 'value' => '')); $radio1 = new html_radiobutton(array('name' => '_parent', 'value' => ''));
$radio2 = new html_radiobutton(array('name' => '_parent', 'value' => $path)); $radio2 = new html_radiobutton(array('name' => '_parent', 'value' => $path_id));
$selected = isset($_POST['_parent']) ? $_POST['_parent'] : $path; $selected = isset($_POST['_parent']) ? $_POST['_parent'] : $path_id;
$html_path = str_replace($delimiter, ' &raquo; ', rcmail_localize_folderpath($path)); $html_path = str_replace($delimiter, ' &raquo; ', rcmail_localize_folderpath($path));

@ -127,11 +127,10 @@ else if ($RCMAIL->action == 'rename-folder')
for ($x=sizeof($folderlist)-1; $x>=0; $x--) { for ($x=sizeof($folderlist)-1; $x>=0; $x--) {
if (preg_match($regexp, $folderlist[$x])) { if (preg_match($regexp, $folderlist[$x])) {
$oldfolder = $oldname . $delimiter . preg_replace($regexp, '', $folderlist[$x]); $oldfolder = $oldname . $delimiter . preg_replace($regexp, '', $folderlist[$x]);
$foldersplit = explode($delimiter, $folderlist[$x]); $foldersplit = explode($delimiter, $IMAP->mod_mailbox($folderlist[$x]));
$level = count($foldersplit) - 1; $level = count($foldersplit) - 1;
$display_rename = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level) $display_rename = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level)
. rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP'); . rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP');
$before = isset($folderlist[$x+1]) ? rcube_charset_convert($folderlist[$x+1], 'UTF7-IMAP') : false; $before = isset($folderlist[$x+1]) ? rcube_charset_convert($folderlist[$x+1], 'UTF7-IMAP') : false;
$OUTPUT->command('replace_folder_row', rcube_charset_convert($oldfolder, 'UTF7-IMAP'), $OUTPUT->command('replace_folder_row', rcube_charset_convert($oldfolder, 'UTF7-IMAP'),
@ -139,14 +138,14 @@ else if ($RCMAIL->action == 'rename-folder')
} }
} }
$index = array_search($name, $folderlist);
$name = $IMAP->mod_mailbox($name);
$foldersplit = explode($delimiter, $name); $foldersplit = explode($delimiter, $name);
$level = count($foldersplit) - 1; $level = count($foldersplit) - 1;
$display_rename = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level) . rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP'); $display_rename = str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', $level) . rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP');
$index = array_search($name, $folderlist);
$before = $index !== false && isset($folderlist[$index+1]) ? rcube_charset_convert($folderlist[$index+1], 'UTF7-IMAP') : false; $before = $index !== false && isset($folderlist[$index+1]) ? rcube_charset_convert($folderlist[$index+1], 'UTF7-IMAP') : false;
$OUTPUT->command('replace_folder_row', $oldname_utf8, $OUTPUT->command('replace_folder_row', $oldname_utf8, $name_utf8, $display_rename, $before);
rcube_charset_convert($name, 'UTF7-IMAP'), $display_rename, $before);
} }
else if (!$rename) { else if (!$rename) {
rcmail_display_server_error('errorsaving'); rcmail_display_server_error('errorsaving');
@ -243,13 +242,15 @@ function rcube_subscription_form($attrib)
// pre-process folders list // pre-process folders list
foreach ($a_unsubscribed as $i => $folder) { foreach ($a_unsubscribed as $i => $folder) {
$folder_id = $folder;
$folder = $IMAP->mod_mailbox($folder);
$foldersplit = explode($delimiter, $folder); $foldersplit = explode($delimiter, $folder);
$name = rcube_charset_convert(array_pop($foldersplit), 'UTF7-IMAP'); $name = rcube_charset_convert(array_pop($foldersplit), 'UTF7-IMAP');
$parent_folder = join($delimiter, $foldersplit); $parent_folder = join($delimiter, $foldersplit);
$level = count($foldersplit); $level = count($foldersplit);
// add any necessary "virtual" parent folders // add any necessary "virtual" parent folders
if ($parent_folder && !$seen[$parent_folder]) { if ($parent_folder && !isset($seen[$parent_folder])) {
for ($i=1; $i<=$level; $i++) { for ($i=1; $i<=$level; $i++) {
$ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i)); $ancestor_folder = join($delimiter, array_slice($foldersplit, 0, $i));
if ($ancestor_folder && !$seen[$ancestor_folder]++) { if ($ancestor_folder && !$seen[$ancestor_folder]++) {
@ -264,10 +265,15 @@ function rcube_subscription_form($attrib)
} }
} }
// Handle properly INBOX.INBOX situation
if (isset($seen[$folder])) {
continue;
}
$seen[$folder]++; $seen[$folder]++;
$list_folders[] = array( $list_folders[] = array(
'id' => $folder, 'id' => $folder_id,
'name' => $name, 'name' => $name,
'level' => $level, 'level' => $level,
); );

@ -65,6 +65,9 @@ else {
else if (strlen($path)) { else if (strlen($path)) {
$name_imap = $path . $delimiter . $name_imap; $name_imap = $path . $delimiter . $name_imap;
} }
else {
$name_imap = $RCMAIL->imap->mod_mailbox($name, 'in');
}
$folder['name'] = $name_imap; $folder['name'] = $name_imap;
$folder['oldname'] = $old_imap; $folder['oldname'] = $old_imap;

Loading…
Cancel
Save