Geary.Imap: Make command cancellable a property of the command object
Since both submitting a command no longer requires a cancellable, and it is desirable to avoid sending a queued command that has already been cancelled beforehand, add a new `Command.should_send` Cancellable property to specify if a command should (still) be sent or not, and stop passing a cancellable to ClientSession when submitting commands. Allow call sites to pass in existing cancellable objects, and thus also add it it as a ctor property to the Command class and all subclasses. Lastly, throw a cancelled exception in `wait_until_complete` if send was cancelled so that the caller knows what happened. Remove redundant cancellable argument from `Imap.Client.command_transaction_async` and rename it to `submit_command` to make it more obvious about what it does.
This commit is contained in:
parent
67f0678b1d
commit
85e9046c71
33 changed files with 382 additions and 189 deletions
|
|
@ -290,13 +290,13 @@ class ImapConsole : Gtk.Window {
|
|||
private void capabilities(string cmd, string[] args) throws Error {
|
||||
check_connected(cmd, args, 0, null);
|
||||
|
||||
this.cx.send_command(new Geary.Imap.CapabilityCommand());
|
||||
this.cx.send_command(new Geary.Imap.CapabilityCommand(null));
|
||||
}
|
||||
|
||||
private void noop(string cmd, string[] args) throws Error {
|
||||
private void noop(string cmd, string[] args) throws GLib.Error {
|
||||
check_connected(cmd, args, 0, null);
|
||||
|
||||
this.cx.send_command(new Geary.Imap.NoopCommand());
|
||||
this.cx.send_command(new Geary.Imap.NoopCommand(null));
|
||||
}
|
||||
|
||||
private void connect_cmd(string cmd, string[] args) throws Error {
|
||||
|
|
@ -370,7 +370,7 @@ class ImapConsole : Gtk.Window {
|
|||
}
|
||||
|
||||
private async void do_starttls_async() throws Error {
|
||||
Geary.Imap.StarttlsCommand cmd = new Geary.Imap.StarttlsCommand();
|
||||
Geary.Imap.StarttlsCommand cmd = new Geary.Imap.StarttlsCommand(null);
|
||||
this.cx.send_command(cmd);
|
||||
|
||||
Geary.Imap.StatusResponse response = yield wait_for_response_async(cmd.tag);
|
||||
|
|
@ -394,14 +394,18 @@ class ImapConsole : Gtk.Window {
|
|||
check_connected(cmd, args, 2, "user pass");
|
||||
|
||||
status("Logging in...");
|
||||
this.cx.send_command(new Geary.Imap.LoginCommand(args[0], args[1]));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.LoginCommand(args[0], args[1], null)
|
||||
);
|
||||
}
|
||||
|
||||
private void logout(string cmd, string[] args) throws Error {
|
||||
check_connected(cmd, args, 0, null);
|
||||
|
||||
status("Logging out...");
|
||||
this.cx.send_command(new Geary.Imap.LogoutCommand());
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.LogoutCommand(null)
|
||||
);
|
||||
}
|
||||
|
||||
private void id(string cmd, string[] args) throws Error {
|
||||
|
|
@ -413,14 +417,16 @@ class ImapConsole : Gtk.Window {
|
|||
fields.set("name", "geary-console");
|
||||
fields.set("version", _VERSION);
|
||||
|
||||
this.cx.send_command(new Geary.Imap.IdCommand(fields));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.IdCommand(fields, null)
|
||||
);
|
||||
}
|
||||
|
||||
private void namespace(string cmd, string[] args) throws Error {
|
||||
check_connected(cmd, args, 0, null);
|
||||
|
||||
status("Retrieving NAMESPACE...");
|
||||
this.cx.send_command(new Geary.Imap.NamespaceCommand());
|
||||
this.cx.send_command(new Geary.Imap.NamespaceCommand(null));
|
||||
}
|
||||
|
||||
private void list(string cmd, string[] args) throws Error {
|
||||
|
|
@ -437,7 +443,8 @@ class ImapConsole : Gtk.Window {
|
|||
args[0],
|
||||
new Geary.Imap.MailboxSpecifier(args[1]),
|
||||
(cmd.down() == "xlist"),
|
||||
return_param
|
||||
return_param,
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -446,7 +453,12 @@ class ImapConsole : Gtk.Window {
|
|||
check_connected(cmd, args, 1, "<mailbox>");
|
||||
|
||||
status("Opening %s read-only".printf(args[0]));
|
||||
this.cx.send_command(new Geary.Imap.ExamineCommand(new Geary.Imap.MailboxSpecifier(args[0])));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.ExamineCommand(
|
||||
new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void create(string cmd, string[] args) throws Error {
|
||||
|
|
@ -455,7 +467,8 @@ class ImapConsole : Gtk.Window {
|
|||
status("Creating %s".printf(args[0]));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.CreateCommand(
|
||||
new Geary.Imap.MailboxSpecifier(args[0])
|
||||
new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -466,7 +479,8 @@ class ImapConsole : Gtk.Window {
|
|||
status("Deleting %s".printf(args[0]));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.DeleteCommand(
|
||||
new Geary.Imap.MailboxSpecifier(args[0])
|
||||
new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -487,7 +501,9 @@ class ImapConsole : Gtk.Window {
|
|||
data_items.add(data_type);
|
||||
}
|
||||
|
||||
this.cx.send_command(new Geary.Imap.FetchCommand(msg_set, data_items, null));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.FetchCommand(msg_set, data_items, null, null)
|
||||
);
|
||||
}
|
||||
|
||||
private void fetch_fields(string cmd, string[] args) throws Error {
|
||||
|
|
@ -501,8 +517,11 @@ class ImapConsole : Gtk.Window {
|
|||
Gee.List<Geary.Imap.FetchBodyDataSpecifier> list = new Gee.ArrayList<Geary.Imap.FetchBodyDataSpecifier>();
|
||||
list.add(fields);
|
||||
|
||||
this.cx.send_command(new Geary.Imap.FetchCommand(
|
||||
new Geary.Imap.MessageSet.custom(args[0]), null, list));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.FetchCommand(
|
||||
new Geary.Imap.MessageSet.custom(args[0]), null, list, null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void append(string cmd, string[] args) throws Error {
|
||||
|
|
@ -510,8 +529,15 @@ class ImapConsole : Gtk.Window {
|
|||
|
||||
status("Appending %s to %s".printf(args[1], args[0]));
|
||||
|
||||
this.cx.send_command(new Geary.Imap.AppendCommand(new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
null, null, new Geary.Memory.FileBuffer(File.new_for_path(args[1]), true)));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.AppendCommand(
|
||||
new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
null,
|
||||
null,
|
||||
new Geary.Memory.FileBuffer(File.new_for_path(args[1]), true),
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void search(string cmd, string[] args) throws Error {
|
||||
|
|
@ -525,9 +551,9 @@ class ImapConsole : Gtk.Window {
|
|||
|
||||
Geary.Imap.SearchCommand search;
|
||||
if (cmd == "uid-search")
|
||||
search = new Geary.Imap.SearchCommand.uid(criteria);
|
||||
search = new Geary.Imap.SearchCommand.uid(criteria, null);
|
||||
else
|
||||
search = new Geary.Imap.SearchCommand(criteria);
|
||||
search = new Geary.Imap.SearchCommand(criteria, null);
|
||||
|
||||
this.cx.send_command(search);
|
||||
}
|
||||
|
|
@ -537,7 +563,9 @@ class ImapConsole : Gtk.Window {
|
|||
|
||||
status("Closing");
|
||||
|
||||
this.cx.send_command(new Geary.Imap.CloseCommand());
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.CloseCommand(null)
|
||||
);
|
||||
}
|
||||
|
||||
private void folder_status(string cmd, string[] args) throws Error {
|
||||
|
|
@ -551,8 +579,13 @@ class ImapConsole : Gtk.Window {
|
|||
data_items += Geary.Imap.StatusDataType.from_parameter(stringp);
|
||||
}
|
||||
|
||||
this.cx.send_command(new Geary.Imap.StatusCommand(new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
data_items));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.StatusCommand(
|
||||
new Geary.Imap.MailboxSpecifier(args[0]),
|
||||
data_items,
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void preview(string cmd, string[] args) throws Error {
|
||||
|
|
@ -567,8 +600,11 @@ class ImapConsole : Gtk.Window {
|
|||
Gee.ArrayList<Geary.Imap.FetchBodyDataSpecifier> list = new Gee.ArrayList<Geary.Imap.FetchBodyDataSpecifier>();
|
||||
list.add(preview_data_type);
|
||||
|
||||
this.cx.send_command(new Geary.Imap.FetchCommand(
|
||||
new Geary.Imap.MessageSet.custom(args[0]), null, list));
|
||||
this.cx.send_command(
|
||||
new Geary.Imap.FetchCommand(
|
||||
new Geary.Imap.MessageSet.custom(args[0]), null, list, null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void quit(string cmd, string[] args) throws Error {
|
||||
|
|
|
|||
|
|
@ -97,9 +97,11 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
ClientSession session = claim_session();
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(path);
|
||||
bool can_create_special = session.capabilities.has_capability(Capabilities.CREATE_SPECIAL_USE);
|
||||
CreateCommand cmd = (use != null && can_create_special)
|
||||
? new CreateCommand.special_use(mailbox, use)
|
||||
: new CreateCommand(mailbox);
|
||||
CreateCommand cmd = (
|
||||
use != null && can_create_special
|
||||
? new CreateCommand.special_use(mailbox, use, cancellable)
|
||||
: new CreateCommand(mailbox, cancellable)
|
||||
);
|
||||
|
||||
StatusResponse response = yield send_command_async(
|
||||
session, cmd, null, null, cancellable
|
||||
|
|
@ -187,7 +189,9 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
// Mailbox needs a SELECT
|
||||
info_map.set(mailbox_info.mailbox, mailbox_info);
|
||||
cmd_map.set(
|
||||
new StatusCommand(mailbox_info.mailbox, StatusDataType.all()),
|
||||
new StatusCommand(
|
||||
mailbox_info.mailbox, StatusDataType.all(), cancellable
|
||||
),
|
||||
mailbox_info.mailbox
|
||||
);
|
||||
} else {
|
||||
|
|
@ -323,7 +327,10 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
if (folder.is_root) {
|
||||
// List the server root
|
||||
cmd = new ListCommand.wildcarded(
|
||||
"", new MailboxSpecifier("%"), use_xlist, return_param
|
||||
"", new MailboxSpecifier("%"),
|
||||
use_xlist,
|
||||
return_param,
|
||||
cancellable
|
||||
);
|
||||
} else {
|
||||
// List either the given folder or its children
|
||||
|
|
@ -335,7 +342,12 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
}
|
||||
specifier = specifier + delim + "%";
|
||||
}
|
||||
cmd = new ListCommand(new MailboxSpecifier(specifier), use_xlist, return_param);
|
||||
cmd = new ListCommand(
|
||||
new MailboxSpecifier(specifier),
|
||||
use_xlist,
|
||||
return_param,
|
||||
cancellable
|
||||
);
|
||||
}
|
||||
|
||||
Gee.List<MailboxInformation> list_results = new Gee.ArrayList<MailboxInformation>();
|
||||
|
|
@ -372,7 +384,7 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
|
|||
Gee.List<StatusData> status_results = new Gee.ArrayList<StatusData>();
|
||||
StatusResponse response = yield send_command_async(
|
||||
session,
|
||||
new StatusCommand(mailbox, status_types),
|
||||
new StatusCommand(mailbox, status_types, cancellable),
|
||||
null,
|
||||
status_results,
|
||||
cancellable
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ public class Geary.Imap.ClientService : Geary.ClientService {
|
|||
try {
|
||||
debug("Sending NOOP when claiming a session");
|
||||
yield target.send_command_async(
|
||||
new NoopCommand(), this.close_cancellable
|
||||
new NoopCommand(this.close_cancellable)
|
||||
);
|
||||
} catch (Error err) {
|
||||
debug("Error sending NOOP: %s", err.message);
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
public async void send_noop(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
yield exec_commands_async(
|
||||
Collection.single(new NoopCommand()),
|
||||
Collection.single(new NoopCommand(cancellable)),
|
||||
null,
|
||||
null,
|
||||
cancellable
|
||||
|
|
@ -334,12 +334,13 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
}
|
||||
|
||||
// Utility method for listing UIDs on the remote within the supplied range
|
||||
public async Gee.Set<Imap.UID>? list_uids_async(MessageSet msg_set, Cancellable? cancellable)
|
||||
throws Error {
|
||||
public async Gee.Set<Imap.UID>? list_uids_async(MessageSet msg_set,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
// Although FETCH could be used, SEARCH is more efficient in returning pure UID results,
|
||||
// which is all we're interested in here
|
||||
SearchCriteria criteria = new SearchCriteria(SearchCriterion.message_set(msg_set));
|
||||
SearchCommand cmd = new SearchCommand.uid(criteria);
|
||||
SearchCommand cmd = new SearchCommand.uid(criteria, cancellable);
|
||||
|
||||
Gee.Set<Imap.UID> search_results = new Gee.HashSet<Imap.UID>();
|
||||
yield exec_commands_async(
|
||||
|
|
@ -355,6 +356,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
private Gee.Collection<FetchCommand> assemble_list_commands(
|
||||
Imap.MessageSet msg_set,
|
||||
Geary.Email.Field fields,
|
||||
GLib.Cancellable? cancellable,
|
||||
out FetchBodyDataSpecifier[]? header_specifiers,
|
||||
out FetchBodyDataSpecifier? body_specifier,
|
||||
out FetchBodyDataSpecifier? preview_specifier,
|
||||
|
|
@ -369,8 +371,13 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
// pulled down, not a guarantee); if request is for NONE, that guarantees that the
|
||||
// EmailIdentifier will be set, and so fetch UIDs (which looks funny but works when
|
||||
// listing a range for contents: UID FETCH x:y UID)
|
||||
if (!msg_set.is_uid || fields == Geary.Email.Field.NONE)
|
||||
cmds.add(new FetchCommand.data_type(msg_set, FetchDataSpecifier.UID));
|
||||
if (!msg_set.is_uid || fields == Geary.Email.Field.NONE) {
|
||||
cmds.add(
|
||||
new FetchCommand.data_type(
|
||||
msg_set, FetchDataSpecifier.UID, cancellable
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// convert bulk of the "basic" fields into a one or two FETCH commands (some servers have
|
||||
// exhibited bugs or return NO when too many FETCH data types are combined on a single
|
||||
|
|
@ -385,7 +392,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
|
||||
// Add all simple data types as one FETCH command
|
||||
if (!basic_types.is_empty) {
|
||||
cmds.add(new FetchCommand(msg_set, basic_types, null));
|
||||
cmds.add(
|
||||
new FetchCommand(msg_set, basic_types, null, cancellable)
|
||||
);
|
||||
}
|
||||
|
||||
// Add all header field requests as separate FETCH
|
||||
|
|
@ -424,7 +433,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
if (this.quirks.fetch_header_part_no_space) {
|
||||
header.omit_request_header_fields_space();
|
||||
}
|
||||
cmds.add(new FetchCommand.body_data_type(msg_set, header));
|
||||
cmds.add(
|
||||
new FetchCommand.body_data_type(
|
||||
msg_set, header, cancellable
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -434,7 +447,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
body_specifier = new FetchBodyDataSpecifier.peek(FetchBodyDataSpecifier.SectionPart.TEXT,
|
||||
null, -1, -1, null);
|
||||
|
||||
cmds.add(new FetchCommand.body_data_type(msg_set, body_specifier));
|
||||
cmds.add(
|
||||
new FetchCommand.body_data_type(
|
||||
msg_set, body_specifier, cancellable
|
||||
)
|
||||
);
|
||||
} else {
|
||||
body_specifier = null;
|
||||
}
|
||||
|
|
@ -453,12 +470,20 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
|
||||
preview_specifier = new FetchBodyDataSpecifier.peek(FetchBodyDataSpecifier.SectionPart.NONE,
|
||||
{ 1 }, 0, Geary.Email.MAX_PREVIEW_BYTES, null);
|
||||
cmds.add(new FetchCommand.body_data_type(msg_set, preview_specifier));
|
||||
cmds.add(
|
||||
new FetchCommand.body_data_type(
|
||||
msg_set, preview_specifier, cancellable
|
||||
)
|
||||
);
|
||||
|
||||
// Also get the character set to properly decode it
|
||||
preview_charset_specifier = new FetchBodyDataSpecifier.peek(
|
||||
FetchBodyDataSpecifier.SectionPart.MIME, { 1 }, -1, -1, null);
|
||||
cmds.add(new FetchCommand.body_data_type(msg_set, preview_charset_specifier));
|
||||
cmds.add(
|
||||
new FetchCommand.body_data_type(
|
||||
msg_set, preview_charset_specifier, cancellable
|
||||
)
|
||||
);
|
||||
} else {
|
||||
preview_specifier = null;
|
||||
preview_charset_specifier = null;
|
||||
|
|
@ -476,7 +501,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
if (fields.require(Geary.Email.Field.FLAGS))
|
||||
data_types.add(FetchDataSpecifier.FLAGS);
|
||||
|
||||
cmds.add(new FetchCommand(msg_set, data_types, null));
|
||||
cmds.add(new FetchCommand(msg_set, data_types, null, cancellable));
|
||||
}
|
||||
|
||||
return cmds;
|
||||
|
|
@ -498,6 +523,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
Gee.Collection<FetchCommand> cmds = assemble_list_commands(
|
||||
msg_set,
|
||||
fields,
|
||||
cancellable,
|
||||
out header_specifiers,
|
||||
out body_specifier,
|
||||
out preview_specifier,
|
||||
|
|
@ -593,7 +619,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
}
|
||||
|
||||
Gee.List<Command> cmds = new Gee.ArrayList<Command>();
|
||||
cmds.add(new FetchCommand.data_type(msg_set, FetchDataSpecifier.UID));
|
||||
cmds.add(
|
||||
new FetchCommand.data_type(
|
||||
msg_set, FetchDataSpecifier.UID, cancellable
|
||||
)
|
||||
);
|
||||
|
||||
Gee.HashMap<SequenceNumber, FetchedData> fetched =
|
||||
new Gee.HashMap<SequenceNumber, FetchedData>();
|
||||
|
|
@ -613,8 +643,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
return map;
|
||||
}
|
||||
|
||||
public async void remove_email_async(Gee.List<MessageSet> msg_sets, Cancellable? cancellable)
|
||||
throws Error {
|
||||
public async void remove_email_async(Gee.List<MessageSet> msg_sets,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
Gee.List<MessageFlag> flags = new Gee.ArrayList<MessageFlag>();
|
||||
flags.add(MessageFlag.DELETED);
|
||||
|
|
@ -627,7 +658,9 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
if (!msg_set.is_uid)
|
||||
all_uid = false;
|
||||
|
||||
cmds.add(new StoreCommand(msg_set, flags, StoreCommand.Option.ADD_FLAGS));
|
||||
cmds.add(
|
||||
new StoreCommand(msg_set, flags, StoreCommand.Option.ADD_FLAGS, cancellable)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Only use old-school EXPUNGE when closing folder (or rely on CLOSE to do that work
|
||||
|
|
@ -638,10 +671,11 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
// shuts down, which means deleted messages return at application start. See:
|
||||
// http://redmine.yorba.org/issues/6865
|
||||
if (all_uid && session.capabilities.supports_uidplus()) {
|
||||
foreach (MessageSet msg_set in msg_sets)
|
||||
cmds.add(new ExpungeCommand.uid(msg_set));
|
||||
foreach (MessageSet msg_set in msg_sets) {
|
||||
cmds.add(new ExpungeCommand.uid(msg_set, cancellable));
|
||||
}
|
||||
} else {
|
||||
cmds.add(new ExpungeCommand());
|
||||
cmds.add(new ExpungeCommand(cancellable));
|
||||
}
|
||||
|
||||
yield exec_commands_async(cmds, null, null, cancellable);
|
||||
|
|
@ -659,11 +693,21 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
|
||||
Gee.Collection<Command> cmds = new Gee.ArrayList<Command>();
|
||||
foreach (MessageSet msg_set in msg_sets) {
|
||||
if (msg_flags_add.size > 0)
|
||||
cmds.add(new StoreCommand(msg_set, msg_flags_add, StoreCommand.Option.ADD_FLAGS));
|
||||
if (msg_flags_add.size > 0) {
|
||||
cmds.add(
|
||||
new StoreCommand(
|
||||
msg_set, msg_flags_add, ADD_FLAGS, cancellable
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (msg_flags_remove.size > 0)
|
||||
cmds.add(new StoreCommand(msg_set, msg_flags_remove, StoreCommand.Option.REMOVE_FLAGS));
|
||||
if (msg_flags_remove.size > 0) {
|
||||
cmds.add(
|
||||
new StoreCommand(
|
||||
msg_set, msg_flags_remove, REMOVE_FLAGS, cancellable
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
yield exec_commands_async(cmds, null, null, cancellable);
|
||||
|
|
@ -671,12 +715,14 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
|
||||
// Returns a mapping of the source UID to the destination UID. If the MessageSet is not for
|
||||
// UIDs, then null is returned. If the server doesn't support COPYUID, null is returned.
|
||||
public async Gee.Map<UID, UID>? copy_email_async(MessageSet msg_set, FolderPath destination,
|
||||
Cancellable? cancellable) throws Error {
|
||||
public async Gee.Map<UID, UID>? copy_email_async(MessageSet msg_set,
|
||||
FolderPath destination,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(destination);
|
||||
CopyCommand cmd = new CopyCommand(msg_set, mailbox);
|
||||
CopyCommand cmd = new CopyCommand(msg_set, mailbox, cancellable);
|
||||
|
||||
Gee.Map<Command, StatusResponse>? responses = yield exec_commands_async(
|
||||
Geary.iterate<Command>(cmd).to_array_list(), null, null, cancellable);
|
||||
|
|
@ -718,11 +764,12 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
return null;
|
||||
}
|
||||
|
||||
public async Gee.SortedSet<Imap.UID>? search_async(SearchCriteria criteria, Cancellable? cancellable)
|
||||
throws Error {
|
||||
public async Gee.SortedSet<Imap.UID>? search_async(SearchCriteria criteria,
|
||||
GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
// always perform a UID SEARCH
|
||||
Gee.Collection<Command> cmds = new Gee.ArrayList<Command>();
|
||||
cmds.add(new SearchCommand.uid(criteria));
|
||||
cmds.add(new SearchCommand.uid(criteria, cancellable));
|
||||
|
||||
Gee.Set<Imap.UID> search_results = new Gee.HashSet<Imap.UID>();
|
||||
yield exec_commands_async(cmds, null, search_results, cancellable);
|
||||
|
|
@ -1044,12 +1091,22 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
return email;
|
||||
}
|
||||
|
||||
// Returns a no-message-id ImapDB.EmailIdentifier with the UID stored in it.
|
||||
// This method does not take a cancellable; there is currently no way to tell if an email was
|
||||
// created or not if exec_commands_async() is cancelled during the append. For atomicity's sake,
|
||||
// callers need to remove the returned email ID if a cancel occurred.
|
||||
public async Geary.EmailIdentifier? create_email_async(RFC822.Message message, Geary.EmailFlags? flags,
|
||||
DateTime? date_received) throws Error {
|
||||
/**
|
||||
* Stores a new message in the remote mailbox.
|
||||
*
|
||||
* Returns a no-message-id ImapDB.EmailIdentifier with the UID
|
||||
* stored in it.
|
||||
*
|
||||
* This method does not take a cancellable; there is currently no
|
||||
* way to tell if an email was created or not if {@link
|
||||
* exec_commands_async} is cancelled during the append. For
|
||||
* atomicity's sake, callers need to remove the returned email ID
|
||||
* if a cancel occurred.
|
||||
*/
|
||||
public async Geary.EmailIdentifier? create_email_async(RFC822.Message message,
|
||||
Geary.EmailFlags? flags,
|
||||
GLib.DateTime? date_received)
|
||||
throws GLib.Error {
|
||||
ClientSession session = claim_session();
|
||||
|
||||
MessageFlags? msg_flags = null;
|
||||
|
|
@ -1066,11 +1123,16 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
|
|||
|
||||
MailboxSpecifier mailbox = session.get_mailbox_for_path(this.folder.path);
|
||||
AppendCommand cmd = new AppendCommand(
|
||||
mailbox, msg_flags, internaldate, message.get_rfc822_buffer()
|
||||
mailbox,
|
||||
msg_flags,
|
||||
internaldate,
|
||||
message.get_rfc822_buffer(),
|
||||
null
|
||||
);
|
||||
|
||||
Gee.Map<Command, StatusResponse> responses = yield exec_commands_async(
|
||||
Geary.iterate<AppendCommand>(cmd).to_array_list(), null, null, null);
|
||||
Geary.iterate<AppendCommand>(cmd).to_array_list(), null, null, null
|
||||
);
|
||||
|
||||
// Grab the response and parse out the UID, if available.
|
||||
StatusResponse response = responses.get(cmd);
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@ public class Geary.Imap.AppendCommand : Command {
|
|||
|
||||
public const string NAME = "append";
|
||||
|
||||
public AppendCommand(MailboxSpecifier mailbox, MessageFlags? flags, InternalDate? internal_date,
|
||||
Memory.Buffer message) {
|
||||
base (NAME);
|
||||
public AppendCommand(MailboxSpecifier mailbox,
|
||||
MessageFlags? flags,
|
||||
InternalDate? internal_date,
|
||||
Memory.Buffer message,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
|
||||
this.args.add(mailbox.to_parameter());
|
||||
|
||||
|
|
|
|||
|
|
@ -27,17 +27,21 @@ public class Geary.Imap.AuthenticateCommand : Command {
|
|||
private GLib.Cancellable error_cancellable = new GLib.Cancellable();
|
||||
|
||||
|
||||
private AuthenticateCommand(string method, string data) {
|
||||
base(NAME, { method, data });
|
||||
private AuthenticateCommand(string method,
|
||||
string data,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, { method, data }, should_send);
|
||||
this.method = method;
|
||||
this.error_lock = new Geary.Nonblocking.Spinlock(this.error_cancellable);
|
||||
}
|
||||
|
||||
public AuthenticateCommand.oauth2(string user, string token) {
|
||||
public AuthenticateCommand.oauth2(string user,
|
||||
string token,
|
||||
GLib.Cancellable? should_send) {
|
||||
string encoded_token = Base64.encode(
|
||||
OAUTH2_RESP.printf(user, token).data
|
||||
);
|
||||
this(OAUTH2_METHOD, encoded_token);
|
||||
this(OAUTH2_METHOD, encoded_token, should_send);
|
||||
}
|
||||
|
||||
internal override async void send(Serializer ser,
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.CapabilityCommand : Command {
|
||||
|
||||
public const string NAME = "capability";
|
||||
|
||||
public CapabilityCommand() {
|
||||
base (NAME);
|
||||
public CapabilityCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.CloseCommand : Command {
|
||||
|
||||
public const string NAME = "close";
|
||||
|
||||
public CloseCommand() {
|
||||
base (NAME);
|
||||
public CloseCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,20 @@ public abstract class Geary.Imap.Command : BaseObject {
|
|||
/** The status response for the command, once it has been received. */
|
||||
public StatusResponse? status { get; private set; default = null; }
|
||||
|
||||
/**
|
||||
* A guard to allow cancelling a command before it is sent.
|
||||
*
|
||||
* Since IMAP does not allow commands that have been sent to the
|
||||
* server to be cancelled, cancelling a command before sending it
|
||||
* is the last opportunity to prevent it from being executed. A
|
||||
* command queued to be sent will be sent as long as the
|
||||
* connection it was queued is open and this cancellable is null
|
||||
* or is not cancelled.
|
||||
*
|
||||
* @see Command.Command
|
||||
*/
|
||||
public GLib.Cancellable? should_send { get; private set; default = null; }
|
||||
|
||||
/**
|
||||
* The command's arguments as parameters.
|
||||
*
|
||||
|
|
@ -93,11 +107,15 @@ public abstract class Geary.Imap.Command : BaseObject {
|
|||
* Constructs a new command with an unassigned tag.
|
||||
*
|
||||
* Any arguments provided here will be converted to appropriate
|
||||
* string arguments
|
||||
* string arguments. The given cancellable will be set as {@link
|
||||
* should_send}.
|
||||
*
|
||||
* @see Tag
|
||||
* @see should_send
|
||||
*/
|
||||
protected Command(string name, string[]? args = null) {
|
||||
protected Command(string name,
|
||||
string[]? args,
|
||||
GLib.Cancellable? should_send) {
|
||||
this.tag = Tag.get_unassigned();
|
||||
this.name = name;
|
||||
if (args != null) {
|
||||
|
|
@ -105,6 +123,7 @@ public abstract class Geary.Imap.Command : BaseObject {
|
|||
this.args.add(Parameter.get_for_string(arg));
|
||||
}
|
||||
}
|
||||
this.should_send = should_send;
|
||||
|
||||
this.response_timer = new TimeoutManager.seconds(
|
||||
this._response_timeout, on_response_timeout
|
||||
|
|
@ -269,6 +288,15 @@ public abstract class Geary.Imap.Command : BaseObject {
|
|||
this.status.to_string()
|
||||
);
|
||||
}
|
||||
|
||||
// If everything else looks fine, but sending was cancelled,
|
||||
// throw an error here so the caller knows that was the case.
|
||||
if (this.should_send != null &&
|
||||
this.should_send.is_cancelled()) {
|
||||
throw new GLib.IOError.CANCELLED(
|
||||
"Sent command was cancelled: %s", to_brief_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string to_string() {
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.CompressCommand : Command {
|
||||
|
||||
public const string NAME = "compress";
|
||||
|
||||
public const string ALGORITHM_DEFLATE = "deflate";
|
||||
|
||||
public CompressCommand(string algorithm) {
|
||||
base (NAME, { algorithm });
|
||||
}
|
||||
}
|
||||
|
||||
public CompressCommand(string algorithm, GLib.Cancellable? should_send) {
|
||||
base(NAME, { algorithm }, should_send);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ public class Geary.Imap.CopyCommand : Command {
|
|||
public const string NAME = "copy";
|
||||
public const string UID_NAME = "uid copy";
|
||||
|
||||
public CopyCommand(MessageSet message_set, MailboxSpecifier destination) {
|
||||
base(message_set.is_uid ? UID_NAME : NAME);
|
||||
public CopyCommand(MessageSet message_set,
|
||||
MailboxSpecifier destination,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(message_set.is_uid ? UID_NAME : NAME, null, should_send);
|
||||
|
||||
this.args.add(message_set.to_parameter());
|
||||
this.args.add(destination.to_parameter());
|
||||
|
|
|
|||
|
|
@ -55,15 +55,16 @@ public class Geary.Imap.CreateCommand : Command {
|
|||
}
|
||||
}
|
||||
|
||||
public CreateCommand(MailboxSpecifier mailbox) {
|
||||
base(NAME_ATOM);
|
||||
public CreateCommand(MailboxSpecifier mailbox, GLib.Cancellable? should_send) {
|
||||
base(NAME_ATOM, null, should_send);
|
||||
this.mailbox = mailbox;
|
||||
this.args.add(mailbox.to_parameter());
|
||||
}
|
||||
|
||||
public CreateCommand.special_use(MailboxSpecifier mailbox,
|
||||
Geary.Folder.SpecialUse use) {
|
||||
this(mailbox);
|
||||
Geary.Folder.SpecialUse use,
|
||||
GLib.Cancellable? should_send) {
|
||||
this(mailbox, should_send);
|
||||
this.use = use;
|
||||
|
||||
MailboxAttribute? attr = get_special_folder_type(use);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ public class Geary.Imap.DeleteCommand : Command {
|
|||
|
||||
public const string NAME = "DELETE";
|
||||
|
||||
public DeleteCommand(MailboxSpecifier mailbox) {
|
||||
base(NAME);
|
||||
public DeleteCommand(MailboxSpecifier mailbox,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
this.args.add(mailbox.to_parameter());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ public class Geary.Imap.ExamineCommand : Command {
|
|||
|
||||
public MailboxSpecifier mailbox { get; private set; }
|
||||
|
||||
public ExamineCommand(MailboxSpecifier mailbox) {
|
||||
base(NAME);
|
||||
public ExamineCommand(MailboxSpecifier mailbox,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
this.mailbox = mailbox;
|
||||
this.args.add(mailbox.to_parameter());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ public class Geary.Imap.ExpungeCommand : Command {
|
|||
public const string NAME = "expunge";
|
||||
public const string UID_NAME = "uid expunge";
|
||||
|
||||
public ExpungeCommand() {
|
||||
base(NAME);
|
||||
public ExpungeCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
|
||||
public ExpungeCommand.uid(MessageSet message_set) {
|
||||
base(UID_NAME);
|
||||
public ExpungeCommand.uid(MessageSet message_set,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(UID_NAME, null, should_send);
|
||||
assert(message_set.is_uid);
|
||||
this.args.add(message_set.to_parameter());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@ public class Geary.Imap.FetchCommand : Command {
|
|||
public Gee.List<FetchBodyDataSpecifier> for_body_data_specifiers { get; private set;
|
||||
default = new Gee.ArrayList<FetchBodyDataSpecifier>(); }
|
||||
|
||||
public FetchCommand(MessageSet msg_set, Gee.List<FetchDataSpecifier>? data_items,
|
||||
Gee.List<FetchBodyDataSpecifier>? body_data_items) {
|
||||
base (msg_set.is_uid ? UID_NAME : NAME);
|
||||
public FetchCommand(MessageSet msg_set,
|
||||
Gee.List<FetchDataSpecifier>? data_items,
|
||||
Gee.List<FetchBodyDataSpecifier>? body_data_items,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(msg_set.is_uid ? UID_NAME : NAME, null, should_send);
|
||||
|
||||
this.args.add(msg_set.to_parameter());
|
||||
|
||||
|
|
@ -71,8 +73,10 @@ public class Geary.Imap.FetchCommand : Command {
|
|||
for_body_data_specifiers.add_all(body_data_items);
|
||||
}
|
||||
|
||||
public FetchCommand.data_type(MessageSet msg_set, FetchDataSpecifier data_type) {
|
||||
base (msg_set.is_uid ? UID_NAME : NAME);
|
||||
public FetchCommand.data_type(MessageSet msg_set,
|
||||
FetchDataSpecifier data_type,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(msg_set.is_uid ? UID_NAME : NAME, null, should_send);
|
||||
|
||||
for_data_types.add(data_type);
|
||||
|
||||
|
|
@ -80,8 +84,10 @@ public class Geary.Imap.FetchCommand : Command {
|
|||
this.args.add(data_type.to_parameter());
|
||||
}
|
||||
|
||||
public FetchCommand.body_data_type(MessageSet msg_set, FetchBodyDataSpecifier body_data_specifier) {
|
||||
base (msg_set.is_uid ? UID_NAME : NAME);
|
||||
public FetchCommand.body_data_type(MessageSet msg_set,
|
||||
FetchBodyDataSpecifier body_data_specifier,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(msg_set.is_uid ? UID_NAME : NAME, null, should_send);
|
||||
|
||||
for_body_data_specifiers.add(body_data_specifier);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ public class Geary.Imap.IdCommand : Command {
|
|||
|
||||
public const string NAME = "id";
|
||||
|
||||
public IdCommand(Gee.HashMap<string, string> fields) {
|
||||
base(NAME);
|
||||
public IdCommand(Gee.HashMap<string, string> fields,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
|
||||
ListParameter list = new ListParameter();
|
||||
foreach (string key in fields.keys) {
|
||||
|
|
@ -24,8 +25,8 @@ public class Geary.Imap.IdCommand : Command {
|
|||
this.args.add(list);
|
||||
}
|
||||
|
||||
public IdCommand.nil() {
|
||||
base(NAME);
|
||||
public IdCommand.nil(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
this.args.add(NilParameter.instance);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ public class Geary.Imap.IdleCommand : Command {
|
|||
private GLib.Cancellable? exit_cancellable = new GLib.Cancellable();
|
||||
|
||||
|
||||
public IdleCommand() {
|
||||
base(NAME);
|
||||
public IdleCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
this.exit_lock = new Geary.Nonblocking.Semaphore(this.exit_cancellable);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,16 +38,22 @@ public class Geary.Imap.ListCommand : Command {
|
|||
*
|
||||
* See [[http://redmine.yorba.org/issues/7624]] for more information.
|
||||
*/
|
||||
public ListCommand(MailboxSpecifier mailbox, bool use_xlist, ListReturnParameter? return_param) {
|
||||
base(use_xlist ? XLIST_NAME : NAME, { "" });
|
||||
public ListCommand(MailboxSpecifier mailbox,
|
||||
bool use_xlist,
|
||||
ListReturnParameter? return_param,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(use_xlist ? XLIST_NAME : NAME, { "" }, should_send);
|
||||
|
||||
this.args.add(mailbox.to_parameter());
|
||||
add_return_parameter(return_param);
|
||||
}
|
||||
|
||||
public ListCommand.wildcarded(string reference, MailboxSpecifier mailbox, bool use_xlist,
|
||||
ListReturnParameter? return_param) {
|
||||
base(use_xlist ? XLIST_NAME : NAME, { reference });
|
||||
public ListCommand.wildcarded(string reference,
|
||||
MailboxSpecifier mailbox,
|
||||
bool use_xlist,
|
||||
ListReturnParameter? return_param,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(use_xlist ? XLIST_NAME : NAME, { reference }, should_send);
|
||||
|
||||
this.args.add(mailbox.to_parameter());
|
||||
add_return_parameter(return_param);
|
||||
|
|
|
|||
|
|
@ -9,14 +9,17 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.LoginCommand : Command {
|
||||
|
||||
public const string NAME = "login";
|
||||
|
||||
public LoginCommand(string user, string pass) {
|
||||
base (NAME, { user, pass });
|
||||
public LoginCommand(string user,
|
||||
string pass,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, { user, pass }, should_send);
|
||||
}
|
||||
|
||||
public override string to_string() {
|
||||
return "%s %s <user> <pass>".printf(tag.to_string(), name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.LogoutCommand : Command {
|
||||
|
||||
public const string NAME = "logout";
|
||||
|
||||
public LogoutCommand() {
|
||||
base (NAME);
|
||||
public LogoutCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ public class Geary.Imap.NamespaceCommand : Command {
|
|||
|
||||
public const string NAME = "NAMESPACE";
|
||||
|
||||
public NamespaceCommand() {
|
||||
base(NAME);
|
||||
public NamespaceCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.NoopCommand : Command {
|
||||
|
||||
public const string NAME = "noop";
|
||||
|
||||
public NoopCommand() {
|
||||
base (NAME);
|
||||
public NoopCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ public class Geary.Imap.SearchCommand : Command {
|
|||
public const string NAME = "search";
|
||||
public const string UID_NAME = "uid search";
|
||||
|
||||
public SearchCommand(SearchCriteria criteria) {
|
||||
base(NAME);
|
||||
public SearchCommand(SearchCriteria criteria,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
|
||||
// Extend rather than append the criteria, so the top-level
|
||||
// criterion appear in the top-level list and not as a child
|
||||
|
|
@ -24,8 +25,9 @@ public class Geary.Imap.SearchCommand : Command {
|
|||
this.args.extend(criteria);
|
||||
}
|
||||
|
||||
public SearchCommand.uid(SearchCriteria criteria) {
|
||||
base(UID_NAME);
|
||||
public SearchCommand.uid(SearchCriteria criteria,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(UID_NAME, null, should_send);
|
||||
|
||||
// Extend rather than append the criteria, so the top-level
|
||||
// criterion appear in the top-level list and not as a child
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ public class Geary.Imap.SelectCommand : Command {
|
|||
|
||||
public MailboxSpecifier mailbox { get; private set; }
|
||||
|
||||
public SelectCommand(MailboxSpecifier mailbox) {
|
||||
base(NAME);
|
||||
public SelectCommand(MailboxSpecifier mailbox,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
this.mailbox = mailbox;
|
||||
this.args.add(mailbox.to_parameter());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@
|
|||
*/
|
||||
|
||||
public class Geary.Imap.StarttlsCommand : Command {
|
||||
|
||||
public const string NAME = "STARTTLS";
|
||||
|
||||
public StarttlsCommand() {
|
||||
base (NAME);
|
||||
public StarttlsCommand(GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@ public class Geary.Imap.StatusCommand : Command {
|
|||
public const string NAME = "STATUS";
|
||||
|
||||
|
||||
public StatusCommand(MailboxSpecifier mailbox, StatusDataType[] data_items) {
|
||||
base (NAME);
|
||||
public StatusCommand(MailboxSpecifier mailbox,
|
||||
StatusDataType[] data_items,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(NAME, null, should_send);
|
||||
|
||||
this.args.add(mailbox.to_parameter());
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,11 @@ public class Geary.Imap.StoreCommand : Command {
|
|||
SILENT
|
||||
}
|
||||
|
||||
public StoreCommand(MessageSet message_set, Gee.List<MessageFlag> flag_list, Option options) {
|
||||
base (message_set.is_uid ? UID_NAME : NAME);
|
||||
public StoreCommand(MessageSet message_set,
|
||||
Gee.List<MessageFlag> flag_list,
|
||||
Option options,
|
||||
GLib.Cancellable? should_send) {
|
||||
base(message_set.is_uid ? UID_NAME : NAME, null, should_send);
|
||||
|
||||
bool add_flag = (options & Option.ADD_FLAGS) != 0;
|
||||
bool silent = (options & Option.SILENT) != 0;
|
||||
|
|
|
|||
|
|
@ -576,8 +576,8 @@ public class Geary.Imap.ClientConnection : BaseObject, Logging.Source {
|
|||
private void on_idle_timeout() {
|
||||
debug("Initiating IDLE");
|
||||
try {
|
||||
this.send_command(new IdleCommand());
|
||||
} catch (ImapError err) {
|
||||
this.send_command(new IdleCommand(this.open_cancellable));
|
||||
warning("Error sending IDLE: %s", err.message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,10 +159,13 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
public override async Object? execute_async(Cancellable? cancellable) throws Error {
|
||||
response = yield owner.command_transaction_async(cmd, cancellable);
|
||||
|
||||
return response;
|
||||
public override async Object? execute_async(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
// The command's should_send cancellable will be used to
|
||||
// cancel the command if needed, so don't need to check or
|
||||
// pass this method's cancellable through.
|
||||
this.response = yield owner.submit_command(cmd);
|
||||
return this.response;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -903,7 +906,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
switch (credentials.supported_method) {
|
||||
case Geary.Credentials.Method.PASSWORD:
|
||||
cmd = new LoginCommand(
|
||||
credentials.user, credentials.token
|
||||
credentials.user,
|
||||
credentials.token,
|
||||
cancellable
|
||||
);
|
||||
break;
|
||||
|
||||
|
|
@ -915,7 +920,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
);
|
||||
}
|
||||
cmd = new AuthenticateCommand.oauth2(
|
||||
credentials.user, credentials.token
|
||||
credentials.user,
|
||||
credentials.token,
|
||||
cancellable
|
||||
);
|
||||
break;
|
||||
|
||||
|
|
@ -936,10 +943,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// should always proceed; only an Error could change this
|
||||
assert(params.proceed);
|
||||
|
||||
StatusResponse response = yield command_transaction_async(
|
||||
cmd, cancellable
|
||||
);
|
||||
|
||||
StatusResponse response = yield submit_command(cmd);
|
||||
if (response.status != Status.OK) {
|
||||
// Throw an error indicating auth failed here, unless
|
||||
// there is a status response and it indicates that the
|
||||
|
|
@ -987,7 +991,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
throws GLib.Error {
|
||||
// If no capabilities available, get them now
|
||||
if (this.capabilities.is_empty()) {
|
||||
yield send_command_async(new CapabilityCommand(), cancellable);
|
||||
yield send_command_async(new CapabilityCommand(cancellable));
|
||||
}
|
||||
|
||||
var last_capabilities = this.capabilities.revision;
|
||||
|
|
@ -1000,7 +1004,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
|
||||
debug("Attempting STARTTLS...");
|
||||
StatusResponse resp = yield send_command_async(
|
||||
new StarttlsCommand(), cancellable
|
||||
new StarttlsCommand(cancellable)
|
||||
);
|
||||
|
||||
if (resp.status == Status.OK) {
|
||||
|
|
@ -1021,7 +1025,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// mitigate main-in-the-middle attacks. If the TLS
|
||||
// command response did not update capabilities,
|
||||
// explicitly do so now.
|
||||
yield send_command_async(new CapabilityCommand(), cancellable);
|
||||
yield send_command_async(new CapabilityCommand(cancellable));
|
||||
last_capabilities = this.capabilities.revision;
|
||||
}
|
||||
}
|
||||
|
|
@ -1031,7 +1035,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
|
||||
// if new capabilities not offered after login, get them now
|
||||
if (last_capabilities == capabilities.revision) {
|
||||
yield send_command_async(new CapabilityCommand(), cancellable);
|
||||
yield send_command_async(new CapabilityCommand(cancellable));
|
||||
}
|
||||
|
||||
var list_results = new Gee.ArrayList<MailboxInformation>();
|
||||
|
|
@ -1041,8 +1045,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
try {
|
||||
// Determine what this connection calls the inbox
|
||||
Imap.StatusResponse response = yield send_command_async(
|
||||
new ListCommand(MailboxSpecifier.inbox, false, null),
|
||||
cancellable
|
||||
new ListCommand(MailboxSpecifier.inbox, false, null, cancellable)
|
||||
);
|
||||
if (response.status == Status.OK && !list_results.is_empty) {
|
||||
this.inbox = list_results[0];
|
||||
|
|
@ -1055,8 +1058,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// Try to determine what the connection's namespaces are
|
||||
if (this.capabilities.has_capability(Capabilities.NAMESPACE)) {
|
||||
response = yield send_command_async(
|
||||
new NamespaceCommand(),
|
||||
cancellable
|
||||
new NamespaceCommand(cancellable)
|
||||
);
|
||||
if (response.status != Status.OK) {
|
||||
warning("NAMESPACE command failed");
|
||||
|
|
@ -1082,8 +1084,12 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// it. In particular, uw-imap sends a null prefix
|
||||
// for the inbox.
|
||||
response = yield send_command_async(
|
||||
new ListCommand(new MailboxSpecifier(prefix), false, null),
|
||||
cancellable
|
||||
new ListCommand(
|
||||
new MailboxSpecifier(prefix),
|
||||
false,
|
||||
null,
|
||||
cancellable
|
||||
)
|
||||
);
|
||||
if (response.status == Status.OK && !list_results.is_empty) {
|
||||
MailboxInformation list = list_results[0];
|
||||
|
|
@ -1243,7 +1249,10 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// is now dead
|
||||
keepalive_id = 0;
|
||||
|
||||
send_command_async.begin(new NoopCommand(), null, on_keepalive_completed);
|
||||
send_command_async.begin(
|
||||
new NoopCommand(null),
|
||||
on_keepalive_completed
|
||||
);
|
||||
debug("Sending keepalive...");
|
||||
|
||||
// No need to reschedule keepalive, as the notification that the command was sent should
|
||||
|
|
@ -1264,8 +1273,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// send commands
|
||||
//
|
||||
|
||||
public async StatusResponse send_command_async(Command cmd,
|
||||
GLib.Cancellable? cancellable)
|
||||
public async StatusResponse send_command_async(Command cmd)
|
||||
throws GLib.Error {
|
||||
check_unsupported_send_command(cmd);
|
||||
|
||||
|
|
@ -1277,7 +1285,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
|
||||
assert(params.proceed);
|
||||
|
||||
return yield command_transaction_async(cmd, cancellable);
|
||||
return yield submit_command(cmd);
|
||||
}
|
||||
|
||||
public async Gee.Map<Command, StatusResponse>
|
||||
|
|
@ -1402,9 +1410,9 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// Ternary troubles
|
||||
Command cmd;
|
||||
if (is_select)
|
||||
cmd = new SelectCommand(mailbox);
|
||||
cmd = new SelectCommand(mailbox, cancellable);
|
||||
else
|
||||
cmd = new ExamineCommand(mailbox);
|
||||
cmd = new ExamineCommand(mailbox, cancellable);
|
||||
|
||||
MachineParams params = new MachineParams(cmd);
|
||||
fsm.issue(Event.SELECT, null, params);
|
||||
|
|
@ -1414,7 +1422,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
|
||||
assert(params.proceed);
|
||||
|
||||
return yield command_transaction_async(cmd, cancellable);
|
||||
return yield submit_command(cmd);
|
||||
}
|
||||
|
||||
private uint on_select(uint state, uint event, void *user, Object? object) {
|
||||
|
|
@ -1471,7 +1479,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
|
||||
public async StatusResponse close_mailbox_async(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
CloseCommand cmd = new CloseCommand();
|
||||
CloseCommand cmd = new CloseCommand(cancellable);
|
||||
|
||||
MachineParams params = new MachineParams(cmd);
|
||||
fsm.issue(Event.CLOSE_MAILBOX, null, params);
|
||||
|
|
@ -1479,7 +1487,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
if (params.err != null)
|
||||
throw params.err;
|
||||
|
||||
return yield command_transaction_async(cmd, cancellable);
|
||||
return yield submit_command(cmd);
|
||||
}
|
||||
|
||||
private uint on_close_mailbox(uint state, uint event, void *user, Object? object) {
|
||||
|
|
@ -1527,7 +1535,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
*/
|
||||
public async void logout_async(GLib.Cancellable? cancellable)
|
||||
throws GLib.Error {
|
||||
LogoutCommand cmd = new LogoutCommand();
|
||||
LogoutCommand cmd = new LogoutCommand(cancellable);
|
||||
|
||||
MachineParams params = new MachineParams(cmd);
|
||||
fsm.issue(Event.LOGOUT, null, params);
|
||||
|
|
@ -1536,7 +1544,7 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
throw params.err;
|
||||
|
||||
if (params.proceed) {
|
||||
yield command_transaction_async(cmd, cancellable);
|
||||
yield submit_command(cmd);
|
||||
yield do_disconnect(DisconnectReason.LOCAL_CLOSE);
|
||||
}
|
||||
}
|
||||
|
|
@ -1779,11 +1787,13 @@ public class Geary.Imap.ClientSession : BaseObject, Logging.Source {
|
|||
// command submission
|
||||
//
|
||||
|
||||
private async StatusResponse command_transaction_async(Command cmd, Cancellable? cancellable)
|
||||
throws Error {
|
||||
if (this.cx == null)
|
||||
throw new ImapError.NOT_CONNECTED("Not connected to %s", imap_endpoint.to_string());
|
||||
|
||||
private async StatusResponse submit_command(Command cmd)
|
||||
throws GLib.Error {
|
||||
if (this.cx == null) {
|
||||
throw new ImapError.NOT_CONNECTED(
|
||||
"Not connected to %s", imap_endpoint.to_string()
|
||||
);
|
||||
}
|
||||
this.cx.send_command(cmd);
|
||||
|
||||
// Once a command has been sent over the wire, it can't be
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class Geary.Imap.CreateCommandTest : TestCase {
|
|||
|
||||
public void basic_create() throws Error {
|
||||
assert_equal(
|
||||
new CreateCommand(new MailboxSpecifier("owatagusiam/")).to_string(),
|
||||
new CreateCommand(new MailboxSpecifier("owatagusiam/"), null).to_string(),
|
||||
"---- create owatagusiam/"
|
||||
);
|
||||
}
|
||||
|
|
@ -25,7 +25,8 @@ class Geary.Imap.CreateCommandTest : TestCase {
|
|||
assert_equal(
|
||||
new CreateCommand.special_use(
|
||||
new MailboxSpecifier("Everything"),
|
||||
ALL_MAIL
|
||||
ALL_MAIL,
|
||||
null
|
||||
).to_string(),
|
||||
"---- create Everything (use (\\All))"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
|
|||
data_items.add(FetchDataSpecifier.UID);
|
||||
|
||||
assert_equal(
|
||||
new FetchCommand(this.msg_set, data_items, null).to_string(),
|
||||
new FetchCommand(this.msg_set, data_items, null, null).to_string(),
|
||||
"---- fetch 1 uid"
|
||||
);
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
|
|||
);
|
||||
|
||||
assert_equal(
|
||||
new FetchCommand(this.msg_set, null, body_items).to_string(),
|
||||
new FetchCommand(this.msg_set, null, body_items, null).to_string(),
|
||||
"---- fetch 1 body[text]"
|
||||
);
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
|
|||
data_items.add(FetchDataSpecifier.BODY);
|
||||
|
||||
assert_equal(
|
||||
new FetchCommand(this.msg_set, data_items, null).to_string(),
|
||||
new FetchCommand(this.msg_set, data_items, null, null).to_string(),
|
||||
"---- fetch 1 (uid body)"
|
||||
);
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
|
|||
);
|
||||
|
||||
assert_equal(
|
||||
new FetchCommand(this.msg_set, null, body_items).to_string(),
|
||||
new FetchCommand(this.msg_set, null, body_items, null).to_string(),
|
||||
"---- fetch 1 (body[header] body[text])"
|
||||
);
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ class Geary.Imap.FetchCommandTest : TestCase {
|
|||
);
|
||||
|
||||
assert_equal(
|
||||
new FetchCommand(this.msg_set, data_items, body_items).to_string(),
|
||||
new FetchCommand(this.msg_set, data_items, body_items, null).to_string(),
|
||||
"---- fetch 1 (uid flags body[header] body[text])"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class Geary.Imap.ClientConnectionTest : TestCase {
|
|||
private class TestCommand : Command {
|
||||
|
||||
public TestCommand() {
|
||||
base("TEST");
|
||||
base("TEST", null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue