Add initial NAMESPACE command, response and console support.

Bug 768422
This commit is contained in:
Michael James Gratton 2016-07-07 01:32:05 +10:00
parent 2a9f749145
commit 53dd5a5f69
9 changed files with 192 additions and 6 deletions

View file

@ -191,6 +191,7 @@ src/engine/imap/command/imap-list-return-parameter.vala
src/engine/imap/command/imap-login-command.vala
src/engine/imap/command/imap-logout-command.vala
src/engine/imap/command/imap-message-set.vala
src/engine/imap/command/imap-namespace-command.vala
src/engine/imap/command/imap-noop-command.vala
src/engine/imap/command/imap-search-command.vala
src/engine/imap/command/imap-search-criteria.vala
@ -275,6 +276,7 @@ src/engine/imap/message/imap-mailbox-specifier.vala
src/engine/imap/message/imap-message-data.vala
src/engine/imap/message/imap-message-flag.vala
src/engine/imap/message/imap-message-flags.vala
src/engine/imap/message/imap-namespace.vala
src/engine/imap/message/imap-sequence-number.vala
src/engine/imap/message/imap-status-data-type.vala
src/engine/imap/message/imap-tag.vala
@ -297,6 +299,7 @@ src/engine/imap/response/imap-fetched-data.vala
src/engine/imap/response/imap-mailbox-attribute.vala
src/engine/imap/response/imap-mailbox-attributes.vala
src/engine/imap/response/imap-mailbox-information.vala
src/engine/imap/response/imap-namespace-response.vala
src/engine/imap/response/imap-response-code-type.vala
src/engine/imap/response/imap-response-code.vala
src/engine/imap/response/imap-server-data-type.vala

View file

@ -108,6 +108,7 @@ engine/imap/command/imap-list-return-parameter.vala
engine/imap/command/imap-login-command.vala
engine/imap/command/imap-logout-command.vala
engine/imap/command/imap-message-set.vala
engine/imap/command/imap-namespace-command.vala
engine/imap/command/imap-noop-command.vala
engine/imap/command/imap-search-command.vala
engine/imap/command/imap-search-criteria.vala
@ -128,6 +129,7 @@ engine/imap/message/imap-mailbox-parameter.vala
engine/imap/message/imap-message-data.vala
engine/imap/message/imap-message-flag.vala
engine/imap/message/imap-message-flags.vala
engine/imap/message/imap-namespace.vala
engine/imap/message/imap-sequence-number.vala
engine/imap/message/imap-status-data-type.vala
engine/imap/message/imap-tag.vala
@ -150,6 +152,7 @@ engine/imap/response/imap-fetched-data.vala
engine/imap/response/imap-mailbox-attribute.vala
engine/imap/response/imap-mailbox-attributes.vala
engine/imap/response/imap-mailbox-information.vala
engine/imap/response/imap-namespace-response.vala
engine/imap/response/imap-response-code.vala
engine/imap/response/imap-response-code-type.vala
engine/imap/response/imap-server-data.vala

View file

