Thomas
2013-10-09 9684dc018f68b037e8ee369e7ed08f4c760fe736
Support globally unique message UIDs with IMAP folder name appended
6 files modified
125 ■■■■ changed files
program/js/app.js 27 ●●●●● patch | view | raw | blame | history
program/steps/mail/copy.inc 6 ●●●● patch | view | raw | blame | history
program/steps/mail/func.inc 44 ●●●●● patch | view | raw | blame | history
program/steps/mail/mark.inc 10 ●●●●● patch | view | raw | blame | history
program/steps/mail/move_del.inc 22 ●●●● patch | view | raw | blame | history
program/steps/mail/search.inc 16 ●●●●● patch | view | raw | blame | history
program/js/app.js
@@ -685,7 +685,7 @@
      case 'open':
        if (uid = this.get_single_uid()) {
          obj.href = this.url('show', {_mbox: this.env.mailbox, _uid: uid});
          obj.href = this.url('show', {_mbox: this.get_message_mailbox(uid), _uid: uid});
          return true;
        }
        break;
@@ -788,9 +788,9 @@
          this.load_contact(cid, 'edit');
        else if (this.task == 'settings' && props)
          this.load_identity(props, 'edit-identity');
        else if (this.task == 'mail' && (cid = this.get_single_uid())) {
          url = { _mbox: this.env.mailbox };
          url[this.env.mailbox == this.env.drafts_mailbox && props != 'new' ? '_draft_uid' : '_uid'] = cid;
        else if (this.task == 'mail' && (uid = this.get_single_uid())) {
          url = { _mbox: this.get_message_mailbox(uid) };
          url[this.env.mailbox == this.env.drafts_mailbox && props != 'new' ? '_draft_uid' : '_uid'] = uid;
          this.open_compose_step(url);
        }
        break;
@@ -1070,7 +1070,7 @@
      case 'reply-list':
      case 'reply':
        if (uid = this.get_single_uid()) {
          url = {_reply_uid: uid, _mbox: this.env.mailbox};
          url = {_reply_uid: uid, _mbox: this.get_message_mailbox(uid)};
          if (command == 'reply-all')
            // do reply-list, when list is detected and popup menu wasn't used
            url._all = (!props && this.env.reply_all_mode == 1 && this.commands['reply-list'] ? 'list' : 'all');
@@ -1098,7 +1098,7 @@
          this.gui_objects.messagepartframe.contentWindow.print();
        }
        else if (uid = this.get_single_uid()) {
          ref.printwin = this.open_window(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''), true, true);
          ref.printwin = this.open_window(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.get_message_mailbox(uid))+(this.env.safemode ? '&_safe=1' : ''), true, true);
          if (this.printwin) {
            if (this.env.action != 'show')
              this.mark_message('read', uid);
@@ -1115,8 +1115,9 @@
        if (this.env.action == 'get') {
          location.href = location.href.replace(/_frame=/, '_download=');
        }
        else if (uid = this.get_single_uid())
          this.goto_url('viewsource', { _uid: uid, _mbox: this.env.mailbox, _save: 1 });
        else if (uid = this.get_single_uid()) {
          this.goto_url('viewsource', { _uid: uid, _mbox: this.get_message_mailbox(uid), _save: 1 });
        }
        break;
      // quicksearch
@@ -1820,6 +1821,7 @@
      selected: this.select_all_mode || this.message_list.in_selection(uid),
      ml: flags.ml?1:0,
      ctype: flags.ctype,
      mbox: flags.mbox,
      // flags from plugins
      flags: flags.extra_flags
    });
@@ -2022,7 +2024,7 @@
    var win, target = window,
      action = preview ? 'preview': 'show',
      url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox);
      url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.get_message_mailbox(id));
    if (preview && (win = this.get_frame_window(this.env.contentframe))) {
      target = win;
@@ -7424,6 +7426,13 @@
    return this.env.cid ? this.env.cid : (this.contact_list ? this.contact_list.get_single_selection() : null);
  };
  // get the IMP mailbox of the message with the given UID
  this.get_message_mailbox = function(uid)
  {
    var msg = this.env.messages ? this.env.messages[uid] : {};
    return msg.mbox || this.env.mailbox;
  }
  // gets cursor position
  this.get_caret_pos = function(obj)
  {
program/steps/mail/copy.inc
@@ -26,11 +26,11 @@
// move messages
if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
    $uids   = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
    $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
    $mbox   = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
    $copied = $RCMAIL->storage->copy_message($uids, $target, $mbox);
    foreach (rcmail_get_uids() as $mbox => $uids) {
      $copied += (int)$RCMAIL->storage->copy_message($uids, $target, $mbox);
    }
    if (!$copied) {
        // send error message
program/steps/mail/func.inc
@@ -68,6 +68,21 @@
    $OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
}
// remove mbox part from _uid
if (($_uid  = get_input_value('_uid', RCUBE_INPUT_GPC)) && preg_match('/^\d+-[^,]+$/', $_uid)) {
  list($_uid, $mbox) = explode('-', $_uid);
  if (isset($_GET['_uid']))  $_GET['_uid']  = $_uid;
  if (isset($_POST['_uid'])) $_POST['_uid'] = $_uid;
  $_REQUEST['_uid'] = $_uid;
  unset($_uid);
  if (empty($_REQUEST['_mbox']) && !empty($mbox)) {
    $_GET['_mbox']  = $mbox;
    $_POST['_mbox'] = $mbox;
  }
}
// set main env variables, labels and page title
if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
    // connect to storage server and trigger error on failure
@@ -166,6 +181,35 @@
));
/**
 * Returns message UID(s) and IMAP folder(s) from GET/POST data
 *
 * @return array List of message UIDs per folder
 */
function rcmail_get_uids()
{
    // message UID (or comma-separated list of IDs) is provided in
    // the form of <ID>-<MBOX>[,<ID>-<MBOX>]*
    $_uid  = get_input_value('_uid', RCUBE_INPUT_GPC);
    $_mbox = (string)get_input_value('_mbox', RCUBE_INPUT_GPC);
    if (is_array($uid)) {
        return $uid;
    }
    // create a per-folder UIDs array
    $result = array();
    foreach (explode(',', $_uid) as $uid) {
        list($uid, $mbox) = explode('-', $uid, 2);
        if (empty($mbox))
            $mbox = $_mbox;
        $result[$mbox][] = $uid;
    }
    return $result;
}
/**
 * Returns default search mods
program/steps/mail/mark.inc
@@ -36,7 +36,7 @@
    'unflagged' => 'UNFLAGGED',
);
if (($uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST))
if (($_uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST))
    && ($flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST))
) {
    $flag = $a_flags_map[$flag] ? $a_flags_map[$flag] : strtoupper($flag);
@@ -45,10 +45,12 @@
        // count messages before changing anything
        $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL');
        $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize());
        $count     = sizeof(explode(',', $uids));
    }
    $marked = $RCMAIL->storage->set_flag($uids, $flag);
    foreach (rcmail_get_uids() as $mbox => $uids) {
        $marked += (int)$RCMAIL->storage->set_flag($uids, $flag, $mbox);
        $count += count($uids);
    }
    if (!$marked) {
        // send error message
@@ -128,7 +130,7 @@
            }
            // add new rows from next page (if any)
            if ($count && $uids != '*' && ($jump_back || $nextpage_count > 0)) {
            if ($old_count && $_uids != '*' && ($jump_back || $nextpage_count > 0)) {
                $a_headers = $RCMAIL->storage->list_messages($mbox, NULL,
                    rcmail_sort_column(), rcmail_sort_order(), $jump_back ? NULL : $count);
program/steps/mail/move_del.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/move_del.inc                                       |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2009, The Roundcube Dev Team                       |
 | Copyright (C) 2005-2013, The Roundcube Dev Team                       |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
@@ -32,11 +32,13 @@
// move messages
if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) {
    $count  = sizeof(explode(',', ($uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST))));
    $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true);
    $mbox   = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
    $trash  = $RCMAIL->config->get('trash_mbox');
    $moved = $RCMAIL->storage->move_message($uids, $target, $mbox);
    foreach (rcmail_get_uids() as $mbox => $uids) {
        $moved += (int)$RCMAIL->storage->move_message($uids, $target, $mbox);
        $count += count($uids);
    }
    if (!$moved) {
        // send error message
@@ -47,17 +49,17 @@
        exit;
    }
    else {
      $OUTPUT->show_message('messagemoved', 'confirmation');
        $OUTPUT->show_message('messagemoved', 'confirmation');
    }
    $addrows = true;
}
// delete messages 
else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) {
    $count = sizeof(explode(',', ($uids = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST))));
    $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true);
    $del = $RCMAIL->storage->delete_message($uids, $mbox);
    foreach (rcmail_get_uids() as $mbox => $uids) {
        $del += (int)$RCMAIL->storage->delete_message($uids, $mbox);
        $count += count($uids);
    }
    if (!$del) {
        // send error message
@@ -68,7 +70,7 @@
        exit;
    }
    else {
      $OUTPUT->show_message('messagedeleted', 'confirmation');
        $OUTPUT->show_message('messagedeleted', 'confirmation');
    }
    $addrows = true;
program/steps/mail/search.inc
@@ -127,9 +127,23 @@
$result_h = $RCMAIL->storage->list_messages($mbox, 1, $sort_column, rcmail_sort_order());
$count    = $RCMAIL->storage->count($mbox, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL');
// Add 'folder' column to list
if ($multi_folder_search) {
  $a_show_cols = $_SESSION['list_attrib']['columns'] ? $_SESSION['list_attrib']['columns'] : (array)$CONFIG['list_cols'];
  if (!in_array($a_show_cols))
    $a_show_cols[] = 'folder';
  // make message UIDs unique by appending the folder name
  foreach ($result_h as $i => $header) {
    $header->uid .= '-'.$header->folder;
    if ($header->parent_uid)
      $header->parent_uid .= '-'.$header->folder;
  }
}
// Make sure we got the headers
if (!empty($result_h)) {
    rcmail_js_message_list($result_h);
    rcmail_js_message_list($result_h, false, $a_show_cols);
    if ($search_str) {
        $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $RCMAIL->storage->count(NULL, 'ALL')));
    }