@ -88,6 +88,7 @@ class ImapConsole : Gtk.Window {
"logout",
"id",
"bye",
"namespace",
"list",
"xlist",
"examine",
@ -166,7 +167,11 @@ class ImapConsole : Gtk.Window {
case "id":
id(cmd, args);
break;
case "namespace":
namespace(cmd, args);
break;
case "list":
case "xlist":
list(cmd, args);
@ -433,7 +438,23 @@ class ImapConsole : Gtk.Window {
exception(err);
}
}
private void namespace(string cmd, string[] args) throws Error {
check_connected(cmd, args, 0, null);
status("Retrieving NAMESPACE...");
cx.send_async.begin(new Geary.Imap.NamespaceCommand(), null, on_namespace);
}
private void on_namespace(Object? source, AsyncResult result) {
try {
cx.send_async.end(result);
status("Retrieved NAMESPACE");
} catch (Error err) {
exception(err);
}
}
private void list(string cmd, string[] args) throws Error {
check_connected(cmd, args, 2, "<reference> <mailbox>");

View file

@ -0,0 +1,24 @@
/*
* Copyright 2016 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* The RFC 2342 NAMESPACE command.
*
* Determines the mailbox name prefix and hierarchy delimiter for the
* personal, other user's and public namespaces.
*
* @see [[https://tools.ietf.org/html/rfc2342]]
*/
public class Geary.Imap.NamespaceCommand : Command {
public const string NAME = "NAMESPACE";
public NamespaceCommand() {
base(NAME);
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2016 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* Namespace component in a response for a NAMESPACE command.
*
* @see Geary.Imap.NamespaceCommand
*/
public class Geary.Imap.Namespace : BaseObject {
public string prefix { get; private set; }
public string? delim { get; private set; }
public Namespace(string prefix, string? delim) {
this.prefix = prefix;
this.delim = delim;
}
public string to_string() {
return "(%s,%s)".printf(this.prefix, this.delim ?? "NIL");
}
}

View file

@ -12,7 +12,8 @@ public class Geary.Imap.Capabilities : Geary.GenericCapabilities {
public const string DEFLATE_SETTING = "DEFLATE";
public const string UIDPLUS = "UIDPLUS";
public const string SPECIAL_USE = "SPECIAL-USE";
public const string NAMESPACE = "NAMESPACE";
public const string NAME_SEPARATOR = "=";
public const string? VALUE_SEPARATOR = null;

View file

@ -0,0 +1,83 @@
/*
* Copyright 2016 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* Response for a NAMESPACE command.
*
* @see Geary.Imap.NamespaceCommand
*/
public class Geary.Imap.NamespaceResponse : BaseObject {
public Namespace[]? personal { get; private set; default = null; }
public Namespace[]? user { get; private set; default = null; }
public Namespace[]? shared { get; private set; default = null; }
/**
* Decodes {@link ServerData} into a NamespaceResponse representation.
*
* The ServerData must be the response to a NAMESPACE command.
*
* @see ServerData.get_list
*/
public static NamespaceResponse decode(ServerData server_data) throws ImapError {
StringParameter cmd = server_data.get_as_string(1);
if (!cmd.equals_ci(NamespaceCommand.NAME))
throw new ImapError.PARSE_ERROR(
"Not NAMESPACE data: %s", server_data.to_string()
);
if (server_data.size <= 2) {
throw new ImapError.PARSE_ERROR(
"No NAMESPACEs privided: %s", server_data.to_string()
);
}
ListParameter? personal = server_data.get_as_nullable_list(2);
ListParameter? user = null;
if (server_data.size >= 4) {
user = server_data.get_as_nullable_list(3);
}
ListParameter? shared = null;
if (server_data.size >= 5) {
shared = server_data.get_as_nullable_list(4);
}
return new NamespaceResponse(
parse_namespaces(personal),
user != null ? parse_namespaces(user) : null,
shared != null ? parse_namespaces(shared) : null
);
}
private static Namespace[]? parse_namespaces(ListParameter? list) throws ImapError {
Namespace[] nss = new Namespace[list.size];
for (int i = 0; i < list.size; i++) {
nss[i] = parse_namespace(list.get_as_list(i));
}
return nss;
}
private static Namespace? parse_namespace(ListParameter? list) throws ImapError {
Namespace? ns = null;
if (list != null && list.size >= 1) {
ns = new Namespace(
list.get_as_string(0).ascii,
list.get_as_nullable_string(1).nullable_ascii
);
}
return ns;
}
public NamespaceResponse(Namespace[]? personal, Namespace[]? user, Namespace[]? shared) {
this.personal = personal;
this.user = user;
this.shared = shared;
}
}

View file

@ -18,6 +18,7 @@ public enum Geary.Imap.ServerDataType {
FLAGS,
LIST,
LSUB,
NAMESPACE,
RECENT,
SEARCH,
STATUS,
@ -45,7 +46,10 @@ public enum Geary.Imap.ServerDataType {
case LSUB:
return "lsub";
case NAMESPACE:
return "namespace";
case RECENT:
return "recent";
@ -91,7 +95,10 @@ public enum Geary.Imap.ServerDataType {
case "lsub":
return LSUB;
case "namespace":
return NAMESPACE;
case "recent":
return RECENT;
@ -137,6 +144,9 @@ public enum Geary.Imap.ServerDataType {
case "lsub":
return LSUB;
case "namespace":
return NAMESPACE;
case "search":
return SEARCH;

View file

@ -129,7 +129,19 @@ public class Geary.Imap.ServerData : ServerResponse {
return MailboxInformation.decode(this, true);
}
/**
* Parses the {@link ServerData} into {@link MailboxInformation}, if possible.
*
* @throws ImapError.INVALID if not a NAMESPACE response.
*/
public NamespaceResponse get_namespace() throws ImapError {
if (server_data_type != ServerDataType.NAMESPACE)
throw new ImapError.INVALID("Not NAMESPACE data: %s", to_string());
return NamespaceResponse.decode(this);
}
/**
* Parses the {@link ServerData} into a {@link ServerDataType.RECENT} value, if possible.
*